From: TimePath Date: Sat, 6 Jan 2018 02:56:39 +0000 (+1100) Subject: reformat code! now the code is only ugly on the *inside* X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=commitdiff_plain;h=9dfae1c9b270ee369c6362903a9205b30751b95f reformat code! now the code is only ugly on the *inside* --- diff --git a/contrib/bkgrnd2d/bkgrnd2d.cpp b/contrib/bkgrnd2d/bkgrnd2d.cpp index b1159525..7ed6315d 100644 --- a/contrib/bkgrnd2d/bkgrnd2d.cpp +++ b/contrib/bkgrnd2d/bkgrnd2d.cpp @@ -30,62 +30,65 @@ CBackgroundRender render; -CBackgroundImage backgroundXY( XY ),backgroundXZ( XZ ),backgroundYZ( YZ ); +CBackgroundImage backgroundXY(XY), backgroundXZ(XZ), backgroundYZ(YZ); -CBackgroundRender::CBackgroundRender(){ - refCount = 1; +CBackgroundRender::CBackgroundRender() +{ + refCount = 1; } -CBackgroundRender::~CBackgroundRender(){ +CBackgroundRender::~CBackgroundRender() +{ } -void CBackgroundRender::Register(){ - g_QglTable.m_pfnHookGL2DWindow( this ); +void CBackgroundRender::Register() +{ + g_QglTable.m_pfnHookGL2DWindow(this); } -void CBackgroundRender::Draw2D( VIEWTYPE vt ){ - switch ( vt ) - { - case XY: - backgroundXY.Render(); - break; - case XZ: - backgroundXZ.Render(); - break; - case YZ: - backgroundYZ.Render(); - break; - } +void CBackgroundRender::Draw2D(VIEWTYPE vt) +{ + switch (vt) { + case XY: + backgroundXY.Render(); + break; + case XZ: + backgroundXZ.Render(); + break; + case YZ: + backgroundYZ.Render(); + break; + } } -CBackgroundImage::CBackgroundImage( VIEWTYPE vt ){ - m_tex = NULL; - m_alpha = 0.5; - - // TODO, sensible defaults ? Or not show until we have extents ? - m_xmin = m_ymin = 0.0f; - m_xmax = m_ymax = 0.0f; - - m_bActive = false; - - m_vt = vt; - - switch ( m_vt ) - { - case XY: - m_ix = 0; - m_iy = 1; - break; - case XZ: - m_ix = 0; - m_iy = 2; - break; - case YZ: - m_ix = 1; - m_iy = 2; - break; - } +CBackgroundImage::CBackgroundImage(VIEWTYPE vt) +{ + m_tex = NULL; + m_alpha = 0.5; + + // TODO, sensible defaults ? Or not show until we have extents ? + m_xmin = m_ymin = 0.0f; + m_xmax = m_ymax = 0.0f; + + m_bActive = false; + + m_vt = vt; + + switch (m_vt) { + case XY: + m_ix = 0; + m_iy = 1; + break; + case XZ: + m_ix = 0; + m_iy = 2; + break; + case YZ: + m_ix = 1; + m_iy = 2; + break; + } } /* @@ -96,214 +99,214 @@ CBackgroundImage::CBackgroundImage( VIEWTYPE vt ){ } */ -void CBackgroundImage::Cleanup(){ - if ( m_tex ) { - g_QglTable.m_pfn_qglDeleteTextures( 1,&m_tex->texture_number ); - g_free( m_tex ); - m_tex = NULL; - } +void CBackgroundImage::Cleanup() +{ + if (m_tex) { + g_QglTable.m_pfn_qglDeleteTextures(1, &m_tex->texture_number); + g_free(m_tex); + m_tex = NULL; + } } -void CBackgroundImage::Render(){ - if ( !m_bActive || !Valid() ) { - return; - } - g_QglTable.m_pfn_qglPushAttrib( GL_ALL_ATTRIB_BITS ); +void CBackgroundImage::Render() +{ + if (!m_bActive || !Valid()) { + return; + } + g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS); - g_QglTable.m_pfn_qglEnable( GL_TEXTURE_2D ); - g_QglTable.m_pfn_qglEnable( GL_BLEND ); - g_QglTable.m_pfn_qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - g_QglTable.m_pfn_qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - g_QglTable.m_pfn_qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); - g_QglTable.m_pfn_qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + g_QglTable.m_pfn_qglEnable(GL_TEXTURE_2D); + g_QglTable.m_pfn_qglEnable(GL_BLEND); + g_QglTable.m_pfn_qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + g_QglTable.m_pfn_qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + g_QglTable.m_pfn_qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + g_QglTable.m_pfn_qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - g_QglTable.m_pfn_qglPolygonMode( GL_FRONT,GL_FILL ); - // TODO, just so we can tell if we end up going the wrong way - // g_QglTable.m_pfn_qglPolygonMode(GL_BACK,GL_LINE); - // TODO any other state we should not assume ? + g_QglTable.m_pfn_qglPolygonMode(GL_FRONT, GL_FILL); + // TODO, just so we can tell if we end up going the wrong way + // g_QglTable.m_pfn_qglPolygonMode(GL_BACK,GL_LINE); + // TODO any other state we should not assume ? - g_QglTable.m_pfn_qglBindTexture( GL_TEXTURE_2D, m_tex->texture_number ); - g_QglTable.m_pfn_qglBegin( GL_QUADS ); + g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, m_tex->texture_number); + g_QglTable.m_pfn_qglBegin(GL_QUADS); - g_QglTable.m_pfn_qglColor4f( 1.0,1.0,1.0,m_alpha ); - g_QglTable.m_pfn_qglTexCoord2f( 0.0,1.0 ); - g_QglTable.m_pfn_qglVertex2f( m_xmin,m_ymin ); + g_QglTable.m_pfn_qglColor4f(1.0, 1.0, 1.0, m_alpha); + g_QglTable.m_pfn_qglTexCoord2f(0.0, 1.0); + g_QglTable.m_pfn_qglVertex2f(m_xmin, m_ymin); - g_QglTable.m_pfn_qglTexCoord2f( 1.0,1.0 ); - g_QglTable.m_pfn_qglVertex2f( m_xmax,m_ymin ); + g_QglTable.m_pfn_qglTexCoord2f(1.0, 1.0); + g_QglTable.m_pfn_qglVertex2f(m_xmax, m_ymin); - g_QglTable.m_pfn_qglTexCoord2f( 1.0,0.0 ); - g_QglTable.m_pfn_qglVertex2f( m_xmax,m_ymax ); + g_QglTable.m_pfn_qglTexCoord2f(1.0, 0.0); + g_QglTable.m_pfn_qglVertex2f(m_xmax, m_ymax); - g_QglTable.m_pfn_qglTexCoord2f( 0.0,0.0 ); - g_QglTable.m_pfn_qglVertex2f( m_xmin,m_ymax ); + g_QglTable.m_pfn_qglTexCoord2f(0.0, 0.0); + g_QglTable.m_pfn_qglVertex2f(m_xmin, m_ymax); - g_QglTable.m_pfn_qglEnd(); - g_QglTable.m_pfn_qglBindTexture( GL_TEXTURE_2D, 0 ); + g_QglTable.m_pfn_qglEnd(); + g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, 0); - g_QglTable.m_pfn_qglPopAttrib(); + g_QglTable.m_pfn_qglPopAttrib(); } -bool CBackgroundImage::Load( const char *filename ){ - qtexture_t *newtex; +bool CBackgroundImage::Load(const char *filename) +{ + qtexture_t *newtex; - unsigned char *image = NULL; // gets allocated with what ? g_malloc - int width = 0, height = 0; + unsigned char *image = NULL; // gets allocated with what ? g_malloc + int width = 0, height = 0; - g_FuncTable.m_pfnLoadImage( filename,&image,&width,&height ); + g_FuncTable.m_pfnLoadImage(filename, &image, &width, &height); - if ( !image ) { - Syn_Printf( MSG_WARN "load %s failed\n",filename ); - return false; - } + if (!image) { + Syn_Printf(MSG_WARN "load %s failed\n", filename); + return false; + } // just in case we want to build for an old version // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=900 #ifdef BKGRND2D_JPG_WORKAROUND - if ( strlen( filename ) > 4 && !strcmp( ".jpg",filename + strlen( filename ) - 4 ) ) { - Syn_Printf( MSG_PREFIX ".jpg workaround, clearing alpha channel\n" ); - int size = width * height * 4; - int i; - for ( i = 3; i < size; i += 4 ) { - image[i] = 255; - } - } + if ( strlen( filename ) > 4 && !strcmp( ".jpg",filename + strlen( filename ) - 4 ) ) { + Syn_Printf( MSG_PREFIX ".jpg workaround, clearing alpha channel\n" ); + int size = width * height * 4; + int i; + for ( i = 3; i < size; i += 4 ) { + image[i] = 255; + } + } #endif - //TODO bug for stored texture size - //TODO whose gl context are we in, anyway ? - newtex = g_FuncTable.m_pfnLoadTextureRGBA( image,width,height ); + //TODO bug for stored texture size + //TODO whose gl context are we in, anyway ? + newtex = g_FuncTable.m_pfnLoadTextureRGBA(image, width, height); - g_free( image ); + g_free(image); - if ( !newtex ) { - Syn_Printf( MSG_WARN "image to texture failed\n" ); - return false; - } + if (!newtex) { + Syn_Printf(MSG_WARN "image to texture failed\n"); + return false; + } - Cleanup(); - m_tex = newtex; + Cleanup(); + m_tex = newtex; - g_FuncTable.m_pfnSysUpdateWindows( W_XY ); + g_FuncTable.m_pfnSysUpdateWindows(W_XY); - return true; + return true; } -bool CBackgroundImage::SetExtentsMM(){ - entity_s *worldentity; - const char *val; - int xmin = 0, ymin = 0, xmax = 0, ymax = 0; - - worldentity = (entity_s *)g_FuncTable.m_pfnGetEntityHandle( 0 ); - if ( !worldentity ) { - Syn_Printf( MSG_WARN "SetExtentsMM worldspawn not found\n" ); - return false; - } - //TODO val is not NULL even if key does not exist - val = g_EntityTable.m_pfnValueForKey( worldentity,"mapcoordsmins" ); - if ( !val || !val[0] ) { - Syn_Printf( MSG_WARN "SetExtentsMM mapcoordsmins not found\n" ); - return false; - } +bool CBackgroundImage::SetExtentsMM() +{ + entity_s *worldentity; + const char *val; + int xmin = 0, ymin = 0, xmax = 0, ymax = 0; + + worldentity = (entity_s *) g_FuncTable.m_pfnGetEntityHandle(0); + if (!worldentity) { + Syn_Printf(MSG_WARN "SetExtentsMM worldspawn not found\n"); + return false; + } + //TODO val is not NULL even if key does not exist + val = g_EntityTable.m_pfnValueForKey(worldentity, "mapcoordsmins"); + if (!val || !val[0]) { + Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmins not found\n"); + return false; + } // we could be more robust // note contortions due to splashs strange idea of min and max - if ( sscanf( val, "%d %d",&xmin,&ymax ) != 2 ) { - Syn_Printf( MSG_WARN "SetExtentsMM mapcoordsmins malformed\n" ); - return false; - } - - val = g_EntityTable.m_pfnValueForKey( worldentity,"mapcoordsmaxs" ); - if ( !val || !val[0] ) { - Syn_Printf( MSG_WARN "SetExtentsMM mapcoordsmaxs not found\n" ); - return false; - } - if ( sscanf( val, "%d %d",&xmax,&ymin ) != 2 ) { - Syn_Printf( MSG_WARN "SetExtentsMM mapcoordsmaxs malformed\n" ); - return false; - } - //might do sanity check before we commit - m_xmin = (float)xmin; - m_ymin = (float)ymin; - m_xmax = (float)xmax; - m_ymax = (float)ymax; - - g_FuncTable.m_pfnSysUpdateWindows( W_XY ); - return true; + if (sscanf(val, "%d %d", &xmin, &ymax) != 2) { + Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmins malformed\n"); + return false; + } + + val = g_EntityTable.m_pfnValueForKey(worldentity, "mapcoordsmaxs"); + if (!val || !val[0]) { + Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmaxs not found\n"); + return false; + } + if (sscanf(val, "%d %d", &xmax, &ymin) != 2) { + Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmaxs malformed\n"); + return false; + } + //might do sanity check before we commit + m_xmin = (float) xmin; + m_ymin = (float) ymin; + m_xmax = (float) xmax; + m_ymax = (float) ymax; + + g_FuncTable.m_pfnSysUpdateWindows(W_XY); + return true; } // TODO, this should just be exported from core // ripped directly from radiant/select.cpp:Select_GetBounds // -static bool get_selection_bounds( vec3_t mins, vec3_t maxs ){ - brush_t *b; - int i; - brush_t *selected_brushes = g_DataTable.m_pfnSelectedBrushes(); - //TODO should never happen - if ( !selected_brushes ) { - Sys_Printf( MSG_PREFIX "selected_brushes = NULL\n" ); - return false; - } - // this should mean no selection - if ( selected_brushes == selected_brushes->next ) { - Sys_Printf( MSG_PREFIX "nothing selected\n" ); - - return false; - } - - for ( i = 0 ; i < 3 ; i++ ) - { - mins[i] = 99999; - maxs[i] = -99999; - } - - for ( b = selected_brushes->next ; b != selected_brushes ; b = b->next ) - { - if ( b->owner->eclass->fixedsize ) { - for ( i = 0 ; i < 3 ; i++ ) - { - if ( b->owner->origin[i] < mins[i] ) { - mins[i] = b->owner->origin[i]; - } - if ( b->owner->origin[i] > maxs[i] ) { - maxs[i] = b->owner->origin[i]; - } - } - } - else - { - for ( i = 0 ; i < 3 ; i++ ) - { - if ( b->mins[i] < mins[i] ) { - mins[i] = b->mins[i]; - } - if ( b->maxs[i] > maxs[i] ) { - maxs[i] = b->maxs[i]; - } - } - } - } - return true; +static bool get_selection_bounds(vec3_t mins, vec3_t maxs) +{ + brush_t *b; + int i; + brush_t *selected_brushes = g_DataTable.m_pfnSelectedBrushes(); + //TODO should never happen + if (!selected_brushes) { + Sys_Printf(MSG_PREFIX "selected_brushes = NULL\n"); + return false; + } + // this should mean no selection + if (selected_brushes == selected_brushes->next) { + Sys_Printf(MSG_PREFIX "nothing selected\n"); + + return false; + } + + for (i = 0; i < 3; i++) { + mins[i] = 99999; + maxs[i] = -99999; + } + + for (b = selected_brushes->next; b != selected_brushes; b = b->next) { + if (b->owner->eclass->fixedsize) { + for (i = 0; i < 3; i++) { + if (b->owner->origin[i] < mins[i]) { + mins[i] = b->owner->origin[i]; + } + if (b->owner->origin[i] > maxs[i]) { + maxs[i] = b->owner->origin[i]; + } + } + } else { + for (i = 0; i < 3; i++) { + if (b->mins[i] < mins[i]) { + mins[i] = b->mins[i]; + } + if (b->maxs[i] > maxs[i]) { + maxs[i] = b->maxs[i]; + } + } + } + } + return true; } -bool CBackgroundImage::SetExtentsSel(){ - vec3_t mins,maxs; +bool CBackgroundImage::SetExtentsSel() +{ + vec3_t mins, maxs; - if ( !get_selection_bounds( mins,maxs ) ) { - return false; - } + if (!get_selection_bounds(mins, maxs)) { + return false; + } - if ( ( (int)mins[m_ix] == (int)maxs[m_ix] ) || - ( (int)mins[m_iy] == (int)maxs[m_iy] ) ) { - Syn_Printf( MSG_PREFIX "tiny selection\n" ); - return false; - } + if (((int) mins[m_ix] == (int) maxs[m_ix]) || + ((int) mins[m_iy] == (int) maxs[m_iy])) { + Syn_Printf(MSG_PREFIX "tiny selection\n"); + return false; + } - m_xmin = mins[m_ix]; - m_ymin = mins[m_iy]; - m_xmax = maxs[m_ix]; - m_ymax = maxs[m_iy]; + m_xmin = mins[m_ix]; + m_ymin = mins[m_iy]; + m_xmax = maxs[m_ix]; + m_ymax = maxs[m_iy]; - g_FuncTable.m_pfnSysUpdateWindows( W_XY ); + g_FuncTable.m_pfnSysUpdateWindows(W_XY); - return true; + return true; } diff --git a/contrib/bkgrnd2d/bkgrnd2d.h b/contrib/bkgrnd2d/bkgrnd2d.h index 41ee2713..5c3bf3ee 100644 --- a/contrib/bkgrnd2d/bkgrnd2d.h +++ b/contrib/bkgrnd2d/bkgrnd2d.h @@ -30,56 +30,66 @@ class CBackgroundImage { private: -qtexture_t *m_tex; -VIEWTYPE m_vt; + qtexture_t *m_tex; + VIEWTYPE m_vt; // which components of a vec3_t correspond to x and y in the image -unsigned m_ix,m_iy; + unsigned m_ix, m_iy; public: -CBackgroundImage( VIEWTYPE vt ); + CBackgroundImage(VIEWTYPE vt); // ~CBackgroundImage(); -float m_alpha; // vertex alpha -bool m_bActive; + float m_alpha; // vertex alpha + bool m_bActive; // x and y axis are in relation to the screen, not world, making rendering // the same for each view type. Whoever sets them is responsible for // shuffling. // units are world units. // TODO should be private -float m_xmin,m_ymin,m_xmax,m_ymax; + float m_xmin, m_ymin, m_xmax, m_ymax; // load file, create new tex, cleanup old tex, set new tex -bool Load( const char *filename ); -void Cleanup(); // free texture, free tex, set make tex NULL -bool SetExtentsMM(); // set extents by ET mapcoordsmaxs/mapcoordsmins -bool SetExtentsSel(); // set extents by selection -void Render(); -bool Valid() { return ( m_tex && ( m_xmin != m_xmax ) && ( m_ymin != m_ymax ) ); } + bool Load(const char *filename); + + void Cleanup(); // free texture, free tex, set make tex NULL + bool SetExtentsMM(); // set extents by ET mapcoordsmaxs/mapcoordsmins + bool SetExtentsSel(); // set extents by selection + void Render(); + + bool Valid() + { return (m_tex && (m_xmin != m_xmax) && (m_ymin != m_ymax)); } }; class CBackgroundRender : public IGL2DWindow { public: -CBackgroundRender(); -virtual ~CBackgroundRender(); + CBackgroundRender(); + + virtual ~CBackgroundRender(); protected: -int refCount; + int refCount; public: // IGL2DWindow IGL3DWindow interface -void IncRef() { refCount++; } -void DecRef() { - refCount--; if ( refCount <= 0 ) { - delete this; - } -} -void Draw2D( VIEWTYPE vt ); -void Register(); + void IncRef() + { refCount++; } + + void DecRef() + { + refCount--; + if (refCount <= 0) { + delete this; + } + } + + void Draw2D(VIEWTYPE vt); + + void Register(); }; -extern CBackgroundImage backgroundXY,backgroundXZ,backgroundYZ; +extern CBackgroundImage backgroundXY, backgroundXZ, backgroundYZ; extern CBackgroundRender render; diff --git a/contrib/bkgrnd2d/dialog.cpp b/contrib/bkgrnd2d/dialog.cpp index 01a1b985..7bdf466a 100644 --- a/contrib/bkgrnd2d/dialog.cpp +++ b/contrib/bkgrnd2d/dialog.cpp @@ -38,250 +38,268 @@ static ui::Window pDialogWnd{ui::null}; static GtkWidget *pNotebook; static GtkTooltips *pTooltips; -class CBackgroundDialogPage -{ +class CBackgroundDialogPage { private: -GtkWidget *m_pWidget; -GtkWidget *m_pTabLabel; -ui::Label m_pFileLabel; -GtkWidget *m_pPosLabel; -VIEWTYPE m_vt; -bool m_bValidFile; + GtkWidget *m_pWidget; + GtkWidget *m_pTabLabel; + ui::Label m_pFileLabel; + GtkWidget *m_pPosLabel; + VIEWTYPE m_vt; + bool m_bValidFile; public: -CBackgroundImage *m_pImage; -CBackgroundDialogPage( VIEWTYPE vt ); -void Append( GtkWidget *notebook ); -void Browse(); -void Reload(); -void SetPosLabel(); + CBackgroundImage *m_pImage; + + CBackgroundDialogPage(VIEWTYPE vt); + + void Append(GtkWidget *notebook); + + void Browse(); + + void Reload(); + + void SetPosLabel(); // ~BackgroundDialogPage(); }; // dialog page callbacks -static void browse_callback( GtkWidget *widget, gpointer data ){ - ( (CBackgroundDialogPage *)data )->Browse(); +static void browse_callback(GtkWidget *widget, gpointer data) +{ + ((CBackgroundDialogPage *) data)->Browse(); } -static void reload_callback( GtkWidget *widget, gpointer data ){ - ( (CBackgroundDialogPage *)data )->Reload(); +static void reload_callback(GtkWidget *widget, gpointer data) +{ + ((CBackgroundDialogPage *) data)->Reload(); } -static void size_sel_callback( GtkWidget *widget, gpointer data ){ - CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data; - if ( pPage->m_pImage->SetExtentsSel() ) { - pPage->SetPosLabel(); - } +static void size_sel_callback(GtkWidget *widget, gpointer data) +{ + CBackgroundDialogPage *pPage = (CBackgroundDialogPage *) data; + if (pPage->m_pImage->SetExtentsSel()) { + pPage->SetPosLabel(); + } } -static void size_mm_callback( GtkWidget *widget, gpointer data ){ - CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data; - if ( pPage->m_pImage->SetExtentsMM() ) { - pPage->SetPosLabel(); - } +static void size_mm_callback(GtkWidget *widget, gpointer data) +{ + CBackgroundDialogPage *pPage = (CBackgroundDialogPage *) data; + if (pPage->m_pImage->SetExtentsMM()) { + pPage->SetPosLabel(); + } } -static void alpha_adjust_callback( GtkWidget *widget, gpointer data ){ - CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data; - pPage->m_pImage->m_alpha = (float)gtk_range_get_value( GTK_RANGE( widget ) ); - g_FuncTable.m_pfnSysUpdateWindows( W_XY ); +static void alpha_adjust_callback(GtkWidget *widget, gpointer data) +{ + CBackgroundDialogPage *pPage = (CBackgroundDialogPage *) data; + pPage->m_pImage->m_alpha = (float) gtk_range_get_value(GTK_RANGE(widget)); + g_FuncTable.m_pfnSysUpdateWindows(W_XY); } -void CBackgroundDialogPage::Reload(){ - if ( m_bValidFile ) { - m_pImage->Load( gtk_label_get_text( GTK_LABEL( m_pFileLabel ) ) ); - } +void CBackgroundDialogPage::Reload() +{ + if (m_bValidFile) { + m_pImage->Load(gtk_label_get_text(GTK_LABEL(m_pFileLabel))); + } } -void CBackgroundDialogPage::Browse(){ - char browsedir[PATH_MAX]; - const char *ct; - const char *newfile; - char *t; +void CBackgroundDialogPage::Browse() +{ + char browsedir[PATH_MAX]; + const char *ct; + const char *newfile; + char *t; - //TODO GetMapName saves the map. eeep! - //also with no map, returns unnamed.map, otherwise returns full path + //TODO GetMapName saves the map. eeep! + //also with no map, returns unnamed.map, otherwise returns full path // Syn_Printf(MSG_PREFIX "GetMapName() %s\n", // g_FuncTable.m_pfnGetMapName()); - ct = g_FuncTable.m_pfnReadProjectKey( "basepath" ); - // TODO shouldn't need this stuff - if ( !ct || !strlen( ct ) ) { - Syn_Printf( MSG_PREFIX "basepath = NULL or empty\n" ); - return; - } - Syn_Printf( MSG_PREFIX "basepath: %s\n",ct ); - if ( strlen( ct ) >= PATH_MAX ) { - Syn_Printf( MSG_PREFIX "base game dir too long\n" ); - return; - } - - strcpy( browsedir,ct ); - // make sure we have a trailing / - if ( browsedir[strlen( browsedir ) - 1] != '/' ) { - strcat( browsedir,"/" ); - } - - //if we dont have a file yet, don't try to use it for default dir - if ( m_bValidFile ) { - // filename should always be a nice clean unix style relative path - ct = gtk_label_get_text( GTK_LABEL( m_pFileLabel ) ); - strcat( browsedir,ct ); - Syn_Printf( MSG_PREFIX "full path: %s\n",browsedir ); - - // lop off the file part - t = browsedir + strlen( browsedir ) - 1; - while ( t != browsedir && *t != '/' ) - t--; - *t = 0; - } - Syn_Printf( MSG_PREFIX "browse directory %s\n",browsedir ); + ct = g_FuncTable.m_pfnReadProjectKey("basepath"); + // TODO shouldn't need this stuff + if (!ct || !strlen(ct)) { + Syn_Printf(MSG_PREFIX "basepath = NULL or empty\n"); + return; + } + Syn_Printf(MSG_PREFIX "basepath: %s\n", ct); + if (strlen(ct) >= PATH_MAX) { + Syn_Printf(MSG_PREFIX "base game dir too long\n"); + return; + } + + strcpy(browsedir, ct); + // make sure we have a trailing / + if (browsedir[strlen(browsedir) - 1] != '/') { + strcat(browsedir, "/"); + } + + //if we dont have a file yet, don't try to use it for default dir + if (m_bValidFile) { + // filename should always be a nice clean unix style relative path + ct = gtk_label_get_text(GTK_LABEL(m_pFileLabel)); + strcat(browsedir, ct); + Syn_Printf(MSG_PREFIX "full path: %s\n", browsedir); + + // lop off the file part + t = browsedir + strlen(browsedir) - 1; + while (t != browsedir && *t != '/') { + t--; + } + *t = 0; + } + Syn_Printf(MSG_PREFIX "browse directory %s\n", browsedir); //does NOT need freeing contrary to include/qerplugin.h comments //TODO bug/patch for comments //TODO patern gets fucked up sometimes if empty //http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=915 - newfile = g_FuncTable.m_pfnFileDialog( pDialogWnd,TRUE, - "Load Background Image",browsedir,FILETYPE_KEY ); - if ( !newfile ) { - Syn_Printf( MSG_PREFIX "newfile = NULL\n" ); - return; - } - Syn_Printf( MSG_PREFIX "newfile: %s\n",newfile ); - newfile = g_FileSystemTable.m_pfnExtractRelativePath( newfile ); - - if ( !newfile ) { - Syn_Printf( MSG_PREFIX "newfile = NULL\n" ); - return; - } - Syn_Printf( MSG_PREFIX "newfile: %s\n",newfile ); - - if ( m_pImage->Load( newfile ) ) { - m_bValidFile = true; - m_pFileLabel.text(newfile); - } + newfile = g_FuncTable.m_pfnFileDialog(pDialogWnd, TRUE, + "Load Background Image", browsedir, FILETYPE_KEY); + if (!newfile) { + Syn_Printf(MSG_PREFIX "newfile = NULL\n"); + return; + } + Syn_Printf(MSG_PREFIX "newfile: %s\n", newfile); + newfile = g_FileSystemTable.m_pfnExtractRelativePath(newfile); + + if (!newfile) { + Syn_Printf(MSG_PREFIX "newfile = NULL\n"); + return; + } + Syn_Printf(MSG_PREFIX "newfile: %s\n", newfile); + + if (m_pImage->Load(newfile)) { + m_bValidFile = true; + m_pFileLabel.text(newfile); + } } -void CBackgroundDialogPage::SetPosLabel(){ - char s[64]; - // TODO no snprintf ? - sprintf( s, "Size/Position (%d,%d) (%d,%d)",(int)( m_pImage->m_xmin ), - (int)( m_pImage->m_ymin ),(int)( m_pImage->m_xmax ),(int)( m_pImage->m_ymax ) ); - m_pPosLabel.text(s); +void CBackgroundDialogPage::SetPosLabel() +{ + char s[64]; + // TODO no snprintf ? + sprintf(s, "Size/Position (%d,%d) (%d,%d)", (int) (m_pImage->m_xmin), + (int) (m_pImage->m_ymin), (int) (m_pImage->m_xmax), (int) (m_pImage->m_ymax)); + m_pPosLabel.text(s); } -CBackgroundDialogPage::CBackgroundDialogPage( VIEWTYPE vt ){ - GtkWidget *w; - - m_vt = vt; - - m_bValidFile = false; - - switch ( m_vt ) - { - case XY: - m_pTabLabel = ui::Label( "X/Y" ); - m_pImage = &backgroundXY; - break; - case XZ: - m_pTabLabel = ui::Label( "X/Z" ); - m_pImage = &backgroundXZ; - break; - case YZ: - m_pTabLabel = ui::Label( "Y/Z" ); - m_pImage = &backgroundYZ; - break; - } +CBackgroundDialogPage::CBackgroundDialogPage(VIEWTYPE vt) +{ + GtkWidget *w; + + m_vt = vt; + + m_bValidFile = false; + + switch (m_vt) { + case XY: + m_pTabLabel = ui::Label("X/Y"); + m_pImage = &backgroundXY; + break; + case XZ: + m_pTabLabel = ui::Label("X/Z"); + m_pImage = &backgroundXZ; + break; + case YZ: + m_pTabLabel = ui::Label("Y/Z"); + m_pImage = &backgroundYZ; + break; + } // A vbox to hold everything - m_pWidget = ui::VBox( FALSE,0 ); + m_pWidget = ui::VBox(FALSE, 0); // Frame for file row - auto frame = ui::Frame( "File" ); - m_pWidget.pack_start(frame, FALSE, FALSE, 2 ); + auto frame = ui::Frame("File"); + m_pWidget.pack_start(frame, FALSE, FALSE, 2); // hbox for first row - auto hbox = ui::HBox( FALSE,5 ); - gtk_container_set_border_width( GTK_CONTAINER( hbox ),4 ); - frame.add(hbox); + auto hbox = ui::HBox(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 4); + frame.add(hbox); // label to display filename - m_pFileLabel = ui::Label( NO_FILE_MSG ); - gtk_label_set_selectable( GTK_LABEL( m_pFileLabel ),TRUE ); + m_pFileLabel = ui::Label(NO_FILE_MSG); + gtk_label_set_selectable(GTK_LABEL(m_pFileLabel), TRUE); //TODO set min size ? done with spaces right now - hbox.pack_start(m_pFileLabel, TRUE, TRUE, 5 ); + hbox.pack_start(m_pFileLabel, TRUE, TRUE, 5); - m_pFileLabel.show(); + m_pFileLabel.show(); - w = ui::Button( "Browse..." ); - w.connect( "clicked", G_CALLBACK( browse_callback ), ( gpointer ) this ); - hbox.pack_start(w, FALSE, FALSE, 5 ); - gtk_tooltips_set_tip( pTooltips, w, "Select a file", NULL ); - w.show(); + w = ui::Button("Browse..."); + w.connect("clicked", G_CALLBACK(browse_callback), (gpointer) this ); + hbox.pack_start(w, FALSE, FALSE, 5); + gtk_tooltips_set_tip(pTooltips, w, "Select a file", NULL); + w.show(); - w = ui::Button( "Reload" ); - w.connect( "clicked", G_CALLBACK( reload_callback ), ( gpointer ) this ); - // TODO disable until we have file - // gtk_widget_set_sensitive(w,FALSE); - gtk_tooltips_set_tip( pTooltips, w, "Reload current file", NULL ); - hbox.pack_start(w, FALSE, FALSE, 5 ); - w.show(); + w = ui::Button("Reload"); + w.connect("clicked", G_CALLBACK(reload_callback), (gpointer) this ); + // TODO disable until we have file + // gtk_widget_set_sensitive(w,FALSE); + gtk_tooltips_set_tip(pTooltips, w, "Reload current file", NULL); + hbox.pack_start(w, FALSE, FALSE, 5); + w.show(); - hbox.show(); - frame.show(); + hbox.show(); + frame.show(); // second row (rendering options) - frame = ui::Frame( "Rendering" ); - m_pWidget.pack_start(frame, FALSE, FALSE, 2 ); - - hbox = ui::HBox( FALSE,5 ); - gtk_container_set_border_width( GTK_CONTAINER( hbox ),4 ); - frame.add(hbox); - - w = ui::Label( "Vertex alpha:" ); - hbox.pack_start(w, FALSE, FALSE, 5 ); - w.show(); - - w = ui::HScale( 0.0, 1.0, 0.01 ); - gtk_range_set_value( GTK_RANGE( w ),0.5 ); - gtk_scale_set_value_pos( GTK_SCALE( w ),GTK_POS_LEFT ); - w.connect( "value-changed", G_CALLBACK( alpha_adjust_callback ), ( gpointer ) this ); - hbox.pack_start(w, TRUE, TRUE, 5 ); - gtk_tooltips_set_tip( pTooltips, w, "Set image transparancy", NULL ); - w.show(); - - hbox.show(); - frame.show(); + frame = ui::Frame("Rendering"); + m_pWidget.pack_start(frame, FALSE, FALSE, 2); + + hbox = ui::HBox(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 4); + frame.add(hbox); + + w = ui::Label("Vertex alpha:"); + hbox.pack_start(w, FALSE, FALSE, 5); + w.show(); + + w = ui::HScale(0.0, 1.0, 0.01); + gtk_range_set_value(GTK_RANGE(w), 0.5); + gtk_scale_set_value_pos(GTK_SCALE(w), GTK_POS_LEFT); + w.connect("value-changed", G_CALLBACK(alpha_adjust_callback), (gpointer) this ); + hbox.pack_start(w, TRUE, TRUE, 5); + gtk_tooltips_set_tip(pTooltips, w, "Set image transparancy", NULL); + w.show(); + + hbox.show(); + frame.show(); // Third row (size and position) - frame = ui::Frame( "Size/Position (undefined)" ); - m_pPosLabel = gtk_frame_get_label_widget( GTK_FRAME( frame ) ); - m_pWidget.pack_start( frame, FALSE, FALSE, 2 ); - - hbox = ui::HBox( FALSE,5 ); - frame.add(hbox); - gtk_container_set_border_width( GTK_CONTAINER( hbox ),4 ); - - w = ui::Button( "from selection" ); - hbox.pack_start(w, TRUE, FALSE, 5 ); - w.connect( "clicked", G_CALLBACK( size_sel_callback ), ( gpointer ) this ); - gtk_tooltips_set_tip( pTooltips, w, "Set the size of the image to the bounding rectangle of all selected brushes and entities", NULL ); - w.show(); - - if ( m_vt == XY ) { - w = ui::Button( "from map mins/maxs" ); - hbox.pack_start(w, TRUE, FALSE, 2 ); - w.connect( "clicked", G_CALLBACK( size_mm_callback ), ( gpointer ) this ); - gtk_tooltips_set_tip( pTooltips, w, "Set the size of the image using the mapcoordsmins and mapcoordsmaxs keys of the worldspawn entity", NULL ); - w.show(); - } - - hbox.show(); - frame.show(); - - m_pWidget.show(); + frame = ui::Frame("Size/Position (undefined)"); + m_pPosLabel = gtk_frame_get_label_widget(GTK_FRAME(frame)); + m_pWidget.pack_start(frame, FALSE, FALSE, 2); + + hbox = ui::HBox(FALSE, 5); + frame.add(hbox); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 4); + + w = ui::Button("from selection"); + hbox.pack_start(w, TRUE, FALSE, 5); + w.connect("clicked", G_CALLBACK(size_sel_callback), (gpointer) this ); + gtk_tooltips_set_tip(pTooltips, w, + "Set the size of the image to the bounding rectangle of all selected brushes and entities", + NULL); + w.show(); + + if (m_vt == XY) { + w = ui::Button("from map mins/maxs"); + hbox.pack_start(w, TRUE, FALSE, 2); + w.connect("clicked", G_CALLBACK(size_mm_callback), (gpointer) this ); + gtk_tooltips_set_tip(pTooltips, w, + "Set the size of the image using the mapcoordsmins and mapcoordsmaxs keys of the worldspawn entity", + NULL); + w.show(); + } + + hbox.show(); + frame.show(); + + m_pWidget.show(); } -void CBackgroundDialogPage::Append( GtkWidget *notebook ){ - gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), m_pWidget, m_pTabLabel ); +void CBackgroundDialogPage::Append(GtkWidget *notebook) +{ + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), m_pWidget, m_pTabLabel); } // dialog global callbacks @@ -292,53 +310,58 @@ void CBackgroundDialogPage::Append( GtkWidget *notebook ){ } */ -static void response_callback( GtkWidget *widget, gint response, gpointer data ){ - if ( response == GTK_RESPONSE_CLOSE ) { - gtk_widget_hide( pDialogWnd ); - } +static void response_callback(GtkWidget *widget, gint response, gpointer data) +{ + if (response == GTK_RESPONSE_CLOSE) { + gtk_widget_hide(pDialogWnd); + } } -static gint close_callback( GtkWidget *widget, gpointer data ){ - gtk_widget_hide( pDialogWnd ); - return TRUE; +static gint close_callback(GtkWidget *widget, gpointer data) +{ + gtk_widget_hide(pDialogWnd); + return TRUE; } -void InitBackgroundDialog(){ - CBackgroundDialogPage *pPage; - - pDialogWnd = gtk_dialog_new_with_buttons( "Background Images", - g_pMainWidget, - (GtkDialogFlags)( GTK_DIALOG_DESTROY_WITH_PARENT ), - // TODO dialog with no buttons - // GTK_STOCK_CLOSE, - // GTK_RESPONSE_CLOSE, - NULL ); - pDialogWnd.connect( "delete_event", G_CALLBACK( close_callback ), NULL ); - pDialogWnd.connect( "response", G_CALLBACK( response_callback ), NULL ); +void InitBackgroundDialog() +{ + CBackgroundDialogPage *pPage; + + pDialogWnd = gtk_dialog_new_with_buttons("Background Images", + g_pMainWidget, + (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT), + // TODO dialog with no buttons + // GTK_STOCK_CLOSE, + // GTK_RESPONSE_CLOSE, + NULL); + pDialogWnd.connect("delete_event", G_CALLBACK(close_callback), NULL); + pDialogWnd.connect("response", G_CALLBACK(response_callback), NULL); // pDialogWnd.connect( "expose_event", G_CALLBACK( ci_expose ), NULL ); - pTooltips = gtk_tooltips_new(); + pTooltips = gtk_tooltips_new(); - pNotebook = gtk_notebook_new(); - pPage = new CBackgroundDialogPage( XY ); - pPage->Append( pNotebook ); - pPage = new CBackgroundDialogPage( XZ ); - pPage->Append( pNotebook ); - pPage = new CBackgroundDialogPage( YZ ); - pPage->Append( pNotebook ); + pNotebook = gtk_notebook_new(); + pPage = new CBackgroundDialogPage(XY); + pPage->Append(pNotebook); + pPage = new CBackgroundDialogPage(XZ); + pPage->Append(pNotebook); + pPage = new CBackgroundDialogPage(YZ); + pPage->Append(pNotebook); - gtk_box_pack_start( GTK_BOX( GTK_DIALOG( pDialogWnd )->vbox ), pNotebook, TRUE, TRUE, 0 ); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pDialogWnd)->vbox), pNotebook, TRUE, TRUE, 0); - pNotebook.show(); + pNotebook.show(); - gtk_widget_realize( pDialogWnd ); + gtk_widget_realize(pDialogWnd); } -void ShowBackgroundDialog(){ - gtk_window_present( pDialogWnd ); +void ShowBackgroundDialog() +{ + gtk_window_present(pDialogWnd); } -void ShowBackgroundDialogPG( int page ){ - gtk_notebook_set_current_page( GTK_NOTEBOOK( pNotebook ),page ); - ShowBackgroundDialog(); +void ShowBackgroundDialogPG(int page) +{ + gtk_notebook_set_current_page(GTK_NOTEBOOK(pNotebook), page); + ShowBackgroundDialog(); } diff --git a/contrib/bkgrnd2d/dialog.h b/contrib/bkgrnd2d/dialog.h index 29a511d6..e442dda4 100644 --- a/contrib/bkgrnd2d/dialog.h +++ b/contrib/bkgrnd2d/dialog.h @@ -29,7 +29,9 @@ #define _BKGRND2D_DIALOG_H_ void InitBackgroundDialog(); + void ShowBackgroundDialog(); -void ShowBackgroundDialogPG( int page ); + +void ShowBackgroundDialogPG(int page); #endif // _BKGRND2D_DIALOG_H_ diff --git a/contrib/bkgrnd2d/plugin.cpp b/contrib/bkgrnd2d/plugin.cpp index 35fb0720..261b5412 100644 --- a/contrib/bkgrnd2d/plugin.cpp +++ b/contrib/bkgrnd2d/plugin.cpp @@ -80,224 +80,248 @@ static const char *PLUGIN_NAME = "2d window background plugin"; //backwards for some reason static const char *PLUGIN_COMMANDS = CMD_ABOUT ";" - CMD_SEP ";" - CMD_CONFIG -; + CMD_SEP ";" + CMD_CONFIG; static const char *PLUGIN_ABOUT = "2d window background v0.25\n\n" - "By reyalP (hellsownpuppy@yahoo.com)"; - - + "By reyalP (hellsownpuppy@yahoo.com)"; void DoBkgrndToggleXY(); + void DoBkgrndToggleXZ(); + void DoBkgrndToggleYZ(); #define NUM_TOOLBAR_BUTTONS 4 -struct toolbar_button_info_s -{ - const char *image; - const char *text; - const char *tip; - void ( *func )(); - IToolbarButton::EType type; -}; -struct toolbar_button_info_s toolbar_buttons[NUM_TOOLBAR_BUTTONS] = -{ - { - "bkgrnd2d_xy_toggle.png", - "xy background", - "Toggle xy background image", - DoBkgrndToggleXY, - IToolbarButton::eToggleButton - }, - { - "bkgrnd2d_xz_toggle.png", - "xz background", - "Toggle xz background image", - DoBkgrndToggleXZ, - IToolbarButton::eToggleButton - }, - { - "bkgrnd2d_yz_toggle.png", - "yz background", - "Toggle yz background image", - DoBkgrndToggleYZ, - IToolbarButton::eToggleButton - }, - { - "bkgrnd2d_conf.png", - "Configure", - "Configure background images", - ShowBackgroundDialog, - IToolbarButton::eButton - }, +struct toolbar_button_info_s { + const char *image; + const char *text; + const char *tip; + + void ( *func )(); + + IToolbarButton::EType type; }; -class Bkgrnd2dButton : public IToolbarButton -{ +struct toolbar_button_info_s toolbar_buttons[NUM_TOOLBAR_BUTTONS] = + { + { + "bkgrnd2d_xy_toggle.png", + "xy background", + "Toggle xy background image", + DoBkgrndToggleXY, + IToolbarButton::eToggleButton + }, + { + "bkgrnd2d_xz_toggle.png", + "xz background", + "Toggle xz background image", + DoBkgrndToggleXZ, + IToolbarButton::eToggleButton + }, + { + "bkgrnd2d_yz_toggle.png", + "yz background", + "Toggle yz background image", + DoBkgrndToggleYZ, + IToolbarButton::eToggleButton + }, + { + "bkgrnd2d_conf.png", + "Configure", + "Configure background images", + ShowBackgroundDialog, + IToolbarButton::eButton + }, + }; + +class Bkgrnd2dButton : public IToolbarButton { public: -const toolbar_button_info_s *bi; -virtual const char* getImage() const { - return bi->image; -} -virtual const char* getText() const { - return bi->text; -} -virtual const char* getTooltip() const { - return bi->tip; -} -virtual void activate() const { - bi->func(); - return ; -} -virtual EType getType() const { - return bi->type; -} + const toolbar_button_info_s *bi; + + virtual const char *getImage() const + { + return bi->image; + } + + virtual const char *getText() const + { + return bi->text; + } + + virtual const char *getTooltip() const + { + return bi->tip; + } + + virtual void activate() const + { + bi->func(); + return; + } + + virtual EType getType() const + { + return bi->type; + } }; Bkgrnd2dButton g_bkgrnd2dbuttons[NUM_TOOLBAR_BUTTONS]; -unsigned int ToolbarButtonCount(){ - return NUM_TOOLBAR_BUTTONS; +unsigned int ToolbarButtonCount() +{ + return NUM_TOOLBAR_BUTTONS; } -const IToolbarButton* GetToolbarButton( unsigned int index ){ - g_bkgrnd2dbuttons[index].bi = &toolbar_buttons[index]; - return &g_bkgrnd2dbuttons[index]; +const IToolbarButton *GetToolbarButton(unsigned int index) +{ + g_bkgrnd2dbuttons[index].bi = &toolbar_buttons[index]; + return &g_bkgrnd2dbuttons[index]; } -extern "C" const char* QERPlug_Init( void *hApp, void* pMainWidget ){ - g_pMainWidget = pMainWidget; +extern "C" const char *QERPlug_Init(void *hApp, void *pMainWidget) +{ + g_pMainWidget = pMainWidget; - InitBackgroundDialog(); - render.Register(); + InitBackgroundDialog(); + render.Register(); //TODO is it right ? is it wrong ? it works //TODO figure out supported image types - GetFileTypeRegistry()->addType( FILETYPE_KEY, filetype_t( "all files", "*.*" ) ); - GetFileTypeRegistry()->addType( FILETYPE_KEY, filetype_t( "jpeg files", "*.jpg" ) ); - GetFileTypeRegistry()->addType( FILETYPE_KEY, filetype_t( "targa files", "*.tga" ) ); - return (char *) PLUGIN_NAME; + GetFileTypeRegistry()->addType(FILETYPE_KEY, filetype_t("all files", "*.*")); + GetFileTypeRegistry()->addType(FILETYPE_KEY, filetype_t("jpeg files", "*.jpg")); + GetFileTypeRegistry()->addType(FILETYPE_KEY, filetype_t("targa files", "*.tga")); + return (char *) PLUGIN_NAME; } -extern "C" const char* QERPlug_GetName(){ - return (char *) PLUGIN_NAME; +extern "C" const char *QERPlug_GetName() +{ + return (char *) PLUGIN_NAME; } -extern "C" const char* QERPlug_GetCommandList(){ - return (char *) PLUGIN_COMMANDS; +extern "C" const char *QERPlug_GetCommandList() +{ + return (char *) PLUGIN_COMMANDS; } -extern "C" void QERPlug_Dispatch( const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush ){ - Sys_Printf( MSG_PREFIX "Command \"%s\"\n",p ); - if ( !strcmp( p, CMD_ABOUT ) ) { - g_FuncTable.m_pfnMessageBox( NULL, PLUGIN_ABOUT, "About", MB_OK, NULL ); - } - else if ( !strcmp( p,CMD_CONFIG ) ) { - ShowBackgroundDialog(); - } +extern "C" void QERPlug_Dispatch(const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush) +{ + Sys_Printf(MSG_PREFIX "Command \"%s\"\n", p); + if (!strcmp(p, CMD_ABOUT)) { + g_FuncTable.m_pfnMessageBox(NULL, PLUGIN_ABOUT, "About", MB_OK, NULL); + } else if (!strcmp(p, CMD_CONFIG)) { + ShowBackgroundDialog(); + } } //TODO these three suck -void DoBkgrndToggleXY(){ - Sys_Printf( MSG_PREFIX "DoBkgrndToggleXY\n" ); - // always toggle, since the buttons do - backgroundXY.m_bActive = ( backgroundXY.m_bActive ) ? false : true; - // if we don't have image or extents, and we activated, - // bring up the dialog with the corresponding page - // would be better to hide or grey out button, but we can't - if ( backgroundXY.m_bActive && !backgroundXY.Valid() ) { - ShowBackgroundDialogPG( 0 ); - } - else{ - g_FuncTable.m_pfnSysUpdateWindows( W_XY ); - } +void DoBkgrndToggleXY() +{ + Sys_Printf(MSG_PREFIX "DoBkgrndToggleXY\n"); + // always toggle, since the buttons do + backgroundXY.m_bActive = (backgroundXY.m_bActive) ? false : true; + // if we don't have image or extents, and we activated, + // bring up the dialog with the corresponding page + // would be better to hide or grey out button, but we can't + if (backgroundXY.m_bActive && !backgroundXY.Valid()) { + ShowBackgroundDialogPG(0); + } else { + g_FuncTable.m_pfnSysUpdateWindows(W_XY); + } } -void DoBkgrndToggleXZ(){ - Sys_Printf( MSG_PREFIX "DoBkgrndToggleXZ\n" ); - backgroundXZ.m_bActive = ( backgroundXZ.m_bActive ) ? false : true; - if ( backgroundXZ.m_bActive && !backgroundXZ.Valid() ) { - ShowBackgroundDialogPG( 1 ); - } - else{ - g_FuncTable.m_pfnSysUpdateWindows( W_XY ); - } +void DoBkgrndToggleXZ() +{ + Sys_Printf(MSG_PREFIX "DoBkgrndToggleXZ\n"); + backgroundXZ.m_bActive = (backgroundXZ.m_bActive) ? false : true; + if (backgroundXZ.m_bActive && !backgroundXZ.Valid()) { + ShowBackgroundDialogPG(1); + } else { + g_FuncTable.m_pfnSysUpdateWindows(W_XY); + } } -void DoBkgrndToggleYZ(){ - Sys_Printf( MSG_PREFIX "DoBkgrndToggleYZ\n" ); - backgroundYZ.m_bActive = ( backgroundYZ.m_bActive ) ? false : true; - if ( backgroundYZ.m_bActive && !backgroundYZ.Valid() ) { - ShowBackgroundDialogPG( 2 ); - } - else{ - g_FuncTable.m_pfnSysUpdateWindows( W_XY ); - } +void DoBkgrndToggleYZ() +{ + Sys_Printf(MSG_PREFIX "DoBkgrndToggleYZ\n"); + backgroundYZ.m_bActive = (backgroundYZ.m_bActive) ? false : true; + if (backgroundYZ.m_bActive && !backgroundYZ.Valid()) { + ShowBackgroundDialogPG(2); + } else { + g_FuncTable.m_pfnSysUpdateWindows(W_XY); + } } // ============================================================================= // SYNAPSE -CSynapseServer* g_pSynapseServer = NULL; +CSynapseServer *g_pSynapseServer = NULL; CSynapseClientBkgrnd2d g_SynapseClient; -extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ){ - if ( strcmp( version, SYNAPSE_VERSION ) ) { - Syn_Printf( "ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version ); - return NULL; - } - g_pSynapseServer = pServer; - g_pSynapseServer->IncRef(); - Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() ); +extern "C" CSynapseClient *SYNAPSE_DLL_EXPORT - g_SynapseClient.AddAPI( TOOLBAR_MAJOR, BKGRND2D_MINOR, sizeof( _QERPlugToolbarTable ) ); - g_SynapseClient.AddAPI( PLUGIN_MAJOR, BKGRND2D_MINOR, sizeof( _QERPluginTable ) ); - - g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( g_FuncTable ), SYN_REQUIRE, &g_FuncTable ); - g_SynapseClient.AddAPI( QGL_MAJOR, NULL, sizeof( g_QglTable ), SYN_REQUIRE, &g_QglTable ); +Synapse_EnumerateInterfaces(const char *version, CSynapseServer *pServer) +{ + if (strcmp(version, SYNAPSE_VERSION)) { + Syn_Printf("ERROR: synapse API version mismatch: should be '" + SYNAPSE_VERSION + "', got '%s'\n", version ); + return NULL; + } + g_pSynapseServer = pServer; + g_pSynapseServer->IncRef(); + Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf()); + + g_SynapseClient.AddAPI(TOOLBAR_MAJOR, BKGRND2D_MINOR, sizeof(_QERPlugToolbarTable)); + g_SynapseClient.AddAPI(PLUGIN_MAJOR, BKGRND2D_MINOR, sizeof(_QERPluginTable)); + + g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable); + g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(g_QglTable), SYN_REQUIRE, &g_QglTable); // TODO is this the right way to ask for 'whichever VFS we have loaded' ? Seems to work // for misc filename functions - g_SynapseClient.AddAPI( VFS_MAJOR, "*", sizeof( g_FileSystemTable ), SYN_REQUIRE, &g_FileSystemTable ); + g_SynapseClient.AddAPI(VFS_MAJOR, "*", sizeof(g_FileSystemTable), SYN_REQUIRE, &g_FileSystemTable); // get worldspawn - g_SynapseClient.AddAPI( ENTITY_MAJOR, NULL, sizeof( g_EntityTable ), SYN_REQUIRE, &g_EntityTable ); + g_SynapseClient.AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable); // selected brushes - g_SynapseClient.AddAPI( DATA_MAJOR, NULL, sizeof( g_DataTable ), SYN_REQUIRE, &g_DataTable ); + g_SynapseClient.AddAPI(DATA_MAJOR, NULL, sizeof(g_DataTable), SYN_REQUIRE, &g_DataTable); - return &g_SynapseClient; + return &g_SynapseClient; } -bool CSynapseClientBkgrnd2d::RequestAPI( APIDescriptor_t *pAPI ){ - if ( !strcmp( pAPI->major_name, PLUGIN_MAJOR ) ) { - _QERPluginTable* pTable = static_cast<_QERPluginTable*>( pAPI->mpTable ); - - pTable->m_pfnQERPlug_Init = QERPlug_Init; - pTable->m_pfnQERPlug_GetName = QERPlug_GetName; - pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; - pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; - return true; - } - if ( !strcmp( pAPI->major_name, TOOLBAR_MAJOR ) ) { - _QERPlugToolbarTable* pTable = static_cast<_QERPlugToolbarTable*>( pAPI->mpTable ); - - pTable->m_pfnToolbarButtonCount = &ToolbarButtonCount; - pTable->m_pfnGetToolbarButton = &GetToolbarButton; - return true; - } - - Syn_Printf( "ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo() ); - return false; +bool CSynapseClientBkgrnd2d::RequestAPI(APIDescriptor_t *pAPI) +{ + if (!strcmp(pAPI->major_name, PLUGIN_MAJOR)) { + _QERPluginTable *pTable = static_cast<_QERPluginTable *>( pAPI->mpTable ); + + pTable->m_pfnQERPlug_Init = QERPlug_Init; + pTable->m_pfnQERPlug_GetName = QERPlug_GetName; + pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; + pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; + return true; + } + if (!strcmp(pAPI->major_name, TOOLBAR_MAJOR)) { + _QERPlugToolbarTable *pTable = static_cast<_QERPlugToolbarTable *>( pAPI->mpTable ); + + pTable->m_pfnToolbarButtonCount = &ToolbarButtonCount; + pTable->m_pfnGetToolbarButton = &GetToolbarButton; + return true; + } + + Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo()); + return false; } #include "version.h" -const char* CSynapseClientBkgrnd2d::GetInfo(){ - return "2d Background plugin built " __DATE__ " " RADIANT_VERSION; +const char *CSynapseClientBkgrnd2d::GetInfo() +{ + return "2d Background plugin built " __DATE__ " " + RADIANT_VERSION; } -const char* CSynapseClientBkgrnd2d::GetName(){ - return "bkgrnd2d"; +const char *CSynapseClientBkgrnd2d::GetName() +{ + return "bkgrnd2d"; } diff --git a/contrib/bkgrnd2d/plugin.h b/contrib/bkgrnd2d/plugin.h index 13ca7378..361bf833 100644 --- a/contrib/bkgrnd2d/plugin.h +++ b/contrib/bkgrnd2d/plugin.h @@ -41,7 +41,9 @@ #include "synapse.h" #include "iplugin.h" #include "itoolbar.h" + #define USE_QERTABLE_DEFINE + #include "qerplugin.h" #include "igl.h" #include "ifilesystem.h" @@ -58,19 +60,24 @@ extern _QEREntityTable g_EntityTable; extern _QERAppDataTable g_DataTable; extern void *g_pMainWidget; -extern CSynapseServer* g_pSynapseServer; +extern CSynapseServer *g_pSynapseServer; -class CSynapseClientBkgrnd2d : public CSynapseClient -{ +class CSynapseClientBkgrnd2d : public CSynapseClient { public: // CSynapseClient API -bool RequestAPI( APIDescriptor_t *pAPI ); -const char* GetInfo(); -const char* GetName(); + bool RequestAPI(APIDescriptor_t *pAPI); + + const char *GetInfo(); -CSynapseClientBkgrnd2d() { } -virtual ~CSynapseClientBkgrnd2d() { } + const char *GetName(); + + CSynapseClientBkgrnd2d() + {} + + virtual ~CSynapseClientBkgrnd2d() + {} }; + #define MSG_PREFIX "bkgrnd2d: " #define MSG_WARN "bkgrnd2d WARNING: " #define BKGRND2D_MINOR "bkgrnd2d" diff --git a/contrib/bobtoolz/CPortals.h b/contrib/bobtoolz/CPortals.h index fc555531..eea867cc 100644 --- a/contrib/bobtoolz/CPortals.h +++ b/contrib/bobtoolz/CPortals.h @@ -19,29 +19,34 @@ class CBspPoint { public: -float p[3]; + float p[3]; }; class CBspPortal { public: -CBspPortal(); -~CBspPortal(); + CBspPortal(); -unsigned point_count; -CBspPoint *point; -bool Build( char *def, unsigned int pointCnt, bool bInverse ); + ~CBspPortal(); + + unsigned point_count; + CBspPoint *point; + + bool Build(char *def, unsigned int pointCnt, bool bInverse); }; class CBspNode { public: -CBspPortal *portal; -unsigned int portal_count; + CBspPortal *portal; + unsigned int portal_count; + + bool AddPortal(char *def, unsigned int pointCnt, bool bInverse); -bool AddPortal( char* def, unsigned int pointCnt, bool bInverse ); -unsigned int portal_next; -CBspNode(); -~CBspNode(); + unsigned int portal_next; + + CBspNode(); + + ~CBspNode(); }; @@ -50,14 +55,15 @@ CBspNode(); class CPortals { public: -CPortals(); -~CPortals(); + CPortals(); + + ~CPortals(); -void Load(); // use filename in fn -void Purge(); + void Load(); // use filename in fn + void Purge(); -char fn[NAME_MAX]; -CBspNode *node; + char fn[NAME_MAX]; + CBspNode *node; -unsigned int node_count; + unsigned int node_count; }; diff --git a/contrib/bobtoolz/DBobView.cpp b/contrib/bobtoolz/DBobView.cpp index decfe779..940d1918 100644 --- a/contrib/bobtoolz/DBobView.cpp +++ b/contrib/bobtoolz/DBobView.cpp @@ -41,227 +41,237 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DBobView::DBobView(){ - nPathCount = 0; +DBobView::DBobView() +{ + nPathCount = 0; - path = NULL; + path = NULL; - boundingShow = BOUNDS_APEX; + boundingShow = BOUNDS_APEX; - constructShaders(); - GlobalShaderCache().attachRenderable( *this ); + constructShaders(); + GlobalShaderCache().attachRenderable(*this); } -DBobView::~DBobView(){ - GlobalShaderCache().detachRenderable( *this ); - destroyShaders(); +DBobView::~DBobView() +{ + GlobalShaderCache().detachRenderable(*this); + destroyShaders(); - if ( path ) { - delete[] path; - } + if (path) { + delete[] path; + } - g_PathView = NULL; + g_PathView = NULL; } ////////////////////////////////////////////////////////////////////// // Implementation ////////////////////////////////////////////////////////////////////// -void DBobView::render( RenderStateFlags state ) const { - glBegin( GL_LINE_STRIP ); +void DBobView::render(RenderStateFlags state) const +{ + glBegin(GL_LINE_STRIP); - for ( int i = 0; i < nPathCount; i++ ) - glVertex3fv( path[i] ); + for (int i = 0; i < nPathCount; i++) + glVertex3fv(path[i]); - glEnd(); + glEnd(); } -const char* DBobView_state_line = "$bobtoolz/bobview/line"; -const char* DBobView_state_box = "$bobtoolz/bobview/box"; - -void DBobView::constructShaders(){ - OpenGLState state; - GlobalOpenGLStateLibrary().getDefaultState( state ); - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND | RENDER_LINESMOOTH; - state.m_sort = OpenGLState::eSortOpaque; - state.m_linewidth = 1; - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - GlobalOpenGLStateLibrary().insert( DBobView_state_line, state ); - - state.m_colour[0] = 0.25f; - state.m_colour[1] = 0.75f; - state.m_colour[2] = 0.75f; - state.m_colour[3] = 1; - GlobalOpenGLStateLibrary().insert( DBobView_state_box, state ); - - m_shader_line = GlobalShaderCache().capture( DBobView_state_line ); - m_shader_box = GlobalShaderCache().capture( DBobView_state_box ); +const char *DBobView_state_line = "$bobtoolz/bobview/line"; +const char *DBobView_state_box = "$bobtoolz/bobview/box"; + +void DBobView::constructShaders() +{ + OpenGLState state; + GlobalOpenGLStateLibrary().getDefaultState(state); + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND | RENDER_LINESMOOTH; + state.m_sort = OpenGLState::eSortOpaque; + state.m_linewidth = 1; + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + GlobalOpenGLStateLibrary().insert(DBobView_state_line, state); + + state.m_colour[0] = 0.25f; + state.m_colour[1] = 0.75f; + state.m_colour[2] = 0.75f; + state.m_colour[3] = 1; + GlobalOpenGLStateLibrary().insert(DBobView_state_box, state); + + m_shader_line = GlobalShaderCache().capture(DBobView_state_line); + m_shader_box = GlobalShaderCache().capture(DBobView_state_box); } -void DBobView::destroyShaders(){ - GlobalOpenGLStateLibrary().erase( DBobView_state_line ); - GlobalOpenGLStateLibrary().erase( DBobView_state_box ); - GlobalShaderCache().release( DBobView_state_line ); - GlobalShaderCache().release( DBobView_state_box ); +void DBobView::destroyShaders() +{ + GlobalOpenGLStateLibrary().erase(DBobView_state_line); + GlobalOpenGLStateLibrary().erase(DBobView_state_box); + GlobalShaderCache().release(DBobView_state_line); + GlobalShaderCache().release(DBobView_state_box); } -Matrix4 g_transform_box1 = matrix4_translation_for_vec3( Vector3( 16.0f, 16.0f, 28.0f ) ); -Matrix4 g_transform_box2 = matrix4_translation_for_vec3( Vector3( -16.0f, 16.0f, 28.0f ) ); -Matrix4 g_transform_box3 = matrix4_translation_for_vec3( Vector3( 16.0f, -16.0f, -28.0f ) ); -Matrix4 g_transform_box4 = matrix4_translation_for_vec3( Vector3( -16.0f, -16.0f, -28.0f ) ); - -void DBobView::renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - if ( !path ) { - return; - } - - renderer.SetState( m_shader_line, Renderer::eWireframeOnly ); - renderer.SetState( m_shader_line, Renderer::eFullMaterials ); - renderer.addRenderable( *this, g_matrix4_identity ); - - if ( m_bShowExtra ) { - renderer.SetState( m_shader_box, Renderer::eWireframeOnly ); - renderer.SetState( m_shader_box, Renderer::eFullMaterials ); - renderer.addRenderable( *this, g_transform_box1 ); - renderer.addRenderable( *this, g_transform_box2 ); - renderer.addRenderable( *this, g_transform_box3 ); - renderer.addRenderable( *this, g_transform_box4 ); - } +Matrix4 g_transform_box1 = matrix4_translation_for_vec3(Vector3(16.0f, 16.0f, 28.0f)); +Matrix4 g_transform_box2 = matrix4_translation_for_vec3(Vector3(-16.0f, 16.0f, 28.0f)); +Matrix4 g_transform_box3 = matrix4_translation_for_vec3(Vector3(16.0f, -16.0f, -28.0f)); +Matrix4 g_transform_box4 = matrix4_translation_for_vec3(Vector3(-16.0f, -16.0f, -28.0f)); + +void DBobView::renderSolid(Renderer &renderer, const VolumeTest &volume) const +{ + if (!path) { + return; + } + + renderer.SetState(m_shader_line, Renderer::eWireframeOnly); + renderer.SetState(m_shader_line, Renderer::eFullMaterials); + renderer.addRenderable(*this, g_matrix4_identity); + + if (m_bShowExtra) { + renderer.SetState(m_shader_box, Renderer::eWireframeOnly); + renderer.SetState(m_shader_box, Renderer::eFullMaterials); + renderer.addRenderable(*this, g_transform_box1); + renderer.addRenderable(*this, g_transform_box2); + renderer.addRenderable(*this, g_transform_box3); + renderer.addRenderable(*this, g_transform_box4); + } } -void DBobView::renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - renderSolid( renderer, volume ); + +void DBobView::renderWireframe(Renderer &renderer, const VolumeTest &volume) const +{ + renderSolid(renderer, volume); } -void DBobView::SetPath( vec3_t *pPath ){ - if ( path ) { - delete[] path; - } +void DBobView::SetPath(vec3_t *pPath) +{ + if (path) { + delete[] path; + } - path = pPath; + path = pPath; } const float LOCAL_GRAVITY = -800.0f; -bool DBobView::CalculateTrajectory( vec3_t start, vec3_t apex, float multiplier, int points, float varGravity ){ - if ( apex[2] <= start[2] ) { - SetPath( NULL ); - return false; - } - // ----think q3a actually would allow these - //scrub that, coz the plugin wont :] +bool DBobView::CalculateTrajectory(vec3_t start, vec3_t apex, float multiplier, int points, float varGravity) +{ + if (apex[2] <= start[2]) { + SetPath(NULL); + return false; + } + // ----think q3a actually would allow these + //scrub that, coz the plugin wont :] - vec3_t dist, speed; - VectorSubtract( apex, start, dist ); + vec3_t dist, speed; + VectorSubtract(apex, start, dist); - vec_t speed_z = (float)sqrt( -2 * LOCAL_GRAVITY * dist[2] ); - float flight_time = -speed_z / LOCAL_GRAVITY; + vec_t speed_z = (float) sqrt(-2 * LOCAL_GRAVITY * dist[2]); + float flight_time = -speed_z / LOCAL_GRAVITY; - VectorScale( dist, 1 / flight_time, speed ); - speed[2] = speed_z; + VectorScale(dist, 1 / flight_time, speed); + speed[2] = speed_z; // Sys_Printf("Speed: (%.4f %.4f %.4f)\n", speed[0], speed[1], speed[2]); - vec3_t* pPath = new vec3_t[points]; + vec3_t *pPath = new vec3_t[points]; - float interval = multiplier * flight_time / points; - for ( int i = 0; i < points; i++ ) - { - float ltime = interval * i; + float interval = multiplier * flight_time / points; + for (int i = 0; i < points; i++) { + float ltime = interval * i; - VectorScale( speed, ltime, pPath[i] ); - VectorAdd( pPath[i], start, pPath[i] ); + VectorScale(speed, ltime, pPath[i]); + VectorAdd(pPath[i], start, pPath[i]); - // could do this all with vectors - // vGrav = {0, 0, -800.0f} - // VectorScale(vGrav, 0.5f*ltime*ltime, vAdd); - // VectorScale(speed, ltime, pPath[i]); - // _VectorAdd(pPath[i], start, pPath[i]) - // _VectorAdd(pPath[i], vAdd, pPath[i]) + // could do this all with vectors + // vGrav = {0, 0, -800.0f} + // VectorScale(vGrav, 0.5f*ltime*ltime, vAdd); + // VectorScale(speed, ltime, pPath[i]); + // _VectorAdd(pPath[i], start, pPath[i]) + // _VectorAdd(pPath[i], vAdd, pPath[i]) - pPath[i][2] = start[2] + ( speed_z * ltime ) + ( varGravity * 0.5f * ltime * ltime ); - } + pPath[i][2] = start[2] + (speed_z * ltime) + (varGravity * 0.5f * ltime * ltime); + } - SetPath( pPath ); - return true; + SetPath(pPath); + return true; } -void DBobView::Begin( const char* trigger, const char *target, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra ){ - strcpy( entTrigger, trigger ); - strcpy( entTarget, target ); - - fMultiplier = multiplier; - fVarGravity = varGravity; - nPathCount = points; - m_bShowExtra = bShowExtra; - - if ( !UpdatePath() ) { - globalErrorStream() << "Initialization Failure in DBobView::Begin"; - delete this; - } - globalOutputStream() << "Initialization of Path Plotter succeeded."; +void +DBobView::Begin(const char *trigger, const char *target, float multiplier, int points, float varGravity, bool bNoUpdate, + bool bShowExtra) +{ + strcpy(entTrigger, trigger); + strcpy(entTarget, target); + + fMultiplier = multiplier; + fVarGravity = varGravity; + nPathCount = points; + m_bShowExtra = bShowExtra; + + if (!UpdatePath()) { + globalErrorStream() << "Initialization Failure in DBobView::Begin"; + delete this; + } + globalOutputStream() << "Initialization of Path Plotter succeeded."; } -bool DBobView::UpdatePath(){ - vec3_t start, apex; - - if ( GetEntityCentre( entTrigger, start ) ) { - if ( GetEntityCentre( entTarget, apex ) ) { - CalculateTrajectory( start, apex, fMultiplier, nPathCount, fVarGravity ); - return true; - } - } - return false; +bool DBobView::UpdatePath() +{ + vec3_t start, apex; + + if (GetEntityCentre(entTrigger, start)) { + if (GetEntityCentre(entTarget, apex)) { + CalculateTrajectory(start, apex, fMultiplier, nPathCount, fVarGravity); + return true; + } + } + return false; } -void DBobView_setEntity( Entity& entity, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra ){ - DEntity trigger; - trigger.LoadEPairList( &entity ); - - DEPair* trigger_ep = trigger.FindEPairByKey( "targetname" ); - - if ( trigger_ep ) { - if ( !strcmp( trigger.m_Classname, "trigger_push" ) ) { - DEPair* target_ep = trigger.FindEPairByKey( "target" ); - if ( target_ep ) { - const scene::Path* entTarget = FindEntityFromTargetname( target_ep->value ); - if ( entTarget ) { - if ( g_PathView ) { - delete g_PathView; - } - g_PathView = new DBobView; - - Entity* target = Node_getEntity( entTarget->top() ); - if ( target != 0 ) { - if ( !bNoUpdate ) { - g_PathView->trigger = &entity; - entity.attach( *g_PathView ); - g_PathView->target = target; - target->attach( *g_PathView ); - } - g_PathView->Begin( trigger_ep->value, target_ep->value, multiplier, points, varGravity, bNoUpdate, bShowExtra ); - } - else{ - globalErrorStream() << "bobToolz PathPlotter: trigger_push ARGH\n"; - } - } - else{ - globalErrorStream() << "bobToolz PathPlotter: trigger_push target could not be found..\n"; - } - } - else{ - globalErrorStream() << "bobToolz PathPlotter: trigger_push has no target..\n"; - } - } - else{ - globalErrorStream() << "bobToolz PathPlotter: You must select a 'trigger_push' entity..\n"; - } - } - else{ - globalErrorStream() << "bobToolz PathPlotter: Entity must have a targetname.\n"; - } - return; +void DBobView_setEntity(Entity &entity, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra) +{ + DEntity trigger; + trigger.LoadEPairList(&entity); + + DEPair *trigger_ep = trigger.FindEPairByKey("targetname"); + + if (trigger_ep) { + if (!strcmp(trigger.m_Classname, "trigger_push")) { + DEPair *target_ep = trigger.FindEPairByKey("target"); + if (target_ep) { + const scene::Path *entTarget = FindEntityFromTargetname(target_ep->value); + if (entTarget) { + if (g_PathView) { + delete g_PathView; + } + g_PathView = new DBobView; + + Entity *target = Node_getEntity(entTarget->top()); + if (target != 0) { + if (!bNoUpdate) { + g_PathView->trigger = &entity; + entity.attach(*g_PathView); + g_PathView->target = target; + target->attach(*g_PathView); + } + g_PathView->Begin(trigger_ep->value, target_ep->value, multiplier, points, varGravity, + bNoUpdate, bShowExtra); + } else { + globalErrorStream() << "bobToolz PathPlotter: trigger_push ARGH\n"; + } + } else { + globalErrorStream() << "bobToolz PathPlotter: trigger_push target could not be found..\n"; + } + } else { + globalErrorStream() << "bobToolz PathPlotter: trigger_push has no target..\n"; + } + } else { + globalErrorStream() << "bobToolz PathPlotter: You must select a 'trigger_push' entity..\n"; + } + } else { + globalErrorStream() << "bobToolz PathPlotter: Entity must have a targetname.\n"; + } + return; } diff --git a/contrib/bobtoolz/DBobView.h b/contrib/bobtoolz/DBobView.h index b20ef141..f0f40fd6 100644 --- a/contrib/bobtoolz/DBobView.h +++ b/contrib/bobtoolz/DBobView.h @@ -30,72 +30,89 @@ #include "mathlib.h" class DListener; + class Shader; -const int BOUNDS_ALL = 0; +const int BOUNDS_ALL = 0; const int BOUNDS_APEX = 1; #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 -class DBobView : public Renderable, public OpenGLRenderable, public Entity::Observer -{ -Shader* m_shader_line; -Shader* m_shader_box; +class DBobView : public Renderable, public OpenGLRenderable, public Entity::Observer { + Shader *m_shader_line; + Shader *m_shader_box; public: -DBobView(); -virtual ~DBobView(); + DBobView(); + + virtual ~DBobView(); protected: -vec3_t* path; + vec3_t *path; public: -bool m_bShowExtra; -int boundingShow; -DListener* eyes; -float fVarGravity; -float fMultiplier; -int nPathCount; - -Entity* trigger; -Entity* target; - -bool UpdatePath(); -char entTarget[256]; -char entTrigger[256]; -void Begin( const char*, const char*, float, int, float, bool, bool ); -bool CalculateTrajectory( vec3_t, vec3_t, float, int, float ); - -void SetPath( vec3_t* pPath ); - -void render( RenderStateFlags state ) const; -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const; -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const; - -void constructShaders(); -void destroyShaders(); - -void valueChanged( const char* value ){ - UpdatePath(); -} -typedef MemberCaller ValueChangedCaller; -void insert( const char* key, EntityKeyValue& value ){ - value.attach( ValueChangedCaller( *this ) ); -} -void erase( const char* key, EntityKeyValue& value ){ - value.detach( ValueChangedCaller( *this ) ); -} -void clear(){ - if ( trigger != 0 ) { - trigger->detach( *this ); - target->detach( *this ); - trigger = 0; - target = 0; - } -} + bool m_bShowExtra; + int boundingShow; + DListener *eyes; + float fVarGravity; + float fMultiplier; + int nPathCount; + + Entity *trigger; + Entity *target; + + bool UpdatePath(); + + char entTarget[256]; + char entTrigger[256]; + + void Begin(const char *, const char *, float, int, float, bool, bool); + + bool CalculateTrajectory(vec3_t, vec3_t, float, int, float); + + void SetPath(vec3_t *pPath); + + void render(RenderStateFlags state) const; + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const; + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const; + + void constructShaders(); + + void destroyShaders(); + + void valueChanged(const char *value) + { + UpdatePath(); + } + + typedef MemberCaller ValueChangedCaller; + + void insert(const char *key, EntityKeyValue &value) + { + value.attach(ValueChangedCaller(*this)); + } + + void erase(const char *key, EntityKeyValue &value) + { + value.detach(ValueChangedCaller(*this)); + } + + void clear() + { + if (trigger != 0) { + trigger->detach(*this); + target->detach(*this); + trigger = 0; + target = 0; + } + } }; class Entity; -void DBobView_setEntity( Entity& entity, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra ); + +void +DBobView_setEntity(Entity &entity, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra); #endif // !defined(AFX_BOBVIEW_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_) diff --git a/contrib/bobtoolz/DBrush.cpp b/contrib/bobtoolz/DBrush.cpp index a0d97699..a5b18cef 100644 --- a/contrib/bobtoolz/DBrush.cpp +++ b/contrib/bobtoolz/DBrush.cpp @@ -52,829 +52,840 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DBrush::DBrush( int ID ){ - m_nBrushID = ID; - bBoundsBuilt = false; - QER_entity = NULL; - QER_brush = NULL; +DBrush::DBrush(int ID) +{ + m_nBrushID = ID; + bBoundsBuilt = false; + QER_entity = NULL; + QER_brush = NULL; } -DBrush::~DBrush(){ - ClearFaces(); - ClearPoints(); +DBrush::~DBrush() +{ + ClearFaces(); + ClearPoints(); } ////////////////////////////////////////////////////////////////////// // Implementation ////////////////////////////////////////////////////////////////////// -DPlane* DBrush::AddFace( const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData* texData ){ +DPlane *DBrush::AddFace(const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData *texData) +{ #if GDEF_DEBUG // Sys_Printf("(%f %f %f) (%f %f %f) (%f %f %f)\n", va[0], va[1], va[2], vb[0], vb[1], vb[2], vc[0], vc[1], vc[2]); #endif - bBoundsBuilt = false; - DPlane* newFace = new DPlane( va, vb, vc, texData ); - faceList.push_back( newFace ); - - return newFace; -} - -int DBrush::BuildPoints(){ - ClearPoints(); - - if ( faceList.size() <= 3 ) { // if less than 3 faces, there can be no points - return 0; // with only 3 faces u can't have a bounded soild - - } - for ( std::list::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++ ) - { - std::list::const_iterator p2 = p1; - for ( p2++; p2 != faceList.end(); p2++ ) - { - std::list::const_iterator p3 = p2; - for ( p3++; p3 != faceList.end(); p3++ ) - { - vec3_t pnt; - if ( ( *p1 )->PlaneIntersection( *p2, *p3, pnt ) ) { - int pos = PointPosition( pnt ); - - if ( pos == POINT_IN_BRUSH ) { // ???? shouldn't happen here - globalErrorStream() << "ERROR:: Build Brush Points: Point IN brush!!!\n"; - } - else if ( pos == POINT_ON_BRUSH ) { // normal point - if ( !HasPoint( pnt ) ) { - AddPoint( pnt ); - } + bBoundsBuilt = false; + DPlane *newFace = new DPlane(va, vb, vc, texData); + faceList.push_back(newFace); + + return newFace; +} + +int DBrush::BuildPoints() +{ + ClearPoints(); + + if (faceList.size() <= 3) { // if less than 3 faces, there can be no points + return 0; // with only 3 faces u can't have a bounded soild + + } + for (std::list::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++) { + std::list::const_iterator p2 = p1; + for (p2++; p2 != faceList.end(); p2++) { + std::list::const_iterator p3 = p2; + for (p3++; p3 != faceList.end(); p3++) { + vec3_t pnt; + if ((*p1)->PlaneIntersection(*p2, *p3, pnt)) { + int pos = PointPosition(pnt); + + if (pos == POINT_IN_BRUSH) { // ???? shouldn't happen here + globalErrorStream() << "ERROR:: Build Brush Points: Point IN brush!!!\n"; + } else if (pos == POINT_ON_BRUSH) { // normal point + if (!HasPoint(pnt)) { + AddPoint(pnt); + } /* else Sys_Printf("Duplicate Point Found, pyramids ahoy!!!!!\n");*/ - // point lies on more that 3 planes - } + // point lies on more that 3 planes + } - // otherwise point is removed due to another plane.. + // otherwise point is removed due to another plane.. - // Sys_Printf("(%f, %f, %f)\n", pnt[0], pnt[1], pnt[2]); - } - } - } - } + // Sys_Printf("(%f, %f, %f)\n", pnt[0], pnt[1], pnt[2]); + } + } + } + } #if GDEF_DEBUG // Sys_Printf("%i points on brush\n", pointList.size()); #endif - return static_cast( pointList.size() ); + return static_cast( pointList.size()); } -void DBrush_addFace( DBrush& brush, const _QERFaceData& faceData ){ - brush.AddFace( vector3_to_array( faceData.m_p0 ), vector3_to_array( faceData.m_p1 ), vector3_to_array( faceData.m_p2 ), 0 ); +void DBrush_addFace(DBrush &brush, const _QERFaceData &faceData) +{ + brush.AddFace(vector3_to_array(faceData.m_p0), vector3_to_array(faceData.m_p1), vector3_to_array(faceData.m_p2), 0); } -typedef ReferenceCaller DBrushAddFaceCaller; -void DBrush_addFaceTextured( DBrush& brush, const _QERFaceData& faceData ){ - brush.AddFace( vector3_to_array( faceData.m_p0 ), vector3_to_array( faceData.m_p1 ), vector3_to_array( faceData.m_p2 ), &faceData ); +typedef ReferenceCaller DBrushAddFaceCaller; + +void DBrush_addFaceTextured(DBrush &brush, const _QERFaceData &faceData) +{ + brush.AddFace(vector3_to_array(faceData.m_p0), vector3_to_array(faceData.m_p1), vector3_to_array(faceData.m_p2), + &faceData); } -typedef ReferenceCaller DBrushAddFaceTexturedCaller; -void DBrush::LoadFromBrush( scene::Instance& brush, bool textured ){ - ClearFaces(); - ClearPoints(); +typedef ReferenceCaller DBrushAddFaceTexturedCaller; + +void DBrush::LoadFromBrush(scene::Instance &brush, bool textured) +{ + ClearFaces(); + ClearPoints(); - GlobalBrushCreator().Brush_forEachFace( brush.path().top(), textured ? BrushFaceDataCallback( DBrushAddFaceTexturedCaller( *this ) ) : BrushFaceDataCallback( DBrushAddFaceCaller( *this ) ) ); + GlobalBrushCreator().Brush_forEachFace(brush.path().top(), + textured ? BrushFaceDataCallback(DBrushAddFaceTexturedCaller(*this)) + : BrushFaceDataCallback(DBrushAddFaceCaller(*this))); - QER_entity = brush.path().parent().get_pointer(); - QER_brush = brush.path().top().get_pointer(); + QER_entity = brush.path().parent().get_pointer(); + QER_brush = brush.path().top().get_pointer(); } -int DBrush::PointPosition( vec3_t pnt ){ - int state = POINT_IN_BRUSH; // if nothing happens point is inside brush +int DBrush::PointPosition(vec3_t pnt) +{ + int state = POINT_IN_BRUSH; // if nothing happens point is inside brush - for ( std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - float dist = ( *chkPlane )->DistanceToPoint( pnt ); + for (std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + float dist = (*chkPlane)->DistanceToPoint(pnt); - if ( dist > MAX_ROUND_ERROR ) { - return POINT_OUT_BRUSH; // if point is in front of plane, it CANT be in the brush - } - else if ( fabs( dist ) < MAX_ROUND_ERROR ) { - state = POINT_ON_BRUSH; // if point is ON plane point is either ON the brush - } - // or outside it, it can no longer be in it - } + if (dist > MAX_ROUND_ERROR) { + return POINT_OUT_BRUSH; // if point is in front of plane, it CANT be in the brush + } else if (fabs(dist) < MAX_ROUND_ERROR) { + state = POINT_ON_BRUSH; // if point is ON plane point is either ON the brush + } + // or outside it, it can no longer be in it + } - return state; + return state; } -void DBrush::ClearPoints(){ - for ( std::list::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++ ) { - delete *deadPoint; - } - pointList.clear(); +void DBrush::ClearPoints() +{ + for (std::list::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++) { + delete *deadPoint; + } + pointList.clear(); } -void DBrush::ClearFaces(){ - bBoundsBuilt = false; - for ( std::list::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) - { - delete *deadPlane; - } - faceList.clear(); +void DBrush::ClearFaces() +{ + bBoundsBuilt = false; + for (std::list::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++) { + delete *deadPlane; + } + faceList.clear(); } -void DBrush::AddPoint( vec3_t pnt ){ - DPoint* newPoint = new DPoint; - VectorCopy( pnt, newPoint->_pnt ); - pointList.push_back( newPoint ); +void DBrush::AddPoint(vec3_t pnt) +{ + DPoint *newPoint = new DPoint; + VectorCopy(pnt, newPoint->_pnt); + pointList.push_back(newPoint); } -bool DBrush::HasPoint( vec3_t pnt ){ - for ( std::list::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++ ) - { - if ( **chkPoint == pnt ) { - return true; - } - } +bool DBrush::HasPoint(vec3_t pnt) +{ + for (std::list::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++) { + if (**chkPoint == pnt) { + return true; + } + } - return false; + return false; } -int DBrush::RemoveRedundantPlanes(){ - int cnt = 0; - std::list::iterator chkPlane; +int DBrush::RemoveRedundantPlanes() +{ + int cnt = 0; + std::list::iterator chkPlane; + + // find duplicate planes + std::list::iterator p1 = faceList.begin(); - // find duplicate planes - std::list::iterator p1 = faceList.begin(); + while (p1 != faceList.end()) { + std::list::iterator p2 = p1; - while ( p1 != faceList.end() ) - { - std::list::iterator p2 = p1; + for (p2++; p2 != faceList.end(); p2++) { + if (**p1 == **p2) { + if (!strcmp((*p1)->m_shader.c_str(), "textures/common/caulk")) { + delete *p1; + p1 = faceList.erase(p1); // duplicate plane + } else { + delete *p2; + p2 = faceList.erase(p2); // duplicate plane + } - for ( p2++; p2 != faceList.end(); p2++ ) - { - if ( **p1 == **p2 ) { - if ( !strcmp( ( *p1 )->m_shader.c_str(), "textures/common/caulk" ) ) { - delete *p1; - p1 = faceList.erase( p1 ); // duplicate plane - } - else - { - delete *p2; - p2 = faceList.erase( p2 ); // duplicate plane - } + cnt++; + break; + } + } + + if (p2 == faceList.end()) { + p1++; + } + } - cnt++; - break; - } - } - - if ( p2 == faceList.end() ) { - p1++; - } - } - - //+djbob kill planes with bad normal, they are more of a nuisance than losing a brush - chkPlane = faceList.begin(); - while ( chkPlane != faceList.end() ) - { - if ( VectorLength( ( *chkPlane )->normal ) == 0 ) { // plane has bad normal - delete *chkPlane; - chkPlane = faceList.erase( chkPlane ); - cnt++; - } - else { - chkPlane++; - } - } - //-djbob - - if ( pointList.size() == 0 ) { // if points may not have been built, build them + //+djbob kill planes with bad normal, they are more of a nuisance than losing a brush + chkPlane = faceList.begin(); + while (chkPlane != faceList.end()) { + if (VectorLength((*chkPlane)->normal) == 0) { // plane has bad normal + delete *chkPlane; + chkPlane = faceList.erase(chkPlane); + cnt++; + } else { + chkPlane++; + } + } + //-djbob + + if (pointList.size() == 0) { // if points may not have been built, build them /* if(BuildPoints() == 0) // just let the planes die if they are all bad return cnt;*/ - BuildPoints(); - } - - chkPlane = faceList.begin(); - while ( chkPlane != faceList.end() ) - { - if ( ( *chkPlane )->IsRedundant( pointList ) ) { // checks that plane "0wnz" :), 3 or more points - delete *chkPlane; - chkPlane = faceList.erase( chkPlane ); - cnt++; - } - else{ - chkPlane++; - } - } - - return cnt; -} - -bool DBrush::GetBounds( vec3_t min, vec3_t max ){ - BuildBounds(); - - if ( !bBoundsBuilt ) { - return false; - } - - VectorCopy( bbox_min, min ); - VectorCopy( bbox_max, max ); - - return true; -} - -bool DBrush::BBoxCollision( DBrush* chkBrush ){ - vec3_t min1, min2; - vec3_t max1, max2; - - GetBounds( min1, max1 ); - chkBrush->GetBounds( min2, max2 ); - - if ( min1[0] >= max2[0] ) { - return false; - } - if ( min1[1] >= max2[1] ) { - return false; - } - if ( min1[2] >= max2[2] ) { - return false; - } - - if ( max1[0] <= min2[0] ) { - return false; - } - if ( max1[1] <= min2[1] ) { - return false; - } - if ( max1[2] <= min2[2] ) { - return false; - } - - return true; -} - -DPlane* DBrush::HasPlane( DPlane* chkPlane ){ - for ( std::list::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ ) - { - if ( **brushPlane == *chkPlane ) { - return *brushPlane; - } - } - return NULL; -} - -bool DBrush::IsCutByPlane( DPlane *cuttingPlane ){ - bool isInFront; - - if ( pointList.size() == 0 ) { - if ( BuildPoints() == 0 ) { - return false; - } - } - - std::list::const_iterator chkPnt = pointList.begin(); - - if ( chkPnt == pointList.end() ) { - return false; - } - - float dist = cuttingPlane->DistanceToPoint( ( *chkPnt )->_pnt ); - - if ( dist > MAX_ROUND_ERROR ) { - isInFront = false; - } - else if ( dist < MAX_ROUND_ERROR ) { - isInFront = true; - } - else{ - return true; - } - - for ( chkPnt++ = pointList.begin(); chkPnt != pointList.end(); chkPnt++ ) - { - dist = cuttingPlane->DistanceToPoint( ( *chkPnt )->_pnt ); - - if ( dist > MAX_ROUND_ERROR ) { - if ( isInFront ) { - return true; - } - } - else if ( dist < MAX_ROUND_ERROR ) { - if ( !isInFront ) { - return true; - } - } - else{ - return true; - } - } - - return false; -} - - -scene::Node* DBrush::BuildInRadiant( bool allowDestruction, int* changeCnt, scene::Node* entity ){ - if ( allowDestruction ) { - bool kill = true; - - for ( std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( ( *chkPlane )->m_bChkOk ) { - kill = false; - break; - } - } - if ( kill ) { - return NULL; - } - } - - //+djbob: fixed bug when brush had no faces "phantom brush" in radiant. - if ( faceList.size() < 4 ) { - globalErrorStream() << "Possible Phantom Brush Found, will not rebuild\n"; - return NULL; - } - //-djbob - - NodeSmartReference node( GlobalBrushCreator().createBrush() ); - - for ( std::list::const_iterator buildPlane = faceList.begin(); buildPlane != faceList.end(); buildPlane++ ) { - if ( ( *buildPlane )->AddToBrush( node ) && changeCnt ) { - ( *changeCnt )++; - } - } - - if ( entity ) { - Node_getTraversable( *entity )->insert( node ); - } - else { - Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( node ); - } - - QER_entity = entity; - QER_brush = node.get_pointer(); - - return node.get_pointer(); -} - -void DBrush::CutByPlane( DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2 ){ - if ( !IsCutByPlane( cutPlane ) ) { - *newBrush1 = NULL; - *newBrush2 = NULL; - return; - } - - DBrush* b1 = new DBrush; - DBrush* b2 = new DBrush; - - for ( std::list::const_iterator parsePlane = faceList.begin(); parsePlane != faceList.end(); parsePlane++ ) - { - b1->AddFace( ( *parsePlane )->points[0], ( *parsePlane )->points[1], ( *parsePlane )->points[2], NULL ); - b2->AddFace( ( *parsePlane )->points[0], ( *parsePlane )->points[1], ( *parsePlane )->points[2], NULL ); - } - - b1->AddFace( cutPlane->points[0], cutPlane->points[1], cutPlane->points[2], NULL ); - b2->AddFace( cutPlane->points[2], cutPlane->points[1], cutPlane->points[0], NULL ); - - b1->RemoveRedundantPlanes(); - b2->RemoveRedundantPlanes(); - - *newBrush1 = b1; - *newBrush2 = b2; -} - -bool DBrush::IntersectsWith( DBrush *chkBrush ){ - if ( pointList.size() == 0 ) { - if ( BuildPoints() == 0 ) { - return false; // invalid brush!!!! - - } - } - if ( chkBrush->pointList.size() == 0 ) { - if ( chkBrush->BuildPoints() == 0 ) { - return false; // invalid brush!!!! - - } - } - if ( !BBoxCollision( chkBrush ) ) { - return false; - } - - std::list::const_iterator iplPlane; - - for ( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++ ) - { - - bool allInFront = true; - for ( std::list::const_iterator iPoint = chkBrush->pointList.begin(); iPoint != chkBrush->pointList.end(); iPoint++ ) - { - if ( ( *iplPlane )->DistanceToPoint( ( *iPoint )->_pnt ) < -MAX_ROUND_ERROR ) { - allInFront = false; - break; - } - } - if ( allInFront ) { - return false; - } - } - - for ( iplPlane = chkBrush->faceList.begin(); iplPlane != chkBrush->faceList.end(); iplPlane++ ) - { - bool allInFront = true; - for ( std::list::const_iterator iPoint = pointList.begin(); iPoint != pointList.end(); iPoint++ ) - { - if ( ( *iplPlane )->DistanceToPoint( ( *iPoint )->_pnt ) < -MAX_ROUND_ERROR ) { - allInFront = false; - break; - } - } - if ( allInFront ) { - return false; - } - } - - return true; -} - -bool DBrush::IntersectsWith( DPlane* p1, DPlane* p2, vec3_t v ) { - vec3_t vDown = { 0, 0, -1 }; - - std::list::const_iterator iplPlane; - for ( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++ ) { - DPlane* p = ( *iplPlane ); - - vec_t d = DotProduct( p->normal, vDown ); - if ( d >= 0 ) { - continue; - } - if ( p->PlaneIntersection( p1, p2, v ) ) { - if ( PointPosition( v ) != POINT_OUT_BRUSH ) { - return true; - } - } - } - - return false; -} - -void DBrush::BuildBounds(){ - if ( !bBoundsBuilt ) { - if ( pointList.size() == 0 ) { // if points may not have been built, build them - if ( BuildPoints() == 0 ) { - return; - } - } - - std::list::const_iterator first = pointList.begin(); - VectorCopy( ( *first )->_pnt, bbox_min ); - VectorCopy( ( *first )->_pnt, bbox_max ); - - std::list::const_iterator point = pointList.begin(); - for ( point++; point != pointList.end(); point++ ) - { - if ( ( *point )->_pnt[0] > bbox_max[0] ) { - bbox_max[0] = ( *point )->_pnt[0]; - } - if ( ( *point )->_pnt[1] > bbox_max[1] ) { - bbox_max[1] = ( *point )->_pnt[1]; - } - if ( ( *point )->_pnt[2] > bbox_max[2] ) { - bbox_max[2] = ( *point )->_pnt[2]; - } - - if ( ( *point )->_pnt[0] < bbox_min[0] ) { - bbox_min[0] = ( *point )->_pnt[0]; - } - if ( ( *point )->_pnt[1] < bbox_min[1] ) { - bbox_min[1] = ( *point )->_pnt[1]; - } - if ( ( *point )->_pnt[2] < bbox_min[2] ) { - bbox_min[2] = ( *point )->_pnt[2]; - } - } - - bBoundsBuilt = true; - } -} - -bool DBrush::BBoxTouch( DBrush *chkBrush ){ - vec3_t min1, min2; - vec3_t max1, max2; - - GetBounds( min1, max1 ); - chkBrush->GetBounds( min2, max2 ); - - if ( ( min1[0] - max2[0] ) > MAX_ROUND_ERROR ) { - return false; - } - if ( ( min1[1] - max2[1] ) > MAX_ROUND_ERROR ) { - return false; - } - if ( ( min1[2] - max2[2] ) > MAX_ROUND_ERROR ) { - return false; - } - - if ( ( min2[0] - max1[0] ) > MAX_ROUND_ERROR ) { - return false; - } - if ( ( min2[1] - max1[1] ) > MAX_ROUND_ERROR ) { - return false; - } - if ( ( min2[2] - max1[2] ) > MAX_ROUND_ERROR ) { - return false; - } - - int cnt = 0; - - if ( ( min2[0] - max1[0] ) == 0 ) { - cnt++; - } - - if ( ( min2[1] - max1[1] ) == 0 ) { - cnt++; - } - - if ( ( min2[2] - max1[2] ) == 0 ) { - cnt++; - } - - if ( ( min1[0] - max2[0] ) == 0 ) { - cnt++; - } - - if ( ( min1[1] - max2[1] ) == 0 ) { - cnt++; - } - - if ( ( min1[2] - max2[2] ) == 0 ) { - cnt++; - } - - if ( cnt > 1 ) { - return false; - } - - return true; -} - -void DBrush::ResetChecks( std::list* exclusionList ){ - for ( std::list::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ ) - { - bool set = false; - - if ( exclusionList ) { - for ( std::list::iterator eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++ ) - { - if ( strstr( ( *resetPlane )->m_shader.c_str(), eTexture->GetBuffer() ) ) { - set = true; - break; - } - } - } - - ( *resetPlane )->m_bChkOk = set; - } -} - -DPlane* DBrush::HasPlaneInverted( DPlane *chkPlane ){ - for ( std::list::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ ) - { - if ( **brushPlane != *chkPlane ) { - if ( fabs( ( *brushPlane )->_d + chkPlane->_d ) < 0.1 ) { - return ( *brushPlane ); - } - } - } - return NULL; -} - -bool DBrush::HasTexture( const char *textureName ){ - for ( std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( strstr( ( *chkPlane )->m_shader.c_str(), textureName ) ) { - return true; - } - - } - return false; -} - -bool DBrush::IsDetail(){ - for ( std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( ( *chkPlane )->texInfo.contents & FACE_DETAIL ) { - return true; - } - - } - return false; -} - -void DBrush::BuildFromWinding( DWinding *w ){ - if ( w->numpoints < 3 ) { - globalErrorStream() << "Winding has invalid number of points"; - return; - } - - DPlane* wPlane = w->WindingPlane(); - - DWinding* w2; - w2 = w->CopyWinding(); - int i; - for ( i = 0; i < w2->numpoints; i++ ) - VectorAdd( w2->p[i], wPlane->normal, w2->p[i] ); - - AddFace( w2->p[0], w2->p[1], w2->p[2], NULL ); - AddFace( w->p[2], w->p[1], w->p[0], NULL ); - - for ( i = 0; i < w->numpoints - 1; i++ ) - AddFace( w2->p[i], w->p[i], w->p[i + 1], NULL ); - AddFace( w2->p[w->numpoints - 1], w->p[w->numpoints - 1], w->p[0], NULL ); - - delete wPlane; - delete w2; -} - -void DBrush::SaveToFile( FILE *pFile ){ - fprintf( pFile, "{\n" ); - - for ( std::list::const_iterator pp = faceList.begin(); pp != faceList.end(); pp++ ) - { - char buffer[512]; - - sprintf( buffer, "( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) %s %.0f %.0f %f %f %.0f 0 0 0\n", - ( *pp )->points[0][0], ( *pp )->points[0][1], ( *pp )->points[0][2], - ( *pp )->points[1][0], ( *pp )->points[1][1], ( *pp )->points[1][2], - ( *pp )->points[2][0], ( *pp )->points[2][1], ( *pp )->points[2][2], - ( *pp )->m_shader.c_str(), - ( *pp )->texInfo.m_texdef.shift[0], ( *pp )->texInfo.m_texdef.shift[1], - ( *pp )->texInfo.m_texdef.scale[0], ( *pp )->texInfo.m_texdef.scale[0], - ( *pp )->texInfo.m_texdef.rotate ); - - fprintf( pFile, "%s", buffer ); - } - - fprintf( pFile, "}\n" ); -} - -void DBrush::Rotate( vec3_t vOrigin, vec3_t vRotation ){ - for ( std::list::const_iterator rotPlane = faceList.begin(); rotPlane != faceList.end(); rotPlane++ ) - { - for ( int i = 0; i < 3; i++ ) - VectorRotate( ( *rotPlane )->points[i], vRotation, vOrigin ); - - ( *rotPlane )->Rebuild(); - } -} - -void DBrush::RotateAboutCentre( vec3_t vRotation ){ - vec3_t min, max, centre; - GetBounds( min, max ); - VectorAdd( min, max, centre ); - VectorScale( centre, 0.5f, centre ); - - Rotate( centre, vRotation ); -} - -bool DBrush::ResetTextures( const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, - int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation ){ - if ( textureName ) { - bool changed = false; - for ( std::list::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ ) - { - if ( !strcmp( ( *resetPlane )->m_shader.c_str(), textureName ) ) { - if ( bResetTextureName ) { - ( *resetPlane )->m_shader = newTextureName; - } - - if ( bResetScale[0] ) { - ( *resetPlane )->texInfo.m_texdef.scale[0] = fScale[0]; - } - if ( bResetScale[1] ) { - ( *resetPlane )->texInfo.m_texdef.scale[1] = fScale[1]; - } - - if ( bResetShift[0] ) { - ( *resetPlane )->texInfo.m_texdef.shift[0] = fShift[0]; - } - if ( bResetShift[1] ) { - ( *resetPlane )->texInfo.m_texdef.shift[1] = fShift[1]; - } - - if ( bResetRotation ) { - ( *resetPlane )->texInfo.m_texdef.rotate = (float)rotation; - } - - changed = true; - } - } - return changed; // no point rebuilding unless we need to, only slows things down - } - else - { - for ( std::list::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ ) - { - if ( bResetTextureName ) { - ( *resetPlane )->m_shader = newTextureName; - } - - if ( bResetScale[0] ) { - ( *resetPlane )->texInfo.m_texdef.scale[0] = fScale[0]; - } - if ( bResetScale[1] ) { - ( *resetPlane )->texInfo.m_texdef.scale[1] = fScale[1]; - } - - if ( bResetShift[0] ) { - ( *resetPlane )->texInfo.m_texdef.shift[0] = fShift[0]; - } - if ( bResetShift[1] ) { - ( *resetPlane )->texInfo.m_texdef.shift[1] = fShift[1]; - } - - if ( bResetRotation ) { - ( *resetPlane )->texInfo.m_texdef.rotate = (float)rotation; - } - } - return true; - } -} - -bool DBrush::operator ==( DBrush* other ){ - std::list::const_iterator chkPlane; - - for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( !other->HasPlane( ( *chkPlane ) ) ) { - return false; - } - } - - for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) - { - if ( !HasPlane( ( *chkPlane ) ) ) { - return false; - } - } - - return true; -} - -DPlane* DBrush::AddFace( const vec3_t va, const vec3_t vb, const vec3_t vc, const char *textureName, bool bDetail ){ - bBoundsBuilt = false; - DPlane* newFace = new DPlane( va, vb, vc, textureName, bDetail ); - faceList.push_back( newFace ); - - return newFace; -} - -DPlane* DBrush::FindPlaneWithClosestNormal( vec_t* normal ) { - vec_t bestDot = -2; - DPlane* bestDotPlane = NULL; - std::list::const_iterator chkPlane; - for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) { - DPlane* pPlane = ( *chkPlane ); - - vec_t dot = DotProduct( pPlane->normal, normal ); - if ( dot > bestDot ) { - bestDot = dot; - bestDotPlane = pPlane; - } - } - - return bestDotPlane; -} - -int DBrush::FindPointsForPlane( DPlane* plane, DPoint** pnts, int maxpnts ) { - int numpnts = 0; - - if ( !maxpnts ) { - return 0; - } - - BuildPoints(); - - for ( std::list::const_iterator points = pointList.begin(); points != pointList.end(); points++ ) { - DPoint* point = ( *points ); - - if ( fabs( plane->DistanceToPoint( point->_pnt ) ) < MAX_ROUND_ERROR ) { - pnts[numpnts] = point; - numpnts++; - - if ( numpnts >= maxpnts ) { - return numpnts; - } - - } - } - - return numpnts; -} - -void DBrush::RemovePlane( DPlane* plane ) { - bBoundsBuilt = false; - for ( std::list::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) { - if ( *deadPlane == plane ) { - delete *deadPlane; - faceList.remove( plane ); - } - } + BuildPoints(); + } + + chkPlane = faceList.begin(); + while (chkPlane != faceList.end()) { + if ((*chkPlane)->IsRedundant(pointList)) { // checks that plane "0wnz" :), 3 or more points + delete *chkPlane; + chkPlane = faceList.erase(chkPlane); + cnt++; + } else { + chkPlane++; + } + } + + return cnt; +} + +bool DBrush::GetBounds(vec3_t min, vec3_t max) +{ + BuildBounds(); + + if (!bBoundsBuilt) { + return false; + } + + VectorCopy(bbox_min, min); + VectorCopy(bbox_max, max); + + return true; +} + +bool DBrush::BBoxCollision(DBrush *chkBrush) +{ + vec3_t min1, min2; + vec3_t max1, max2; + + GetBounds(min1, max1); + chkBrush->GetBounds(min2, max2); + + if (min1[0] >= max2[0]) { + return false; + } + if (min1[1] >= max2[1]) { + return false; + } + if (min1[2] >= max2[2]) { + return false; + } + + if (max1[0] <= min2[0]) { + return false; + } + if (max1[1] <= min2[1]) { + return false; + } + if (max1[2] <= min2[2]) { + return false; + } + + return true; +} + +DPlane *DBrush::HasPlane(DPlane *chkPlane) +{ + for (std::list::const_iterator brushPlane = faceList.begin(); + brushPlane != faceList.end(); brushPlane++) { + if (**brushPlane == *chkPlane) { + return *brushPlane; + } + } + return NULL; +} + +bool DBrush::IsCutByPlane(DPlane *cuttingPlane) +{ + bool isInFront; + + if (pointList.size() == 0) { + if (BuildPoints() == 0) { + return false; + } + } + + std::list::const_iterator chkPnt = pointList.begin(); + + if (chkPnt == pointList.end()) { + return false; + } + + float dist = cuttingPlane->DistanceToPoint((*chkPnt)->_pnt); + + if (dist > MAX_ROUND_ERROR) { + isInFront = false; + } else if (dist < MAX_ROUND_ERROR) { + isInFront = true; + } else { + return true; + } + + for (chkPnt++ = pointList.begin(); chkPnt != pointList.end(); chkPnt++) { + dist = cuttingPlane->DistanceToPoint((*chkPnt)->_pnt); + + if (dist > MAX_ROUND_ERROR) { + if (isInFront) { + return true; + } + } else if (dist < MAX_ROUND_ERROR) { + if (!isInFront) { + return true; + } + } else { + return true; + } + } + + return false; +} + + +scene::Node *DBrush::BuildInRadiant(bool allowDestruction, int *changeCnt, scene::Node *entity) +{ + if (allowDestruction) { + bool kill = true; + + for (std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if ((*chkPlane)->m_bChkOk) { + kill = false; + break; + } + } + if (kill) { + return NULL; + } + } + + //+djbob: fixed bug when brush had no faces "phantom brush" in radiant. + if (faceList.size() < 4) { + globalErrorStream() << "Possible Phantom Brush Found, will not rebuild\n"; + return NULL; + } + //-djbob + + NodeSmartReference node(GlobalBrushCreator().createBrush()); + + for (std::list::const_iterator buildPlane = faceList.begin(); + buildPlane != faceList.end(); buildPlane++) { + if ((*buildPlane)->AddToBrush(node) && changeCnt) { + (*changeCnt)++; + } + } + + if (entity) { + Node_getTraversable(*entity)->insert(node); + } else { + Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(node); + } + + QER_entity = entity; + QER_brush = node.get_pointer(); + + return node.get_pointer(); +} + +void DBrush::CutByPlane(DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2) +{ + if (!IsCutByPlane(cutPlane)) { + *newBrush1 = NULL; + *newBrush2 = NULL; + return; + } + + DBrush *b1 = new DBrush; + DBrush *b2 = new DBrush; + + for (std::list::const_iterator parsePlane = faceList.begin(); + parsePlane != faceList.end(); parsePlane++) { + b1->AddFace((*parsePlane)->points[0], (*parsePlane)->points[1], (*parsePlane)->points[2], NULL); + b2->AddFace((*parsePlane)->points[0], (*parsePlane)->points[1], (*parsePlane)->points[2], NULL); + } + + b1->AddFace(cutPlane->points[0], cutPlane->points[1], cutPlane->points[2], NULL); + b2->AddFace(cutPlane->points[2], cutPlane->points[1], cutPlane->points[0], NULL); + + b1->RemoveRedundantPlanes(); + b2->RemoveRedundantPlanes(); + + *newBrush1 = b1; + *newBrush2 = b2; +} + +bool DBrush::IntersectsWith(DBrush *chkBrush) +{ + if (pointList.size() == 0) { + if (BuildPoints() == 0) { + return false; // invalid brush!!!! + + } + } + if (chkBrush->pointList.size() == 0) { + if (chkBrush->BuildPoints() == 0) { + return false; // invalid brush!!!! + + } + } + if (!BBoxCollision(chkBrush)) { + return false; + } + + std::list::const_iterator iplPlane; + + for (iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++) { + + bool allInFront = true; + for (std::list::const_iterator iPoint = chkBrush->pointList.begin(); + iPoint != chkBrush->pointList.end(); iPoint++) { + if ((*iplPlane)->DistanceToPoint((*iPoint)->_pnt) < -MAX_ROUND_ERROR) { + allInFront = false; + break; + } + } + if (allInFront) { + return false; + } + } + + for (iplPlane = chkBrush->faceList.begin(); iplPlane != chkBrush->faceList.end(); iplPlane++) { + bool allInFront = true; + for (std::list::const_iterator iPoint = pointList.begin(); iPoint != pointList.end(); iPoint++) { + if ((*iplPlane)->DistanceToPoint((*iPoint)->_pnt) < -MAX_ROUND_ERROR) { + allInFront = false; + break; + } + } + if (allInFront) { + return false; + } + } + + return true; +} + +bool DBrush::IntersectsWith(DPlane *p1, DPlane *p2, vec3_t v) +{ + vec3_t vDown = {0, 0, -1}; + + std::list::const_iterator iplPlane; + for (iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++) { + DPlane *p = (*iplPlane); + + vec_t d = DotProduct(p->normal, vDown); + if (d >= 0) { + continue; + } + if (p->PlaneIntersection(p1, p2, v)) { + if (PointPosition(v) != POINT_OUT_BRUSH) { + return true; + } + } + } + + return false; +} + +void DBrush::BuildBounds() +{ + if (!bBoundsBuilt) { + if (pointList.size() == 0) { // if points may not have been built, build them + if (BuildPoints() == 0) { + return; + } + } + + std::list::const_iterator first = pointList.begin(); + VectorCopy((*first)->_pnt, bbox_min); + VectorCopy((*first)->_pnt, bbox_max); + + std::list::const_iterator point = pointList.begin(); + for (point++; point != pointList.end(); point++) { + if ((*point)->_pnt[0] > bbox_max[0]) { + bbox_max[0] = (*point)->_pnt[0]; + } + if ((*point)->_pnt[1] > bbox_max[1]) { + bbox_max[1] = (*point)->_pnt[1]; + } + if ((*point)->_pnt[2] > bbox_max[2]) { + bbox_max[2] = (*point)->_pnt[2]; + } + + if ((*point)->_pnt[0] < bbox_min[0]) { + bbox_min[0] = (*point)->_pnt[0]; + } + if ((*point)->_pnt[1] < bbox_min[1]) { + bbox_min[1] = (*point)->_pnt[1]; + } + if ((*point)->_pnt[2] < bbox_min[2]) { + bbox_min[2] = (*point)->_pnt[2]; + } + } + + bBoundsBuilt = true; + } +} + +bool DBrush::BBoxTouch(DBrush *chkBrush) +{ + vec3_t min1, min2; + vec3_t max1, max2; + + GetBounds(min1, max1); + chkBrush->GetBounds(min2, max2); + + if ((min1[0] - max2[0]) > MAX_ROUND_ERROR) { + return false; + } + if ((min1[1] - max2[1]) > MAX_ROUND_ERROR) { + return false; + } + if ((min1[2] - max2[2]) > MAX_ROUND_ERROR) { + return false; + } + + if ((min2[0] - max1[0]) > MAX_ROUND_ERROR) { + return false; + } + if ((min2[1] - max1[1]) > MAX_ROUND_ERROR) { + return false; + } + if ((min2[2] - max1[2]) > MAX_ROUND_ERROR) { + return false; + } + + int cnt = 0; + + if ((min2[0] - max1[0]) == 0) { + cnt++; + } + + if ((min2[1] - max1[1]) == 0) { + cnt++; + } + + if ((min2[2] - max1[2]) == 0) { + cnt++; + } + + if ((min1[0] - max2[0]) == 0) { + cnt++; + } + + if ((min1[1] - max2[1]) == 0) { + cnt++; + } + + if ((min1[2] - max2[2]) == 0) { + cnt++; + } + + if (cnt > 1) { + return false; + } + + return true; +} + +void DBrush::ResetChecks(std::list *exclusionList) +{ + for (std::list::const_iterator resetPlane = faceList.begin(); + resetPlane != faceList.end(); resetPlane++) { + bool set = false; + + if (exclusionList) { + for (std::list::iterator eTexture = exclusionList->begin(); + eTexture != exclusionList->end(); eTexture++) { + if (strstr((*resetPlane)->m_shader.c_str(), eTexture->GetBuffer())) { + set = true; + break; + } + } + } + + (*resetPlane)->m_bChkOk = set; + } +} + +DPlane *DBrush::HasPlaneInverted(DPlane *chkPlane) +{ + for (std::list::const_iterator brushPlane = faceList.begin(); + brushPlane != faceList.end(); brushPlane++) { + if (**brushPlane != *chkPlane) { + if (fabs((*brushPlane)->_d + chkPlane->_d) < 0.1) { + return (*brushPlane); + } + } + } + return NULL; +} + +bool DBrush::HasTexture(const char *textureName) +{ + for (std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if (strstr((*chkPlane)->m_shader.c_str(), textureName)) { + return true; + } + + } + return false; +} + +bool DBrush::IsDetail() +{ + for (std::list::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if ((*chkPlane)->texInfo.contents & FACE_DETAIL) { + return true; + } + + } + return false; +} + +void DBrush::BuildFromWinding(DWinding *w) +{ + if (w->numpoints < 3) { + globalErrorStream() << "Winding has invalid number of points"; + return; + } + + DPlane *wPlane = w->WindingPlane(); + + DWinding *w2; + w2 = w->CopyWinding(); + int i; + for (i = 0; i < w2->numpoints; i++) + VectorAdd(w2->p[i], wPlane->normal, w2->p[i]); + + AddFace(w2->p[0], w2->p[1], w2->p[2], NULL); + AddFace(w->p[2], w->p[1], w->p[0], NULL); + + for (i = 0; i < w->numpoints - 1; i++) { + AddFace(w2->p[i], w->p[i], w->p[i + 1], NULL); + } + AddFace(w2->p[w->numpoints - 1], w->p[w->numpoints - 1], w->p[0], NULL); + + delete wPlane; + delete w2; +} + +void DBrush::SaveToFile(FILE *pFile) +{ + fprintf(pFile, "{\n"); + + for (std::list::const_iterator pp = faceList.begin(); pp != faceList.end(); pp++) { + char buffer[512]; + + sprintf(buffer, "( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) %s %.0f %.0f %f %f %.0f 0 0 0\n", + (*pp)->points[0][0], (*pp)->points[0][1], (*pp)->points[0][2], + (*pp)->points[1][0], (*pp)->points[1][1], (*pp)->points[1][2], + (*pp)->points[2][0], (*pp)->points[2][1], (*pp)->points[2][2], + (*pp)->m_shader.c_str(), + (*pp)->texInfo.m_texdef.shift[0], (*pp)->texInfo.m_texdef.shift[1], + (*pp)->texInfo.m_texdef.scale[0], (*pp)->texInfo.m_texdef.scale[0], + (*pp)->texInfo.m_texdef.rotate); + + fprintf(pFile, "%s", buffer); + } + + fprintf(pFile, "}\n"); +} + +void DBrush::Rotate(vec3_t vOrigin, vec3_t vRotation) +{ + for (std::list::const_iterator rotPlane = faceList.begin(); rotPlane != faceList.end(); rotPlane++) { + for (int i = 0; i < 3; i++) { + VectorRotate((*rotPlane)->points[i], vRotation, vOrigin); + } + + (*rotPlane)->Rebuild(); + } +} + +void DBrush::RotateAboutCentre(vec3_t vRotation) +{ + vec3_t min, max, centre; + GetBounds(min, max); + VectorAdd(min, max, centre); + VectorScale(centre, 0.5f, centre); + + Rotate(centre, vRotation); +} + +bool DBrush::ResetTextures(const char *textureName, float fScale[2], float fShift[2], int rotation, + const char *newTextureName, + int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation) +{ + if (textureName) { + bool changed = false; + for (std::list::const_iterator resetPlane = faceList.begin(); + resetPlane != faceList.end(); resetPlane++) { + if (!strcmp((*resetPlane)->m_shader.c_str(), textureName)) { + if (bResetTextureName) { + (*resetPlane)->m_shader = newTextureName; + } + + if (bResetScale[0]) { + (*resetPlane)->texInfo.m_texdef.scale[0] = fScale[0]; + } + if (bResetScale[1]) { + (*resetPlane)->texInfo.m_texdef.scale[1] = fScale[1]; + } + + if (bResetShift[0]) { + (*resetPlane)->texInfo.m_texdef.shift[0] = fShift[0]; + } + if (bResetShift[1]) { + (*resetPlane)->texInfo.m_texdef.shift[1] = fShift[1]; + } + + if (bResetRotation) { + (*resetPlane)->texInfo.m_texdef.rotate = (float) rotation; + } + + changed = true; + } + } + return changed; // no point rebuilding unless we need to, only slows things down + } else { + for (std::list::const_iterator resetPlane = faceList.begin(); + resetPlane != faceList.end(); resetPlane++) { + if (bResetTextureName) { + (*resetPlane)->m_shader = newTextureName; + } + + if (bResetScale[0]) { + (*resetPlane)->texInfo.m_texdef.scale[0] = fScale[0]; + } + if (bResetScale[1]) { + (*resetPlane)->texInfo.m_texdef.scale[1] = fScale[1]; + } + + if (bResetShift[0]) { + (*resetPlane)->texInfo.m_texdef.shift[0] = fShift[0]; + } + if (bResetShift[1]) { + (*resetPlane)->texInfo.m_texdef.shift[1] = fShift[1]; + } + + if (bResetRotation) { + (*resetPlane)->texInfo.m_texdef.rotate = (float) rotation; + } + } + return true; + } +} + +bool DBrush::operator==(DBrush *other) +{ + std::list::const_iterator chkPlane; + + for (chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if (!other->HasPlane((*chkPlane))) { + return false; + } + } + + for (chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + if (!HasPlane((*chkPlane))) { + return false; + } + } + + return true; +} + +DPlane *DBrush::AddFace(const vec3_t va, const vec3_t vb, const vec3_t vc, const char *textureName, bool bDetail) +{ + bBoundsBuilt = false; + DPlane *newFace = new DPlane(va, vb, vc, textureName, bDetail); + faceList.push_back(newFace); + + return newFace; +} + +DPlane *DBrush::FindPlaneWithClosestNormal(vec_t *normal) +{ + vec_t bestDot = -2; + DPlane *bestDotPlane = NULL; + std::list::const_iterator chkPlane; + for (chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++) { + DPlane *pPlane = (*chkPlane); + + vec_t dot = DotProduct(pPlane->normal, normal); + if (dot > bestDot) { + bestDot = dot; + bestDotPlane = pPlane; + } + } + + return bestDotPlane; +} + +int DBrush::FindPointsForPlane(DPlane *plane, DPoint **pnts, int maxpnts) +{ + int numpnts = 0; + + if (!maxpnts) { + return 0; + } + + BuildPoints(); + + for (std::list::const_iterator points = pointList.begin(); points != pointList.end(); points++) { + DPoint *point = (*points); + + if (fabs(plane->DistanceToPoint(point->_pnt)) < MAX_ROUND_ERROR) { + pnts[numpnts] = point; + numpnts++; + + if (numpnts >= maxpnts) { + return numpnts; + } + + } + } + + return numpnts; +} + +void DBrush::RemovePlane(DPlane *plane) +{ + bBoundsBuilt = false; + for (std::list::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++) { + if (*deadPlane == plane) { + delete *deadPlane; + faceList.remove(plane); + } + } } diff --git a/contrib/bobtoolz/DBrush.h b/contrib/bobtoolz/DBrush.h index 7b3e8d60..d88bee25 100644 --- a/contrib/bobtoolz/DBrush.h +++ b/contrib/bobtoolz/DBrush.h @@ -34,80 +34,106 @@ #include "str.h" class DPlane; + class DWinding; + class DPoint; + class _QERFaceData; -namespace scene -{ -class Node; -class Instance; +namespace scene { + class Node; + + class Instance; } -const int POINT_IN_BRUSH = 0; -const int POINT_ON_BRUSH = 1; +const int POINT_IN_BRUSH = 0; +const int POINT_ON_BRUSH = 1; const int POINT_OUT_BRUSH = 2; -class DBrush -{ +class DBrush { public: -DPlane* AddFace( const vec3_t va, const vec3_t vb, const vec3_t vc, const char* textureName, bool bDetail ); -void SaveToFile( FILE* pFile ); + DPlane *AddFace(const vec3_t va, const vec3_t vb, const vec3_t vc, const char *textureName, bool bDetail); + + void SaveToFile(FILE *pFile); + + void Rotate(vec3_t vOrigin, vec3_t vRotation); + + void RotateAboutCentre(vec3_t vRotation); + + DPlane *HasPlaneInverted(DPlane *chkPlane); + + DPlane *HasPlane(DPlane *chkPlane); + + DPlane *AddFace(const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData *texData); + + bool + ResetTextures(const char *textureName, float fScale[2], float fShift[2], int rotation, const char *newTextureName, + int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation); + + bool IsDetail(); + + bool HasTexture(const char *textureName); + + bool IntersectsWith(DBrush *chkBrush); + + bool IntersectsWith(DPlane *p1, DPlane *p2, vec3_t v); + + bool IsCutByPlane(DPlane *cuttingPlane); + + bool GetBounds(vec3_t min, vec3_t max); + + bool HasPoint(vec3_t pnt); + + bool BBoxCollision(DBrush *chkBrush); + + bool BBoxTouch(DBrush *chkBrush); + + int BuildPoints(); + + void BuildBounds(); + + void BuildFromWinding(DWinding *w); + + scene::Node *BuildInRadiant(bool allowDestruction, int *changeCnt, scene::Node *entity = NULL); + + void ResetChecks(std::list *exclusionList); + + void ClearFaces(); -void Rotate( vec3_t vOrigin, vec3_t vRotation ); -void RotateAboutCentre( vec3_t vRotation ); + void ClearPoints(); -DPlane* HasPlaneInverted( DPlane* chkPlane ); -DPlane* HasPlane( DPlane* chkPlane ); -DPlane* AddFace( const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData* texData ); + int RemoveRedundantPlanes(void); -bool ResetTextures( const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation ); -bool IsDetail(); -bool HasTexture( const char* textureName ); -bool IntersectsWith( DBrush *chkBrush ); -bool IntersectsWith( DPlane* p1, DPlane* p2, vec3_t v ); -bool IsCutByPlane( DPlane* cuttingPlane ); -bool GetBounds( vec3_t min, vec3_t max ); -bool HasPoint( vec3_t pnt ); -bool BBoxCollision( DBrush* chkBrush ); -bool BBoxTouch( DBrush* chkBrush ); + void RemovePlane(DPlane *plane); -int BuildPoints(); -void BuildBounds(); -void BuildFromWinding( DWinding* w ); -scene::Node* BuildInRadiant( bool allowDestruction, int* changeCnt, scene::Node* entity = NULL ); + int PointPosition(vec3_t pnt); -void ResetChecks( std::list* exclusionList ); -void ClearFaces(); -void ClearPoints(); + void CutByPlane(DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2); -int RemoveRedundantPlanes( void ); -void RemovePlane( DPlane* plane ); -int PointPosition( vec3_t pnt ); + void LoadFromBrush(scene::Instance &brush, bool textured); + void AddPoint(vec3_t pnt); -void CutByPlane( DPlane* cutPlane, DBrush** newBrush1, DBrush** newBrush2 ); + DPlane *FindPlaneWithClosestNormal(vec_t *normal); -void LoadFromBrush( scene::Instance& brush, bool textured ); -void AddPoint( vec3_t pnt ); + int FindPointsForPlane(DPlane *plane, DPoint **pnts, int maxpnts); -DPlane* FindPlaneWithClosestNormal( vec_t* normal ); -int FindPointsForPlane( DPlane* plane, DPoint** pnts, int maxpnts ); + DBrush(int ID = -1); -DBrush( int ID = -1 ); -virtual ~DBrush(); + virtual ~DBrush(); -bool operator==( DBrush* other ); + bool operator==(DBrush *other); // members -scene::Node* QER_entity; -scene::Node* QER_brush; -std::list faceList; -std::list pointList; -int m_nBrushID; -vec3_t bbox_min, bbox_max; -bool bBoundsBuilt; + scene::Node *QER_entity; + scene::Node *QER_brush; + std::list faceList; + std::list pointList; + int m_nBrushID; + vec3_t bbox_min, bbox_max; + bool bBoundsBuilt; }; //typedef CList DBrushList; diff --git a/contrib/bobtoolz/DEPair.cpp b/contrib/bobtoolz/DEPair.cpp index c75a8751..f32ebee9 100644 --- a/contrib/bobtoolz/DEPair.cpp +++ b/contrib/bobtoolz/DEPair.cpp @@ -27,11 +27,13 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DEPair::DEPair(){ +DEPair::DEPair() +{ } -DEPair::~DEPair(){ +DEPair::~DEPair() +{ } @@ -39,7 +41,8 @@ DEPair::~DEPair(){ // Implementation ////////////////////////////////////////////////////////////////////// -void DEPair::Build( const char *pKey, const char *pValue ){ - key = pKey; - value = pValue; +void DEPair::Build(const char *pKey, const char *pValue) +{ + key = pKey; + value = pValue; } diff --git a/contrib/bobtoolz/DEPair.h b/contrib/bobtoolz/DEPair.h index 3b5ca3ae..f3f0cebb 100644 --- a/contrib/bobtoolz/DEPair.h +++ b/contrib/bobtoolz/DEPair.h @@ -30,16 +30,16 @@ #include "str.h" -class DEPair -{ +class DEPair { public: -DEPair(); -virtual ~DEPair(); + DEPair(); -void Build( const char* pKey, const char* pValue ); + virtual ~DEPair(); -Str key; -Str value; + void Build(const char *pKey, const char *pValue); + + Str key; + Str value; }; //typedef CList DEPairList; diff --git a/contrib/bobtoolz/DEntity.cpp b/contrib/bobtoolz/DEntity.cpp index 22aa05a1..f4d9f0b1 100644 --- a/contrib/bobtoolz/DEntity.cpp +++ b/contrib/bobtoolz/DEntity.cpp @@ -55,621 +55,651 @@ #include "scenelib.h" -const char* brushEntityList[] = { - "worldspawn", - "trigger_always", - "trigger_hurt", - "trigger_multiple", - "trigger_push", - "trigger_teleport", - "func_bobbing", - "func_button", - "func_door", - "func_group", - "func_pendulum", - "func_plat", - "func_rotating", - "func_static", - "func_timer", - "func_train", - 0 +const char *brushEntityList[] = { + "worldspawn", + "trigger_always", + "trigger_hurt", + "trigger_multiple", + "trigger_push", + "trigger_teleport", + "func_bobbing", + "func_button", + "func_door", + "func_group", + "func_pendulum", + "func_plat", + "func_rotating", + "func_static", + "func_timer", + "func_train", + 0 }; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DEntity::DEntity( const char *classname, int ID ){ - SetClassname( classname ); - m_nID = ID; - QER_Entity = NULL; +DEntity::DEntity(const char *classname, int ID) +{ + SetClassname(classname); + m_nID = ID; + QER_Entity = NULL; } -DEntity::~DEntity(){ - ClearPatches(); - ClearBrushes(); - ClearEPairs(); +DEntity::~DEntity() +{ + ClearPatches(); + ClearBrushes(); + ClearEPairs(); } ////////////////////////////////////////////////////////////////////// // Implementation ////////////////////////////////////////////////////////////////////// -void DEntity::ClearBrushes(){ - for ( std::list::const_iterator deadBrush = brushList.begin(); deadBrush != brushList.end(); deadBrush++ ) - { - delete *deadBrush; - } - brushList.clear(); +void DEntity::ClearBrushes() +{ + for (std::list::const_iterator deadBrush = brushList.begin(); deadBrush != brushList.end(); deadBrush++) { + delete *deadBrush; + } + brushList.clear(); } -void DEntity::ClearPatches(){ - for ( std::list::const_iterator deadPatch = patchList.begin(); deadPatch != patchList.end(); deadPatch++ ) - { - delete *deadPatch; - } - patchList.clear(); -} - -DPatch* DEntity::NewPatch(){ - DPatch* newPatch = new DPatch; - - patchList.push_back( newPatch ); - - return newPatch; -} +void DEntity::ClearPatches() +{ + for (std::list::const_iterator deadPatch = patchList.begin(); deadPatch != patchList.end(); deadPatch++) { + delete *deadPatch; + } + patchList.clear(); +} -DBrush* DEntity::NewBrush( int ID ){ - DBrush* newBrush = new DBrush( ID ); +DPatch *DEntity::NewPatch() +{ + DPatch *newPatch = new DPatch; - brushList.push_back( newBrush ); + patchList.push_back(newPatch); - return newBrush; + return newPatch; } -char* getNextBracket( char* s ){ - char* p = s; - while ( *p ) - { - p++; - if ( *p == '(' ) { - break; - } - } +DBrush *DEntity::NewBrush(int ID) +{ + DBrush *newBrush = new DBrush(ID); + + brushList.push_back(newBrush); - return p; + return newBrush; } -bool DEntity::LoadFromPrt( char *filename ){ - CPortals portals; - strcpy( portals.fn, filename ); - portals.Load(); +char *getNextBracket(char *s) +{ + char *p = s; + while (*p) { + p++; + if (*p == '(') { + break; + } + } - if ( portals.node_count == 0 ) { - return false; - } + return p; +} - ClearBrushes(); - ClearEPairs(); +bool DEntity::LoadFromPrt(char *filename) +{ + CPortals portals; + strcpy(portals.fn, filename); + portals.Load(); + + if (portals.node_count == 0) { + return false; + } + + ClearBrushes(); + ClearEPairs(); + + bool build = false; + for (unsigned int i = 0; i < portals.node_count; i++) { + build = false; + DBrush *brush = NewBrush(); + + for (unsigned int j = 0; j < portals.node[i].portal_count; j++) { + for (unsigned int k = 0; k < portals.node[i].portal[j].point_count - 2; k++) { + vec3_t v1, v2, normal, n; + VectorSubtract(portals.node[i].portal[j].point[k + 2].p, portals.node[i].portal[j].point[k + 1].p, v1); + VectorSubtract(portals.node[i].portal[j].point[k].p, portals.node[i].portal[j].point[k + 1].p, v2); + CrossProduct(v1, v2, n); + VectorNormalize(n, v2); + + if (k == 0) { + VectorCopy(v2, normal); + } else { + VectorSubtract(v2, normal, v1); + if (VectorLength(v1) > 0.01) { + build = true; + break; + } + } + } + + if (!build) { + brush->AddFace(portals.node[i].portal[j].point[2].p, portals.node[i].portal[j].point[1].p, + portals.node[i].portal[j].point[0].p, "textures/common/caulk", false); + } else { + brush->AddFace(portals.node[i].portal[j].point[0].p, portals.node[i].portal[j].point[1].p, + portals.node[i].portal[j].point[2].p, "textures/common/caulk", false); + } + } + if (build) { + brush->BuildInRadiant(false, NULL); + } + } + + return true; +} + +DPlane *DEntity::AddFaceToBrush(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData *faceData, int ID) +{ + DBrush *buildBrush = GetBrushForID(ID); + return buildBrush->AddFace(va, vb, vc, faceData); + // slow, dont use much +} - bool build = false; - for ( unsigned int i = 0; i < portals.node_count; i++ ) - { - build = false; - DBrush* brush = NewBrush(); +DBrush *DEntity::GetBrushForID(int ID) +{ + DBrush *buildBrush = NULL; - for ( unsigned int j = 0; j < portals.node[i].portal_count; j++ ) - { - for ( unsigned int k = 0; k < portals.node[i].portal[j].point_count - 2; k++ ) - { - vec3_t v1, v2, normal, n; - VectorSubtract( portals.node[i].portal[j].point[k + 2].p, portals.node[i].portal[j].point[k + 1].p, v1 ); - VectorSubtract( portals.node[i].portal[j].point[k].p, portals.node[i].portal[j].point[k + 1].p, v2 ); - CrossProduct( v1, v2, n ); - VectorNormalize( n, v2 ); + for (std::list::const_iterator chkBrush = brushList.begin(); chkBrush != brushList.end(); chkBrush++) { + if ((*chkBrush)->m_nBrushID == ID) { + buildBrush = (*chkBrush); + break; + } + } - if ( k == 0 ) { - VectorCopy( v2, normal ); - } - else - { - VectorSubtract( v2, normal, v1 ); - if ( VectorLength( v1 ) > 0.01 ) { - build = true; - break; - } - } - } + if (!buildBrush) { + buildBrush = NewBrush(ID); + } - if ( !build ) { - brush->AddFace( portals.node[i].portal[j].point[2].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[0].p, "textures/common/caulk", false ); - } - else{ - brush->AddFace( portals.node[i].portal[j].point[0].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[2].p, "textures/common/caulk", false ); - } - } - if ( build ) { - brush->BuildInRadiant( false, NULL ); - } - } + return buildBrush; +} + +template +class BrushSelectedVisitor : public SelectionSystem::Visitor { + const Functor &m_functor; +public: + BrushSelectedVisitor(const Functor &functor) : m_functor(functor) + { + } + + void visit(scene::Instance &instance) const + { + if (Node_isBrush(instance.path().top())) { + m_functor(instance); + } + } +}; - return true; +template +inline const Functor &Scene_forEachSelectedBrush(const Functor &functor) +{ + GlobalSelectionSystem().foreachSelected(BrushSelectedVisitor(functor)); + return functor; } -DPlane* DEntity::AddFaceToBrush( vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* faceData, int ID ){ - DBrush* buildBrush = GetBrushForID( ID ); - return buildBrush->AddFace( va, vb, vc, faceData ); - // slow, dont use much +void DEntity_loadBrush(DEntity &entity, scene::Instance &brush) +{ + DBrush *loadBrush = entity.NewBrush(static_cast( entity.brushList.size())); + loadBrush->LoadFromBrush(brush, true); } -DBrush* DEntity::GetBrushForID( int ID ){ - DBrush* buildBrush = NULL; +typedef ReferenceCaller DEntityLoadBrushCaller; - for ( std::list::const_iterator chkBrush = brushList.begin(); chkBrush != brushList.end(); chkBrush++ ) - { - if ( ( *chkBrush )->m_nBrushID == ID ) { - buildBrush = ( *chkBrush ); - break; - } - } +void DEntity::LoadSelectedBrushes() +{ + ClearBrushes(); + ClearEPairs(); - if ( !buildBrush ) { - buildBrush = NewBrush( ID ); - } - - return buildBrush; + Scene_forEachSelectedBrush(DEntityLoadBrushCaller(*this)); } template -class BrushSelectedVisitor : public SelectionSystem::Visitor -{ -const Functor& m_functor; +class PatchSelectedVisitor : public SelectionSystem::Visitor { + const Functor &m_functor; public: -BrushSelectedVisitor( const Functor& functor ) : m_functor( functor ){ -} -void visit( scene::Instance& instance ) const { - if ( Node_isBrush( instance.path().top() ) ) { - m_functor( instance ); - } -} + PatchSelectedVisitor(const Functor &functor) : m_functor(functor) + { + } + + void visit(scene::Instance &instance) const + { + if (Node_isPatch(instance.path().top())) { + m_functor(instance); + } + } }; template -inline const Functor& Scene_forEachSelectedBrush( const Functor& functor ){ - GlobalSelectionSystem().foreachSelected( BrushSelectedVisitor( functor ) ); - return functor; +inline const Functor &Scene_forEachSelectedPatch(const Functor &functor) +{ + GlobalSelectionSystem().foreachSelected(PatchSelectedVisitor(functor)); + return functor; } -void DEntity_loadBrush( DEntity& entity, scene::Instance& brush ){ - DBrush* loadBrush = entity.NewBrush( static_cast( entity.brushList.size() ) ); - loadBrush->LoadFromBrush( brush, true ); +void DEntity_loadPatch(DEntity &entity, scene::Instance &patch) +{ + DPatch *loadPatch = entity.NewPatch(); + loadPatch->LoadFromPatch(patch); } -typedef ReferenceCaller DEntityLoadBrushCaller; -void DEntity::LoadSelectedBrushes(){ - ClearBrushes(); - ClearEPairs(); +typedef ReferenceCaller DEntityLoadPatchCaller; - Scene_forEachSelectedBrush( DEntityLoadBrushCaller( *this ) ); +void DEntity::LoadSelectedPatches() +{ + ClearPatches(); + ClearEPairs(); + + Scene_forEachSelectedPatch(DEntityLoadPatchCaller(*this)); } -template -class PatchSelectedVisitor : public SelectionSystem::Visitor +bool *DEntity::BuildIntersectList() { -const Functor& m_functor; -public: -PatchSelectedVisitor( const Functor& functor ) : m_functor( functor ){ -} -void visit( scene::Instance& instance ) const { - if ( Node_isPatch( instance.path().top() ) ) { - m_functor( instance ); - } -} -}; + int max = GetIDMax(); + if (max == 0) { + return NULL; + } -template -inline const Functor& Scene_forEachSelectedPatch( const Functor& functor ){ - GlobalSelectionSystem().foreachSelected( PatchSelectedVisitor( functor ) ); - return functor; -} + bool *pbIntList = new bool[max]; + memset(pbIntList, 0, sizeof(bool) * (max)); + + for (std::list::const_iterator pB1 = brushList.begin(); pB1 != brushList.end(); pB1++) { + std::list::const_iterator pB2 = pB1; + for (pB2++; pB2 != brushList.end(); pB2++) { + if ((*pB1)->IntersectsWith((*pB2))) { + pbIntList[(*pB1)->m_nBrushID] = true; + pbIntList[(*pB2)->m_nBrushID] = true; + } + } + } -void DEntity_loadPatch( DEntity& entity, scene::Instance& patch ){ - DPatch* loadPatch = entity.NewPatch(); - loadPatch->LoadFromPatch( patch ); + return pbIntList; } -typedef ReferenceCaller DEntityLoadPatchCaller; -void DEntity::LoadSelectedPatches(){ - ClearPatches(); - ClearEPairs(); - - Scene_forEachSelectedPatch( DEntityLoadPatchCaller( *this ) ); -} - -bool* DEntity::BuildIntersectList(){ - int max = GetIDMax(); - if ( max == 0 ) { - return NULL; - } - - bool* pbIntList = new bool[max]; - memset( pbIntList, 0, sizeof( bool ) * ( max ) ); - - for ( std::list::const_iterator pB1 = brushList.begin(); pB1 != brushList.end(); pB1++ ) - { - std::list::const_iterator pB2 = pB1; - for ( pB2++; pB2 != brushList.end(); pB2++ ) - { - if ( ( *pB1 )->IntersectsWith( ( *pB2 ) ) ) { - pbIntList[( *pB1 )->m_nBrushID] = true; - pbIntList[( *pB2 )->m_nBrushID] = true; - } - } - } - - return pbIntList; -} - -bool* DEntity::BuildDuplicateList(){ - int max = GetIDMax(); - if ( max == 0 ) { - return NULL; - } - - bool* pbDupList = new bool[max]; - memset( pbDupList, 0, sizeof( bool ) * ( max ) ); - - for ( std::list::const_iterator pB1 = brushList.begin(); pB1 != brushList.end(); pB1++ ) - { - std::list::const_iterator pB2 = pB1; - for ( pB2++; pB2 != brushList.end(); pB2++ ) - { - if ( **pB1 == *pB2 ) { - pbDupList[( *pB1 )->m_nBrushID] = true; - pbDupList[( *pB2 )->m_nBrushID] = true; - } - } - } - - return pbDupList; -} - -void DEntity::SelectBrushes( bool *selectList ){ - if ( selectList == NULL ) { - return; - } - - GlobalSelectionSystem().setSelectedAll( false ); - - scene::Path path( NodeReference( GlobalSceneGraph().root() ) ); - path.push( NodeReference( *QER_Entity ) ); - - for ( std::list::const_iterator pBrush = brushList.begin(); pBrush != brushList.end(); pBrush++ ) - { - if ( selectList[( *pBrush )->m_nBrushID] ) { - path.push( NodeReference( *( *pBrush )->QER_brush ) ); - Instance_getSelectable( *GlobalSceneGraph().find( path ) )->setSelected( true ); - path.pop(); - } - } -} - -bool DEntity::LoadFromEntity( scene::Node& ent, bool bLoadPatches ) { - ClearPatches(); - ClearBrushes(); - ClearEPairs(); - - QER_Entity = &ent; - - LoadEPairList( Node_getEntity( ent ) ); - - bool keep = false; - int i; - for ( i = 0; brushEntityList[i]; i++ ) - { - if ( string_equal_nocase( brushEntityList[i], m_Classname ) ) { - keep = true; - break; - } - } - - if ( !keep ) { - return false; - } - - if ( Node_getTraversable( ent ) ) { - class load_brushes_t : public scene::Traversable::Walker - { - DEntity* m_entity; - mutable int m_count; -public: - load_brushes_t( DEntity* entity ) - : m_entity( entity ), m_count( 0 ){ - } - bool pre( scene::Node& node ) const { - scene::Path path( NodeReference( GlobalSceneGraph().root() ) ); - path.push( NodeReference( *m_entity->QER_Entity ) ); - path.push( NodeReference( node ) ); - scene::Instance* instance = GlobalSceneGraph().find( path ); - ASSERT_MESSAGE( instance != 0, "" ); +bool *DEntity::BuildDuplicateList() +{ + int max = GetIDMax(); + if (max == 0) { + return NULL; + } - if ( Node_isPatch( node ) ) { - DPatch* loadPatch = m_entity->NewPatch(); - loadPatch->LoadFromPatch( *instance ); - } - else if ( Node_isBrush( node ) ) { - DBrush* loadBrush = m_entity->NewBrush( m_count++ ); - loadBrush->LoadFromBrush( *instance, true ); - } - return false; - } - } load_brushes( this ); + bool *pbDupList = new bool[max]; + memset(pbDupList, 0, sizeof(bool) * (max)); - Node_getTraversable( ent )->traverse( load_brushes ); - } + for (std::list::const_iterator pB1 = brushList.begin(); pB1 != brushList.end(); pB1++) { + std::list::const_iterator pB2 = pB1; + for (pB2++; pB2 != brushList.end(); pB2++) { + if (**pB1 == *pB2) { + pbDupList[(*pB1)->m_nBrushID] = true; + pbDupList[(*pB2)->m_nBrushID] = true; + } + } + } - return true; + return pbDupList; } -void DEntity::RemoveNonCheckBrushes( std::list* exclusionList, bool useDetail ){ - std::list::iterator chkBrush = brushList.begin(); - - while ( chkBrush != brushList.end() ) - { - if ( !useDetail ) { - if ( ( *chkBrush )->IsDetail() ) { - delete *chkBrush; - chkBrush = brushList.erase( chkBrush ); - continue; - } - } +void DEntity::SelectBrushes(bool *selectList) +{ + if (selectList == NULL) { + return; + } - std::list::iterator eTexture; + GlobalSelectionSystem().setSelectedAll(false); - for ( eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++ ) - { - if ( ( *chkBrush )->HasTexture( ( *eTexture ).GetBuffer() ) ) { - delete *chkBrush; - chkBrush = brushList.erase( chkBrush ); - break; - } - } + scene::Path path(NodeReference(GlobalSceneGraph().root())); + path.push(NodeReference(*QER_Entity)); - if ( eTexture == exclusionList->end() ) { - chkBrush++; - } - } + for (std::list::const_iterator pBrush = brushList.begin(); pBrush != brushList.end(); pBrush++) { + if (selectList[(*pBrush)->m_nBrushID]) { + path.push(NodeReference(*(*pBrush)->QER_brush)); + Instance_getSelectable(*GlobalSceneGraph().find(path))->setSelected(true); + path.pop(); + } + } } -void DEntity::ResetChecks( std::list* exclusionList ){ - for ( std::list::const_iterator resetBrush = brushList.begin(); resetBrush != brushList.end(); resetBrush++ ) - { - ( *resetBrush )->ResetChecks( exclusionList ); - } +bool DEntity::LoadFromEntity(scene::Node &ent, bool bLoadPatches) +{ + ClearPatches(); + ClearBrushes(); + ClearEPairs(); + + QER_Entity = &ent; + + LoadEPairList(Node_getEntity(ent)); + + bool keep = false; + int i; + for (i = 0; brushEntityList[i]; i++) { + if (string_equal_nocase(brushEntityList[i], m_Classname)) { + keep = true; + break; + } + } + + if (!keep) { + return false; + } + + if (Node_getTraversable(ent)) { + class load_brushes_t : public scene::Traversable::Walker { + DEntity *m_entity; + mutable int m_count; + public: + load_brushes_t(DEntity *entity) + : m_entity(entity), m_count(0) + { + } + + bool pre(scene::Node &node) const + { + scene::Path path(NodeReference(GlobalSceneGraph().root())); + path.push(NodeReference(*m_entity->QER_Entity)); + path.push(NodeReference(node)); + scene::Instance *instance = GlobalSceneGraph().find(path); + ASSERT_MESSAGE(instance != 0, ""); + + if (Node_isPatch(node)) { + DPatch *loadPatch = m_entity->NewPatch(); + loadPatch->LoadFromPatch(*instance); + } else if (Node_isBrush(node)) { + DBrush *loadBrush = m_entity->NewBrush(m_count++); + loadBrush->LoadFromBrush(*instance, true); + } + return false; + } + } load_brushes(this); + + Node_getTraversable(ent)->traverse(load_brushes); + } + + return true; +} + +void DEntity::RemoveNonCheckBrushes(std::list *exclusionList, bool useDetail) +{ + std::list::iterator chkBrush = brushList.begin(); + + while (chkBrush != brushList.end()) { + if (!useDetail) { + if ((*chkBrush)->IsDetail()) { + delete *chkBrush; + chkBrush = brushList.erase(chkBrush); + continue; + } + } + + std::list::iterator eTexture; + + for (eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++) { + if ((*chkBrush)->HasTexture((*eTexture).GetBuffer())) { + delete *chkBrush; + chkBrush = brushList.erase(chkBrush); + break; + } + } + + if (eTexture == exclusionList->end()) { + chkBrush++; + } + } +} + +void DEntity::ResetChecks(std::list *exclusionList) +{ + for (std::list::const_iterator resetBrush = brushList.begin(); + resetBrush != brushList.end(); resetBrush++) { + (*resetBrush)->ResetChecks(exclusionList); + } } -int DEntity::FixBrushes(){ - int count = 0; +int DEntity::FixBrushes() +{ + int count = 0; - for ( std::list::const_iterator fixBrush = brushList.begin(); fixBrush != brushList.end(); fixBrush++ ) - { - count += ( *fixBrush )->RemoveRedundantPlanes(); - } + for (std::list::const_iterator fixBrush = brushList.begin(); fixBrush != brushList.end(); fixBrush++) { + count += (*fixBrush)->RemoveRedundantPlanes(); + } - return count; + return count; } -void DEntity::BuildInRadiant( bool allowDestruction ){ - bool makeEntity = strcmp( m_Classname, "worldspawn" ) ? true : false; +void DEntity::BuildInRadiant(bool allowDestruction) +{ + bool makeEntity = strcmp(m_Classname, "worldspawn") ? true : false; - if ( makeEntity ) { - NodeSmartReference node( GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( m_Classname.GetBuffer(), !brushList.empty() || !patchList.empty() ) ) ); + if (makeEntity) { + NodeSmartReference node(GlobalEntityCreator().createEntity( + GlobalEntityClassManager().findOrInsert(m_Classname.GetBuffer(), + !brushList.empty() || !patchList.empty()))); - for ( std::list::const_iterator buildEPair = epairList.begin(); buildEPair != epairList.end(); buildEPair++ ) - { - Node_getEntity( node )->setKeyValue( ( *buildEPair )->key, ( *buildEPair )->value ); - } + for (std::list::const_iterator buildEPair = epairList.begin(); + buildEPair != epairList.end(); buildEPair++) { + Node_getEntity(node)->setKeyValue((*buildEPair)->key, (*buildEPair)->value); + } - Node_getTraversable( GlobalSceneGraph().root() )->insert( node ); + Node_getTraversable(GlobalSceneGraph().root())->insert(node); - for ( std::list::const_iterator buildBrush = brushList.begin(); buildBrush != brushList.end(); buildBrush++ ) - ( *buildBrush )->BuildInRadiant( allowDestruction, NULL, node.get_pointer() ); + for (std::list::const_iterator buildBrush = brushList.begin(); + buildBrush != brushList.end(); buildBrush++) { + (*buildBrush)->BuildInRadiant(allowDestruction, NULL, node.get_pointer()); + } - for ( std::list::const_iterator buildPatch = patchList.begin(); buildPatch != patchList.end(); buildPatch++ ) - ( *buildPatch )->BuildInRadiant( node.get_pointer() ); + for (std::list::const_iterator buildPatch = patchList.begin(); + buildPatch != patchList.end(); buildPatch++) { + (*buildPatch)->BuildInRadiant(node.get_pointer()); + } - QER_Entity = node.get_pointer(); - } - else - { - for ( std::list::const_iterator buildBrush = brushList.begin(); buildBrush != brushList.end(); buildBrush++ ) - ( *buildBrush )->BuildInRadiant( allowDestruction, NULL ); + QER_Entity = node.get_pointer(); + } else { + for (std::list::const_iterator buildBrush = brushList.begin(); + buildBrush != brushList.end(); buildBrush++) { + (*buildBrush)->BuildInRadiant(allowDestruction, NULL); + } - for ( std::list::const_iterator buildPatch = patchList.begin(); buildPatch != patchList.end(); buildPatch++ ) - ( *buildPatch )->BuildInRadiant(); - } + for (std::list::const_iterator buildPatch = patchList.begin(); + buildPatch != patchList.end(); buildPatch++) { + (*buildPatch)->BuildInRadiant(); + } + } } +int DEntity::GetIDMax(void) +{ + int max = -1; + for (std::list::const_iterator cntBrush = brushList.begin(); cntBrush != brushList.end(); cntBrush++) { + if ((*cntBrush)->m_nBrushID > max) { + max = (*cntBrush)->m_nBrushID; + } + } + return max + 1; +} -int DEntity::GetIDMax( void ) { - int max = -1; - for ( std::list::const_iterator cntBrush = brushList.begin(); cntBrush != brushList.end(); cntBrush++ ) { - if ( ( *cntBrush )->m_nBrushID > max ) { - max = ( *cntBrush )->m_nBrushID; - } - } - return max + 1; +void DEntity::SetClassname(const char *classname) +{ + m_Classname = classname; } -void DEntity::SetClassname( const char *classname ) { - m_Classname = classname; +void DEntity::SaveToFile(FILE *pFile) +{ + fprintf(pFile, "{\n"); + + fprintf(pFile, "\"classname\" \"%s\"\n", (const char *) m_Classname); + + for (std::list::const_iterator ep = epairList.begin(); ep != epairList.end(); ep++) { + fprintf(pFile, "\"%s\" \"%s\"\n", (const char *) (*ep)->key, (const char *) (*ep)->value); + } + + for (std::list::const_iterator bp = brushList.begin(); bp != brushList.end(); bp++) { + (*bp)->SaveToFile(pFile); + } + + fprintf(pFile, "}\n"); } -void DEntity::SaveToFile( FILE *pFile ){ - fprintf( pFile, "{\n" ); +void DEntity::ClearEPairs() +{ + for (std::list::const_iterator deadEPair = epairList.begin(); deadEPair != epairList.end(); deadEPair++) { + delete (*deadEPair); + } + epairList.clear(); +} - fprintf( pFile, "\"classname\" \"%s\"\n", (const char *)m_Classname ); +void DEntity::AddEPair(const char *key, const char *value) +{ + DEPair *newEPair; + newEPair = FindEPairByKey(key); + if (!newEPair) { + newEPair = new DEPair; + newEPair->Build(key, value); + epairList.push_back(newEPair); + } else { + newEPair->Build(key, value); + } +} + +void DEntity::LoadEPairList(Entity *epl) +{ + class load_epairs_t : public Entity::Visitor { + DEntity *m_entity; + public: + load_epairs_t(DEntity *entity) + : m_entity(entity) + { + } + + void visit(const char *key, const char *value) + { + if (strcmp(key, "classname") == 0) { + m_entity->SetClassname(value); + } else { + m_entity->AddEPair(key, value); + } + } + + } load_epairs(this); + + epl->forEachKeyValue(load_epairs); +} + +bool DEntity::ResetTextures(const char *textureName, float fScale[2], float fShift[2], int rotation, + const char *newTextureName, + int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation, + bool rebuild) +{ + bool reset = false; + + for (std::list::const_iterator resetBrush = brushList.begin(); + resetBrush != brushList.end(); resetBrush++) { + bool tmp = (*resetBrush)->ResetTextures(textureName, fScale, fShift, rotation, newTextureName, + bResetTextureName, bResetScale, bResetShift, bResetRotation); + + if (tmp) { + reset = true; + if (rebuild) { + Node_getTraversable(*(*resetBrush)->QER_entity)->erase(*(*resetBrush)->QER_brush); + (*resetBrush)->BuildInRadiant(false, NULL, (*resetBrush)->QER_entity); + } + } + } + + if (bResetTextureName) { + for (std::list::const_iterator resetPatch = patchList.begin(); + resetPatch != patchList.end(); resetPatch++) { + bool tmp = (*resetPatch)->ResetTextures(textureName, newTextureName); + + if (tmp) { + reset = true; + if (rebuild) { + Node_getTraversable(*(*resetPatch)->QER_entity)->erase(*(*resetPatch)->QER_brush); + (*resetPatch)->BuildInRadiant((*resetPatch)->QER_entity); + } + } + } + } + + return reset; +} + +DEPair *DEntity::FindEPairByKey(const char *keyname) +{ + for (std::list::const_iterator ep = epairList.begin(); ep != epairList.end(); ep++) { + char *c = (*ep)->key; + if (!strcmp(c, keyname)) { + return *ep; + } + } + return NULL; +} + +void DEntity::RemoveFromRadiant() +{ + Node_getTraversable(GlobalSceneGraph().root())->erase(*QER_Entity); + + QER_Entity = NULL; +} - for ( std::list::const_iterator ep = epairList.begin(); ep != epairList.end(); ep++ ) - { - fprintf( pFile, "\"%s\" \"%s\"\n", (const char *)( *ep )->key, (const char *)( *ep )->value ); - } +void DEntity::SpawnString(const char *key, const char *defaultstring, const char **out) +{ + DEPair *pEP = FindEPairByKey(key); + if (pEP) { + *out = pEP->value; + } else { + *out = defaultstring; + } +} - for ( std::list::const_iterator bp = brushList.begin(); bp != brushList.end(); bp++ ) - { - ( *bp )->SaveToFile( pFile ); - } +void DEntity::SpawnInt(const char *key, const char *defaultstring, int *out) +{ + DEPair *pEP = FindEPairByKey(key); + if (pEP) { + *out = atoi(pEP->value); + } else { + *out = atoi(defaultstring); + } +} - fprintf( pFile, "}\n" ); +void DEntity::SpawnFloat(const char *key, const char *defaultstring, float *out) +{ + DEPair *pEP = FindEPairByKey(key); + if (pEP) { + *out = static_cast( atof(pEP->value)); + } else { + *out = static_cast( atof(defaultstring)); + } } -void DEntity::ClearEPairs(){ - for ( std::list::const_iterator deadEPair = epairList.begin(); deadEPair != epairList.end(); deadEPair++ ) - { - delete ( *deadEPair ); - } - epairList.clear(); +void DEntity::SpawnVector(const char *key, const char *defaultstring, vec_t *out) +{ + DEPair *pEP = FindEPairByKey(key); + if (pEP) { + sscanf(pEP->value, "%f %f %f", &out[0], &out[1], &out[2]); + } else { + sscanf(defaultstring, "%f %f %f", &out[0], &out[1], &out[2]); + } } -void DEntity::AddEPair( const char *key, const char *value ) { - DEPair* newEPair; - newEPair = FindEPairByKey( key ); - if ( !newEPair ) { - newEPair = new DEPair; - newEPair->Build( key, value ); - epairList.push_back( newEPair ); - } - else { - newEPair->Build( key, value ); - } +int DEntity::GetBrushCount(void) +{ + return static_cast( brushList.size()); } -void DEntity::LoadEPairList( Entity *epl ){ - class load_epairs_t : public Entity::Visitor - { - DEntity* m_entity; -public: - load_epairs_t( DEntity* entity ) - : m_entity( entity ){ - } - void visit( const char* key, const char* value ){ - if ( strcmp( key, "classname" ) == 0 ) { - m_entity->SetClassname( value ); - } - else{ - m_entity->AddEPair( key, value ); - } - } - - } load_epairs( this ); - - epl->forEachKeyValue( load_epairs ); -} - -bool DEntity::ResetTextures( const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, - int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation, bool rebuild ){ - bool reset = false; - - for ( std::list::const_iterator resetBrush = brushList.begin(); resetBrush != brushList.end(); resetBrush++ ) - { - bool tmp = ( *resetBrush )->ResetTextures( textureName, fScale, fShift, rotation, newTextureName, - bResetTextureName, bResetScale, bResetShift, bResetRotation ); - - if ( tmp ) { - reset = true; - if ( rebuild ) { - Node_getTraversable( *( *resetBrush )->QER_entity )->erase( *( *resetBrush )->QER_brush ); - ( *resetBrush )->BuildInRadiant( false, NULL, ( *resetBrush )->QER_entity ); - } - } - } - - if ( bResetTextureName ) { - for ( std::list::const_iterator resetPatch = patchList.begin(); resetPatch != patchList.end(); resetPatch++ ) - { - bool tmp = ( *resetPatch )->ResetTextures( textureName, newTextureName ); - - if ( tmp ) { - reset = true; - if ( rebuild ) { - Node_getTraversable( *( *resetPatch )->QER_entity )->erase( *( *resetPatch )->QER_brush ); - ( *resetPatch )->BuildInRadiant( ( *resetPatch )->QER_entity ); - } - } - } - } - - return reset; -} - -DEPair* DEntity::FindEPairByKey( const char* keyname ){ - for ( std::list::const_iterator ep = epairList.begin(); ep != epairList.end(); ep++ ) - { - char* c = ( *ep )->key; - if ( !strcmp( c, keyname ) ) { - return *ep; - } - } - return NULL; -} - -void DEntity::RemoveFromRadiant(){ - Node_getTraversable( GlobalSceneGraph().root() )->erase( *QER_Entity ); - - QER_Entity = NULL; -} - -void DEntity::SpawnString( const char* key, const char* defaultstring, const char** out ){ - DEPair* pEP = FindEPairByKey( key ); - if ( pEP ) { - *out = pEP->value; - } - else { - *out = defaultstring; - } -} - -void DEntity::SpawnInt( const char* key, const char* defaultstring, int* out ){ - DEPair* pEP = FindEPairByKey( key ); - if ( pEP ) { - *out = atoi( pEP->value ); - } - else { - *out = atoi( defaultstring ); - } -} - -void DEntity::SpawnFloat( const char* key, const char* defaultstring, float* out ){ - DEPair* pEP = FindEPairByKey( key ); - if ( pEP ) { - *out = static_cast( atof( pEP->value ) ); - } - else { - *out = static_cast( atof( defaultstring ) ); - } -} - -void DEntity::SpawnVector( const char* key, const char* defaultstring, vec_t* out ){ - DEPair* pEP = FindEPairByKey( key ); - if ( pEP ) { - sscanf( pEP->value, "%f %f %f", &out[0], &out[1], &out[2] ); - } - else { - sscanf( defaultstring, "%f %f %f", &out[0], &out[1], &out[2] ); - } -} - -int DEntity::GetBrushCount( void ) { - return static_cast( brushList.size() ); -} - -DBrush* DEntity::FindBrushByPointer( scene::Node& brush ) { - for ( std::list::const_iterator listBrush = brushList.begin(); listBrush != brushList.end(); listBrush++ ) { - DBrush* pBrush = ( *listBrush ); - if ( pBrush->QER_brush == &brush ) { - return pBrush; - } - } - return NULL; +DBrush *DEntity::FindBrushByPointer(scene::Node &brush) +{ + for (std::list::const_iterator listBrush = brushList.begin(); listBrush != brushList.end(); listBrush++) { + DBrush *pBrush = (*listBrush); + if (pBrush->QER_brush == &brush) { + return pBrush; + } + } + return NULL; } diff --git a/contrib/bobtoolz/DEntity.h b/contrib/bobtoolz/DEntity.h index 415442a2..1eb3fec2 100644 --- a/contrib/bobtoolz/DEntity.h +++ b/contrib/bobtoolz/DEntity.h @@ -33,93 +33,117 @@ #include "mathlib.h" class DEPair; + class DBrush; + class DPlane; + class DPatch; + class Entity; -namespace scene -{ -class Node; +namespace scene { + class Node; } class _QERFaceData; -class DEntity -{ +class DEntity { public: -void RemoveFromRadiant(); -scene::Node* QER_Entity; -int m_nID; + void RemoveFromRadiant(); + + scene::Node *QER_Entity; + int m_nID; // Constrcution/Destruction -DEntity( const char* classname = "worldspawn", int ID = -1 ); // sets classname -virtual ~DEntity(); + DEntity(const char *classname = "worldspawn", int ID = -1); // sets classname + virtual ~DEntity(); // --------------------------------------------- // epair functions........ -void LoadEPairList( Entity* epl ); -void AddEPair( const char* key, const char* value ); -void ClearEPairs(); -DEPair* FindEPairByKey( const char* keyname ); + void LoadEPairList(Entity *epl); + + void AddEPair(const char *key, const char *value); + + void ClearEPairs(); + + DEPair *FindEPairByKey(const char *keyname); // --------------------------------------------- // random functions........ -bool ResetTextures( const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation, bool rebuild ); -void SaveToFile( FILE* pFile ); -void SetClassname( const char* classname ); -int GetIDMax(); - -void BuildInRadiant( bool allowDestruction ); -void ResetChecks( std::list* exclusionList ); -void RemoveNonCheckBrushes( std::list* exclusionList, bool useDetail ); - -DPlane* AddFaceToBrush( vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* faceData, int ID ); // slow, try not to use much -int GetBrushCount( void ); -DBrush* FindBrushByPointer( scene::Node& brush ); + bool + ResetTextures(const char *textureName, float fScale[2], float fShift[2], int rotation, const char *newTextureName, + int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation, bool rebuild); + + void SaveToFile(FILE *pFile); + + void SetClassname(const char *classname); + + int GetIDMax(); + + void BuildInRadiant(bool allowDestruction); + + void ResetChecks(std::list *exclusionList); + + void RemoveNonCheckBrushes(std::list *exclusionList, bool useDetail); + + DPlane * + AddFaceToBrush(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData *faceData, int ID); // slow, try not to use much + int GetBrushCount(void); + + DBrush *FindBrushByPointer(scene::Node &brush); // --------------------------------------------- // bool list functions -void SelectBrushes( bool* selectList ); -bool* BuildDuplicateList(); -bool* BuildIntersectList(); + void SelectBrushes(bool *selectList); + + bool *BuildDuplicateList(); + + bool *BuildIntersectList(); // --------------------------------------------- // brush operations -void ClearBrushes(); // clears brush list and frees memory for brushes + void ClearBrushes(); // clears brush list and frees memory for brushes + + DBrush *GetBrushForID(int ID); -DBrush* GetBrushForID( int ID ); -DBrush* NewBrush( int ID = -1 ); + DBrush *NewBrush(int ID = -1); // --------------------------------------------- // patch operations -void ClearPatches(); + void ClearPatches(); -DPatch* NewPatch(); + DPatch *NewPatch(); // --------------------------------------------- // vars -std::list epairList; -std::list brushList; + std::list epairList; + std::list brushList; // new patches, wahey!!! -std::list patchList; -Str m_Classname; + std::list patchList; + Str m_Classname; // --------------------------------------------- -int FixBrushes(); + int FixBrushes(); -bool LoadFromEntity( scene::Node& ent, bool bLoadPatches = false ); -void LoadSelectedBrushes(); -void LoadSelectedPatches(); + bool LoadFromEntity(scene::Node &ent, bool bLoadPatches = false); + + void LoadSelectedBrushes(); + + void LoadSelectedPatches(); + + bool LoadFromPrt(char *filename); -bool LoadFromPrt( char* filename ); // --------------------------------------------- -void SpawnString( const char* key, const char* defaultstring, const char** out ); -void SpawnInt( const char* key, const char* defaultstring, int* out ); -void SpawnFloat( const char* key, const char* defaultstring, float* out ); -void SpawnVector( const char* key, const char* defaultstring, vec_t* out ); + void SpawnString(const char *key, const char *defaultstring, const char **out); + + void SpawnInt(const char *key, const char *defaultstring, int *out); + + void SpawnFloat(const char *key, const char *defaultstring, float *out); + + void SpawnVector(const char *key, const char *defaultstring, vec_t *out); }; #endif // !defined(AFX_DENTITY_H__35B2C523_F0A7_11D4_ACF7_004095A18133__INCLUDED_) diff --git a/contrib/bobtoolz/DMap.cpp b/contrib/bobtoolz/DMap.cpp index 18edc3b1..13898c8f 100644 --- a/contrib/bobtoolz/DMap.cpp +++ b/contrib/bobtoolz/DMap.cpp @@ -49,120 +49,135 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DMap::DMap(){ - m_nNextEntity = 1; - AddEntity( "worldspawn", 0 ); +DMap::DMap() +{ + m_nNextEntity = 1; + AddEntity("worldspawn", 0); } -DMap::~DMap(){ - ClearEntities(); +DMap::~DMap() +{ + ClearEntities(); } -DEntity* DMap::AddEntity( const char *classname, int ID ){ - DEntity* newEntity; - if ( ID == -1 ) { - newEntity = new DEntity( classname, m_nNextEntity++ ); - } - else{ - newEntity = new DEntity( classname, ID ); - } +DEntity *DMap::AddEntity(const char *classname, int ID) +{ + DEntity *newEntity; + if (ID == -1) { + newEntity = new DEntity(classname, m_nNextEntity++); + } else { + newEntity = new DEntity(classname, ID); + } - entityList.push_back( newEntity ); + entityList.push_back(newEntity); - return newEntity; + return newEntity; } -void DMap::ClearEntities(){ - m_nNextEntity = 1; +void DMap::ClearEntities() +{ + m_nNextEntity = 1; - for ( std::list::const_iterator deadEntity = entityList.begin(); deadEntity != entityList.end(); deadEntity++ ) - delete *deadEntity; + for (std::list::const_iterator deadEntity = entityList.begin(); + deadEntity != entityList.end(); deadEntity++) { + delete *deadEntity; + } - entityList.clear(); + entityList.clear(); } -DEntity* DMap::GetEntityForID( int ID ){ - DEntity* findEntity = NULL; +DEntity *DMap::GetEntityForID(int ID) +{ + DEntity *findEntity = NULL; - for ( std::list::const_iterator chkEntity = entityList.begin(); chkEntity != entityList.end(); chkEntity++ ) - { - if ( ( *chkEntity )->m_nID == ID ) { - findEntity = ( *chkEntity ); - break; - } - } + for (std::list::const_iterator chkEntity = entityList.begin(); + chkEntity != entityList.end(); chkEntity++) { + if ((*chkEntity)->m_nID == ID) { + findEntity = (*chkEntity); + break; + } + } - if ( !findEntity ) { - findEntity = AddEntity( "worldspawn", ID ); - } + if (!findEntity) { + findEntity = AddEntity("worldspawn", ID); + } - return findEntity; + return findEntity; } -DEntity* DMap::GetWorldSpawn(){ - return GetEntityForID( 0 ); +DEntity *DMap::GetWorldSpawn() +{ + return GetEntityForID(0); } -void DMap::BuildInRadiant( bool bAllowDestruction ){ - for ( std::list::const_iterator buildEntity = entityList.begin(); buildEntity != entityList.end(); buildEntity++ ) - ( *buildEntity )->BuildInRadiant( bAllowDestruction ); +void DMap::BuildInRadiant(bool bAllowDestruction) +{ + for (std::list::const_iterator buildEntity = entityList.begin(); + buildEntity != entityList.end(); buildEntity++) { + (*buildEntity)->BuildInRadiant(bAllowDestruction); + } } -void DMap::LoadAll( bool bLoadPatches ){ - ClearEntities(); - - GlobalSelectionSystem().setSelectedAll( false ); - - class load_entities_t : public scene::Traversable::Walker - { - DMap* m_map; - bool m_bLoadPatches; -public: - load_entities_t( DMap* map, bool bLoadPatches ) - : m_map( map ), m_bLoadPatches( bLoadPatches ){ - } - bool pre( scene::Node& node ) const { - if ( Node_isEntity( node ) ) { - DEntity* loadEntity = m_map->AddEntity( "", 0 ); - loadEntity->LoadFromEntity( node, m_bLoadPatches ); - } - return false; - } - } load_entities( this, bLoadPatches ); - - Node_getTraversable( GlobalSceneGraph().root() )->traverse( load_entities ); +void DMap::LoadAll(bool bLoadPatches) +{ + ClearEntities(); + + GlobalSelectionSystem().setSelectedAll(false); + + class load_entities_t : public scene::Traversable::Walker { + DMap *m_map; + bool m_bLoadPatches; + public: + load_entities_t(DMap *map, bool bLoadPatches) + : m_map(map), m_bLoadPatches(bLoadPatches) + { + } + + bool pre(scene::Node &node) const + { + if (Node_isEntity(node)) { + DEntity *loadEntity = m_map->AddEntity("", 0); + loadEntity->LoadFromEntity(node, m_bLoadPatches); + } + return false; + } + } load_entities(this, bLoadPatches); + + Node_getTraversable(GlobalSceneGraph().root())->traverse(load_entities); } -int DMap::FixBrushes(){ - int count = 0; - for ( std::list::const_iterator fixEntity = entityList.begin(); fixEntity != entityList.end(); fixEntity++ ) - { - count += ( *fixEntity )->FixBrushes(); - } +int DMap::FixBrushes() +{ + int count = 0; + for (std::list::const_iterator fixEntity = entityList.begin(); + fixEntity != entityList.end(); fixEntity++) { + count += (*fixEntity)->FixBrushes(); + } - return count; + return count; } -void DMap::ResetTextures( const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, - int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation ){ - for ( std::list::const_iterator texEntity = entityList.begin(); texEntity != entityList.end(); texEntity++ ) - { - if ( string_equal_nocase( "worldspawn", ( *texEntity )->m_Classname ) ) { - ( *texEntity )->ResetTextures( textureName, fScale, fShift, rotation, newTextureName, - bResetTextureName, bResetScale, bResetShift, bResetRotation, true ); - } - else - { - if ( ( *texEntity )->ResetTextures( textureName, fScale, fShift, rotation, newTextureName, - bResetTextureName, bResetScale, bResetShift, bResetRotation, false ) ) { - RebuildEntity( *texEntity ); - } - } - } +void +DMap::ResetTextures(const char *textureName, float fScale[2], float fShift[2], int rotation, const char *newTextureName, + int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation) +{ + for (std::list::const_iterator texEntity = entityList.begin(); + texEntity != entityList.end(); texEntity++) { + if (string_equal_nocase("worldspawn", (*texEntity)->m_Classname)) { + (*texEntity)->ResetTextures(textureName, fScale, fShift, rotation, newTextureName, + bResetTextureName, bResetScale, bResetShift, bResetRotation, true); + } else { + if ((*texEntity)->ResetTextures(textureName, fScale, fShift, rotation, newTextureName, + bResetTextureName, bResetScale, bResetShift, bResetRotation, false)) { + RebuildEntity(*texEntity); + } + } + } } -void DMap::RebuildEntity( DEntity *ent ){ - ent->RemoveFromRadiant(); - ent->BuildInRadiant( false ); +void DMap::RebuildEntity(DEntity *ent) +{ + ent->RemoveFromRadiant(); + ent->BuildInRadiant(false); } diff --git a/contrib/bobtoolz/DMap.h b/contrib/bobtoolz/DMap.h index f527d04d..99590347 100644 --- a/contrib/bobtoolz/DMap.h +++ b/contrib/bobtoolz/DMap.h @@ -32,27 +32,35 @@ class DEntity; -class DMap -{ +class DMap { public: -static void RebuildEntity( DEntity* ent ); + static void RebuildEntity(DEntity *ent); -void ResetTextures( const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation ); -void LoadAll( bool bLoadPatches = false ); -void BuildInRadiant( bool bAllowDestruction ); -int m_nNextEntity; -DEntity* GetWorldSpawn(); -void ClearEntities(); + void + ResetTextures(const char *textureName, float fScale[2], float fShift[2], int rotation, const char *newTextureName, + int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation); -DEntity* GetEntityForID( int ID ); -DEntity* AddEntity( const char* classname = "worldspawn", int ID = -1 ); + void LoadAll(bool bLoadPatches = false); -std::list entityList; + void BuildInRadiant(bool bAllowDestruction); -DMap(); -virtual ~DMap(); + int m_nNextEntity; -int FixBrushes(); + DEntity *GetWorldSpawn(); + + void ClearEntities(); + + DEntity *GetEntityForID(int ID); + + DEntity *AddEntity(const char *classname = "worldspawn", int ID = -1); + + std::list entityList; + + DMap(); + + virtual ~DMap(); + + int FixBrushes(); }; #endif // !defined(AFX_DMAP_H__ACAE597A_D26D_49AD_AA69_EDE743DB54FA__INCLUDED_) diff --git a/contrib/bobtoolz/DPatch.cpp b/contrib/bobtoolz/DPatch.cpp index be49df4e..5c806f8d 100644 --- a/contrib/bobtoolz/DPatch.cpp +++ b/contrib/bobtoolz/DPatch.cpp @@ -42,69 +42,72 @@ // problem is, you cant put patches into entities as yet :( // -DPatch::DPatch(){ - width = MIN_PATCH_WIDTH; - height = MIN_PATCH_HEIGHT; - QER_entity = NULL; - QER_brush = NULL; +DPatch::DPatch() +{ + width = MIN_PATCH_WIDTH; + height = MIN_PATCH_HEIGHT; + QER_entity = NULL; + QER_brush = NULL; } -DPatch::~DPatch(){ +DPatch::~DPatch() +{ } -void DPatch::SetTexture( const char *textureName ){ - strcpy( texture, textureName ); +void DPatch::SetTexture(const char *textureName) +{ + strcpy(texture, textureName); } -void CopyDrawVert( const drawVert_t* in, drawVert_t* out ){ - out->lightmap[0] = in->lightmap[0]; - out->lightmap[1] = in->lightmap[1]; - out->st[0] = in->st[0]; - out->st[1] = in->st[1]; - VectorCopy( in->normal, out->normal ); - VectorCopy( in->xyz, out->xyz ); +void CopyDrawVert(const drawVert_t *in, drawVert_t *out) +{ + out->lightmap[0] = in->lightmap[0]; + out->lightmap[1] = in->lightmap[1]; + out->st[0] = in->st[0]; + out->st[1] = in->st[1]; + VectorCopy(in->normal, out->normal); + VectorCopy(in->xyz, out->xyz); } -void DPatch::BuildInRadiant( scene::Node* entity ){ - NodeSmartReference patch( GlobalPatchCreator().createPatch() ); - - scene::Node& parent = entity != 0 ? *entity : GlobalRadiant().getMapWorldEntity(); - Node_getTraversable( parent )->insert( patch ); - - GlobalPatchCreator().Patch_setShader( patch, texture ); - GlobalPatchCreator().Patch_resize( patch, height, width ); - PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints( patch ); - for ( int x = 0; x < width; x++ ) - { - for ( int y = 0; y < height; y++ ) - { - PatchControl& p = matrix( x, y ); - p.m_vertex[0] = points[x][y].xyz[0]; - p.m_vertex[1] = points[x][y].xyz[1]; - p.m_vertex[2] = points[x][y].xyz[2]; - p.m_texcoord[0] = points[x][y].st[0]; - p.m_texcoord[1] = points[x][y].st[1]; - } - } - GlobalPatchCreator().Patch_controlPointsChanged( patch ); - - QER_entity = entity; - QER_brush = patch.get_pointer(); +void DPatch::BuildInRadiant(scene::Node *entity) +{ + NodeSmartReference patch(GlobalPatchCreator().createPatch()); + + scene::Node &parent = entity != 0 ? *entity : GlobalRadiant().getMapWorldEntity(); + Node_getTraversable(parent)->insert(patch); + + GlobalPatchCreator().Patch_setShader(patch, texture); + GlobalPatchCreator().Patch_resize(patch, height, width); + PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + PatchControl &p = matrix(x, y); + p.m_vertex[0] = points[x][y].xyz[0]; + p.m_vertex[1] = points[x][y].xyz[1]; + p.m_vertex[2] = points[x][y].xyz[2]; + p.m_texcoord[0] = points[x][y].st[0]; + p.m_texcoord[1] = points[x][y].st[1]; + } + } + GlobalPatchCreator().Patch_controlPointsChanged(patch); + + QER_entity = entity; + QER_brush = patch.get_pointer(); #if 0 - int nIndex = g_FuncTable.m_pfnCreatePatchHandle(); - //$ FIXME: m_pfnGetPatchHandle - patchMesh_t* pm = g_FuncTable.m_pfnGetPatchData( nIndex ); + int nIndex = g_FuncTable.m_pfnCreatePatchHandle(); + //$ FIXME: m_pfnGetPatchHandle + patchMesh_t* pm = g_FuncTable.m_pfnGetPatchData( nIndex ); - b->patchBrush = true; - b->pPatch = Patch_Alloc(); - b->pPatch->setDims( width,height ); + b->patchBrush = true; + b->pPatch = Patch_Alloc(); + b->pPatch->setDims( width,height ); - for ( int x = 0; x < width; x++ ) - for ( int y = 0; y < height; y++ ) - CopyDrawVert( &points[x][y], &pm->ctrl[x][y] ); + for ( int x = 0; x < width; x++ ) + for ( int y = 0; y < height; y++ ) + CopyDrawVert( &points[x][y], &pm->ctrl[x][y] ); /* if(entity) { @@ -124,216 +127,218 @@ void DPatch::BuildInRadiant( scene::Node* entity ){ } else*/ // patch to entity just plain dont work atm - if ( entity ) { - g_FuncTable.m_pfnCommitPatchHandleToEntity( nIndex, pm, texture, entity ); - } - else{ - g_FuncTable.m_pfnCommitPatchHandleToMap( nIndex, pm, texture ); - } + if ( entity ) { + g_FuncTable.m_pfnCommitPatchHandleToEntity( nIndex, pm, texture, entity ); + } + else{ + g_FuncTable.m_pfnCommitPatchHandleToMap( nIndex, pm, texture ); + } - QER_brush = pm->pSymbiot; + QER_brush = pm->pSymbiot; #endif } -void DPatch::LoadFromPatch( scene::Instance& patch ){ - QER_entity = patch.path().parent().get_pointer(); - QER_brush = patch.path().top().get_pointer(); - - PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints( patch.path().top() ); - - width = static_cast( matrix.x() ); - height = static_cast( matrix.y() ); - - for ( int x = 0; x < width; x++ ) - { - for ( int y = 0; y < height; y++ ) - { - PatchControl& p = matrix( x, y ); - points[x][y].xyz[0] = p.m_vertex[0]; - points[x][y].xyz[1] = p.m_vertex[1]; - points[x][y].xyz[2] = p.m_vertex[2]; - points[x][y].st[0] = p.m_texcoord[0]; - points[x][y].st[1] = p.m_texcoord[1]; - } - } - SetTexture( GlobalPatchCreator().Patch_getShader( patch.path().top() ) ); +void DPatch::LoadFromPatch(scene::Instance &patch) +{ + QER_entity = patch.path().parent().get_pointer(); + QER_brush = patch.path().top().get_pointer(); + + PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch.path().top()); + + width = static_cast( matrix.x()); + height = static_cast( matrix.y()); + + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + PatchControl &p = matrix(x, y); + points[x][y].xyz[0] = p.m_vertex[0]; + points[x][y].xyz[1] = p.m_vertex[1]; + points[x][y].xyz[2] = p.m_vertex[2]; + points[x][y].st[0] = p.m_texcoord[0]; + points[x][y].st[1] = p.m_texcoord[1]; + } + } + SetTexture(GlobalPatchCreator().Patch_getShader(patch.path().top())); #if 0 - SetTexture( brush->pPatch->GetShader() ); - - width = brush->pPatch->getWidth(); - height = brush->pPatch->getHeight(); - - for ( int x = 0; x < height; x++ ) - { - for ( int y = 0; y < width; y++ ) - { - float *p = brush->pPatch->ctrlAt( ROW,x,y ); - p[0] = points[x][y].xyz[0]; - p[1] = points[x][y].xyz[1]; - p[2] = points[x][y].xyz[2]; - p[3] = points[x][y].st[0]; - p[4] = points[x][y].st[1]; - } - } + SetTexture( brush->pPatch->GetShader() ); + + width = brush->pPatch->getWidth(); + height = brush->pPatch->getHeight(); + + for ( int x = 0; x < height; x++ ) + { + for ( int y = 0; y < width; y++ ) + { + float *p = brush->pPatch->ctrlAt( ROW,x,y ); + p[0] = points[x][y].xyz[0]; + p[1] = points[x][y].xyz[1]; + p[2] = points[x][y].xyz[2]; + p[3] = points[x][y].st[0]; + p[4] = points[x][y].st[1]; + } + } #endif } -bool DPatch::ResetTextures( const char *oldTextureName, const char *newTextureName ){ - if ( !oldTextureName || !strcmp( texture, oldTextureName ) ) { - strcpy( texture, newTextureName ); - return true; - } +bool DPatch::ResetTextures(const char *oldTextureName, const char *newTextureName) +{ + if (!oldTextureName || !strcmp(texture, oldTextureName)) { + strcpy(texture, newTextureName); + return true; + } - return false; + return false; } -void Build1dArray( vec3_t* array, drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT], - int startX, int startY, int number, bool horizontal, bool inverse ){ - int x = startX, y = startY, i, step; - - if ( inverse ) { - step = -1; - } - else{ - step = 1; - } - - for ( i = 0; i < number; i++ ) - { - VectorCopy( points[x][y].xyz, array[i] ); - - if ( horizontal ) { - x += step; - } - else{ - y += step; - } - } +void Build1dArray(vec3_t *array, drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT], + int startX, int startY, int number, bool horizontal, bool inverse) +{ + int x = startX, y = startY, i, step; + + if (inverse) { + step = -1; + } else { + step = 1; + } + + for (i = 0; i < number; i++) { + VectorCopy(points[x][y].xyz, array[i]); + + if (horizontal) { + x += step; + } else { + y += step; + } + } } -void Print1dArray( vec3_t* array, int size ){ - for ( int i = 0; i < size; i++ ) - globalOutputStream() << "(" << array[i][0] << " " << array[i][1] << " " << array[i][2] << ")\t"; - globalOutputStream() << "\n"; +void Print1dArray(vec3_t *array, int size) +{ + for (int i = 0; i < size; i++) { + globalOutputStream() << "(" << array[i][0] << " " << array[i][1] << " " << array[i][2] << ")\t"; + } + globalOutputStream() << "\n"; } -bool Compare1dArrays( vec3_t* a1, vec3_t* a2, int size ){ - int i; - bool equal = true; - - for ( i = 0; i < size; i++ ) - { - if ( !VectorCompare( a1[i], a2[size - i - 1] ) ) { - equal = false; - break; - } - } - return equal; +bool Compare1dArrays(vec3_t *a1, vec3_t *a2, int size) +{ + int i; + bool equal = true; + + for (i = 0; i < size; i++) { + if (!VectorCompare(a1[i], a2[size - i - 1])) { + equal = false; + break; + } + } + return equal; } -patch_merge_t DPatch::IsMergable( DPatch *other ){ - int i, j; - vec3_t p1Array[4][MAX_PATCH_HEIGHT]; - vec3_t p2Array[4][MAX_PATCH_HEIGHT]; - - int p1ArraySizes[4]; - int p2ArraySizes[4]; - - patch_merge_t merge_info; - - Build1dArray( p1Array[0], this->points, 0, 0, this->width, true, false ); - Build1dArray( p1Array[1], this->points, this->width - 1, 0, this->height, false, false ); - Build1dArray( p1Array[2], this->points, this->width - 1, this->height - 1, this->width, true, true ); - Build1dArray( p1Array[3], this->points, 0, this->height - 1, this->height, false, true ); - - Build1dArray( p2Array[0], other->points, 0, 0, other->width, true, false ); - Build1dArray( p2Array[1], other->points, other->width - 1, 0, other->height, false, false ); - Build1dArray( p2Array[2], other->points, other->width - 1, other->height - 1, other->width, true, true ); - Build1dArray( p2Array[3], other->points, 0, other->height - 1, other->height, false, true ); - - p1ArraySizes[0] = this->width; - p1ArraySizes[1] = this->height; - p1ArraySizes[2] = this->width; - p1ArraySizes[3] = this->height; - - p2ArraySizes[0] = other->width; - p2ArraySizes[1] = other->height; - p2ArraySizes[2] = other->width; - p2ArraySizes[3] = other->height; - - for ( i = 0; i < 4; i++ ) - { - for ( j = 0; j < 4; j++ ) - { - if ( p1ArraySizes[i] == p2ArraySizes[j] ) { - if ( Compare1dArrays( p1Array[i], p2Array[j], p1ArraySizes[i] ) ) { - merge_info.pos1 = i; - merge_info.pos2 = j; - merge_info.mergable = true; - return merge_info; - } - } - } - } - - merge_info.mergable = false; - return merge_info; +patch_merge_t DPatch::IsMergable(DPatch *other) +{ + int i, j; + vec3_t p1Array[4][MAX_PATCH_HEIGHT]; + vec3_t p2Array[4][MAX_PATCH_HEIGHT]; + + int p1ArraySizes[4]; + int p2ArraySizes[4]; + + patch_merge_t merge_info; + + Build1dArray(p1Array[0], this->points, 0, 0, this->width, true, false); + Build1dArray(p1Array[1], this->points, this->width - 1, 0, this->height, false, false); + Build1dArray(p1Array[2], this->points, this->width - 1, this->height - 1, this->width, true, true); + Build1dArray(p1Array[3], this->points, 0, this->height - 1, this->height, false, true); + + Build1dArray(p2Array[0], other->points, 0, 0, other->width, true, false); + Build1dArray(p2Array[1], other->points, other->width - 1, 0, other->height, false, false); + Build1dArray(p2Array[2], other->points, other->width - 1, other->height - 1, other->width, true, true); + Build1dArray(p2Array[3], other->points, 0, other->height - 1, other->height, false, true); + + p1ArraySizes[0] = this->width; + p1ArraySizes[1] = this->height; + p1ArraySizes[2] = this->width; + p1ArraySizes[3] = this->height; + + p2ArraySizes[0] = other->width; + p2ArraySizes[1] = other->height; + p2ArraySizes[2] = other->width; + p2ArraySizes[3] = other->height; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + if (p1ArraySizes[i] == p2ArraySizes[j]) { + if (Compare1dArrays(p1Array[i], p2Array[j], p1ArraySizes[i])) { + merge_info.pos1 = i; + merge_info.pos2 = j; + merge_info.mergable = true; + return merge_info; + } + } + } + } + + merge_info.mergable = false; + return merge_info; } -DPatch* DPatch::MergePatches( patch_merge_t merge_info, DPatch *p1, DPatch *p2 ){ - while ( merge_info.pos1 != 2 ) - { - p1->Transpose(); - merge_info.pos1--; - if ( merge_info.pos1 < 0 ) { - merge_info.pos1 += 4; - } - } - - while ( merge_info.pos2 != 0 ) - { - p2->Transpose(); - merge_info.pos2--; - if ( merge_info.pos2 < 0 ) { - merge_info.pos2 += 3; - } - } - - int newHeight = p1->height + p2->height - 1; - if ( newHeight > MAX_PATCH_HEIGHT ) { - return NULL; - } - - DPatch* newPatch = new DPatch(); - - newPatch->height = newHeight; - newPatch->width = p1->width; - newPatch->SetTexture( p1->texture ); - - for ( int y = 0; y < p1->height; y++ ) - for ( int x = 0; x < p1->width; x++ ) - newPatch->points[x][y] = p1->points[x][y]; - - for ( int y = 1; y < p2->height; y++ ) - for ( int x = 0; x < p2->width; x++ ) - newPatch->points[x][( y + p1->height - 1 )] = p2->points[x][y]; +DPatch *DPatch::MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2) +{ + while (merge_info.pos1 != 2) { + p1->Transpose(); + merge_info.pos1--; + if (merge_info.pos1 < 0) { + merge_info.pos1 += 4; + } + } + + while (merge_info.pos2 != 0) { + p2->Transpose(); + merge_info.pos2--; + if (merge_info.pos2 < 0) { + merge_info.pos2 += 3; + } + } + + int newHeight = p1->height + p2->height - 1; + if (newHeight > MAX_PATCH_HEIGHT) { + return NULL; + } + + DPatch *newPatch = new DPatch(); + + newPatch->height = newHeight; + newPatch->width = p1->width; + newPatch->SetTexture(p1->texture); + + for (int y = 0; y < p1->height; y++) { + for (int x = 0; x < p1->width; x++) { + newPatch->points[x][y] = p1->points[x][y]; + } + } + + for (int y = 1; y < p2->height; y++) { + for (int x = 0; x < p2->width; x++) { + newPatch->points[x][(y + p1->height - 1)] = p2->points[x][y]; + } + } // newPatch->Invert(); - return newPatch; + return newPatch; } -void DPatch::Invert(){ - int i, j; +void DPatch::Invert() +{ + int i, j; - for ( i = 0 ; i < width ; i++ ) - { - for ( j = 0; j < height / 2; j++ ) - { - std::swap( points[i][height - 1 - j], points[i][j] ); - } - } + for (i = 0; i < width; i++) { + for (j = 0; j < height / 2; j++) { + std::swap(points[i][height - 1 - j], points[i][j]); + } + } } + /* //Was used for debugging, obsolete function DPatch* DPatch::TransposePatch(DPatch *p1) @@ -374,140 +379,122 @@ void DPatch::Invert(){ } */ -void DPatch::Transpose(){ - int i, j, w; - - if ( width > height ) { - for ( i = 0 ; i < height ; i++ ) - { - for ( j = i + 1 ; j < width ; j++ ) - { - if ( j < height ) { - // swap the value - std::swap( points[j][i], points[i][j] ); - } - else - { - // just copy - points[i][j] = points[j][i]; - } - } - } - } - else - { - for ( i = 0 ; i < width ; i++ ) - { - for ( j = i + 1 ; j < height ; j++ ) - { - if ( j < width ) { - // swap the value - std::swap( points[i][j], points[j][i] ); - } - else - { - // just copy - points[j][i] = points[i][j]; - } - } - } - } - - w = width; - width = height; - height = w; - - Invert(); +void DPatch::Transpose() +{ + int i, j, w; + + if (width > height) { + for (i = 0; i < height; i++) { + for (j = i + 1; j < width; j++) { + if (j < height) { + // swap the value + std::swap(points[j][i], points[i][j]); + } else { + // just copy + points[i][j] = points[j][i]; + } + } + } + } else { + for (i = 0; i < width; i++) { + for (j = i + 1; j < height; j++) { + if (j < width) { + // swap the value + std::swap(points[i][j], points[j][i]); + } else { + // just copy + points[j][i] = points[i][j]; + } + } + } + } + + w = width; + width = height; + height = w; + + Invert(); } -std::list DPatch::SplitCols(){ - std::list patchList; - int i; - int x, y; - - if ( height >= 5 ) { - for ( i = 0; i < ( height - 1 ) / 2; i++ ) - { - DPatch p; - - p.width = width; - p.height = MIN_PATCH_HEIGHT; - p.SetTexture( texture ); - for ( x = 0; x < p.width; x++ ) - { - for ( y = 0; y < MIN_PATCH_HEIGHT; y++ ) - { - p.points[x][y] = points[x][( i * 2 ) + y]; - } - } - patchList.push_back( p ); - } - } - else { - //globalErrorStream() << "bobToolz SplitPatchRows: Patch has not enough rows for splitting.\n"; - patchList.push_back( *this ); - } - return patchList; +std::list DPatch::SplitCols() +{ + std::list patchList; + int i; + int x, y; + + if (height >= 5) { + for (i = 0; i < (height - 1) / 2; i++) { + DPatch p; + + p.width = width; + p.height = MIN_PATCH_HEIGHT; + p.SetTexture(texture); + for (x = 0; x < p.width; x++) { + for (y = 0; y < MIN_PATCH_HEIGHT; y++) { + p.points[x][y] = points[x][(i * 2) + y]; + } + } + patchList.push_back(p); + } + } else { + //globalErrorStream() << "bobToolz SplitPatchRows: Patch has not enough rows for splitting.\n"; + patchList.push_back(*this); + } + return patchList; } -std::list DPatch::SplitRows(){ - std::list patchList; - int i; - int x, y; - - if ( width >= 5 ) { - for ( i = 0; i < ( width - 1 ) / 2; i++ ) - { - DPatch p; - - p.width = MIN_PATCH_WIDTH; - p.height = height; - p.SetTexture( texture ); - - for ( x = 0; x < MIN_PATCH_WIDTH; x++ ) - { - for ( y = 0; y < p.height; y++ ) - { - p.points[x][y] = points[( i * 2 ) + x][y]; - } - } - patchList.push_back( p ); - } - } - else - { - patchList.push_back( *this ); - } - return patchList; +std::list DPatch::SplitRows() +{ + std::list patchList; + int i; + int x, y; + + if (width >= 5) { + for (i = 0; i < (width - 1) / 2; i++) { + DPatch p; + + p.width = MIN_PATCH_WIDTH; + p.height = height; + p.SetTexture(texture); + + for (x = 0; x < MIN_PATCH_WIDTH; x++) { + for (y = 0; y < p.height; y++) { + p.points[x][y] = points[(i * 2) + x][y]; + } + } + patchList.push_back(p); + } + } else { + patchList.push_back(*this); + } + return patchList; } -std::list DPatch::Split(){ - std::list patchList; - int i; - int x, y; - - if ( width >= 5 ) { - std::list patchColList = SplitCols(); - for ( std::list::iterator patchesCol = patchColList.begin(); patchesCol != patchColList.end(); patchesCol++ ) - { - std::list patchRowList = ( *patchesCol ).SplitRows(); - for ( std::list::iterator patchesRow = patchRowList.begin(); patchesRow != patchRowList.end(); patchesRow++ ) - { - patchList.push_front( *patchesRow ); - } - } - } - else if ( height >= 5 ) { - std::list patchRowList = SplitRows(); - for ( std::list::iterator patchesRow = patchRowList.begin(); patchesRow != patchRowList.end(); patchesRow++ ) - { - patchList.push_front( *patchesRow ); - } - } - else - { - //globalErrorStream() << "bobToolz SplitPatchRows: Patch has not enough rows for splitting.\n"; - patchList.push_back( *this ); - } - return patchList; +std::list DPatch::Split() +{ + std::list patchList; + int i; + int x, y; + + if (width >= 5) { + std::list patchColList = SplitCols(); + for (std::list::iterator patchesCol = patchColList.begin(); + patchesCol != patchColList.end(); patchesCol++) { + std::list patchRowList = (*patchesCol).SplitRows(); + for (std::list::iterator patchesRow = patchRowList.begin(); + patchesRow != patchRowList.end(); patchesRow++) { + patchList.push_front(*patchesRow); + } + } + } else if (height >= 5) { + std::list patchRowList = SplitRows(); + for (std::list::iterator patchesRow = patchRowList.begin(); + patchesRow != patchRowList.end(); patchesRow++) { + patchList.push_front(*patchesRow); + } + } else { + //globalErrorStream() << "bobToolz SplitPatchRows: Patch has not enough rows for splitting.\n"; + patchList.push_back(*this); + } + return patchList; } diff --git a/contrib/bobtoolz/DPatch.h b/contrib/bobtoolz/DPatch.h index 4d0c26c5..e60b1c07 100644 --- a/contrib/bobtoolz/DPatch.h +++ b/contrib/bobtoolz/DPatch.h @@ -27,24 +27,23 @@ #include #include -typedef struct -{ - bool mergable; - int pos1; - int pos2; +typedef struct { + bool mergable; + int pos1; + int pos2; } patch_merge_t; typedef struct { - float xyz[3]; - float st[2]; - float normal[3]; - float lightmap[2]; + float xyz[3]; + float st[2]; + float normal[3]; + float lightmap[2]; } drawVert_t; -namespace scene -{ -class Node; -class Instance; +namespace scene { + class Node; + + class Instance; } const int MAX_PATCH_WIDTH = 32; @@ -52,29 +51,42 @@ const int MAX_PATCH_HEIGHT = 32; const int MIN_PATCH_WIDTH = 3; const int MIN_PATCH_HEIGHT = 3; -class DPatch -{ +class DPatch { public: -std::list SplitRows(); -std::list SplitCols(); -std::list Split(); -void Transpose(); + std::list SplitRows(); + + std::list SplitCols(); + + std::list Split(); + + void Transpose(); + //DPatch* TransposePatch(DPatch* p1); //void DebugPrint(); -void Invert(); -DPatch* MergePatches( patch_merge_t merge_info, DPatch* p1, DPatch* p2 ); -patch_merge_t IsMergable( DPatch* other ); -bool ResetTextures( const char *oldTextureName, const char *newTextureName ); -scene::Node* QER_entity; -scene::Node* QER_brush; -void LoadFromPatch( scene::Instance& patch ); -void BuildInRadiant( scene::Node* entity = NULL ); -void SetTexture( const char* textureName ); -char texture[256]; -int width, height; -drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT]; -DPatch(); -virtual ~DPatch(); + void Invert(); + + DPatch *MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2); + + patch_merge_t IsMergable(DPatch *other); + + bool ResetTextures(const char *oldTextureName, const char *newTextureName); + + scene::Node *QER_entity; + scene::Node *QER_brush; + + void LoadFromPatch(scene::Instance &patch); + + void BuildInRadiant(scene::Node *entity = NULL); + + void SetTexture(const char *textureName); + + char texture[256]; + int width, height; + drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT]; + + DPatch(); + + virtual ~DPatch(); }; diff --git a/contrib/bobtoolz/DPlane.cpp b/contrib/bobtoolz/DPlane.cpp index 46990854..1258e2bc 100644 --- a/contrib/bobtoolz/DPlane.cpp +++ b/contrib/bobtoolz/DPlane.cpp @@ -35,29 +35,30 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DPlane::DPlane( const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData* texData ){ - MakeNormal( va, vb, vc, normal ); - if ( VectorNormalize( normal, normal ) == 0 ) { // normalizes and returns length - globalErrorStream() << "DPlane::DPlane: Bad Normal.\n"; - } - - _d = ( normal[0] * va[0] ) + ( normal[1] * va[1] ) + ( normal[2] * va[2] ); - - VectorCopy( va, points[0] ); - VectorCopy( vb, points[1] ); - VectorCopy( vc, points[2] ); - - m_bChkOk = true; - - if ( texData ) { - memcpy( &texInfo, texData, sizeof( _QERFaceData ) ); - } - else{ - FillDefaultTexture( &texInfo, points[0], points[1], points[2], "textures/common/caulk" ); - } +DPlane::DPlane(const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData *texData) +{ + MakeNormal(va, vb, vc, normal); + if (VectorNormalize(normal, normal) == 0) { // normalizes and returns length + globalErrorStream() << "DPlane::DPlane: Bad Normal.\n"; + } + + _d = (normal[0] * va[0]) + (normal[1] * va[1]) + (normal[2] * va[2]); + + VectorCopy(va, points[0]); + VectorCopy(vb, points[1]); + VectorCopy(vc, points[2]); + + m_bChkOk = true; + + if (texData) { + memcpy(&texInfo, texData, sizeof(_QERFaceData)); + } else { + FillDefaultTexture(&texInfo, points[0], points[1], points[2], "textures/common/caulk"); + } } -DPlane::~DPlane(){ +DPlane::~DPlane() +{ } @@ -65,204 +66,216 @@ DPlane::~DPlane(){ // Implementation ////////////////////////////////////////////////////////////////////// -vec_t DPlane::DistanceToPoint( vec3_t pnt ){ - vec3_t tmp; - VectorSubtract( pnt, points[0], tmp ); - return DotProduct( tmp, normal ); +vec_t DPlane::DistanceToPoint(vec3_t pnt) +{ + vec3_t tmp; + VectorSubtract(pnt, points[0], tmp); + return DotProduct(tmp, normal); } -bool DPlane::PlaneIntersection( DPlane *pl1, DPlane *pl2, vec3_t out ){ - float a1, a2, a3; - float b1, b2, b3; - float c1, c2, c3; - - a1 = normal[0]; a2 = normal[1]; a3 = normal[2]; - b1 = pl1->normal[0]; b2 = pl1->normal[1]; b3 = pl1->normal[2]; - c1 = pl2->normal[0]; c2 = pl2->normal[1]; c3 = pl2->normal[2]; - - float d = Determinant3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3 ); - - if ( d == 0 ) { - return false; - } - - float v1 = _d; - float v2 = pl1->_d; - float v3 = pl2->_d; - - float d1 = Determinant3x3( v1, a2, a3, v2, b2, b3, v3, c2, c3 ); - float d2 = Determinant3x3( a1, v1, a3, b1, v2, b3, c1, v3, c3 ); - float d3 = Determinant3x3( a1, a2, v1, b1, b2, v2, c1, c2, v3 ); - - out[0] = d1 / d; - out[1] = d2 / d; - out[2] = d3 / d; - - return true; +bool DPlane::PlaneIntersection(DPlane *pl1, DPlane *pl2, vec3_t out) +{ + float a1, a2, a3; + float b1, b2, b3; + float c1, c2, c3; + + a1 = normal[0]; + a2 = normal[1]; + a3 = normal[2]; + b1 = pl1->normal[0]; + b2 = pl1->normal[1]; + b3 = pl1->normal[2]; + c1 = pl2->normal[0]; + c2 = pl2->normal[1]; + c3 = pl2->normal[2]; + + float d = Determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3); + + if (d == 0) { + return false; + } + + float v1 = _d; + float v2 = pl1->_d; + float v3 = pl2->_d; + + float d1 = Determinant3x3(v1, a2, a3, v2, b2, b3, v3, c2, c3); + float d2 = Determinant3x3(a1, v1, a3, b1, v2, b3, c1, v3, c3); + float d3 = Determinant3x3(a1, a2, v1, b1, b2, v2, c1, c2, v3); + + out[0] = d1 / d; + out[1] = d2 / d; + out[2] = d3 / d; + + return true; } -bool DPlane::IsRedundant( std::list& pointList ){ - int cnt = 0; - - //std::list::const_iterator point=pointList.begin(); - for ( std::list::const_iterator point = pointList.begin(); point != pointList.end(); point++ ) - { - if ( fabs( DistanceToPoint( ( *point )->_pnt ) ) < MAX_ROUND_ERROR ) { - cnt++; - } - - if ( cnt == 3 ) { - return false; - } - } - return true; +bool DPlane::IsRedundant(std::list &pointList) +{ + int cnt = 0; + + //std::list::const_iterator point=pointList.begin(); + for (std::list::const_iterator point = pointList.begin(); point != pointList.end(); point++) { + if (fabs(DistanceToPoint((*point)->_pnt)) < MAX_ROUND_ERROR) { + cnt++; + } + + if (cnt == 3) { + return false; + } + } + return true; } -bool DPlane::operator ==( DPlane& other ){ - vec3_t chk; - VectorSubtract( other.normal, normal, chk ); - if ( fabs( VectorLength( chk ) ) > MAX_ROUND_ERROR ) { - return false; - } +bool DPlane::operator==(DPlane &other) +{ + vec3_t chk; + VectorSubtract(other.normal, normal, chk); + if (fabs(VectorLength(chk)) > MAX_ROUND_ERROR) { + return false; + } - if ( fabs( other._d - _d ) > MAX_ROUND_ERROR ) { - return false; - } + if (fabs(other._d - _d) > MAX_ROUND_ERROR) { + return false; + } - return true; + return true; } -bool DPlane::operator !=( DPlane& other ){ - vec3_t chk; - VectorAdd( other.normal, normal, chk ); - if ( fabs( VectorLength( chk ) ) > MAX_ROUND_ERROR ) { - return false; - } +bool DPlane::operator!=(DPlane &other) +{ + vec3_t chk; + VectorAdd(other.normal, normal, chk); + if (fabs(VectorLength(chk)) > MAX_ROUND_ERROR) { + return false; + } - return true; + return true; } -DWinding* DPlane::BaseWindingForPlane(){ - int i, x; - vec_t max, v; - vec3_t org, vright, vup; +DWinding *DPlane::BaseWindingForPlane() +{ + int i, x; + vec_t max, v; + vec3_t org, vright, vup; // find the major axis - max = -131072; - x = -1; - for ( i = 0 ; i < 3; i++ ) - { - v = (float)fabs( normal[i] ); - if ( v > max ) { - x = i; - max = v; - } - } - if ( x == -1 ) { - globalOutputStream() << "BaseWindingForPlane: no axis found"; - } - - VectorCopy( vec3_origin, vup ); - switch ( x ) - { - case 0: - case 1: - vup[2] = 1; - break; - case 2: - vup[0] = 1; - break; - } - - v = DotProduct( vup, normal ); - VectorMA( vup, -v, normal, vup ); - VectorNormalize( vup, vup ); - - VectorScale( normal, _d, org ); - - CrossProduct( vup, normal, vright ); - - VectorScale( vup, 131072, vup ); - VectorScale( vright, 131072, vright ); + max = -131072; + x = -1; + for (i = 0; i < 3; i++) { + v = (float) fabs(normal[i]); + if (v > max) { + x = i; + max = v; + } + } + if (x == -1) { + globalOutputStream() << "BaseWindingForPlane: no axis found"; + } + + VectorCopy(vec3_origin, vup); + switch (x) { + case 0: + case 1: + vup[2] = 1; + break; + case 2: + vup[0] = 1; + break; + } + + v = DotProduct(vup, normal); + VectorMA(vup, -v, normal, vup); + VectorNormalize(vup, vup); + + VectorScale(normal, _d, org); + + CrossProduct(vup, normal, vright); + + VectorScale(vup, 131072, vup); + VectorScale(vright, 131072, vright); // project a really big axis aligned box onto the plane - DWinding* w = new DWinding; - w->AllocWinding( 4 ); + DWinding *w = new DWinding; + w->AllocWinding(4); - VectorSubtract( org, vright, w->p[0] ); - VectorAdd( w->p[0], vup, w->p[0] ); + VectorSubtract(org, vright, w->p[0]); + VectorAdd(w->p[0], vup, w->p[0]); - VectorAdd( org, vright, w->p[1] ); - VectorAdd( w->p[1], vup, w->p[1] ); + VectorAdd(org, vright, w->p[1]); + VectorAdd(w->p[1], vup, w->p[1]); - VectorAdd( org, vright, w->p[2] ); - VectorSubtract( w->p[2], vup, w->p[2] ); + VectorAdd(org, vright, w->p[2]); + VectorSubtract(w->p[2], vup, w->p[2]); - VectorSubtract( org, vright, w->p[3] ); - VectorSubtract( w->p[3], vup, w->p[3] ); + VectorSubtract(org, vright, w->p[3]); + VectorSubtract(w->p[3], vup, w->p[3]); - return w; + return w; } -void DPlane::Rebuild(){ - vec3_t v1, v2; - VectorSubtract( points[0], points[1], v1 ); - VectorSubtract( points[2], points[1], v2 ); - CrossProduct( v1, v2, normal ); +void DPlane::Rebuild() +{ + vec3_t v1, v2; + VectorSubtract(points[0], points[1], v1); + VectorSubtract(points[2], points[1], v2); + CrossProduct(v1, v2, normal); - if ( VectorNormalize( normal, normal ) == 0 ) { // normalizes and returns length - globalErrorStream() << "DPlane::Rebuild: Bad Normal.\n"; - } + if (VectorNormalize(normal, normal) == 0) { // normalizes and returns length + globalErrorStream() << "DPlane::Rebuild: Bad Normal.\n"; + } - _d = ( normal[0] * points[0][0] ) + ( normal[1] * points[0][1] ) + ( normal[2] * points[0][2] ); + _d = (normal[0] * points[0][0]) + (normal[1] * points[0][1]) + (normal[2] * points[0][2]); - VectorCopy( points[0], texInfo.m_p0 ); - VectorCopy( points[1], texInfo.m_p1 ); - VectorCopy( points[2], texInfo.m_p2 ); + VectorCopy(points[0], texInfo.m_p0); + VectorCopy(points[1], texInfo.m_p1); + VectorCopy(points[2], texInfo.m_p2); } -bool DPlane::AddToBrush( scene::Node& brush ){ - bool changed = false; - if ( !( m_bChkOk || !strcmp( m_shader.c_str(), "textures/common/caulk" ) ) ) { - m_shader = "textures/common/caulk"; - changed = true; - } - - _QERFaceData faceData; - faceData.m_p0 = vector3_from_array( points[0] ); - faceData.m_p1 = vector3_from_array( points[1] ); - faceData.m_p2 = vector3_from_array( points[2] ); - faceData.m_texdef = texInfo.m_texdef; - faceData.m_shader = m_shader.c_str(); - GlobalBrushCreator().Brush_addFace( brush, faceData ); - - return changed; +bool DPlane::AddToBrush(scene::Node &brush) +{ + bool changed = false; + if (!(m_bChkOk || !strcmp(m_shader.c_str(), "textures/common/caulk"))) { + m_shader = "textures/common/caulk"; + changed = true; + } + + _QERFaceData faceData; + faceData.m_p0 = vector3_from_array(points[0]); + faceData.m_p1 = vector3_from_array(points[1]); + faceData.m_p2 = vector3_from_array(points[2]); + faceData.m_texdef = texInfo.m_texdef; + faceData.m_shader = m_shader.c_str(); + GlobalBrushCreator().Brush_addFace(brush, faceData); + + return changed; } void DPlane::ScaleTexture() -{ } +{} -DPlane::DPlane( const vec3_t va, const vec3_t vb, const vec3_t vc, const char* textureName, bool bDetail ){ - vec3_t v1, v2; - VectorSubtract( va, vb, v1 ); - VectorSubtract( vc, vb, v2 ); - CrossProduct( v1, v2, normal ); +DPlane::DPlane(const vec3_t va, const vec3_t vb, const vec3_t vc, const char *textureName, bool bDetail) +{ + vec3_t v1, v2; + VectorSubtract(va, vb, v1); + VectorSubtract(vc, vb, v2); + CrossProduct(v1, v2, normal); - if ( VectorNormalize( normal, normal ) == 0 ) { // normalizes and returns length - globalErrorStream() << "DPlane::DPlane: Bad Normal.\n"; - } + if (VectorNormalize(normal, normal) == 0) { // normalizes and returns length + globalErrorStream() << "DPlane::DPlane: Bad Normal.\n"; + } - _d = ( normal[0] * va[0] ) + ( normal[1] * va[1] ) + ( normal[2] * va[2] ); + _d = (normal[0] * va[0]) + (normal[1] * va[1]) + (normal[2] * va[2]); - VectorCopy( va, points[0] ); - VectorCopy( vb, points[1] ); - VectorCopy( vc, points[2] ); + VectorCopy(va, points[0]); + VectorCopy(vb, points[1]); + VectorCopy(vc, points[2]); - m_bChkOk = true; + m_bChkOk = true; - FillDefaultTexture( &texInfo, points[0], points[1], points[2], textureName ); - if ( bDetail ) { - texInfo.contents |= FACE_DETAIL; - } + FillDefaultTexture(&texInfo, points[0], points[1], points[2], textureName); + if (bDetail) { + texInfo.contents |= FACE_DETAIL; + } } diff --git a/contrib/bobtoolz/DPlane.h b/contrib/bobtoolz/DPlane.h index 88a33584..62c9edbf 100644 --- a/contrib/bobtoolz/DPlane.h +++ b/contrib/bobtoolz/DPlane.h @@ -30,6 +30,7 @@ #include "mathlib.h" class Brush; + class DPoint; #define FACE_DETAIL 0x8000000 @@ -40,34 +41,41 @@ class DPoint; class DWinding; -class DPlane -{ +class DPlane { public: -DPlane( const vec3_t va, const vec3_t vb, const vec3_t vc, const char* textureName, bool bDetail ); -void ScaleTexture(); -DWinding* BaseWindingForPlane(); + DPlane(const vec3_t va, const vec3_t vb, const vec3_t vc, const char *textureName, bool bDetail); + + void ScaleTexture(); + + DWinding *BaseWindingForPlane(); + + void Rebuild(); + + bool AddToBrush(scene::Node &brush); + + bool operator!=(DPlane &other); + + bool operator==(DPlane &other); + + bool IsRedundant(std::list &pointList); -void Rebuild(); + bool PlaneIntersection(DPlane *pl1, DPlane *pl2, vec3_t out); -bool AddToBrush( scene::Node& brush ); -bool operator !=( DPlane& other ); -bool operator ==( DPlane& other ); + vec_t DistanceToPoint(vec3_t pnt); -bool IsRedundant( std::list& pointList ); -bool PlaneIntersection( DPlane* pl1, DPlane* pl2, vec3_t out ); + DPlane(const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData *texData); -vec_t DistanceToPoint( vec3_t pnt ); + DPlane() + {} -DPlane( const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData* texData ); -DPlane() { } -virtual ~DPlane(); + virtual ~DPlane(); -bool m_bChkOk; -_QERFaceData texInfo; -CopiedString m_shader; -vec3_t points[3]; // djbob:do we really need these any more? -vec3_t normal; -float _d; + bool m_bChkOk; + _QERFaceData texInfo; + CopiedString m_shader; + vec3_t points[3]; // djbob:do we really need these any more? + vec3_t normal; + float _d; }; //typedef CList DPlaneList; diff --git a/contrib/bobtoolz/DPoint.cpp b/contrib/bobtoolz/DPoint.cpp index 58628e62..4eb8fca9 100644 --- a/contrib/bobtoolz/DPoint.cpp +++ b/contrib/bobtoolz/DPoint.cpp @@ -28,11 +28,13 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DPoint::DPoint(){ +DPoint::DPoint() +{ } -DPoint::~DPoint(){ +DPoint::~DPoint() +{ } @@ -40,11 +42,12 @@ DPoint::~DPoint(){ // Implementation ////////////////////////////////////////////////////////////////////// -bool DPoint::operator ==( vec3_t other ){ - vec3_t test; - VectorSubtract( other, _pnt, test ); - if ( fabs( VectorLength( test ) ) > MAX_ROUND_ERROR ) { - return false; - } - return true; +bool DPoint::operator==(vec3_t other) +{ + vec3_t test; + VectorSubtract(other, _pnt, test); + if (fabs(VectorLength(test)) > MAX_ROUND_ERROR) { + return false; + } + return true; } diff --git a/contrib/bobtoolz/DPoint.h b/contrib/bobtoolz/DPoint.h index f7b68396..d29d415d 100644 --- a/contrib/bobtoolz/DPoint.h +++ b/contrib/bobtoolz/DPoint.h @@ -30,16 +30,16 @@ #include "mathlib.h" -class DPoint -{ +class DPoint { public: -DPoint(); -virtual ~DPoint(); + DPoint(); -bool operator ==( vec3_t other ); + virtual ~DPoint(); -vec3_t _pnt; -unsigned char m_uData; + bool operator==(vec3_t other); + + vec3_t _pnt; + unsigned char m_uData; }; //typedef CList DPointList; diff --git a/contrib/bobtoolz/DShape.cpp b/contrib/bobtoolz/DShape.cpp index 8c675ff9..aa768889 100644 --- a/contrib/bobtoolz/DShape.cpp +++ b/contrib/bobtoolz/DShape.cpp @@ -45,393 +45,395 @@ bool bFacesAll[6] = {true, true, true, true, true, true}; -DShape::DShape(){ - m_nNextBrush = 0; +DShape::DShape() +{ + m_nNextBrush = 0; } -DShape::~DShape(){ +DShape::~DShape() +{ } -void DShape::BuildRegularPrism( vec3_t min, vec3_t max, int nSides, bool bAlignTop ){ - vec3_t vc[MAX_POLYGON_FACES + 2], vd[MAX_POLYGON_FACES + 2]; +void DShape::BuildRegularPrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop) +{ + vec3_t vc[MAX_POLYGON_FACES + 2], vd[MAX_POLYGON_FACES + 2]; - vec3_t radius; - vec3_t origin; + vec3_t radius; + vec3_t origin; - VectorSubtract( max, min, radius ); - VectorScale( radius, 0.5f, radius ); - // calc 3d radius and origin - VectorAdd( max, min, origin ); - VectorScale( origin, 0.5f, origin ); + VectorSubtract(max, min, radius); + VectorScale(radius, 0.5f, radius); + // calc 3d radius and origin + VectorAdd(max, min, origin); + VectorScale(origin, 0.5f, origin); - float phase = 0.0f; + float phase = 0.0f; - if ( bAlignTop ) { - phase = -( Q_PI / nSides ); - VectorScale( radius, static_cast( 1.0 / cos( phase ) ), radius ); - } + if (bAlignTop) { + phase = -(Q_PI / nSides); + VectorScale(radius, static_cast( 1.0 / cos(phase)), radius); + } - //----- Build Polygon Vertices ----- + //----- Build Polygon Vertices ----- - int i; - for ( i = 0; i < nSides; i++ ) - { - VectorCopy( origin, vc[i] ); - VectorCopy( origin, vd[i] ); + int i; + for (i = 0; i < nSides; i++) { + VectorCopy(origin, vc[i]); + VectorCopy(origin, vd[i]); - vc[i][2] = min[2]; - vd[i][2] = max[2]; + vc[i][2] = min[2]; + vd[i][2] = max[2]; - vc[i][0] += radius[0] * sinf( ( 2 * Q_PI * i / nSides ) + phase ); - vc[i][1] += radius[1] * cosf( ( 2 * Q_PI * i / nSides ) + phase ); + vc[i][0] += radius[0] * sinf((2 * Q_PI * i / nSides) + phase); + vc[i][1] += radius[1] * cosf((2 * Q_PI * i / nSides) + phase); - vd[i][0] = vc[i][0]; - vd[i][1] = vc[i][1]; - } + vd[i][0] = vc[i][0]; + vd[i][1] = vc[i][1]; + } - VectorCopy( vc[0], vc[nSides] ); - VectorCopy( vd[0], vd[nSides] ); - VectorCopy( vc[1], vc[nSides + 1] ); - VectorCopy( vd[1], vd[nSides + 1] ); + VectorCopy(vc[0], vc[nSides]); + VectorCopy(vd[0], vd[nSides]); + VectorCopy(vc[1], vc[nSides + 1]); + VectorCopy(vd[1], vd[nSides + 1]); - //---------------------------------- + //---------------------------------- - DBrush* pB = m_Container.GetWorldSpawn()->NewBrush( m_nNextBrush++ ); + DBrush *pB = m_Container.GetWorldSpawn()->NewBrush(m_nNextBrush++); - for ( i = 1; i <= nSides; i++ ) - pB->AddFace( vc[i - 1], vc[i], vd[i], GetCurrentTexture(), false ); + for (i = 1; i <= nSides; i++) { + pB->AddFace(vc[i - 1], vc[i], vd[i], GetCurrentTexture(), false); + } - pB->AddFace( vc[2], vc[1], vc[0], "textures/common/caulk", false ); - pB->AddFace( vd[0], vd[1], vd[2], "textures/common/caulk", false ); + pB->AddFace(vc[2], vc[1], vc[0], "textures/common/caulk", false); + pB->AddFace(vd[0], vd[1], vd[2], "textures/common/caulk", false); } -void DShape::Commit(){ - m_Container.GetWorldSpawn()->FixBrushes(); - m_Container.BuildInRadiant( true ); +void DShape::Commit() +{ + m_Container.GetWorldSpawn()->FixBrushes(); + m_Container.BuildInRadiant(true); } -void DShape::BuildInversePrism( vec3_t min, vec3_t max, int nSides, bool bAlignTop ){ - vec3_t va[MAX_POLYGON_FACES + 1], vb[MAX_POLYGON_FACES + 1]; - vec3_t radius; - vec3_t origin; - - VectorSubtract( max, min, radius ); - VectorScale( radius, 0.5f, radius ); - // calc 3d radius and origin - VectorAdd( max, min, origin ); - VectorScale( origin, 0.5f, origin ); - - float phase = 0.0f; - - if ( bAlignTop ) { - phase = -( Q_PI / nSides ); - VectorScale( radius, static_cast( 1.0 / cos( phase ) ), radius ); - } - - //----- Build Polygon Vertices ----- - - int i; - for ( i = 0; i < nSides; i++ ) - { - VectorCopy( origin, va[i] ); - VectorCopy( origin, vb[i] ); - - va[i][2] = min[2]; - vb[i][2] = max[2]; - - va[i][0] += radius[0] * sinf( ( 2 * Q_PI * i / nSides ) + phase ); - va[i][1] += radius[1] * cosf( ( 2 * Q_PI * i / nSides ) + phase ); - - vb[i][0] = va[i][0]; - vb[i][1] = va[i][1]; - } - - VectorCopy( va[0], va[nSides] ); - VectorCopy( vb[0], vb[nSides] ); - - //---------------------------------- - - for ( i = 1; i <= nSides; i++ ) - { - DBrush* pB = GetBoundingCube( min, max, "textures/common/caulk" ); - - vec3_t top, bottom; - VectorCopy( va[i - 1], top ); - VectorCopy( va[i], bottom ); - - if ( va[i - 1][1] > va[i][1] ) { - top[0] += 5; - bottom[0] += 5; - } - else // flip direction of plane on crossover - { - top[0] -= 5; - bottom[0] -= 5; - } - - if ( top[1] != bottom[1] ) { // internal line is flat already if true - pB->AddFace( va[i - 1], top, vb[i - 1], "textures/common/caulk", false ); - pB->AddFace( va[i], vb[i], bottom, "textures/common/caulk", false ); - } // add cut-off planes - - pB->AddFace( va[i - 1], vb[i - 1], vb[i], GetCurrentTexture(), false ); - // add internal polygon plane - } +void DShape::BuildInversePrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop) +{ + vec3_t va[MAX_POLYGON_FACES + 1], vb[MAX_POLYGON_FACES + 1]; + vec3_t radius; + vec3_t origin; + + VectorSubtract(max, min, radius); + VectorScale(radius, 0.5f, radius); + // calc 3d radius and origin + VectorAdd(max, min, origin); + VectorScale(origin, 0.5f, origin); + + float phase = 0.0f; + + if (bAlignTop) { + phase = -(Q_PI / nSides); + VectorScale(radius, static_cast( 1.0 / cos(phase)), radius); + } + + //----- Build Polygon Vertices ----- + + int i; + for (i = 0; i < nSides; i++) { + VectorCopy(origin, va[i]); + VectorCopy(origin, vb[i]); + + va[i][2] = min[2]; + vb[i][2] = max[2]; + + va[i][0] += radius[0] * sinf((2 * Q_PI * i / nSides) + phase); + va[i][1] += radius[1] * cosf((2 * Q_PI * i / nSides) + phase); + + vb[i][0] = va[i][0]; + vb[i][1] = va[i][1]; + } + + VectorCopy(va[0], va[nSides]); + VectorCopy(vb[0], vb[nSides]); + + //---------------------------------- + + for (i = 1; i <= nSides; i++) { + DBrush *pB = GetBoundingCube(min, max, "textures/common/caulk"); + + vec3_t top, bottom; + VectorCopy(va[i - 1], top); + VectorCopy(va[i], bottom); + + if (va[i - 1][1] > va[i][1]) { + top[0] += 5; + bottom[0] += 5; + } else // flip direction of plane on crossover + { + top[0] -= 5; + bottom[0] -= 5; + } + + if (top[1] != bottom[1]) { // internal line is flat already if true + pB->AddFace(va[i - 1], top, vb[i - 1], "textures/common/caulk", false); + pB->AddFace(va[i], vb[i], bottom, "textures/common/caulk", false); + } // add cut-off planes + + pB->AddFace(va[i - 1], vb[i - 1], vb[i], GetCurrentTexture(), false); + // add internal polygon plane + } } -void DShape::BuildBorderedPrism( vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop ){ - vec3_t va[MAX_POLYGON_FACES + 2], vb[MAX_POLYGON_FACES + 2]; - vec3_t vc[MAX_POLYGON_FACES + 2], vd[MAX_POLYGON_FACES + 2]; +void DShape::BuildBorderedPrism(vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop) +{ + vec3_t va[MAX_POLYGON_FACES + 2], vb[MAX_POLYGON_FACES + 2]; + vec3_t vc[MAX_POLYGON_FACES + 2], vd[MAX_POLYGON_FACES + 2]; - vec3_t radius; - vec3_t origin; + vec3_t radius; + vec3_t origin; - VectorSubtract( max, min, radius ); - VectorScale( radius, 0.5f, radius ); - // calc 3d radius and origin - VectorAdd( max, min, origin ); - VectorScale( origin, 0.5f, origin ); + VectorSubtract(max, min, radius); + VectorScale(radius, 0.5f, radius); + // calc 3d radius and origin + VectorAdd(max, min, origin); + VectorScale(origin, 0.5f, origin); - if ( nBorder >= Min( radius[0], radius[1] ) ) { + if (nBorder >= Min(radius[0], radius[1])) { // DoMessageBox("Border is too large", "Error", MB_OK); - return; - } - - float phase = 0.0f; + return; + } - if ( bAlignTop ) { - phase = -( Q_PI / nSides ); - VectorScale( radius, static_cast( 1.0 / cos( phase ) ), radius ); - } + float phase = 0.0f; - //----- Build Polygon Vertices ----- + if (bAlignTop) { + phase = -(Q_PI / nSides); + VectorScale(radius, static_cast( 1.0 / cos(phase)), radius); + } - int i; - for ( i = 0; i < nSides; i++ ) - { - VectorCopy( origin, va[i] ); - VectorCopy( origin, vb[i] ); - VectorCopy( origin, vc[i] ); - VectorCopy( origin, vd[i] ); + //----- Build Polygon Vertices ----- - va[i][2] = min[2]; - vb[i][2] = max[2]; + int i; + for (i = 0; i < nSides; i++) { + VectorCopy(origin, va[i]); + VectorCopy(origin, vb[i]); + VectorCopy(origin, vc[i]); + VectorCopy(origin, vd[i]); - va[i][0] += ( radius[0] - nBorder ) * sinf( ( 2 * Q_PI * i / nSides ) + phase ); - va[i][1] += ( radius[1] - nBorder ) * cosf( ( 2 * Q_PI * i / nSides ) + phase ); + va[i][2] = min[2]; + vb[i][2] = max[2]; - vb[i][0] = va[i][0]; - vb[i][1] = va[i][1]; + va[i][0] += (radius[0] - nBorder) * sinf((2 * Q_PI * i / nSides) + phase); + va[i][1] += (radius[1] - nBorder) * cosf((2 * Q_PI * i / nSides) + phase); + vb[i][0] = va[i][0]; + vb[i][1] = va[i][1]; - vc[i][2] = min[2]; - vd[i][2] = max[2]; + vc[i][2] = min[2]; + vd[i][2] = max[2]; - vc[i][0] += radius[0] * sinf( ( 2 * Q_PI * i / nSides ) + phase ); - vc[i][1] += radius[1] * cosf( ( 2 * Q_PI * i / nSides ) + phase ); + vc[i][0] += radius[0] * sinf((2 * Q_PI * i / nSides) + phase); + vc[i][1] += radius[1] * cosf((2 * Q_PI * i / nSides) + phase); - vd[i][0] = vc[i][0]; - vd[i][1] = vc[i][1]; - } + vd[i][0] = vc[i][0]; + vd[i][1] = vc[i][1]; + } - VectorCopy( va[0], va[nSides] ); - VectorCopy( vb[0], vb[nSides] ); - VectorCopy( va[1], va[nSides + 1] ); - VectorCopy( vb[1], vb[nSides + 1] ); + VectorCopy(va[0], va[nSides]); + VectorCopy(vb[0], vb[nSides]); + VectorCopy(va[1], va[nSides + 1]); + VectorCopy(vb[1], vb[nSides + 1]); - VectorCopy( vc[0], vc[nSides] ); - VectorCopy( vd[0], vd[nSides] ); - VectorCopy( vc[1], vc[nSides + 1] ); - VectorCopy( vd[1], vd[nSides + 1] ); + VectorCopy(vc[0], vc[nSides]); + VectorCopy(vd[0], vd[nSides]); + VectorCopy(vc[1], vc[nSides + 1]); + VectorCopy(vd[1], vd[nSides + 1]); - //---------------------------------- + //---------------------------------- - for ( i = 1; i <= nSides; i++ ) - { - DBrush* pB = GetBoundingCube( min, max, "textures/common/caulk" ); + for (i = 1; i <= nSides; i++) { + DBrush *pB = GetBoundingCube(min, max, "textures/common/caulk"); - pB->AddFace( origin, vc[i - 1], vd[i - 1], "textures/common/caulk", false ); - pB->AddFace( origin, vd[i], vc[i], "textures/common/caulk", false ); + pB->AddFace(origin, vc[i - 1], vd[i - 1], "textures/common/caulk", false); + pB->AddFace(origin, vd[i], vc[i], "textures/common/caulk", false); - pB->AddFace( vc[i - 1], vc[i], vd[i], GetCurrentTexture(), false ); - pB->AddFace( vb[i], va[i], va[i - 1], GetCurrentTexture(), false ); - } + pB->AddFace(vc[i - 1], vc[i], vd[i], GetCurrentTexture(), false); + pB->AddFace(vb[i], va[i], va[i - 1], GetCurrentTexture(), false); + } } -DBrush* DShape::GetBoundingCube_Ext( vec3_t min, vec3_t max, const char *textureName, bool* bUseFaces, bool detail ){ - DBrush* pB = new DBrush; - //----- Build Outer Bounds --------- - - vec3_t v1, v2, v3, v5, v6, v7; - VectorCopy( min, v1 ); - VectorCopy( min, v2 ); - VectorCopy( min, v3 ); - VectorCopy( max, v5 ); - VectorCopy( max, v6 ); - VectorCopy( max, v7 ); - - v2[0] = max[0]; - v3[1] = max[1]; - - v6[0] = min[0]; - v7[1] = min[1]; - - //---------------------------------- - - //----- Add Six Cube Faces --------- - - if ( bUseFaces[0] ) { - pB->AddFace( v1, v2, v3, textureName, detail ); - } - if ( bUseFaces[1] ) { - pB->AddFace( v1, v3, v6, textureName, detail ); - } - if ( bUseFaces[2] ) { - pB->AddFace( v1, v7, v2, textureName, detail ); - } - - if ( bUseFaces[3] ) { - pB->AddFace( v5, v6, v3, textureName, detail ); - } - if ( bUseFaces[4] ) { - pB->AddFace( v5, v2, v7, textureName, detail ); - } - if ( bUseFaces[5] ) { - pB->AddFace( v5, v7, v6, textureName, detail ); - } - - //---------------------------------- - - return pB; +DBrush *DShape::GetBoundingCube_Ext(vec3_t min, vec3_t max, const char *textureName, bool *bUseFaces, bool detail) +{ + DBrush *pB = new DBrush; + //----- Build Outer Bounds --------- + + vec3_t v1, v2, v3, v5, v6, v7; + VectorCopy(min, v1); + VectorCopy(min, v2); + VectorCopy(min, v3); + VectorCopy(max, v5); + VectorCopy(max, v6); + VectorCopy(max, v7); + + v2[0] = max[0]; + v3[1] = max[1]; + + v6[0] = min[0]; + v7[1] = min[1]; + + //---------------------------------- + + //----- Add Six Cube Faces --------- + + if (bUseFaces[0]) { + pB->AddFace(v1, v2, v3, textureName, detail); + } + if (bUseFaces[1]) { + pB->AddFace(v1, v3, v6, textureName, detail); + } + if (bUseFaces[2]) { + pB->AddFace(v1, v7, v2, textureName, detail); + } + + if (bUseFaces[3]) { + pB->AddFace(v5, v6, v3, textureName, detail); + } + if (bUseFaces[4]) { + pB->AddFace(v5, v2, v7, textureName, detail); + } + if (bUseFaces[5]) { + pB->AddFace(v5, v7, v6, textureName, detail); + } + + //---------------------------------- + + return pB; } -DBrush* DShape::GetBoundingCube( vec3_t min, vec3_t max, const char *textureName, DEntity* ent, bool* bUseFaces ){ - DBrush* pB; - if ( ent == NULL ) { - pB = m_Container.GetWorldSpawn()->NewBrush( m_nNextBrush++ ); - } - else{ - pB = ent->NewBrush( m_nNextBrush++ ); - } - - //----- Build Outer Bounds --------- - - vec3_t v1, v2, v3, v5, v6, v7; - VectorCopy( min, v1 ); - VectorCopy( min, v2 ); - VectorCopy( min, v3 ); - VectorCopy( max, v5 ); - VectorCopy( max, v6 ); - VectorCopy( max, v7 ); - - v2[0] = max[0]; - v3[1] = max[1]; - - v6[0] = min[0]; - v7[1] = min[1]; - - //---------------------------------- - - //----- Add Six Cube Faces --------- - - if ( bUseFaces[0] ) { - pB->AddFace( v1, v2, v3, textureName, false ); - } - if ( bUseFaces[1] ) { - pB->AddFace( v1, v3, v6, textureName, false ); - } - if ( bUseFaces[2] ) { - pB->AddFace( v1, v7, v2, textureName, false ); - } - - if ( bUseFaces[3] ) { - pB->AddFace( v5, v6, v3, textureName, false ); - } - if ( bUseFaces[4] ) { - pB->AddFace( v5, v2, v7, textureName, false ); - } - if ( bUseFaces[5] ) { - pB->AddFace( v5, v7, v6, textureName, false ); - } - - //---------------------------------- - - return pB; +DBrush *DShape::GetBoundingCube(vec3_t min, vec3_t max, const char *textureName, DEntity *ent, bool *bUseFaces) +{ + DBrush *pB; + if (ent == NULL) { + pB = m_Container.GetWorldSpawn()->NewBrush(m_nNextBrush++); + } else { + pB = ent->NewBrush(m_nNextBrush++); + } + + //----- Build Outer Bounds --------- + + vec3_t v1, v2, v3, v5, v6, v7; + VectorCopy(min, v1); + VectorCopy(min, v2); + VectorCopy(min, v3); + VectorCopy(max, v5); + VectorCopy(max, v6); + VectorCopy(max, v7); + + v2[0] = max[0]; + v3[1] = max[1]; + + v6[0] = min[0]; + v7[1] = min[1]; + + //---------------------------------- + + //----- Add Six Cube Faces --------- + + if (bUseFaces[0]) { + pB->AddFace(v1, v2, v3, textureName, false); + } + if (bUseFaces[1]) { + pB->AddFace(v1, v3, v6, textureName, false); + } + if (bUseFaces[2]) { + pB->AddFace(v1, v7, v2, textureName, false); + } + + if (bUseFaces[3]) { + pB->AddFace(v5, v6, v3, textureName, false); + } + if (bUseFaces[4]) { + pB->AddFace(v5, v2, v7, textureName, false); + } + if (bUseFaces[5]) { + pB->AddFace(v5, v7, v6, textureName, false); + } + + //---------------------------------- + + return pB; } -bool DShape::BuildPit( vec3_t min, vec3_t max ){ - if ( ( max[2] - min[2] ) < 196 ) { - return false; - } +bool DShape::BuildPit(vec3_t min, vec3_t max) +{ + if ((max[2] - min[2]) < 196) { + return false; + } - srand( time( NULL ) ); + srand(time(NULL)); - vec3_t centre; - VectorAdd( min, max, centre ); - VectorScale( centre, 0.5f, centre ); + vec3_t centre; + VectorAdd(min, max, centre); + VectorScale(centre, 0.5f, centre); - char buffer[256]; + char buffer[256]; - int team = ( rand() % 10000 ) + 5000; + int team = (rand() % 10000) + 5000; // ************* SPEAKER *************** - sprintf( buffer, "t%i_1", team ); + sprintf(buffer, "t%i_1", team); // trigger for speaker - vec3_t triggerVoiceBtm; - VectorCopy( min, triggerVoiceBtm ); - triggerVoiceBtm[2] = max[2] - 16; + vec3_t triggerVoiceBtm; + VectorCopy(min, triggerVoiceBtm); + triggerVoiceBtm[2] = max[2] - 16; - DEntity* triggerVoice = m_Container.AddEntity( "trigger_multiple" ); - GetBoundingCube( triggerVoiceBtm, max, "textures/common/trigger", triggerVoice ); - triggerVoice->AddEPair( "target", buffer ); + DEntity *triggerVoice = m_Container.AddEntity("trigger_multiple"); + GetBoundingCube(triggerVoiceBtm, max, "textures/common/trigger", triggerVoice); + triggerVoice->AddEPair("target", buffer); //-------------------- // target for speaker - vec3_t voiceOrigin; - VectorCopy( centre, voiceOrigin ); - voiceOrigin[2] = max[2] + 16; + vec3_t voiceOrigin; + VectorCopy(centre, voiceOrigin); + voiceOrigin[2] = max[2] + 16; - DEntity* targetVoice = m_Container.AddEntity( "target_speaker" ); - targetVoice->AddEPair( "targetname", buffer ); + DEntity *targetVoice = m_Container.AddEntity("target_speaker"); + targetVoice->AddEPair("targetname", buffer); - sprintf( buffer, "%f %f %f", voiceOrigin[0], voiceOrigin[1], voiceOrigin[2] ); - targetVoice->AddEPair( "origin", buffer ); - targetVoice->AddEPair( "spawnflags", "8" ); - targetVoice->AddEPair( "noise", "*falling1.wav" ); + sprintf(buffer, "%f %f %f", voiceOrigin[0], voiceOrigin[1], voiceOrigin[2]); + targetVoice->AddEPair("origin", buffer); + targetVoice->AddEPair("spawnflags", "8"); + targetVoice->AddEPair("noise", "*falling1.wav"); //-------------------- // *********** END SPEAKER ************* // ********* POWERUP REMOVAL *********** - sprintf( buffer, "t%i_2", team ); + sprintf(buffer, "t%i_2", team); // trigger for powerup removal - vec3_t triggerPwrRmvTop, triggerPwrRmvBtm; - VectorCopy( min, triggerPwrRmvBtm ); - VectorCopy( max, triggerPwrRmvTop ); + vec3_t triggerPwrRmvTop, triggerPwrRmvBtm; + VectorCopy(min, triggerPwrRmvBtm); + VectorCopy(max, triggerPwrRmvTop); - triggerPwrRmvTop[2] = triggerVoiceBtm[2] - 64; - triggerPwrRmvBtm[2] = triggerPwrRmvTop[2] - 16; + triggerPwrRmvTop[2] = triggerVoiceBtm[2] - 64; + triggerPwrRmvBtm[2] = triggerPwrRmvTop[2] - 16; - DEntity* triggerPwrRmv = m_Container.AddEntity( "trigger_multiple" ); - GetBoundingCube( triggerPwrRmvBtm, triggerPwrRmvTop, "textures/common/trigger", triggerPwrRmv ); - triggerPwrRmv->AddEPair( "target", buffer ); + DEntity *triggerPwrRmv = m_Container.AddEntity("trigger_multiple"); + GetBoundingCube(triggerPwrRmvBtm, triggerPwrRmvTop, "textures/common/trigger", triggerPwrRmv); + triggerPwrRmv->AddEPair("target", buffer); //-------------------- // target for powerup removal - vec3_t pwrRmvOrigin; - VectorCopy( centre, pwrRmvOrigin ); - pwrRmvOrigin[2] = triggerPwrRmvTop[2] + 16; + vec3_t pwrRmvOrigin; + VectorCopy(centre, pwrRmvOrigin); + pwrRmvOrigin[2] = triggerPwrRmvTop[2] + 16; - DEntity* targetPwrRmv = m_Container.AddEntity( "target_remove_powerups" ); - targetPwrRmv->AddEPair( "targetname", buffer ); + DEntity *targetPwrRmv = m_Container.AddEntity("target_remove_powerups"); + targetPwrRmv->AddEPair("targetname", buffer); - sprintf( buffer, "%f %f %f", pwrRmvOrigin[0], pwrRmvOrigin[1], pwrRmvOrigin[2] ); - targetPwrRmv->AddEPair( "origin", buffer ); + sprintf(buffer, "%f %f %f", pwrRmvOrigin[0], pwrRmvOrigin[1], pwrRmvOrigin[2]); + targetPwrRmv->AddEPair("origin", buffer); //-------------------- // ****** END POWERUP REMOVAL ******** @@ -439,31 +441,31 @@ bool DShape::BuildPit( vec3_t min, vec3_t max ){ // ********* DAMAGE *********** // trigger for damage - vec3_t triggerDmgTop, triggerDmgBtm; - VectorCopy( min, triggerDmgBtm ); - VectorCopy( max, triggerDmgTop ); + vec3_t triggerDmgTop, triggerDmgBtm; + VectorCopy(min, triggerDmgBtm); + VectorCopy(max, triggerDmgTop); - triggerDmgBtm[2] = min[2] + 64; - triggerDmgTop[2] = triggerDmgBtm[2] + 16; + triggerDmgBtm[2] = min[2] + 64; + triggerDmgTop[2] = triggerDmgBtm[2] + 16; - DEntity* triggerDmg = m_Container.AddEntity( "trigger_hurt" ); - GetBoundingCube( triggerDmgBtm, triggerDmgTop, "textures/common/trigger", triggerDmg ); - triggerDmg->AddEPair( "dmg", "9999" ); - triggerDmg->AddEPair( "spawnflags", "12" ); + DEntity *triggerDmg = m_Container.AddEntity("trigger_hurt"); + GetBoundingCube(triggerDmgBtm, triggerDmgTop, "textures/common/trigger", triggerDmg); + triggerDmg->AddEPair("dmg", "9999"); + triggerDmg->AddEPair("spawnflags", "12"); //-------------------- // ****** END DAMAGE ******** // ********* NODROP *********** - vec3_t nodropTop; - VectorCopy( max, nodropTop ); + vec3_t nodropTop; + VectorCopy(max, nodropTop); - nodropTop[2] = min[2] + 64; + nodropTop[2] = min[2] + 64; - GetBoundingCube( min, nodropTop, "textures/common/nodrop" ); + GetBoundingCube(min, nodropTop, "textures/common/nodrop"); // ****** END NODROP ******** - return true; + return true; } diff --git a/contrib/bobtoolz/DShape.h b/contrib/bobtoolz/DShape.h index 31c66e13..1a062863 100644 --- a/contrib/bobtoolz/DShape.h +++ b/contrib/bobtoolz/DShape.h @@ -31,7 +31,9 @@ #include #include "mathlib.h" #include "DMap.h" + class DBrush; + class DEntity; // defines for polygon stuff @@ -39,25 +41,32 @@ const int MAX_POLYGON_FACES = 128; extern bool bFacesAll[]; -class DShape -{ +class DShape { public: -bool BuildPit( vec3_t min, vec3_t max ); -void BuildBorderedPrism( vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop ); -void BuildInversePrism( vec3_t min, vec3_t max, int nSides, bool bAlignTop ); -void BuildRegularPrism( vec3_t min, vec3_t max, int nSides, bool bAlignTop ); + bool BuildPit(vec3_t min, vec3_t max); + + void BuildBorderedPrism(vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop); + + void BuildInversePrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop); + + void BuildRegularPrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop); + + int m_nNextBrush; + + static DBrush *GetBoundingCube_Ext(vec3_t min, vec3_t max, const char *textureName, bool *bUseFaces = bFacesAll, + bool detail = false); + + DShape(); -int m_nNextBrush; -static DBrush* GetBoundingCube_Ext( vec3_t min, vec3_t max, const char* textureName, bool* bUseFaces = bFacesAll, bool detail = false ); + virtual ~DShape(); -DShape(); -virtual ~DShape(); + void Commit(); -void Commit(); private: -DBrush* GetBoundingCube( vec3_t min, vec3_t max, const char* textureName, DEntity* ent = NULL, bool* bUseFaces = bFacesAll ); + DBrush * + GetBoundingCube(vec3_t min, vec3_t max, const char *textureName, DEntity *ent = NULL, bool *bUseFaces = bFacesAll); -DMap m_Container; + DMap m_Container; }; #endif // !defined(AFX_DSHAPE_H__0B30B302_9D21_4C2D_836A_61F3C8D4244D__INCLUDED_) diff --git a/contrib/bobtoolz/DTrainDrawer.cpp b/contrib/bobtoolz/DTrainDrawer.cpp index da7edcc1..0a3307de 100644 --- a/contrib/bobtoolz/DTrainDrawer.cpp +++ b/contrib/bobtoolz/DTrainDrawer.cpp @@ -38,294 +38,313 @@ #include "dialogs/dialogs-gtk.h" -DTrainDrawer::DTrainDrawer() { - m_bDisplay = false; +DTrainDrawer::DTrainDrawer() +{ + m_bDisplay = false; - BuildPaths(); - constructShaders(); - GlobalShaderCache().attachRenderable( *this ); + BuildPaths(); + constructShaders(); + GlobalShaderCache().attachRenderable(*this); } -DTrainDrawer::~DTrainDrawer( void ) { - GlobalShaderCache().detachRenderable( *this ); - destroyShaders(); +DTrainDrawer::~DTrainDrawer(void) +{ + GlobalShaderCache().detachRenderable(*this); + destroyShaders(); - ClearPoints(); - ClearSplines(); + ClearPoints(); + ClearSplines(); } -void DTrainDrawer::ClearSplines() { - for ( std::list::const_iterator deadSpline = m_splineList.begin(); deadSpline != m_splineList.end(); deadSpline++ ) { - ( *deadSpline )->m_pointList.clear(); - ( *deadSpline )->m_vertexList.clear(); - delete ( *deadSpline ); - } - - m_splineList.clear(); +void DTrainDrawer::ClearSplines() +{ + for (std::list::const_iterator deadSpline = m_splineList.begin(); + deadSpline != m_splineList.end(); deadSpline++) { + (*deadSpline)->m_pointList.clear(); + (*deadSpline)->m_vertexList.clear(); + delete (*deadSpline); + } + + m_splineList.clear(); } -void DTrainDrawer::ClearPoints() { - for ( std::list::const_iterator deadPoint = m_pointList.begin(); deadPoint != m_pointList.end(); deadPoint++ ) { - delete *deadPoint; - } +void DTrainDrawer::ClearPoints() +{ + for (std::list::const_iterator deadPoint = m_pointList.begin(); + deadPoint != m_pointList.end(); deadPoint++) { + delete *deadPoint; + } - m_pointList.clear(); + m_pointList.clear(); } -void CalculateSpline_r( vec3_t* v, int count, vec3_t out, float tension ) { - vec3_t dist; +void CalculateSpline_r(vec3_t *v, int count, vec3_t out, float tension) +{ + vec3_t dist; - if ( count < 2 ) { - return; - } + if (count < 2) { + return; + } - if ( count == 2 ) { - VectorSubtract( v[1], v[0], dist ); - VectorMA( v[0], tension, dist, out ); - return; - } + if (count == 2) { + VectorSubtract(v[1], v[0], dist); + VectorMA(v[0], tension, dist, out); + return; + } - vec3_t* v2 = new vec3_t[count - 1]; + vec3_t *v2 = new vec3_t[count - 1]; - for ( int i = 0; i < count - 1; i++ ) { - VectorSubtract( v[i + 1], v[i], dist ); - VectorMA( v[i], tension, dist, v2[i] ); - } + for (int i = 0; i < count - 1; i++) { + VectorSubtract(v[i + 1], v[i], dist); + VectorMA(v[i], tension, dist, v2[i]); + } - CalculateSpline_r( v2, count - 1, out, tension ); + CalculateSpline_r(v2, count - 1, out, tension); - delete[] v2; + delete[] v2; } -void DTrainDrawer::render( RenderStateFlags state ) const { - for ( std::list::const_iterator sp = m_splineList.begin(); sp != m_splineList.end(); sp++ ) { - splinePoint_t* pSP = ( *sp ); +void DTrainDrawer::render(RenderStateFlags state) const +{ + for (std::list::const_iterator sp = m_splineList.begin(); sp != m_splineList.end(); sp++) { + splinePoint_t *pSP = (*sp); - glBegin( GL_LINE_STRIP ); - for ( std::list::const_iterator v = pSP->m_vertexList.begin(); v != pSP->m_vertexList.end(); v++ ) { - glVertex3fv( ( *v )._pnt ); - } - glEnd(); + glBegin(GL_LINE_STRIP); + for (std::list::const_iterator v = pSP->m_vertexList.begin(); v != pSP->m_vertexList.end(); v++) { + glVertex3fv((*v)._pnt); + } + glEnd(); - } + } } -const char* DTrainDrawer_state_wireframe = "$bobtoolz/traindrawer/wireframe"; -const char* DTrainDrawer_state_solid = "$bobtoolz/traindrawer/solid"; - -void DTrainDrawer::constructShaders(){ - OpenGLState state; - GlobalOpenGLStateLibrary().getDefaultState( state ); - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND; - state.m_sort = OpenGLState::eSortOverlayFirst; - state.m_linewidth = 1; - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_linewidth = 1; - GlobalOpenGLStateLibrary().insert( DTrainDrawer_state_wireframe, state ); - - state.m_colour[0] = 1; - state.m_colour[1] = 1; - state.m_colour[2] = 1; - state.m_colour[3] = 1; - state.m_linewidth = 2; - GlobalOpenGLStateLibrary().insert( DTrainDrawer_state_solid, state ); - - m_shader_wireframe = GlobalShaderCache().capture( DTrainDrawer_state_wireframe ); - m_shader_solid = GlobalShaderCache().capture( DTrainDrawer_state_solid ); +const char *DTrainDrawer_state_wireframe = "$bobtoolz/traindrawer/wireframe"; +const char *DTrainDrawer_state_solid = "$bobtoolz/traindrawer/solid"; + +void DTrainDrawer::constructShaders() +{ + OpenGLState state; + GlobalOpenGLStateLibrary().getDefaultState(state); + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND; + state.m_sort = OpenGLState::eSortOverlayFirst; + state.m_linewidth = 1; + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_linewidth = 1; + GlobalOpenGLStateLibrary().insert(DTrainDrawer_state_wireframe, state); + + state.m_colour[0] = 1; + state.m_colour[1] = 1; + state.m_colour[2] = 1; + state.m_colour[3] = 1; + state.m_linewidth = 2; + GlobalOpenGLStateLibrary().insert(DTrainDrawer_state_solid, state); + + m_shader_wireframe = GlobalShaderCache().capture(DTrainDrawer_state_wireframe); + m_shader_solid = GlobalShaderCache().capture(DTrainDrawer_state_solid); } -void DTrainDrawer::destroyShaders(){ - GlobalOpenGLStateLibrary().erase( DTrainDrawer_state_wireframe ); - GlobalOpenGLStateLibrary().erase( DTrainDrawer_state_solid ); - GlobalShaderCache().release( DTrainDrawer_state_wireframe ); - GlobalShaderCache().release( DTrainDrawer_state_solid ); +void DTrainDrawer::destroyShaders() +{ + GlobalOpenGLStateLibrary().erase(DTrainDrawer_state_wireframe); + GlobalOpenGLStateLibrary().erase(DTrainDrawer_state_solid); + GlobalShaderCache().release(DTrainDrawer_state_wireframe); + GlobalShaderCache().release(DTrainDrawer_state_solid); } -void DTrainDrawer::renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - if ( !m_bDisplay ) { - return; - } +void DTrainDrawer::renderSolid(Renderer &renderer, const VolumeTest &volume) const +{ + if (!m_bDisplay) { + return; + } - renderer.SetState( m_shader_wireframe, Renderer::eWireframeOnly ); - renderer.SetState( m_shader_solid, Renderer::eFullMaterials ); - renderer.addRenderable( *this, g_matrix4_identity ); + renderer.SetState(m_shader_wireframe, Renderer::eWireframeOnly); + renderer.SetState(m_shader_solid, Renderer::eFullMaterials); + renderer.addRenderable(*this, g_matrix4_identity); } -void DTrainDrawer::renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - renderSolid( renderer, volume ); + +void DTrainDrawer::renderWireframe(Renderer &renderer, const VolumeTest &volume) const +{ + renderSolid(renderer, volume); } -void AddSplineControl( const char* control, splinePoint_t* pSP ) { - controlPoint_t cp; - strncpy( cp.strName, control, 64 ); +void AddSplineControl(const char *control, splinePoint_t *pSP) +{ + controlPoint_t cp; + strncpy(cp.strName, control, 64); - pSP->m_pointList.push_front( cp ); + pSP->m_pointList.push_front(cp); } -class EntityBuildPaths -{ -mutable DEntity e; -DTrainDrawer& drawer; +class EntityBuildPaths { + mutable DEntity e; + DTrainDrawer &drawer; public: -EntityBuildPaths( DTrainDrawer& drawer ) : drawer( drawer ){ -} -void operator()( scene::Instance& instance ) const { - e.ClearEPairs(); - e.LoadEPairList( Node_getEntity( instance.path().top() ) ); - - const char* classname = e.m_Classname.GetBuffer(); - const char* target; - const char* control; - const char* targetname; - vec3_t vOrigin; - - e.SpawnString( "targetname", NULL, &targetname ); - e.SpawnVector( "origin", "0 0 0", vOrigin ); - - if ( !strcmp( classname, "info_train_spline_main" ) ) { - if ( !targetname ) { - globalOutputStream() << "info_train_spline_main with no targetname"; - return; - } - - e.SpawnString( "target", NULL, &target ); - - if ( !target ) { - drawer.AddControlPoint( targetname, vOrigin ); - } - else { - splinePoint_t* pSP = drawer.AddSplinePoint( targetname, target, vOrigin ); - - e.SpawnString( "control", NULL, &control ); - - if ( control ) { - AddSplineControl( control, pSP ); - - for ( int j = 2;; j++ ) { - char buffer[16]; - sprintf( buffer, "control%i", j ); - - e.SpawnString( buffer, NULL, &control ); - if ( !control ) { - break; - } - - AddSplineControl( control, pSP ); - } - } - } - } - else if ( !strcmp( classname, "info_train_spline_control" ) ) { - if ( !targetname ) { - globalOutputStream() << "info_train_spline_control with no targetname"; - return; - } - - drawer.AddControlPoint( targetname, vOrigin ); - } -} + EntityBuildPaths(DTrainDrawer &drawer) : drawer(drawer) + { + } + + void operator()(scene::Instance &instance) const + { + e.ClearEPairs(); + e.LoadEPairList(Node_getEntity(instance.path().top())); + + const char *classname = e.m_Classname.GetBuffer(); + const char *target; + const char *control; + const char *targetname; + vec3_t vOrigin; + + e.SpawnString("targetname", NULL, &targetname); + e.SpawnVector("origin", "0 0 0", vOrigin); + + if (!strcmp(classname, "info_train_spline_main")) { + if (!targetname) { + globalOutputStream() << "info_train_spline_main with no targetname"; + return; + } + + e.SpawnString("target", NULL, &target); + + if (!target) { + drawer.AddControlPoint(targetname, vOrigin); + } else { + splinePoint_t *pSP = drawer.AddSplinePoint(targetname, target, vOrigin); + + e.SpawnString("control", NULL, &control); + + if (control) { + AddSplineControl(control, pSP); + + for (int j = 2;; j++) { + char buffer[16]; + sprintf(buffer, "control%i", j); + + e.SpawnString(buffer, NULL, &control); + if (!control) { + break; + } + + AddSplineControl(control, pSP); + } + } + } + } else if (!strcmp(classname, "info_train_spline_control")) { + if (!targetname) { + globalOutputStream() << "info_train_spline_control with no targetname"; + return; + } + + drawer.AddControlPoint(targetname, vOrigin); + } + } }; -void DTrainDrawer::BuildPaths() { - Scene_forEachEntity( EntityBuildPaths( *this ) ); +void DTrainDrawer::BuildPaths() +{ + Scene_forEachEntity(EntityBuildPaths(*this)); - std::list::const_iterator sp; - for ( sp = m_splineList.begin(); sp != m_splineList.end(); sp++ ) { - splinePoint_t* pSP = ( *sp ); + std::list::const_iterator sp; + for (sp = m_splineList.begin(); sp != m_splineList.end(); sp++) { + splinePoint_t *pSP = (*sp); - controlPoint_t* pTarget = FindControlPoint( pSP->strTarget ); + controlPoint_t *pTarget = FindControlPoint(pSP->strTarget); - if ( !pTarget ) { - globalOutputStream() << "couldn't find target " << pSP->strTarget; - return; + if (!pTarget) { + globalOutputStream() << "couldn't find target " << pSP->strTarget; + return; // continue; - } + } - pSP->pTarget = pTarget; + pSP->pTarget = pTarget; - for ( std::list::iterator cp = pSP->m_pointList.begin(); cp != pSP->m_pointList.end(); cp++ ) { - controlPoint_t* pControl = FindControlPoint( ( *cp ).strName ); - if ( !pControl ) { - globalOutputStream() << "couldn't find control " << ( *cp ).strName; - return; - } + for (std::list::iterator cp = pSP->m_pointList.begin(); cp != pSP->m_pointList.end(); cp++) { + controlPoint_t *pControl = FindControlPoint((*cp).strName); + if (!pControl) { + globalOutputStream() << "couldn't find control " << (*cp).strName; + return; + } - VectorCopy( pControl->vOrigin, ( *cp ).vOrigin ); - } - } + VectorCopy(pControl->vOrigin, (*cp).vOrigin); + } + } - m_bDisplay = true; + m_bDisplay = true; - for ( sp = m_splineList.begin(); sp != m_splineList.end(); sp++ ) { - splinePoint_t* pSP = ( *sp ); - DPoint out; + for (sp = m_splineList.begin(); sp != m_splineList.end(); sp++) { + splinePoint_t *pSP = (*sp); + DPoint out; - if ( !pSP->pTarget ) { - continue; - } + if (!pSP->pTarget) { + continue; + } - std::size_t count = pSP->m_pointList.size() + 2; - vec3_t* v = new vec3_t[count]; + std::size_t count = pSP->m_pointList.size() + 2; + vec3_t *v = new vec3_t[count]; - VectorCopy( pSP->point.vOrigin, v[0] ); + VectorCopy(pSP->point.vOrigin, v[0]); - int i = 1; - for ( std::list::reverse_iterator cp = pSP->m_pointList.rbegin(); cp != pSP->m_pointList.rend(); cp++ ) { - VectorCopy( ( *cp ).vOrigin, v[i] ); - i++; - } - VectorCopy( pSP->pTarget->vOrigin, v[i] ); + int i = 1; + for (std::list::reverse_iterator cp = pSP->m_pointList.rbegin(); + cp != pSP->m_pointList.rend(); cp++) { + VectorCopy((*cp).vOrigin, v[i]); + i++; + } + VectorCopy(pSP->pTarget->vOrigin, v[i]); - for ( float tension = 0.0f; tension <= 1.f; tension += 0.01f ) { - CalculateSpline_r( v, static_cast( count ), out._pnt, tension ); - pSP->m_vertexList.push_front( out ); - } + for (float tension = 0.0f; tension <= 1.f; tension += 0.01f) { + CalculateSpline_r(v, static_cast( count ), out._pnt, tension); + pSP->m_vertexList.push_front(out); + } - delete[] v; + delete[] v; - VectorCopy( pSP->pTarget->vOrigin, out._pnt ); - pSP->m_vertexList.push_front( out ); - } + VectorCopy(pSP->pTarget->vOrigin, out._pnt); + pSP->m_vertexList.push_front(out); + } - SceneChangeNotify(); + SceneChangeNotify(); } -void DTrainDrawer::AddControlPoint( const char* name, vec_t* origin ){ - controlPoint_t* pCP = new controlPoint_t; +void DTrainDrawer::AddControlPoint(const char *name, vec_t *origin) +{ + controlPoint_t *pCP = new controlPoint_t; - strncpy( pCP->strName, name, 64 ); - VectorCopy( origin, pCP->vOrigin ); + strncpy(pCP->strName, name, 64); + VectorCopy(origin, pCP->vOrigin); - m_pointList.push_back( pCP ); + m_pointList.push_back(pCP); } -splinePoint_t* DTrainDrawer::AddSplinePoint( const char* name, const char* target, vec_t* origin ){ - splinePoint_t* pSP = new splinePoint_t; +splinePoint_t *DTrainDrawer::AddSplinePoint(const char *name, const char *target, vec_t *origin) +{ + splinePoint_t *pSP = new splinePoint_t; - strncpy( pSP->point.strName, name, 64 ); - strncpy( pSP->strTarget, target, 64 ); - VectorCopy( origin, pSP->point.vOrigin ); - m_splineList.push_back( pSP ); + strncpy(pSP->point.strName, name, 64); + strncpy(pSP->strTarget, target, 64); + VectorCopy(origin, pSP->point.vOrigin); + m_splineList.push_back(pSP); - return pSP; + return pSP; } -controlPoint_t* DTrainDrawer::FindControlPoint( const char* name ){ - for ( std::list::const_iterator cp = m_pointList.begin(); cp != m_pointList.end(); cp++ ) { - if ( !strcmp( name, ( *cp )->strName ) ) { - return ( *cp ); - } - } - - for ( std::list::const_iterator sp = m_splineList.begin(); sp != m_splineList.end(); sp++ ) { - if ( !strcmp( name, ( *sp )->point.strName ) ) { - return &( ( *sp )->point ); - } - } - - return NULL; +controlPoint_t *DTrainDrawer::FindControlPoint(const char *name) +{ + for (std::list::const_iterator cp = m_pointList.begin(); cp != m_pointList.end(); cp++) { + if (!strcmp(name, (*cp)->strName)) { + return (*cp); + } + } + + for (std::list::const_iterator sp = m_splineList.begin(); sp != m_splineList.end(); sp++) { + if (!strcmp(name, (*sp)->point.strName)) { + return &((*sp)->point); + } + } + + return NULL; } diff --git a/contrib/bobtoolz/DTrainDrawer.h b/contrib/bobtoolz/DTrainDrawer.h index 2b79f674..b8ae15c9 100644 --- a/contrib/bobtoolz/DTrainDrawer.h +++ b/contrib/bobtoolz/DTrainDrawer.h @@ -36,53 +36,62 @@ #include "renderable.h" class DPoint; + class Shader; typedef struct { - char strName[64]; + char strName[64]; - vec3_t vOrigin; + vec3_t vOrigin; } controlPoint_t; typedef struct { - controlPoint_t point; + controlPoint_t point; - char strControl[64]; - char strTarget[64]; + char strControl[64]; + char strTarget[64]; - std::list m_pointList; - std::list m_vertexList; + std::list m_pointList; + std::list m_vertexList; - controlPoint_t* pTarget; + controlPoint_t *pTarget; } splinePoint_t; -class DTrainDrawer : public Renderable, public OpenGLRenderable -{ +class DTrainDrawer : public Renderable, public OpenGLRenderable { private: -std::list m_splineList; -std::list m_pointList; + std::list m_splineList; + std::list m_pointList; -bool m_bDisplay; -Shader* m_shader_wireframe; -Shader* m_shader_solid; + bool m_bDisplay; + Shader *m_shader_wireframe; + Shader *m_shader_solid; public: -DTrainDrawer(); -virtual ~DTrainDrawer( void ); + DTrainDrawer(); + + virtual ~DTrainDrawer(void); + + void render(RenderStateFlags state) const; + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const; + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const; + + void constructShaders(); + + void destroyShaders(); + + void ClearSplines(); + + void ClearPoints(); + + void BuildPaths(); -void render( RenderStateFlags state ) const; -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const; -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const; + void AddControlPoint(const char *name, vec_t *origin); -void constructShaders(); -void destroyShaders(); + splinePoint_t *AddSplinePoint(const char *name, const char *target, vec_t *origin); -void ClearSplines(); -void ClearPoints(); -void BuildPaths(); -void AddControlPoint( const char* name, vec_t* origin ); -splinePoint_t* AddSplinePoint( const char* name, const char* target, vec_t* origin ); -controlPoint_t* FindControlPoint( const char* name ); + controlPoint_t *FindControlPoint(const char *name); }; #endif // !defined(AFX_TRAINDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_) diff --git a/contrib/bobtoolz/DTreePlanter.cpp b/contrib/bobtoolz/DTreePlanter.cpp index 78fa550d..9207f1ce 100644 --- a/contrib/bobtoolz/DTreePlanter.cpp +++ b/contrib/bobtoolz/DTreePlanter.cpp @@ -34,221 +34,227 @@ #include "scenelib.h" - #include "funchandlers.h" -SignalHandlerResult DTreePlanter::mouseDown( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ){ - if ( button != c_buttonLeft ) { - return SIGNAL_CONTINUE_EMISSION; - } - VIEWTYPE vt = GlobalRadiant().XYWindow_getViewType(); - - switch ( vt ) { - case XY: - break; - case YZ: - case XZ: - default: - return SIGNAL_CONTINUE_EMISSION; - } +SignalHandlerResult +DTreePlanter::mouseDown(const WindowVector &position, ButtonIdentifier button, ModifierFlags modifiers) +{ + if (button != c_buttonLeft) { + return SIGNAL_CONTINUE_EMISSION; + } + VIEWTYPE vt = GlobalRadiant().XYWindow_getViewType(); + + switch (vt) { + case XY: + break; + case YZ: + case XZ: + default: + return SIGNAL_CONTINUE_EMISSION; + } - Vector3 pt, vhit; + Vector3 pt, vhit; - pt = vector3_snapped( GlobalRadiant().XYWindow_windowToWorld( position ), GlobalRadiant().getGridSize() ); + pt = vector3_snapped(GlobalRadiant().XYWindow_windowToWorld(position), GlobalRadiant().getGridSize()); - if ( FindDropPoint( vector3_to_array( pt ), vector3_to_array( vhit ) ) ) { - vhit[2] += m_offset; + if (FindDropPoint(vector3_to_array(pt), vector3_to_array(vhit))) { + vhit[2] += m_offset; - char buffer[128]; - DEntity e( m_entType ); + char buffer[128]; + DEntity e(m_entType); - sprintf( buffer, "%i %i %i", (int)vhit[0], (int)vhit[1], (int)vhit[2] ); - e.AddEPair( "origin", buffer ); + sprintf(buffer, "%i %i %i", (int) vhit[0], (int) vhit[1], (int) vhit[2]); + e.AddEPair("origin", buffer); - if ( m_autoLink ) { + if (m_autoLink) { - const scene::Path* pLastEntity = NULL; - const scene::Path* pThisEntity = NULL; + const scene::Path *pLastEntity = NULL; + const scene::Path *pThisEntity = NULL; - int entpos; - for ( int i = 0; i < 256; i++ ) { - sprintf( buffer, m_linkName, i ); - pThisEntity = FindEntityFromTargetname( buffer ); + int entpos; + for (int i = 0; i < 256; i++) { + sprintf(buffer, m_linkName, i); + pThisEntity = FindEntityFromTargetname(buffer); - if ( pThisEntity ) { - entpos = i; - pLastEntity = pThisEntity; - } - } + if (pThisEntity) { + entpos = i; + pLastEntity = pThisEntity; + } + } - if ( !pLastEntity ) { - sprintf( buffer, m_linkName, 0 ); - } - else { - sprintf( buffer, m_linkName, entpos + 1 ); - } + if (!pLastEntity) { + sprintf(buffer, m_linkName, 0); + } else { + sprintf(buffer, m_linkName, entpos + 1); + } - e.AddEPair( "targetname", buffer ); + e.AddEPair("targetname", buffer); - if ( pLastEntity ) { - DEntity e2; - e2.LoadFromEntity( pLastEntity->top(), true ); - e2.AddEPair( "target", buffer ); - e2.RemoveFromRadiant(); - e2.BuildInRadiant( false ); - } + if (pLastEntity) { + DEntity e2; + e2.LoadFromEntity(pLastEntity->top(), true); + e2.AddEPair("target", buffer); + e2.RemoveFromRadiant(); + e2.BuildInRadiant(false); + } - } + } - if ( m_setAngles ) { - int angleYaw = ( rand() % ( m_maxYaw - m_minYaw + 1 ) ) + m_minYaw; - int anglePitch = ( rand() % ( m_maxPitch - m_minPitch + 1 ) ) + m_minPitch; + if (m_setAngles) { + int angleYaw = (rand() % (m_maxYaw - m_minYaw + 1)) + m_minYaw; + int anglePitch = (rand() % (m_maxPitch - m_minPitch + 1)) + m_minPitch; - sprintf( buffer, "%i %i 0", anglePitch, angleYaw ); - e.AddEPair( "angles", buffer ); - } + sprintf(buffer, "%i %i 0", anglePitch, angleYaw); + e.AddEPair("angles", buffer); + } - if ( m_numModels ) { - int treetype = rand() % m_numModels; - e.AddEPair( "model", m_trees[treetype].name ); - } + if (m_numModels) { + int treetype = rand() % m_numModels; + e.AddEPair("model", m_trees[treetype].name); + } - if ( m_useScale ) { - float scale = ( ( ( rand() % 1000 ) * 0.001f ) * ( m_maxScale - m_minScale ) ) + m_minScale; + if (m_useScale) { + float scale = (((rand() % 1000) * 0.001f) * (m_maxScale - m_minScale)) + m_minScale; - sprintf( buffer, "%f", scale ); - e.AddEPair( "modelscale", buffer ); - } + sprintf(buffer, "%f", scale); + e.AddEPair("modelscale", buffer); + } - e.BuildInRadiant( false ); - } + e.BuildInRadiant(false); + } - if ( m_autoLink ) { - DoTrainPathPlot(); - } + if (m_autoLink) { + DoTrainPathPlot(); + } - return SIGNAL_STOP_EMISSION; + return SIGNAL_STOP_EMISSION; } -bool DTreePlanter::FindDropPoint( vec3_t in, vec3_t out ) { - DPlane p1; - DPlane p2; - - vec3_t vUp = { 0, 0, 1 }; - vec3_t vForward = { 0, 1, 0 }; - vec3_t vLeft = { 1, 0, 0 }; - - in[2] = 65535; - - VectorCopy( in, p1.points[0] ); - VectorCopy( in, p1.points[1] ); - VectorCopy( in, p1.points[2] ); - VectorMA( p1.points[1], 20, vUp, p1.points[1] ); - VectorMA( p1.points[1], 20, vLeft, p1.points[2] ); - - VectorCopy( in, p2.points[0] ); - VectorCopy( in, p2.points[1] ); - VectorCopy( in, p2.points[2] ); - VectorMA( p1.points[1], 20, vUp, p2.points[1] ); - VectorMA( p1.points[1], 20, vForward, p2.points[2] ); - - p1.Rebuild(); - p2.Rebuild(); - - bool found = false; - vec3_t temp; - vec_t dist; - int cnt = m_world.GetIDMax(); - for ( int i = 0; i < cnt; i++ ) { - DBrush* pBrush = m_world.GetBrushForID( i ); - - if ( pBrush->IntersectsWith( &p1, &p2, temp ) ) { - vec3_t diff; - vec_t tempdist; - VectorSubtract( in, temp, diff ); - tempdist = VectorLength( diff ); - if ( !found || ( tempdist < dist ) ) { - dist = tempdist; - VectorCopy( temp, out ); - found = true; - } - } - } - - return found; +bool DTreePlanter::FindDropPoint(vec3_t in, vec3_t out) +{ + DPlane p1; + DPlane p2; + + vec3_t vUp = {0, 0, 1}; + vec3_t vForward = {0, 1, 0}; + vec3_t vLeft = {1, 0, 0}; + + in[2] = 65535; + + VectorCopy(in, p1.points[0]); + VectorCopy(in, p1.points[1]); + VectorCopy(in, p1.points[2]); + VectorMA(p1.points[1], 20, vUp, p1.points[1]); + VectorMA(p1.points[1], 20, vLeft, p1.points[2]); + + VectorCopy(in, p2.points[0]); + VectorCopy(in, p2.points[1]); + VectorCopy(in, p2.points[2]); + VectorMA(p1.points[1], 20, vUp, p2.points[1]); + VectorMA(p1.points[1], 20, vForward, p2.points[2]); + + p1.Rebuild(); + p2.Rebuild(); + + bool found = false; + vec3_t temp; + vec_t dist; + int cnt = m_world.GetIDMax(); + for (int i = 0; i < cnt; i++) { + DBrush *pBrush = m_world.GetBrushForID(i); + + if (pBrush->IntersectsWith(&p1, &p2, temp)) { + vec3_t diff; + vec_t tempdist; + VectorSubtract(in, temp, diff); + tempdist = VectorLength(diff); + if (!found || (tempdist < dist)) { + dist = tempdist; + VectorCopy(temp, out); + found = true; + } + } + } + + return found; } -class TreePlanterDropEntityIfSelected -{ -mutable DEntity ent; -DTreePlanter& planter; +class TreePlanterDropEntityIfSelected { + mutable DEntity ent; + DTreePlanter &planter; public: -TreePlanterDropEntityIfSelected( DTreePlanter& planter ) : planter( planter ){ -} -void operator()( scene::Instance& instance ) const { - if ( !instance.isSelected() ) { - return; - } - ent.LoadFromEntity( instance.path().top() ); - - DEPair* pEpair = ent.FindEPairByKey( "origin" ); - if ( !pEpair ) { - return; - } - - vec3_t vec, out; - sscanf( pEpair->value.GetBuffer(), "%f %f %f", &vec[0], &vec[1], &vec[2] ); - - planter.FindDropPoint( vec, out ); - - char buffer[256]; - sprintf( buffer, "%f %f %f", out[0], out[1], out[2] ); - ent.AddEPair( "origin", buffer ); - ent.RemoveFromRadiant(); - ent.BuildInRadiant( false ); -} + TreePlanterDropEntityIfSelected(DTreePlanter &planter) : planter(planter) + { + } + + void operator()(scene::Instance &instance) const + { + if (!instance.isSelected()) { + return; + } + ent.LoadFromEntity(instance.path().top()); + + DEPair *pEpair = ent.FindEPairByKey("origin"); + if (!pEpair) { + return; + } + + vec3_t vec, out; + sscanf(pEpair->value.GetBuffer(), "%f %f %f", &vec[0], &vec[1], &vec[2]); + + planter.FindDropPoint(vec, out); + + char buffer[256]; + sprintf(buffer, "%f %f %f", out[0], out[1], out[2]); + ent.AddEPair("origin", buffer); + ent.RemoveFromRadiant(); + ent.BuildInRadiant(false); + } }; -void DTreePlanter::DropEntsToGround( void ) { - Scene_forEachEntity( TreePlanterDropEntityIfSelected( *this ) ); +void DTreePlanter::DropEntsToGround(void) +{ + Scene_forEachEntity(TreePlanterDropEntityIfSelected(*this)); } -void DTreePlanter::MakeChain( int linkNum, const char* linkName ) { - char buffer[256]; - int i; - for ( i = 0; i < linkNum; i++ ) { - DEntity e( "info_train_spline_main" ); +void DTreePlanter::MakeChain(int linkNum, const char *linkName) +{ + char buffer[256]; + int i; + for (i = 0; i < linkNum; i++) { + DEntity e("info_train_spline_main"); - sprintf( buffer, "%s_pt%i", linkName, i ); - e.AddEPair( "targetname", buffer ); + sprintf(buffer, "%s_pt%i", linkName, i); + e.AddEPair("targetname", buffer); - sprintf( buffer, "0 %i 0", i * 64 ); - e.AddEPair( "origin", buffer ); + sprintf(buffer, "0 %i 0", i * 64); + e.AddEPair("origin", buffer); - if ( i != m_linkNum - 1 ) { - sprintf( buffer, "%s_pt%i", linkName, i + 1 ); - e.AddEPair( "target", buffer ); + if (i != m_linkNum - 1) { + sprintf(buffer, "%s_pt%i", linkName, i + 1); + e.AddEPair("target", buffer); - sprintf( buffer, "%s_ctl%i", linkName, i ); - e.AddEPair( "control", buffer ); - } - e.BuildInRadiant( false ); - } + sprintf(buffer, "%s_ctl%i", linkName, i); + e.AddEPair("control", buffer); + } + e.BuildInRadiant(false); + } - for ( i = 0; i < linkNum - 1; i++ ) { - DEntity e( "info_train_spline_control" ); + for (i = 0; i < linkNum - 1; i++) { + DEntity e("info_train_spline_control"); - sprintf( buffer, "%s_ctl%i", linkName, i ); - e.AddEPair( "targetname", buffer ); + sprintf(buffer, "%s_ctl%i", linkName, i); + e.AddEPair("targetname", buffer); - sprintf( buffer, "0 %i 0", ( i * 64 ) + 32 ); - e.AddEPair( "origin", buffer ); + sprintf(buffer, "0 %i 0", (i * 64) + 32); + e.AddEPair("origin", buffer); - e.BuildInRadiant( false ); - } + e.BuildInRadiant(false); + } } -void DTreePlanter::SelectChain( void ) { +void DTreePlanter::SelectChain(void) +{ /* char buffer[256]; for(int i = 0; i < m_linkNum; i++) { diff --git a/contrib/bobtoolz/DTreePlanter.h b/contrib/bobtoolz/DTreePlanter.h index 102976d8..5d661232 100644 --- a/contrib/bobtoolz/DTreePlanter.h +++ b/contrib/bobtoolz/DTreePlanter.h @@ -32,183 +32,198 @@ const int MAX_QPATH = 64; typedef struct treeModel_s { - char name[MAX_QPATH]; + char name[MAX_QPATH]; } treeModel_t; const int MAX_TP_MODELS = 256; class DTreePlanter { -MouseEventHandlerId m_mouseDown; -SignalHandlerId m_destroyed; + MouseEventHandlerId m_mouseDown; + SignalHandlerId m_destroyed; public: -SignalHandlerResult mouseDown( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ); -typedef Member MouseDownCaller; -void destroyed(){ - m_mouseDown = MouseEventHandlerId(); - m_destroyed = SignalHandlerId(); -} -typedef Member DestroyedCaller; - -DTreePlanter() { - m_numModels = 0; - m_offset = 0; - m_maxPitch = 0; - m_minPitch = 0; - m_maxYaw = 0; - m_minYaw = 0; - m_setAngles = false; - m_useScale = false; - m_autoLink = false; - m_linkNum = 0; - - m_world.LoadSelectedBrushes(); - - char buffer[256]; - GetFilename( buffer, "bt/tp_ent.txt" ); - - FILE* file = fopen( buffer, "rb" ); - if ( file ) { - fseek( file, 0, SEEK_END ); - int len = ftell( file ); - fseek( file, 0, SEEK_SET ); - - if ( len ) { - char* buf = new char[len + 1]; - buf[len] = '\0'; - // parser will do the cleanup, dont delete. - - fread( buf, len, 1, file ); - - CScriptParser parser; - parser.SetScript( buf ); - - ReadConfig( &parser ); - } - - fclose( file ); - } - - m_mouseDown = GlobalRadiant().XYWindowMouseDown_connect( makeSignalHandler3( MouseDownCaller(), *this ) ); - m_destroyed = GlobalRadiant().XYWindowDestroyed_connect( makeSignalHandler( DestroyedCaller(), *this ) ); -} - -virtual ~DTreePlanter(){ - if ( !m_mouseDown.isNull() ) { - GlobalRadiant().XYWindowMouseDown_disconnect( m_mouseDown ); - } - if ( !m_destroyed.isNull() ) { - GlobalRadiant().XYWindowDestroyed_disconnect( m_destroyed ); - } -} - -#define MT( t ) string_equal_nocase( pToken, t ) + SignalHandlerResult mouseDown(const WindowVector &position, ButtonIdentifier button, ModifierFlags modifiers); + + typedef Member MouseDownCaller; + + void destroyed() + { + m_mouseDown = MouseEventHandlerId(); + m_destroyed = SignalHandlerId(); + } + + typedef Member DestroyedCaller; + + DTreePlanter() + { + m_numModels = 0; + m_offset = 0; + m_maxPitch = 0; + m_minPitch = 0; + m_maxYaw = 0; + m_minYaw = 0; + m_setAngles = false; + m_useScale = false; + m_autoLink = false; + m_linkNum = 0; + + m_world.LoadSelectedBrushes(); + + char buffer[256]; + GetFilename(buffer, "bt/tp_ent.txt"); + + FILE *file = fopen(buffer, "rb"); + if (file) { + fseek(file, 0, SEEK_END); + int len = ftell(file); + fseek(file, 0, SEEK_SET); + + if (len) { + char *buf = new char[len + 1]; + buf[len] = '\0'; + // parser will do the cleanup, dont delete. + + fread(buf, len, 1, file); + + CScriptParser parser; + parser.SetScript(buf); + + ReadConfig(&parser); + } + + fclose(file); + } + + m_mouseDown = GlobalRadiant().XYWindowMouseDown_connect(makeSignalHandler3(MouseDownCaller(), *this)); + m_destroyed = GlobalRadiant().XYWindowDestroyed_connect(makeSignalHandler(DestroyedCaller(), *this)); + } + + virtual ~DTreePlanter() + { + if (!m_mouseDown.isNull()) { + GlobalRadiant().XYWindowMouseDown_disconnect(m_mouseDown); + } + if (!m_destroyed.isNull()) { + GlobalRadiant().XYWindowDestroyed_disconnect(m_destroyed); + } + } + +#define MT(t) string_equal_nocase( pToken, t ) #define GT pToken = pScriptParser->GetToken( true ) #define CT if ( !*pToken ) { return; } -void ReadConfig( CScriptParser* pScriptParser ) { - const char* GT; - CT; + void ReadConfig(CScriptParser *pScriptParser) + { + const char *GT; + CT; - do { - GT; - if ( *pToken == '}' ) { - break; - } + do { + GT; + if (*pToken == '}') { + break; + } - if ( MT( "model" ) ) { - if ( m_numModels >= MAX_TP_MODELS ) { - return; - } + if (MT("model")) { + if (m_numModels >= MAX_TP_MODELS) { + return; + } - GT; CT; + GT; + CT; - strncpy( m_trees[m_numModels++].name, pToken, MAX_QPATH ); - } - else if ( MT( "link" ) ) { - GT; CT; + strncpy(m_trees[m_numModels++].name, pToken, MAX_QPATH); + } else if (MT("link")) { + GT; + CT; - strncpy( m_linkName, pToken, MAX_QPATH ); + strncpy(m_linkName, pToken, MAX_QPATH); - m_autoLink = true; - } - else if ( MT( "entity" ) ) { - GT; CT; + m_autoLink = true; + } else if (MT("entity")) { + GT; + CT; - strncpy( m_entType, pToken, MAX_QPATH ); - } - else if ( MT( "offset" ) ) { - GT; CT; + strncpy(m_entType, pToken, MAX_QPATH); + } else if (MT("offset")) { + GT; + CT; - m_offset = atoi( pToken ); - } - else if ( MT( "pitch" ) ) { - GT; CT; + m_offset = atoi(pToken); + } else if (MT("pitch")) { + GT; + CT; - m_minPitch = atoi( pToken ); + m_minPitch = atoi(pToken); - GT; CT; + GT; + CT; - m_maxPitch = atoi( pToken ); + m_maxPitch = atoi(pToken); - m_setAngles = true; - } - else if ( MT( "yaw" ) ) { - GT; CT; + m_setAngles = true; + } else if (MT("yaw")) { + GT; + CT; - m_minYaw = atoi( pToken ); + m_minYaw = atoi(pToken); - GT; CT; + GT; + CT; - m_maxYaw = atoi( pToken ); + m_maxYaw = atoi(pToken); - m_setAngles = true; - } - else if ( MT( "scale" ) ) { - GT; CT; + m_setAngles = true; + } else if (MT("scale")) { + GT; + CT; - m_minScale = static_cast( atof( pToken ) ); + m_minScale = static_cast( atof(pToken)); - GT; CT; + GT; + CT; - m_maxScale = static_cast( atof( pToken ) ); + m_maxScale = static_cast( atof(pToken)); - m_useScale = true; - } - else if ( MT( "numlinks" ) ) { - GT; CT; + m_useScale = true; + } else if (MT("numlinks")) { + GT; + CT; - m_linkNum = atoi( pToken ); - } - } while ( true ); -} + m_linkNum = atoi(pToken); + } + } while (true); + } -bool FindDropPoint( vec3_t in, vec3_t out ); -void DropEntsToGround( void ); -void MakeChain( int linkNum, const char* linkName ); -void SelectChain( void ); + bool FindDropPoint(vec3_t in, vec3_t out); + + void DropEntsToGround(void); + + void MakeChain(int linkNum, const char *linkName); + + void SelectChain(void); private: -DEntity m_world; + DEntity m_world; -treeModel_t m_trees[MAX_TP_MODELS]; + treeModel_t m_trees[MAX_TP_MODELS]; -int m_numModels; -int m_offset; -int m_maxPitch; -int m_minPitch; -int m_maxYaw; -int m_minYaw; + int m_numModels; + int m_offset; + int m_maxPitch; + int m_minPitch; + int m_maxYaw; + int m_minYaw; -char m_entType[MAX_QPATH]; -char m_linkName[MAX_QPATH]; -int m_linkNum; + char m_entType[MAX_QPATH]; + char m_linkName[MAX_QPATH]; + int m_linkNum; -float m_minScale; -float m_maxScale; + float m_minScale; + float m_maxScale; -bool m_useScale; -bool m_setAngles; -bool m_autoLink; + bool m_useScale; + bool m_setAngles; + bool m_autoLink; }; #endif diff --git a/contrib/bobtoolz/DVisDrawer.cpp b/contrib/bobtoolz/DVisDrawer.cpp index 9dc37db5..3699a477 100644 --- a/contrib/bobtoolz/DVisDrawer.cpp +++ b/contrib/bobtoolz/DVisDrawer.cpp @@ -39,100 +39,110 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DVisDrawer::DVisDrawer(){ - m_list = NULL; +DVisDrawer::DVisDrawer() +{ + m_list = NULL; - constructShaders(); - GlobalShaderCache().attachRenderable( *this ); + constructShaders(); + GlobalShaderCache().attachRenderable(*this); } -DVisDrawer::~DVisDrawer(){ - GlobalShaderCache().detachRenderable( *this ); - destroyShaders(); +DVisDrawer::~DVisDrawer() +{ + GlobalShaderCache().detachRenderable(*this); + destroyShaders(); - g_VisView = NULL; + g_VisView = NULL; } ////////////////////////////////////////////////////////////////////// // Implementation ////////////////////////////////////////////////////////////////////// -const char* g_state_solid = "$bobtoolz/visdrawer/solid"; -const char* g_state_wireframe = "$bobtoolz/visdrawer/wireframe"; +const char *g_state_solid = "$bobtoolz/visdrawer/solid"; +const char *g_state_wireframe = "$bobtoolz/visdrawer/wireframe"; -void DVisDrawer::constructShaders(){ - OpenGLState state; - GlobalOpenGLStateLibrary().getDefaultState( state ); - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_COLOURCHANGE; - state.m_linewidth = 1; +void DVisDrawer::constructShaders() +{ + OpenGLState state; + GlobalOpenGLStateLibrary().getDefaultState(state); + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_COLOURCHANGE; + state.m_linewidth = 1; - GlobalOpenGLStateLibrary().insert( g_state_wireframe, state ); + GlobalOpenGLStateLibrary().insert(g_state_wireframe, state); - GlobalOpenGLStateLibrary().getDefaultState( state ); - state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_COLOURCHANGE | RENDER_SMOOTH | RENDER_DEPTHWRITE; + GlobalOpenGLStateLibrary().getDefaultState(state); + state.m_state = + RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_COLOURCHANGE | RENDER_SMOOTH | RENDER_DEPTHWRITE; - GlobalOpenGLStateLibrary().insert( g_state_solid, state ); + GlobalOpenGLStateLibrary().insert(g_state_solid, state); - m_shader_solid = GlobalShaderCache().capture( g_state_solid ); - m_shader_wireframe = GlobalShaderCache().capture( g_state_wireframe ); + m_shader_solid = GlobalShaderCache().capture(g_state_solid); + m_shader_wireframe = GlobalShaderCache().capture(g_state_wireframe); } -void DVisDrawer::destroyShaders(){ - GlobalShaderCache().release( g_state_solid ); - GlobalShaderCache().release( g_state_wireframe ); - GlobalOpenGLStateLibrary().erase( g_state_solid ); - GlobalOpenGLStateLibrary().erase( g_state_wireframe ); +void DVisDrawer::destroyShaders() +{ + GlobalShaderCache().release(g_state_solid); + GlobalShaderCache().release(g_state_wireframe); + GlobalOpenGLStateLibrary().erase(g_state_solid); + GlobalOpenGLStateLibrary().erase(g_state_wireframe); } -void DVisDrawer::render( RenderStateFlags state ) const { - //bleh - std::list::const_iterator l = m_list->begin(); +void DVisDrawer::render(RenderStateFlags state) const +{ + //bleh + std::list::const_iterator l = m_list->begin(); - for (; l != m_list->end(); l++ ) - { - DWinding* w = *l; + for (; l != m_list->end(); l++) { + DWinding *w = *l; - glColor4f( w->clr[0], w->clr[1], w->clr[2], 0.5f ); + glColor4f(w->clr[0], w->clr[1], w->clr[2], 0.5f); - glBegin( GL_POLYGON ); - for ( int i = 0; i < w->numpoints; i++ ) { - glVertex3f( ( w->p[i] )[0], ( w->p[i] )[1], ( w->p[i] )[2] ); - } - glEnd(); - } + glBegin(GL_POLYGON); + for (int i = 0; i < w->numpoints; i++) { + glVertex3f((w->p[i])[0], (w->p[i])[1], (w->p[i])[2]); + } + glEnd(); + } } -void DVisDrawer::renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - if ( !m_list ) { - return; - } +void DVisDrawer::renderWireframe(Renderer &renderer, const VolumeTest &volume) const +{ + if (!m_list) { + return; + } - renderer.SetState( m_shader_wireframe, Renderer::eWireframeOnly ); + renderer.SetState(m_shader_wireframe, Renderer::eWireframeOnly); - renderer.addRenderable( *this, g_matrix4_identity ); + renderer.addRenderable(*this, g_matrix4_identity); } -void DVisDrawer::renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - if ( !m_list ) { - return; - } +void DVisDrawer::renderSolid(Renderer &renderer, const VolumeTest &volume) const +{ + if (!m_list) { + return; + } - renderer.SetState( m_shader_solid, Renderer::eWireframeOnly ); - renderer.SetState( m_shader_solid, Renderer::eFullMaterials ); + renderer.SetState(m_shader_solid, Renderer::eWireframeOnly); + renderer.SetState(m_shader_solid, Renderer::eFullMaterials); - renderer.addRenderable( *this, g_matrix4_identity ); + renderer.addRenderable(*this, g_matrix4_identity); } -void DVisDrawer::SetList( std::list *pointList ){ - if ( m_list ) { - ClearPoints(); - } +void DVisDrawer::SetList(std::list *pointList) +{ + if (m_list) { + ClearPoints(); + } - m_list = pointList; + m_list = pointList; } -void DVisDrawer::ClearPoints(){ - std::list::const_iterator deadPoint = m_list->begin(); - for (; deadPoint != m_list->end(); deadPoint++ ) - delete *deadPoint; - m_list->clear(); +void DVisDrawer::ClearPoints() +{ + std::list::const_iterator deadPoint = m_list->begin(); + for (; deadPoint != m_list->end(); deadPoint++) { + delete *deadPoint; + } + m_list->clear(); } diff --git a/contrib/bobtoolz/DVisDrawer.h b/contrib/bobtoolz/DVisDrawer.h index 3ec5e217..11b5d215 100644 --- a/contrib/bobtoolz/DVisDrawer.h +++ b/contrib/bobtoolz/DVisDrawer.h @@ -35,27 +35,31 @@ #include "DWinding.h" -class DVisDrawer : public Renderable, public OpenGLRenderable -{ -Shader* m_shader_solid; -Shader* m_shader_wireframe; +class DVisDrawer : public Renderable, public OpenGLRenderable { + Shader *m_shader_solid; + Shader *m_shader_wireframe; public: -DVisDrawer(); -virtual ~DVisDrawer(); + DVisDrawer(); + + virtual ~DVisDrawer(); protected: -std::list* m_list; -int refCount; + std::list *m_list; + int refCount; public: -void ClearPoints(); -void SetList( std::list* pointList ); + void ClearPoints(); + + void SetList(std::list *pointList); + + void render(RenderStateFlags state) const; + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const; + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const; -void render( RenderStateFlags state ) const; -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const; -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const; + void constructShaders(); -void constructShaders(); -void destroyShaders(); + void destroyShaders(); }; diff --git a/contrib/bobtoolz/DWinding.cpp b/contrib/bobtoolz/DWinding.cpp index e4dc026d..7f42bed9 100644 --- a/contrib/bobtoolz/DWinding.cpp +++ b/contrib/bobtoolz/DWinding.cpp @@ -32,15 +32,17 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DWinding::DWinding(){ - numpoints = 0; - p = NULL; +DWinding::DWinding() +{ + numpoints = 0; + p = NULL; } -DWinding::~DWinding(){ - if ( p ) { - delete[] p; - } +DWinding::~DWinding() +{ + if (p) { + delete[] p; + } } ////////////////////////////////////////////////////////////////////// @@ -49,447 +51,440 @@ DWinding::~DWinding(){ const int BOGUS_RANGE = 4096; -void DWinding::AllocWinding( int points ){ - numpoints = points; - if ( p ) { - delete[] p; - } - p = new vec3_t[points]; +void DWinding::AllocWinding(int points) +{ + numpoints = points; + if (p) { + delete[] p; + } + p = new vec3_t[points]; } -vec_t DWinding::WindingArea(){ - vec3_t d1, d2, cross; - vec_t total; +vec_t DWinding::WindingArea() +{ + vec3_t d1, d2, cross; + vec_t total; - total = 0; - for ( int i = 2; i < numpoints ; i++ ) - { - VectorSubtract( p[i - 1], p[0], d1 ); - VectorSubtract( p[i], p[0], d2 ); + total = 0; + for (int i = 2; i < numpoints; i++) { + VectorSubtract(p[i - 1], p[0], d1); + VectorSubtract(p[i], p[0], d2); - CrossProduct( d1, d2, cross ); + CrossProduct(d1, d2, cross); - total += 0.5f * VectorLength( cross ); - } + total += 0.5f * VectorLength(cross); + } - return total; + return total; } -void DWinding::RemoveColinearPoints(){ - vec3_t p2[MAX_POINTS_ON_WINDING]; - - int nump = 0; - for ( int i = 0; i < numpoints; i++ ) - { - int j = ( i + 1 ) % numpoints; - int k = ( i + numpoints - 1 ) % numpoints; - - vec3_t v1, v2; - VectorSubtract( p[j], p[i], v1 ); - VectorSubtract( p[i], p[k], v2 ); - VectorNormalize( v1, v1 ); - VectorNormalize( v2, v2 ); - - if ( DotProduct( v1, v2 ) < 0.999 ) { - VectorCopy( p[i], p2[nump] ); - nump++; - } - } - - if ( nump == numpoints ) { - return; - } - - AllocWinding( nump ); - memcpy( p, p2, nump * sizeof( vec3_t ) ); +void DWinding::RemoveColinearPoints() +{ + vec3_t p2[MAX_POINTS_ON_WINDING]; + + int nump = 0; + for (int i = 0; i < numpoints; i++) { + int j = (i + 1) % numpoints; + int k = (i + numpoints - 1) % numpoints; + + vec3_t v1, v2; + VectorSubtract(p[j], p[i], v1); + VectorSubtract(p[i], p[k], v2); + VectorNormalize(v1, v1); + VectorNormalize(v2, v2); + + if (DotProduct(v1, v2) < 0.999) { + VectorCopy(p[i], p2[nump]); + nump++; + } + } + + if (nump == numpoints) { + return; + } + + AllocWinding(nump); + memcpy(p, p2, nump * sizeof(vec3_t)); } -DPlane* DWinding::WindingPlane(){ - DPlane* newPlane = new DPlane( p[0], p[1], p[2], NULL ); - return newPlane; +DPlane *DWinding::WindingPlane() +{ + DPlane *newPlane = new DPlane(p[0], p[1], p[2], NULL); + return newPlane; } -void DWinding::WindingBounds( vec3_t mins, vec3_t maxs ){ - if ( numpoints == 0 ) { - return; - } - - VectorCopy( mins, p[0] ); - VectorCopy( maxs, p[0] ); - - for ( int i = 1; i < numpoints ; i++ ) - { - for ( int j = 0; j < 3; j++ ) - { - vec_t v = p[i][j]; - if ( v < mins[j] ) { - mins[j] = v; - } - if ( v > maxs[j] ) { - maxs[j] = v; - } - } - } +void DWinding::WindingBounds(vec3_t mins, vec3_t maxs) +{ + if (numpoints == 0) { + return; + } + + VectorCopy(mins, p[0]); + VectorCopy(maxs, p[0]); + + for (int i = 1; i < numpoints; i++) { + for (int j = 0; j < 3; j++) { + vec_t v = p[i][j]; + if (v < mins[j]) { + mins[j] = v; + } + if (v > maxs[j]) { + maxs[j] = v; + } + } + } } -void DWinding::WindingCentre( vec3_t centre ){ - VectorCopy( vec3_origin, centre ); - for ( int i = 0; i < numpoints; i++ ) - VectorAdd( p[i], centre, centre ); +void DWinding::WindingCentre(vec3_t centre) +{ + VectorCopy(vec3_origin, centre); + for (int i = 0; i < numpoints; i++) + VectorAdd(p[i], centre, centre); - float scale = 1.0f / numpoints; - VectorScale( centre, scale, centre ); + float scale = 1.0f / numpoints; + VectorScale(centre, scale, centre); } -DWinding* DWinding::CopyWinding(){ - DWinding* c = new DWinding; - c->AllocWinding( numpoints ); - memcpy( c->p, p, numpoints * sizeof( vec3_t ) ); - return c; +DWinding *DWinding::CopyWinding() +{ + DWinding *c = new DWinding; + c->AllocWinding(numpoints); + memcpy(c->p, p, numpoints * sizeof(vec3_t)); + return c; } -int DWinding::WindingOnPlaneSide( vec3_t normal, vec_t dist ){ - bool front = false; - bool back = false; - - for ( int i = 0; i < numpoints; i++ ) - { - vec_t d = DotProduct( p[i], normal ) - dist; - if ( d < -ON_EPSILON ) { - if ( front ) { - return SIDE_CROSS; - } - back = true; - continue; - } - if ( d > ON_EPSILON ) { - if ( back ) { - return SIDE_CROSS; - } - front = true; - continue; - } - } - - if ( back ) { - return SIDE_BACK; - } - if ( front ) { - return SIDE_FRONT; - } - return SIDE_ON; +int DWinding::WindingOnPlaneSide(vec3_t normal, vec_t dist) +{ + bool front = false; + bool back = false; + + for (int i = 0; i < numpoints; i++) { + vec_t d = DotProduct(p[i], normal) - dist; + if (d < -ON_EPSILON) { + if (front) { + return SIDE_CROSS; + } + back = true; + continue; + } + if (d > ON_EPSILON) { + if (back) { + return SIDE_CROSS; + } + front = true; + continue; + } + } + + if (back) { + return SIDE_BACK; + } + if (front) { + return SIDE_FRONT; + } + return SIDE_ON; } -void DWinding::CheckWinding(){ - vec_t *p1, *p2; - vec_t edgedist; - vec3_t dir, edgenormal; - - if ( numpoints < 3 ) { - globalOutputStream() << "CheckWinding: " << numpoints << " points\n"; - } - - vec_t area = WindingArea(); - if ( area < 1 ) { - globalOutputStream() << "CheckWinding: " << area << " area\n"; - } - - DPlane* wPlane = WindingPlane(); - int i; - for ( i = 0; i < numpoints; i++ ) - { - p1 = p[i]; - - int j; - for ( j = 0; j < 3; j++ ) - if ( p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE ) { - globalOutputStream() << "CheckFace: BOGUS_RANGE: " << p1[j] << "\n"; - } - - j = i + 1 == numpoints ? 0 : i + 1; - - // check the point is on the face plane - vec_t d = DotProduct( p1, wPlane->normal ) - wPlane->_d; - if ( d < -ON_EPSILON || d > ON_EPSILON ) { - globalOutputStream() << "CheckWinding: point off plane\n"; - } - - // check the edge isnt degenerate - p2 = p[j]; - VectorSubtract( p2, p1, dir ); - - if ( VectorLength( dir ) < ON_EPSILON ) { - globalOutputStream() << "CheckWinding: degenerate edge\n"; - } - - CrossProduct( wPlane->normal, dir, edgenormal ); - VectorNormalize( edgenormal, edgenormal ); - edgedist = DotProduct( p1, edgenormal ); - - // all other points must be on front side - for ( j = 0 ; j < numpoints ; j++ ) - { - if ( j == i ) { - continue; - } - - d = DotProduct( p[j], edgenormal ); - if ( d > ( edgedist + ON_EPSILON ) ) { - globalOutputStream() << "CheckWinding: non-convex\n"; - } - } - } - - delete wPlane; +void DWinding::CheckWinding() +{ + vec_t *p1, *p2; + vec_t edgedist; + vec3_t dir, edgenormal; + + if (numpoints < 3) { + globalOutputStream() << "CheckWinding: " << numpoints << " points\n"; + } + + vec_t area = WindingArea(); + if (area < 1) { + globalOutputStream() << "CheckWinding: " << area << " area\n"; + } + + DPlane *wPlane = WindingPlane(); + int i; + for (i = 0; i < numpoints; i++) { + p1 = p[i]; + + int j; + for (j = 0; j < 3; j++) { + if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE) { + globalOutputStream() << "CheckFace: BOGUS_RANGE: " << p1[j] << "\n"; + } + } + + j = i + 1 == numpoints ? 0 : i + 1; + + // check the point is on the face plane + vec_t d = DotProduct(p1, wPlane->normal) - wPlane->_d; + if (d < -ON_EPSILON || d > ON_EPSILON) { + globalOutputStream() << "CheckWinding: point off plane\n"; + } + + // check the edge isnt degenerate + p2 = p[j]; + VectorSubtract(p2, p1, dir); + + if (VectorLength(dir) < ON_EPSILON) { + globalOutputStream() << "CheckWinding: degenerate edge\n"; + } + + CrossProduct(wPlane->normal, dir, edgenormal); + VectorNormalize(edgenormal, edgenormal); + edgedist = DotProduct(p1, edgenormal); + + // all other points must be on front side + for (j = 0; j < numpoints; j++) { + if (j == i) { + continue; + } + + d = DotProduct(p[j], edgenormal); + if (d > (edgedist + ON_EPSILON)) { + globalOutputStream() << "CheckWinding: non-convex\n"; + } + } + } + + delete wPlane; } -DWinding* DWinding::ReverseWinding(){ - DWinding* c = new DWinding; - c->AllocWinding( numpoints ); +DWinding *DWinding::ReverseWinding() +{ + DWinding *c = new DWinding; + c->AllocWinding(numpoints); - for ( int i = 0; i < numpoints ; i++ ) - VectorCopy( p[numpoints - 1 - i], c->p[i] ); + for (int i = 0; i < numpoints; i++) + VectorCopy(p[numpoints - 1 - i], c->p[i]); - return c; + return c; } -bool DWinding::ChopWindingInPlace( DPlane* chopPlane, vec_t epsilon ){ - vec_t dists[MAX_POINTS_ON_WINDING + 4]; - int sides[MAX_POINTS_ON_WINDING + 4]; - int counts[3]; - vec_t *p1, *p2; - vec3_t mid; +bool DWinding::ChopWindingInPlace(DPlane *chopPlane, vec_t epsilon) +{ + vec_t dists[MAX_POINTS_ON_WINDING + 4]; + int sides[MAX_POINTS_ON_WINDING + 4]; + int counts[3]; + vec_t *p1, *p2; + vec3_t mid; - counts[0] = counts[1] = counts[2] = 0; + counts[0] = counts[1] = counts[2] = 0; // determine sides for each point - int i; - for ( i = 0; i < numpoints; i++ ) - { - vec_t dot = DotProduct( p[i], chopPlane->normal ); - dot -= chopPlane->_d; - dists[i] = dot; - - if ( dot > epsilon ) { - sides[i] = SIDE_FRONT; - } - else if ( dot < -epsilon ) { - sides[i] = SIDE_BACK; - } - else{ - sides[i] = SIDE_ON; - } - - counts[sides[i]]++; - } - sides[i] = sides[0]; - dists[i] = dists[0]; - - if ( !counts[0] ) { - delete this; - return false; - } - - if ( !counts[1] ) { - return true; - } - - int maxpts = numpoints + 4; // cant use counts[0]+2 because - // of fp grouping errors - - DWinding* f = new DWinding; - f->AllocWinding( maxpts ); - f->numpoints = 0; - - for ( i = 0; i < numpoints; i++ ) - { - p1 = p[i]; - - if ( sides[i] == SIDE_ON ) { - VectorCopy( p1, f->p[f->numpoints] ); - f->numpoints++; - continue; - } - - if ( sides[i] == SIDE_FRONT ) { - VectorCopy( p1, f->p[f->numpoints] ); - f->numpoints++; - } - - if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) { - continue; - } - - // generate a split point - p2 = p[( i + 1 ) % numpoints]; - - vec_t dot = dists[i] / ( dists[i] - dists[i + 1] ); - for ( int j = 0; j < 3; j++ ) - { - if ( chopPlane->normal[j] == 1 ) { - mid[j] = chopPlane->_d; - } - else if ( chopPlane->normal[j] == -1 ) { - mid[j] = -chopPlane->_d; - } - else{ - mid[j] = p1[j] + dot * ( p2[j] - p1[j] ); - } - } - - VectorCopy( mid, f->p[f->numpoints] ); - f->numpoints++; - } - - if ( f->numpoints > maxpts ) { - globalOutputStream() << "ClipWinding: points exceeded estimate\n"; - } - if ( f->numpoints > MAX_POINTS_ON_WINDING ) { - globalOutputStream() << "ClipWinding: MAX_POINTS_ON_WINDING\n"; - } - - delete[] p; - p = f->p; - f->p = NULL; - delete f; - return true; + int i; + for (i = 0; i < numpoints; i++) { + vec_t dot = DotProduct(p[i], chopPlane->normal); + dot -= chopPlane->_d; + dists[i] = dot; + + if (dot > epsilon) { + sides[i] = SIDE_FRONT; + } else if (dot < -epsilon) { + sides[i] = SIDE_BACK; + } else { + sides[i] = SIDE_ON; + } + + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + if (!counts[0]) { + delete this; + return false; + } + + if (!counts[1]) { + return true; + } + + int maxpts = numpoints + 4; // cant use counts[0]+2 because + // of fp grouping errors + + DWinding *f = new DWinding; + f->AllocWinding(maxpts); + f->numpoints = 0; + + for (i = 0; i < numpoints; i++) { + p1 = p[i]; + + if (sides[i] == SIDE_ON) { + VectorCopy(p1, f->p[f->numpoints]); + f->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) { + VectorCopy(p1, f->p[f->numpoints]); + f->numpoints++; + } + + if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) { + continue; + } + + // generate a split point + p2 = p[(i + 1) % numpoints]; + + vec_t dot = dists[i] / (dists[i] - dists[i + 1]); + for (int j = 0; j < 3; j++) { + if (chopPlane->normal[j] == 1) { + mid[j] = chopPlane->_d; + } else if (chopPlane->normal[j] == -1) { + mid[j] = -chopPlane->_d; + } else { + mid[j] = p1[j] + dot * (p2[j] - p1[j]); + } + } + + VectorCopy(mid, f->p[f->numpoints]); + f->numpoints++; + } + + if (f->numpoints > maxpts) { + globalOutputStream() << "ClipWinding: points exceeded estimate\n"; + } + if (f->numpoints > MAX_POINTS_ON_WINDING) { + globalOutputStream() << "ClipWinding: MAX_POINTS_ON_WINDING\n"; + } + + delete[] p; + p = f->p; + f->p = NULL; + delete f; + return true; } -void DWinding::ClipWindingEpsilon( DPlane* chopPlane, vec_t epsilon, DWinding **front, DWinding **back ){ - vec_t dists[MAX_POINTS_ON_WINDING + 4]; - int sides[MAX_POINTS_ON_WINDING + 4]; - int counts[3]; - vec_t *p1, *p2; - vec3_t mid; +void DWinding::ClipWindingEpsilon(DPlane *chopPlane, vec_t epsilon, DWinding **front, DWinding **back) +{ + vec_t dists[MAX_POINTS_ON_WINDING + 4]; + int sides[MAX_POINTS_ON_WINDING + 4]; + int counts[3]; + vec_t *p1, *p2; + vec3_t mid; - counts[0] = counts[1] = counts[2] = 0; + counts[0] = counts[1] = counts[2] = 0; // determine sides for each point - int i; - for ( i = 0; i < numpoints; i++ ) - { - vec_t dot = -chopPlane->DistanceToPoint( p[i] ); - dists[i] = dot; - - if ( dot > epsilon ) { - sides[i] = SIDE_FRONT; - } - else if ( dot < -epsilon ) { - sides[i] = SIDE_BACK; - } - else{ - sides[i] = SIDE_ON; - } - - counts[sides[i]]++; - } - sides[i] = sides[0]; - dists[i] = dists[0]; - - *front = *back = NULL; - - if ( !counts[0] ) { - *back = CopyWinding(); - return; - } - if ( !counts[1] ) { - *front = CopyWinding(); - return; - } - - int maxpts = numpoints + 4; // cant use counts[0]+2 because - // of fp grouping errors - - DWinding* f = new DWinding; - DWinding* b = new DWinding; - - f->AllocWinding( maxpts ); - f->numpoints = 0; - - b->AllocWinding( maxpts ); - b->numpoints = 0; - - *front = f; - *back = b; - - for ( i = 0; i < numpoints ; i++ ) - { - p1 = p[i]; - - if ( sides[i] == SIDE_ON ) { - VectorCopy( p1, f->p[f->numpoints] ); - f->numpoints++; - VectorCopy( p1, b->p[b->numpoints] ); - b->numpoints++; - continue; - } - - if ( sides[i] == SIDE_FRONT ) { - VectorCopy( p1, f->p[f->numpoints] ); - f->numpoints++; - } - if ( sides[i] == SIDE_BACK ) { - VectorCopy( p1, b->p[b->numpoints] ); - b->numpoints++; - } - - if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) { - continue; - } - - // generate a split point - p2 = p[( i + 1 ) % numpoints]; - - vec_t dot = dists[i] / ( dists[i] - dists[i + 1] ); - for ( int j = 0; j < 3; j++ ) - { - if ( chopPlane->normal[j] == 1 ) { - mid[j] = chopPlane->_d; - } - else if ( chopPlane->normal[j] == -1 ) { - mid[j] = -chopPlane->_d; - } - else{ - mid[j] = p1[j] + dot * ( p2[j] - p1[j] ); - } - } - - VectorCopy( mid, f->p[f->numpoints] ); - f->numpoints++; - VectorCopy( mid, b->p[b->numpoints] ); - b->numpoints++; - } - - if ( f->numpoints > maxpts || b->numpoints > maxpts ) { - globalOutputStream() << "ClipWinding: points exceeded estimate\n"; - } - if ( f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING ) { - globalOutputStream() << "ClipWinding: MAX_POINTS_ON_WINDING\n"; - } + int i; + for (i = 0; i < numpoints; i++) { + vec_t dot = -chopPlane->DistanceToPoint(p[i]); + dists[i] = dot; + + if (dot > epsilon) { + sides[i] = SIDE_FRONT; + } else if (dot < -epsilon) { + sides[i] = SIDE_BACK; + } else { + sides[i] = SIDE_ON; + } + + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + *front = *back = NULL; + + if (!counts[0]) { + *back = CopyWinding(); + return; + } + if (!counts[1]) { + *front = CopyWinding(); + return; + } + + int maxpts = numpoints + 4; // cant use counts[0]+2 because + // of fp grouping errors + + DWinding *f = new DWinding; + DWinding *b = new DWinding; + + f->AllocWinding(maxpts); + f->numpoints = 0; + + b->AllocWinding(maxpts); + b->numpoints = 0; + + *front = f; + *back = b; + + for (i = 0; i < numpoints; i++) { + p1 = p[i]; + + if (sides[i] == SIDE_ON) { + VectorCopy(p1, f->p[f->numpoints]); + f->numpoints++; + VectorCopy(p1, b->p[b->numpoints]); + b->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) { + VectorCopy(p1, f->p[f->numpoints]); + f->numpoints++; + } + if (sides[i] == SIDE_BACK) { + VectorCopy(p1, b->p[b->numpoints]); + b->numpoints++; + } + + if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) { + continue; + } + + // generate a split point + p2 = p[(i + 1) % numpoints]; + + vec_t dot = dists[i] / (dists[i] - dists[i + 1]); + for (int j = 0; j < 3; j++) { + if (chopPlane->normal[j] == 1) { + mid[j] = chopPlane->_d; + } else if (chopPlane->normal[j] == -1) { + mid[j] = -chopPlane->_d; + } else { + mid[j] = p1[j] + dot * (p2[j] - p1[j]); + } + } + + VectorCopy(mid, f->p[f->numpoints]); + f->numpoints++; + VectorCopy(mid, b->p[b->numpoints]); + b->numpoints++; + } + + if (f->numpoints > maxpts || b->numpoints > maxpts) { + globalOutputStream() << "ClipWinding: points exceeded estimate\n"; + } + if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) { + globalOutputStream() << "ClipWinding: MAX_POINTS_ON_WINDING\n"; + } } -bool DWinding::ChopWinding( DPlane* chopPlane ){ - DWinding *f, *b; +bool DWinding::ChopWinding(DPlane *chopPlane) +{ + DWinding *f, *b; - ClipWindingEpsilon( chopPlane, (float)ON_EPSILON, &f, &b ); + ClipWindingEpsilon(chopPlane, (float) ON_EPSILON, &f, &b); - if ( b ) { - delete ( b ); - } + if (b) { + delete (b); + } - if ( !f ) { - delete this; - return false; - } + if (!f) { + delete this; + return false; + } - delete[] p; - p = f->p; - f->p = NULL; - numpoints = f->numpoints; - delete f; + delete[] p; + p = f->p; + f->p = NULL; + numpoints = f->numpoints; + delete f; - return true; + return true; } diff --git a/contrib/bobtoolz/DWinding.h b/contrib/bobtoolz/DWinding.h index cb8ddda7..61d8e3ff 100644 --- a/contrib/bobtoolz/DWinding.h +++ b/contrib/bobtoolz/DWinding.h @@ -32,35 +32,42 @@ class DPlane; -class DWinding -{ +class DWinding { public: -DWinding(); -virtual ~DWinding(); + DWinding(); -void AllocWinding( int points ); + virtual ~DWinding(); -bool ChopWinding( DPlane* chopPlane ); -bool ChopWindingInPlace( DPlane* chopPlane, vec_t ON_EPSILON ); -void ClipWindingEpsilon( DPlane* chopPlane, vec_t epsilon, DWinding** front, DWinding** back ); + void AllocWinding(int points); -void CheckWinding(); -void WindingCentre( vec3_t centre ); -void WindingBounds( vec3_t mins, vec3_t maxs ); -void RemoveColinearPoints(); + bool ChopWinding(DPlane *chopPlane); -DWinding* ReverseWinding(); -DWinding* CopyWinding(); -DPlane* WindingPlane(); + bool ChopWindingInPlace(DPlane *chopPlane, vec_t ON_EPSILON); -int WindingOnPlaneSide( vec3_t normal, vec_t dist ); + void ClipWindingEpsilon(DPlane *chopPlane, vec_t epsilon, DWinding **front, DWinding **back); -vec_t WindingArea(); + void CheckWinding(); + + void WindingCentre(vec3_t centre); + + void WindingBounds(vec3_t mins, vec3_t maxs); + + void RemoveColinearPoints(); + + DWinding *ReverseWinding(); + + DWinding *CopyWinding(); + + DPlane *WindingPlane(); + + int WindingOnPlaneSide(vec3_t normal, vec_t dist); + + vec_t WindingArea(); // members -int numpoints; -vec3_t* p; -vec3_t clr; + int numpoints; + vec3_t *p; + vec3_t clr; }; const int MAX_POINTS_ON_WINDING = 64; diff --git a/contrib/bobtoolz/ScriptParser.cpp b/contrib/bobtoolz/ScriptParser.cpp index 3c801b26..62e99e06 100644 --- a/contrib/bobtoolz/ScriptParser.cpp +++ b/contrib/bobtoolz/ScriptParser.cpp @@ -20,270 +20,284 @@ #include "ScriptParser.h" #include -CScriptParser::CScriptParser( void ) : - m_pScript( NULL ), - m_pScriptSection( NULL ), - m_pLastScriptSection( NULL ), - m_pToken( NULL ) { - ClearBuffer(); +CScriptParser::CScriptParser(void) : + m_pScript(NULL), + m_pScriptSection(NULL), + m_pLastScriptSection(NULL), + m_pToken(NULL) +{ + ClearBuffer(); } -CScriptParser::~CScriptParser( void ) { - ClearBuffer(); +CScriptParser::~CScriptParser(void) +{ + ClearBuffer(); } -void CScriptParser::ClearBuffer( void ) { - if ( m_pScript ) { - delete[] m_pScript; - m_pScript = NULL; - } - if ( m_pToken ) { - delete[] m_pToken; - m_pToken = NULL; - } - m_pScriptSection = NULL; - m_pLastScriptSection = NULL; - memset( m_breakChars, 0, sizeof( m_breakChars ) ); +void CScriptParser::ClearBuffer(void) +{ + if (m_pScript) { + delete[] m_pScript; + m_pScript = NULL; + } + if (m_pToken) { + delete[] m_pToken; + m_pToken = NULL; + } + m_pScriptSection = NULL; + m_pLastScriptSection = NULL; + memset(m_breakChars, 0, sizeof(m_breakChars)); } -const char* CScriptParser::MakeToken( const char* pToken ) { - if ( m_pToken ) { - delete[] m_pToken; - m_pToken = NULL; - } +const char *CScriptParser::MakeToken(const char *pToken) +{ + if (m_pToken) { + delete[] m_pToken; + m_pToken = NULL; + } - if ( !pToken ) { - pToken = ""; - } + if (!pToken) { + pToken = ""; + } - int len = static_cast( strlen( pToken ) ); + int len = static_cast( strlen(pToken)); - m_pToken = new char[len + 1]; - m_pToken[len] = '\0'; - strcpy( m_pToken, pToken ); + m_pToken = new char[len + 1]; + m_pToken[len] = '\0'; + strcpy(m_pToken, pToken); - return m_pToken; + return m_pToken; } const int MAX_TOKEN_STRING = 1024; + // Should NEVER return NULL -const char* CScriptParser::GetToken( bool bAllowLinebreaks ) { - int c = 0, len; - char token[MAX_TOKEN_STRING]; - bool bNewLines = false; - - m_pLastScriptSection = m_pScriptSection; - - len = 0; - *token = '\0'; - - if ( !m_pScript || !m_pScriptSection ) { - return MakeToken( token ); - } - - while ( true ) { - SkipWhitespace( &bNewLines ); - if ( !*m_pScriptSection ) { - return MakeToken( token ); - } - if ( bNewLines && !bAllowLinebreaks ) { - return MakeToken( token ); - } - - c = *m_pScriptSection; - - if ( c == '/' && m_pScriptSection[1] == '/' ) { // C style comments - m_pScriptSection += 2; - while ( *m_pScriptSection && *m_pScriptSection != '\n' ) { - m_pScriptSection++; - } - } - else if ( c == '/' && m_pScriptSection[1] == '*' ) { // C++ style comments - m_pScriptSection += 2; - while ( *m_pScriptSection && ( *m_pScriptSection != '*' || m_pScriptSection[1] != '/' ) ) { - m_pScriptSection++; - } - if ( *m_pScriptSection ) { - m_pScriptSection += 2; - } - } - else { - break; - } - } - - if ( c == '\"' ) { - m_pScriptSection++; - while ( true ) { - c = *m_pScriptSection++; - if ( c == '\"' || !c ) { - token[len] = 0; - return MakeToken( token ); - } - if ( len < MAX_TOKEN_STRING ) { - token[len] = c; - len++; - } - } - } - - do { - if ( len > 0 && IsBreakChar( *m_pScriptSection ) ) { - break; - } - - if ( len < MAX_TOKEN_STRING ) { - token[len] = c; - len++; - } - m_pScriptSection++; - - if ( IsBreakChar( c ) ) { - break; - } - - c = *m_pScriptSection; - } while ( c > 32 ); - - if ( len == MAX_TOKEN_STRING ) { - len = 0; - } - token[len] = 0; - - return MakeToken( token ); +const char *CScriptParser::GetToken(bool bAllowLinebreaks) +{ + int c = 0, len; + char token[MAX_TOKEN_STRING]; + bool bNewLines = false; + + m_pLastScriptSection = m_pScriptSection; + + len = 0; + *token = '\0'; + + if (!m_pScript || !m_pScriptSection) { + return MakeToken(token); + } + + while (true) { + SkipWhitespace(&bNewLines); + if (!*m_pScriptSection) { + return MakeToken(token); + } + if (bNewLines && !bAllowLinebreaks) { + return MakeToken(token); + } + + c = *m_pScriptSection; + + if (c == '/' && m_pScriptSection[1] == '/') { // C style comments + m_pScriptSection += 2; + while (*m_pScriptSection && *m_pScriptSection != '\n') { + m_pScriptSection++; + } + } else if (c == '/' && m_pScriptSection[1] == '*') { // C++ style comments + m_pScriptSection += 2; + while (*m_pScriptSection && (*m_pScriptSection != '*' || m_pScriptSection[1] != '/')) { + m_pScriptSection++; + } + if (*m_pScriptSection) { + m_pScriptSection += 2; + } + } else { + break; + } + } + + if (c == '\"') { + m_pScriptSection++; + while (true) { + c = *m_pScriptSection++; + if (c == '\"' || !c) { + token[len] = 0; + return MakeToken(token); + } + if (len < MAX_TOKEN_STRING) { + token[len] = c; + len++; + } + } + } + + do { + if (len > 0 && IsBreakChar(*m_pScriptSection)) { + break; + } + + if (len < MAX_TOKEN_STRING) { + token[len] = c; + len++; + } + m_pScriptSection++; + + if (IsBreakChar(c)) { + break; + } + + c = *m_pScriptSection; + } while (c > 32); + + if (len == MAX_TOKEN_STRING) { + len = 0; + } + token[len] = 0; + + return MakeToken(token); } -void CScriptParser::SkipWhitespace( bool* pbNewLines ) { - int c; - - if ( !m_pScript || !m_pScriptSection ) { - return; - } - - while ( ( c = *m_pScriptSection ) <= ' ' ) { - if ( !c ) { - return; - } - if ( c == '\n' ) { - *pbNewLines = true; - } - m_pScriptSection++; - } +void CScriptParser::SkipWhitespace(bool *pbNewLines) +{ + int c; + + if (!m_pScript || !m_pScriptSection) { + return; + } + + while ((c = *m_pScriptSection) <= ' ') { + if (!c) { + return; + } + if (c == '\n') { + *pbNewLines = true; + } + m_pScriptSection++; + } } -void CScriptParser::SkipBracedSection( void ) { - const char *token; - int depth; - - depth = 0; - do { - token = GetToken( true ); - if ( token[1] == 0 ) { - if ( *token == '{' ) { - depth++; - } - else if ( *token == '}' ) { - depth--; - } - } - } while ( depth && *m_pScriptSection ); +void CScriptParser::SkipBracedSection(void) +{ + const char *token; + int depth; + + depth = 0; + do { + token = GetToken(true); + if (token[1] == 0) { + if (*token == '{') { + depth++; + } else if (*token == '}') { + depth--; + } + } + } while (depth && *m_pScriptSection); } -void CScriptParser::SkipRestOfLine( void ) { - char *p; - int c; - - p = m_pScriptSection; - while ( ( c = *p++ ) != 0 ) { - if ( c == '\n' ) { - break; - } - } - m_pScriptSection = p; +void CScriptParser::SkipRestOfLine(void) +{ + char *p; + int c; + + p = m_pScriptSection; + while ((c = *p++) != 0) { + if (c == '\n') { + break; + } + } + m_pScriptSection = p; } -void CScriptParser::UndoGetToken( void ) { - if ( !m_pLastScriptSection ) { - return; - } - m_pScriptSection = m_pLastScriptSection; - m_pLastScriptSection = NULL; +void CScriptParser::UndoGetToken(void) +{ + if (!m_pLastScriptSection) { + return; + } + m_pScriptSection = m_pLastScriptSection; + m_pLastScriptSection = NULL; } -void CScriptParser::ResetParseSession( void ) { - if ( !m_pScript ) { - return; - } +void CScriptParser::ResetParseSession(void) +{ + if (!m_pScript) { + return; + } - m_pScriptSection = m_pScript; - m_pLastScriptSection = NULL; + m_pScriptSection = m_pScript; + m_pLastScriptSection = NULL; } -char* CScriptParser::GetBufferCopy( void ) { - if ( !m_pScript ) { - return NULL; - } +char *CScriptParser::GetBufferCopy(void) +{ + if (!m_pScript) { + return NULL; + } - int len = static_cast( strlen( m_pScript ) ); - char* pBuffer = new char[len + 1]; - strcpy( pBuffer, m_pScript ); - return pBuffer; + int len = static_cast( strlen(m_pScript)); + char *pBuffer = new char[len + 1]; + strcpy(pBuffer, m_pScript); + return pBuffer; } -int CScriptParser::GetTokenOffset( void ) { - if ( !m_pScript || !m_pScriptSection ) { - return 0; - } +int CScriptParser::GetTokenOffset(void) +{ + if (!m_pScript || !m_pScriptSection) { + return 0; + } - return static_cast( m_pScriptSection - m_pScript ); + return static_cast( m_pScriptSection - m_pScript ); } -void CScriptParser::LoadScript( const char* pScript ) { - ClearBuffer(); +void CScriptParser::LoadScript(const char *pScript) +{ + ClearBuffer(); - int len = static_cast( strlen( pScript ) ); - if ( len <= 0 ) { - return; - } + int len = static_cast( strlen(pScript)); + if (len <= 0) { + return; + } - m_pScript = new char[len + 1]; - m_pScript[len] = '\0'; + m_pScript = new char[len + 1]; + m_pScript[len] = '\0'; - strcpy( m_pScript, pScript ); - m_pScriptSection = m_pScript; + strcpy(m_pScript, pScript); + m_pScriptSection = m_pScript; } -void CScriptParser::AddBreakChar( char c ) { - for ( int i = 0; i < SP_MAX_BREAKCHARS; i++ ) { - if ( !m_breakChars[i] ) { - m_breakChars[i] = c; - return; - } - } +void CScriptParser::AddBreakChar(char c) +{ + for (int i = 0; i < SP_MAX_BREAKCHARS; i++) { + if (!m_breakChars[i]) { + m_breakChars[i] = c; + return; + } + } - // TODO: Error: max break chars hit + // TODO: Error: max break chars hit } -bool CScriptParser::IsBreakChar( char c ) { - for ( int i = 0; i < SP_MAX_BREAKCHARS; i++ ) { - if ( !m_breakChars[i] ) { - return false; - } - if ( m_breakChars[i] == c ) { - return true; - } - } - return false; +bool CScriptParser::IsBreakChar(char c) +{ + for (int i = 0; i < SP_MAX_BREAKCHARS; i++) { + if (!m_breakChars[i]) { + return false; + } + if (m_breakChars[i] == c) { + return true; + } + } + return false; } -void CScriptParser::SetScript( char* pScript ) { - ClearBuffer(); +void CScriptParser::SetScript(char *pScript) +{ + ClearBuffer(); - int len = static_cast( strlen( pScript ) ); - if ( len <= 0 ) { - return; - } + int len = static_cast( strlen(pScript)); + if (len <= 0) { + return; + } - m_pScript = pScript; - m_pScriptSection = m_pScript; + m_pScript = pScript; + m_pScriptSection = m_pScript; } diff --git a/contrib/bobtoolz/ScriptParser.h b/contrib/bobtoolz/ScriptParser.h index 2729dcae..ba345db6 100644 --- a/contrib/bobtoolz/ScriptParser.h +++ b/contrib/bobtoolz/ScriptParser.h @@ -28,33 +28,46 @@ const int SP_MAX_BREAKCHARS = 16; class CScriptParser //: public IScriptParser { public: -CScriptParser( void ); -~CScriptParser( void ); + CScriptParser(void); + + ~CScriptParser(void); + private: -char m_breakChars[SP_MAX_BREAKCHARS]; -char* m_pScript; -char* m_pScriptSection; -char* m_pLastScriptSection; -char* m_pToken; - -void SkipWhitespace( bool* pbNewLines ); -void ClearBuffer( void ); -const char* MakeToken( const char* pToken ); -bool IsBreakChar( char c ); + char m_breakChars[SP_MAX_BREAKCHARS]; + char *m_pScript; + char *m_pScriptSection; + char *m_pLastScriptSection; + char *m_pToken; + + void SkipWhitespace(bool *pbNewLines); + + void ClearBuffer(void); + + const char *MakeToken(const char *pToken); + + bool IsBreakChar(char c); + public: -const char* GetToken( bool bAllowLinebreaks ); -void SkipBracedSection( void ); -void SkipRestOfLine( void ); -void UndoGetToken( void ); -void ResetParseSession( void ); + const char *GetToken(bool bAllowLinebreaks); + + void SkipBracedSection(void); + + void SkipRestOfLine(void); + + void UndoGetToken(void); + + void ResetParseSession(void); + + char *GetBufferCopy(void); + + int GetTokenOffset(void); + + void LoadScript(const char *pScript); -char* GetBufferCopy( void ); -int GetTokenOffset( void ); + void SetScript(char *pScript); -void LoadScript( const char* pScript ); -void SetScript( char* pScript ); + void AddBreakChar(char c); -void AddBreakChar( char c ); private: }; diff --git a/contrib/bobtoolz/bobToolz-GTK.cpp b/contrib/bobtoolz/bobToolz-GTK.cpp index bbc3979c..a3cef8fc 100644 --- a/contrib/bobtoolz/bobToolz-GTK.cpp +++ b/contrib/bobtoolz/bobToolz-GTK.cpp @@ -34,223 +34,283 @@ #include "dialogs/dialogs-gtk.h" #include "../../libs/cmdlib.h" -void BobToolz_construct(){ +void BobToolz_construct() +{ } -void BobToolz_destroy(){ - if ( g_PathView ) { - delete g_PathView; - g_PathView = NULL; - } - if ( g_VisView ) { - delete g_VisView; - g_VisView = NULL; - } - if ( g_TrainView ) { - delete g_TrainView; - g_TrainView = NULL; - } - if ( g_TreePlanter ) { - delete g_TreePlanter; - g_TreePlanter = NULL; - } +void BobToolz_destroy() +{ + if (g_PathView) { + delete g_PathView; + g_PathView = NULL; + } + if (g_VisView) { + delete g_VisView; + g_VisView = NULL; + } + if (g_TrainView) { + delete g_TrainView; + g_TrainView = NULL; + } + if (g_TreePlanter) { + delete g_TreePlanter; + g_TreePlanter = NULL; + } } // plugin name -const char* PLUGIN_NAME = "bobToolz"; +const char *PLUGIN_NAME = "bobToolz"; // commands in the menu -static const char* PLUGIN_COMMANDS = "About...,-,Reset Textures...,PitOMatic,-,Vis Viewer,Brush Cleanup,Polygon Builder,Caulk Selection,-,Tree Planter,Drop Entity,Plot Splines,-,Merge Patches,Split patches,Split patches cols,Split patches rows,Turn edge"; +static const char *PLUGIN_COMMANDS = "About...,-,Reset Textures...,PitOMatic,-,Vis Viewer,Brush Cleanup,Polygon Builder,Caulk Selection,-,Tree Planter,Drop Entity,Plot Splines,-,Merge Patches,Split patches,Split patches cols,Split patches rows,Turn edge"; // globals ui::Window g_pRadiantWnd{ui::null}; -static const char *PLUGIN_ABOUT = "bobToolz for SDRadiant\n" - "by digibob (digibob@splashdamage.com)\n" - "http://www.splashdamage.com\n\n" - "Additional Contributors:\n" - "MarsMattel, RR2DO2\n"; +static const char *PLUGIN_ABOUT = "bobToolz for SDRadiant\n" + "by digibob (digibob@splashdamage.com)\n" + "http://www.splashdamage.com\n\n" + "Additional Contributors:\n" + "MarsMattel, RR2DO2\n"; -extern "C" const char* QERPlug_Init( void* hApp, void* pMainWidget ) { - g_pRadiantWnd = ui::Window::from(pMainWidget); +extern "C" const char *QERPlug_Init(void *hApp, void *pMainWidget) +{ + g_pRadiantWnd = ui::Window::from(pMainWidget); - return "bobToolz for GTKradiant"; + return "bobToolz for GTKradiant"; } -extern "C" const char* QERPlug_GetName() { - return PLUGIN_NAME; +extern "C" const char *QERPlug_GetName() +{ + return PLUGIN_NAME; } -extern "C" const char* QERPlug_GetCommandList() { - return PLUGIN_COMMANDS; +extern "C" const char *QERPlug_GetCommandList() +{ + return PLUGIN_COMMANDS; } -extern "C" void QERPlug_Dispatch( const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush ) { - LoadLists(); - - if ( string_equal_nocase( p, "brush cleanup" ) ) { - DoFixBrushes(); - } - else if ( string_equal_nocase( p, "polygon builder" ) ) { - DoPolygonsTB(); - } - else if ( string_equal_nocase( p, "caulk selection" ) ) { - DoCaulkSelection(); - } - else if ( string_equal_nocase( p, "tree planter" ) ) { - DoTreePlanter(); - } - else if ( string_equal_nocase( p, "plot splines" ) ) { - DoTrainPathPlot(); - } - else if ( string_equal_nocase( p, "drop entity" ) ) { - DoDropEnts(); - } - else if ( string_equal_nocase( p, "merge patches" ) ) { - DoMergePatches(); - } - else if ( string_equal_nocase( p, "split patches" ) ) { - DoSplitPatch(); - } - else if ( string_equal_nocase( p, "split patches rows" ) ) { - DoSplitPatchRows(); - } - else if ( string_equal_nocase( p, "split patches cols" ) ) { - DoSplitPatchCols(); - } - else if ( string_equal_nocase( p, "turn edge" ) ) { - DoFlipTerrain(); - } - else if ( string_equal_nocase( p, "reset textures..." ) ) { - DoResetTextures(); - } - else if ( string_equal_nocase( p, "pitomatic" ) ) { - DoPitBuilder(); - } - else if ( string_equal_nocase( p, "vis viewer" ) ) { - DoVisAnalyse(); - } - else if ( string_equal_nocase( p, "stair builder..." ) ) { - DoBuildStairs(); - } - else if ( string_equal_nocase( p, "door builder..." ) ) { - DoBuildDoors(); - } - else if ( string_equal_nocase( p, "intersect..." ) ) { - DoIntersect(); - } - else if ( string_equal_nocase( p, "make chain..." ) ) { - DoMakeChain(); - } - else if ( string_equal_nocase( p, "path plotter..." ) ) { - DoPathPlotter(); - } - else if ( string_equal_nocase( p, "about..." ) ) { - DoMessageBox( PLUGIN_ABOUT, "About", eMB_OK ); - } +extern "C" void QERPlug_Dispatch(const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush) +{ + LoadLists(); + + if (string_equal_nocase(p, "brush cleanup")) { + DoFixBrushes(); + } else if (string_equal_nocase(p, "polygon builder")) { + DoPolygonsTB(); + } else if (string_equal_nocase(p, "caulk selection")) { + DoCaulkSelection(); + } else if (string_equal_nocase(p, "tree planter")) { + DoTreePlanter(); + } else if (string_equal_nocase(p, "plot splines")) { + DoTrainPathPlot(); + } else if (string_equal_nocase(p, "drop entity")) { + DoDropEnts(); + } else if (string_equal_nocase(p, "merge patches")) { + DoMergePatches(); + } else if (string_equal_nocase(p, "split patches")) { + DoSplitPatch(); + } else if (string_equal_nocase(p, "split patches rows")) { + DoSplitPatchRows(); + } else if (string_equal_nocase(p, "split patches cols")) { + DoSplitPatchCols(); + } else if (string_equal_nocase(p, "turn edge")) { + DoFlipTerrain(); + } else if (string_equal_nocase(p, "reset textures...")) { + DoResetTextures(); + } else if (string_equal_nocase(p, "pitomatic")) { + DoPitBuilder(); + } else if (string_equal_nocase(p, "vis viewer")) { + DoVisAnalyse(); + } else if (string_equal_nocase(p, "stair builder...")) { + DoBuildStairs(); + } else if (string_equal_nocase(p, "door builder...")) { + DoBuildDoors(); + } else if (string_equal_nocase(p, "intersect...")) { + DoIntersect(); + } else if (string_equal_nocase(p, "make chain...")) { + DoMakeChain(); + } else if (string_equal_nocase(p, "path plotter...")) { + DoPathPlotter(); + } else if (string_equal_nocase(p, "about...")) { + DoMessageBox(PLUGIN_ABOUT, "About", eMB_OK); + } } -const char* QERPlug_GetCommandTitleList(){ - return ""; +const char *QERPlug_GetCommandTitleList() +{ + return ""; } const int NUM_TOOLBARBUTTONS = 14; -std::size_t ToolbarButtonCount( void ) { - return NUM_TOOLBARBUTTONS; -} - -class CBobtoolzToolbarButton : public IToolbarButton +std::size_t ToolbarButtonCount(void) { -public: -virtual const char* getImage() const { - switch ( mIndex ) { - case 0: return "bobtoolz_cleanup.png"; - case 1: return "bobtoolz_poly.png"; - case 2: return "bobtoolz_caulk.png"; - case 3: return ""; - case 4: return "bobtoolz_treeplanter.png"; - case 5: return "bobtoolz_trainpathplot.png"; - case 6: return "bobtoolz_dropent.png"; - case 7: return ""; - case 8: return "bobtoolz_merge.png"; - case 9: return "bobtoolz_split.png"; - case 10: return "bobtoolz_splitrow.png"; - case 11: return "bobtoolz_splitcol.png"; - case 12: return ""; - case 13: return "bobtoolz_turnedge.png"; - } - return NULL; -} -virtual EType getType() const { - switch ( mIndex ) { - case 3: return eSpace; - case 4: return eToggleButton; - case 7: return eSpace; - case 12: return eSpace; - default: return eButton; - } -} -virtual const char* getText() const { - switch ( mIndex ) { - case 0: return "Cleanup"; - case 1: return "Polygons"; - case 2: return "Caulk"; - case 4: return "Tree Planter"; - case 5: return "Plot Splines"; - case 6: return "Drop Entity"; - case 8: return "Merge 2 Patches"; - case 9: return "Split Patch"; - case 10: return "Split Patch Rows"; - case 11: return "Split Patch Columns"; - case 13: return "Flip Terrain"; - } - return NULL; -} -virtual const char* getTooltip() const { - switch ( mIndex ) { - case 0: return "Brush Cleanup"; - case 1: return "Polygons"; - case 2: return "Caulk selection"; - case 4: return "Tree Planter"; - case 5: return "Plot Splines"; - case 6: return "Drop Entity"; - case 8: return "Merge 2 Patches"; - case 9: return "Split Patch"; - case 10: return "Split Patch Rows"; - case 11: return "Split Patch Columns"; - case 13: return "Flip Terrain (Turn Edge)"; - } - return NULL; + return NUM_TOOLBARBUTTONS; } -virtual void activate() const { - LoadLists(); - - switch ( mIndex ) { - case 0: DoFixBrushes(); break; - case 1: DoPolygonsTB(); break; - case 2: DoCaulkSelection(); break; - case 4: DoTreePlanter(); break; - case 5: DoTrainPathPlot(); break; - case 6: DoDropEnts(); break; - case 8: DoMergePatches(); break; - case 9: DoSplitPatch(); break; - case 10: DoSplitPatchRows(); break; - case 11: DoSplitPatchCols(); break; - case 13: DoFlipTerrain(); break; - } -} - -std::size_t mIndex; +class CBobtoolzToolbarButton : public IToolbarButton { +public: + virtual const char *getImage() const + { + switch (mIndex) { + case 0: + return "bobtoolz_cleanup.png"; + case 1: + return "bobtoolz_poly.png"; + case 2: + return "bobtoolz_caulk.png"; + case 3: + return ""; + case 4: + return "bobtoolz_treeplanter.png"; + case 5: + return "bobtoolz_trainpathplot.png"; + case 6: + return "bobtoolz_dropent.png"; + case 7: + return ""; + case 8: + return "bobtoolz_merge.png"; + case 9: + return "bobtoolz_split.png"; + case 10: + return "bobtoolz_splitrow.png"; + case 11: + return "bobtoolz_splitcol.png"; + case 12: + return ""; + case 13: + return "bobtoolz_turnedge.png"; + } + return NULL; + } + + virtual EType getType() const + { + switch (mIndex) { + case 3: + return eSpace; + case 4: + return eToggleButton; + case 7: + return eSpace; + case 12: + return eSpace; + default: + return eButton; + } + } + + virtual const char *getText() const + { + switch (mIndex) { + case 0: + return "Cleanup"; + case 1: + return "Polygons"; + case 2: + return "Caulk"; + case 4: + return "Tree Planter"; + case 5: + return "Plot Splines"; + case 6: + return "Drop Entity"; + case 8: + return "Merge 2 Patches"; + case 9: + return "Split Patch"; + case 10: + return "Split Patch Rows"; + case 11: + return "Split Patch Columns"; + case 13: + return "Flip Terrain"; + } + return NULL; + } + + virtual const char *getTooltip() const + { + switch (mIndex) { + case 0: + return "Brush Cleanup"; + case 1: + return "Polygons"; + case 2: + return "Caulk selection"; + case 4: + return "Tree Planter"; + case 5: + return "Plot Splines"; + case 6: + return "Drop Entity"; + case 8: + return "Merge 2 Patches"; + case 9: + return "Split Patch"; + case 10: + return "Split Patch Rows"; + case 11: + return "Split Patch Columns"; + case 13: + return "Flip Terrain (Turn Edge)"; + } + return NULL; + } + + virtual void activate() const + { + LoadLists(); + + switch (mIndex) { + case 0: + DoFixBrushes(); + break; + case 1: + DoPolygonsTB(); + break; + case 2: + DoCaulkSelection(); + break; + case 4: + DoTreePlanter(); + break; + case 5: + DoTrainPathPlot(); + break; + case 6: + DoDropEnts(); + break; + case 8: + DoMergePatches(); + break; + case 9: + DoSplitPatch(); + break; + case 10: + DoSplitPatchRows(); + break; + case 11: + DoSplitPatchCols(); + break; + case 13: + DoFlipTerrain(); + break; + } + } + + std::size_t mIndex; }; CBobtoolzToolbarButton g_bobtoolzToolbarButtons[NUM_TOOLBARBUTTONS]; -const IToolbarButton* GetToolbarButton( std::size_t index ){ - g_bobtoolzToolbarButtons[index].mIndex = index; - return &g_bobtoolzToolbarButtons[index]; +const IToolbarButton *GetToolbarButton(std::size_t index) +{ + g_bobtoolzToolbarButtons[index].mIndex = index; + return &g_bobtoolzToolbarButtons[index]; } @@ -268,51 +328,56 @@ const IToolbarButton* GetToolbarButton( std::size_t index ){ #include "iplugin.h" class BobToolzPluginDependencies : - public GlobalRadiantModuleRef, - public GlobalUndoModuleRef, - public GlobalSceneGraphModuleRef, - public GlobalSelectionModuleRef, - public GlobalEntityModuleRef, - public GlobalEntityClassManagerModuleRef, - public GlobalShadersModuleRef, - public GlobalShaderCacheModuleRef, - public GlobalBrushModuleRef, - public GlobalPatchModuleRef, - public GlobalOpenGLModuleRef, - public GlobalOpenGLStateLibraryModuleRef -{ + public GlobalRadiantModuleRef, + public GlobalUndoModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalSelectionModuleRef, + public GlobalEntityModuleRef, + public GlobalEntityClassManagerModuleRef, + public GlobalShadersModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalBrushModuleRef, + public GlobalPatchModuleRef, + public GlobalOpenGLModuleRef, + public GlobalOpenGLStateLibraryModuleRef { public: -BobToolzPluginDependencies() : - GlobalEntityModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entities" ) ), - GlobalEntityClassManagerModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entityclass" ) ), - GlobalShadersModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "shaders" ) ), - GlobalBrushModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "brushtypes" ) ), - GlobalPatchModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "patchtypes" ) ){ -} + BobToolzPluginDependencies() : + GlobalEntityModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entities")), + GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass")), + GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders")), + GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")), + GlobalPatchModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("patchtypes")) + { + } }; -class BobToolzPluginModule : public TypeSystemRef -{ -_QERPluginTable m_plugin; +class BobToolzPluginModule : public TypeSystemRef { + _QERPluginTable m_plugin; public: -typedef _QERPluginTable Type; -STRING_CONSTANT( Name, "bobToolz" ); - -BobToolzPluginModule(){ - m_plugin.m_pfnQERPlug_Init = QERPlug_Init; - m_plugin.m_pfnQERPlug_GetName = QERPlug_GetName; - m_plugin.m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; - m_plugin.m_pfnQERPlug_GetCommandTitleList = QERPlug_GetCommandTitleList; - m_plugin.m_pfnQERPlug_Dispatch = QERPlug_Dispatch; - - BobToolz_construct(); -} -~BobToolzPluginModule(){ - BobToolz_destroy(); -} -_QERPluginTable* getTable(){ - return &m_plugin; -} + typedef _QERPluginTable Type; + + STRING_CONSTANT(Name, "bobToolz"); + + BobToolzPluginModule() + { + m_plugin.m_pfnQERPlug_Init = QERPlug_Init; + m_plugin.m_pfnQERPlug_GetName = QERPlug_GetName; + m_plugin.m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; + m_plugin.m_pfnQERPlug_GetCommandTitleList = QERPlug_GetCommandTitleList; + m_plugin.m_pfnQERPlug_Dispatch = QERPlug_Dispatch; + + BobToolz_construct(); + } + + ~BobToolzPluginModule() + { + BobToolz_destroy(); + } + + _QERPluginTable *getTable() + { + return &m_plugin; + } }; typedef SingletonModule SingletonBobToolzPluginModule; @@ -321,28 +386,31 @@ SingletonBobToolzPluginModule g_BobToolzPluginModule; class BobToolzToolbarDependencies : - public ModuleRef<_QERPluginTable> -{ + public ModuleRef<_QERPluginTable> { public: -BobToolzToolbarDependencies() : - ModuleRef<_QERPluginTable>( "bobToolz" ){ -} + BobToolzToolbarDependencies() : + ModuleRef<_QERPluginTable>("bobToolz") + { + } }; -class BobToolzToolbarModule : public TypeSystemRef -{ -_QERPlugToolbarTable m_table; +class BobToolzToolbarModule : public TypeSystemRef { + _QERPlugToolbarTable m_table; public: -typedef _QERPlugToolbarTable Type; -STRING_CONSTANT( Name, "bobToolz" ); + typedef _QERPlugToolbarTable Type; -BobToolzToolbarModule(){ - m_table.m_pfnToolbarButtonCount = ToolbarButtonCount; - m_table.m_pfnGetToolbarButton = GetToolbarButton; -} -_QERPlugToolbarTable* getTable(){ - return &m_table; -} + STRING_CONSTANT(Name, "bobToolz"); + + BobToolzToolbarModule() + { + m_table.m_pfnToolbarButtonCount = ToolbarButtonCount; + m_table.m_pfnGetToolbarButton = GetToolbarButton; + } + + _QERPlugToolbarTable *getTable() + { + return &m_table; + } }; typedef SingletonModule SingletonBobToolzToolbarModule; @@ -350,9 +418,10 @@ typedef SingletonModule Sing SingletonBobToolzToolbarModule g_BobToolzToolbarModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_BobToolzPluginModule.selfRegister(); - g_BobToolzToolbarModule.selfRegister(); + g_BobToolzPluginModule.selfRegister(); + g_BobToolzToolbarModule.selfRegister(); } diff --git a/contrib/bobtoolz/bobToolz.h b/contrib/bobtoolz/bobToolz.h index 4b80ee73..cdf99cb5 100644 --- a/contrib/bobtoolz/bobToolz.h +++ b/contrib/bobtoolz/bobToolz.h @@ -28,7 +28,7 @@ #endif // _MSC_VER >= 1000 #ifndef __AFXWIN_H__ - #error include 'StdAfx.h' before including this file for PCH +#error include 'StdAfx.h' before including this file for PCH #endif #include "resource.h" // main symbols @@ -38,10 +38,9 @@ // See plugin.cpp for the implementation of this class // -class CPluginApp : public CWinApp -{ +class CPluginApp : public CWinApp { public: -CPluginApp(); + CPluginApp(); // Overrides // ClassWizard generated virtual function overrides @@ -52,7 +51,7 @@ CPluginApp(); // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; diff --git a/contrib/bobtoolz/bobToolz.rc b/contrib/bobtoolz/bobToolz.rc index 4abed936..604d52c9 100644 --- a/contrib/bobtoolz/bobToolz.rc +++ b/contrib/bobtoolz/bobToolz.rc @@ -29,41 +29,45 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,1,0 - PRODUCTVERSION 2,0,0,0 - FILEFLAGSMASK 0x3fL +FILEVERSION 1,1,1,0 +PRODUCTVERSION 2,0,0,0 +FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS 0x1L +FILEFLAGS 0x1L #else - FILEFLAGS 0x0L +FILEFLAGS 0x0L #endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L +FILEOS 0x4L +FILETYPE 0x2L +FILESUBTYPE 0x0L BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904b0" - BEGIN - VALUE "Comments", "by djbob :P and MarsMattel ~:]\0" - VALUE "CompanyName", "bobCo\0" - VALUE "FileDescription", "All your plugins are belong to us\0" - VALUE "FileVersion", "1, 1, 1, 0\0" - VALUE "InternalName", "bobToolz\0" - VALUE "LegalCopyright", "Copyright (C) y2k\0" - VALUE "LegalTrademarks", "\0" - VALUE "OriginalFilename", "bobToolz.DLL\0" - VALUE "PrivateBuild", "\0" - VALUE "ProductName", "\0" - VALUE "ProductVersion", "2, 0, 0, 0\0" - VALUE "SpecialBuild", "\0" + BLOCK +"StringFileInfo" +BEGIN + BLOCK +"080904b0" +BEGIN + VALUE +"Comments", "by djbob :P and MarsMattel ~:]\0" +VALUE "CompanyName", "bobCo\0" +VALUE "FileDescription", "All your plugins are belong to us\0" +VALUE "FileVersion", "1, 1, 1, 0\0" +VALUE "InternalName", "bobToolz\0" +VALUE "LegalCopyright", "Copyright (C) y2k\0" +VALUE "LegalTrademarks", "\0" +VALUE "OriginalFilename", "bobToolz.DLL\0" +VALUE "PrivateBuild", "\0" +VALUE "ProductName", "\0" +VALUE "ProductVersion", "2, 0, 0, 0\0" +VALUE "SpecialBuild", "\0" +END END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1200 - END +BLOCK "VarFileInfo" +BEGIN + VALUE +"Translation", 0x809, 1200 END + END #endif // !_MAC @@ -85,19 +89,29 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT // Dialog // -IDD_ABOUT DIALOG DISCARDABLE 0, 0, 361, 118 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "About" +IDD_ABOUT +DIALOG DISCARDABLE +0, 0, 361, 118 +STYLE DS_MODALFRAME +| WS_POPUP | WS_CAPTION | +WS_SYSMENU + CAPTION +"About" FONT 8, "Arial" BEGIN - DEFPUSHBUTTON "OK",IDOK,305,100,50,14 - CTEXT "BobToolz - Q3radiant version by djbob &&&& Mars Mattel", - IDC_STATIC,5,5,350,14,SS_CENTERIMAGE - CTEXT "Latest Version Can Be Found At http://djbob.fortefide.com", - IDC_STATIC,5,20,350,15,SS_CENTERIMAGE - LTEXT "Random bobToolz comments:",IDC_STATIC,5,35,355,10 - CTEXT "Texture Alignments Are Irrelevant, You Will Be Caulked\n-QPSiren\nCaulk Me Baby One More Time\n-TTimo\nWe're Up The Creek Without A Penguin\n-Mars Mattel", - IDC_STATIC,5,45,355,50 + DEFPUSHBUTTON +"OK",IDOK,305,100,50,14 +CTEXT "BobToolz - Q3radiant version by djbob &&&& Mars Mattel", +IDC_STATIC,5,5,350,14, +SS_CENTERIMAGE + CTEXT +"Latest Version Can Be Found At http://djbob.fortefide.com", +IDC_STATIC,5,20,350,15, +SS_CENTERIMAGE + LTEXT +"Random bobToolz comments:",IDC_STATIC,5,35,355,10 +CTEXT "Texture Alignments Are Irrelevant, You Will Be Caulked\n-QPSiren\nCaulk Me Baby One More Time\n-TTimo\nWe're Up The Creek Without A Penguin\n-Mars Mattel", +IDC_STATIC,5,45,355,50 END @@ -107,7 +121,7 @@ END // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE +GUIDELINES DESIGNINFO DISCARDABLE BEGIN IDD_ABOUT, DIALOG BEGIN @@ -137,205 +151,334 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK // Dialog // -IDD_STAIR_DIALOG DIALOG DISCARDABLE 0, 0, 246, 118 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Stair Designer" +IDD_STAIR_DIALOG +DIALOG DISCARDABLE +0, 0, 246, 118 +STYLE DS_MODALFRAME +| WS_POPUP | WS_CAPTION | +WS_SYSMENU + CAPTION +"Stair Designer" FONT 8, "Arial" BEGIN - DEFPUSHBUTTON "OK",IDOK,189,83,50,12 - PUSHBUTTON "Cancel",IDCANCEL,189,99,50,12 - EDITTEXT IDC_EDIT1,5,5,86,12,ES_AUTOHSCROLL - LTEXT "Stair Height",IDC_STATIC,95,5,42,15,SS_CENTERIMAGE - GROUPBOX "Direction",IDC_STATIC,7,26,85,64 - CONTROL "North",IDC_DIR_N_RADIO,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,14,38,33,10 - CONTROL "South",IDC_DIR_S_RADIO,"Button",BS_AUTORADIOBUTTON,14, - 50,35,10 - CONTROL "East",IDC_DIR_E_RADIO,"Button",BS_AUTORADIOBUTTON,14,62, - 30,10 - CONTROL "West",IDC_DIR_W_RADIO,"Button",BS_AUTORADIOBUTTON,14,74, - 33,10 - GROUPBOX "Style",IDC_STATIC,97,26,82,49 - CONTROL "Original",IDC_STYLE_ORIG_RADIO,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,105,35,39,10 - CONTROL "Bob's Style",IDC_STYLE_BOB_RADIO,"Button", - BS_AUTORADIOBUTTON,105,47,51,10 - CONTROL "Corner",IDC_STYLE_CORNER_RADIO,"Button", - BS_AUTORADIOBUTTON | WS_DISABLED,105,59,51,10 - EDITTEXT IDC_RISER_EDIT,7,99,85,12,ES_AUTOHSCROLL - LTEXT "Riser Texture",IDC_STATIC,95,100,60,11,SS_CENTERIMAGE - CONTROL "Use Detail Brushes",IDC_DETAIL_CHK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,100,80,75,10 + DEFPUSHBUTTON +"OK",IDOK,189,83,50,12 +PUSHBUTTON "Cancel",IDCANCEL,189,99,50,12 +EDITTEXT IDC_EDIT1,5,5,86,12, +ES_AUTOHSCROLL + LTEXT +"Stair Height",IDC_STATIC,95,5,42,15, +SS_CENTERIMAGE + GROUPBOX +"Direction",IDC_STATIC,7,26,85,64 +CONTROL "North",IDC_DIR_N_RADIO,"Button",BS_AUTORADIOBUTTON | +WS_GROUP,14,38,33,10 +CONTROL "South",IDC_DIR_S_RADIO,"Button",BS_AUTORADIOBUTTON,14, +50,35,10 +CONTROL "East",IDC_DIR_E_RADIO,"Button",BS_AUTORADIOBUTTON,14,62, +30,10 +CONTROL "West",IDC_DIR_W_RADIO,"Button",BS_AUTORADIOBUTTON,14,74, +33,10 +GROUPBOX "Style",IDC_STATIC,97,26,82,49 +CONTROL "Original",IDC_STYLE_ORIG_RADIO,"Button", +BS_AUTORADIOBUTTON | WS_GROUP,105,35,39,10 +CONTROL "Bob's Style",IDC_STYLE_BOB_RADIO,"Button", +BS_AUTORADIOBUTTON,105,47,51,10 +CONTROL "Corner",IDC_STYLE_CORNER_RADIO,"Button", +BS_AUTORADIOBUTTON | WS_DISABLED,105,59,51,10 +EDITTEXT IDC_RISER_EDIT,7,99,85,12, +ES_AUTOHSCROLL + LTEXT +"Riser Texture",IDC_STATIC,95,100,60,11, +SS_CENTERIMAGE + CONTROL +"Use Detail Brushes",IDC_DETAIL_CHK,"Button", +BS_AUTOCHECKBOX | WS_TABSTOP,100,80,75,10 END -IDD_POLYGON_DIALOG DIALOG DISCARDABLE 0, 0, 271, 68 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Polygon Builder" +IDD_POLYGON_DIALOG +DIALOG DISCARDABLE +0, 0, 271, 68 +STYLE DS_MODALFRAME +| WS_POPUP | WS_CAPTION | +WS_SYSMENU + CAPTION +"Polygon Builder" FONT 8, "Arial" BEGIN - PUSHBUTTON "OK",IDOK,150,50,50,14 - PUSHBUTTON "Cancel",IDCANCEL,215,50,50,14 - EDITTEXT IDC_EDIT1,7,7,76,13,ES_AUTOHSCROLL - LTEXT "Number Of Sides",IDC_STATIC,85,7,60,13,SS_CENTERIMAGE - CONTROL "Inverse Polygon",IDC_INVERSE_CHK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,149,21,75,10 - CONTROL "Use Border",IDC_BORDER_CHK,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,149,7,66,10 - EDITTEXT IDC_BORDER_EDIT,7,28,76,13,ES_AUTOHSCROLL - LTEXT "Border Size",IDC_STATIC,86,28,60,13,SS_CENTERIMAGE - CONTROL "Align Top Edge",IDC_ALIGN_CHK,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,149,35,75,10 + PUSHBUTTON +"OK",IDOK,150,50,50,14 +PUSHBUTTON "Cancel",IDCANCEL,215,50,50,14 +EDITTEXT IDC_EDIT1,7,7,76,13, +ES_AUTOHSCROLL + LTEXT +"Number Of Sides",IDC_STATIC,85,7,60,13, +SS_CENTERIMAGE + CONTROL +"Inverse Polygon",IDC_INVERSE_CHK,"Button", +BS_AUTOCHECKBOX | WS_TABSTOP,149,21,75,10 +CONTROL "Use Border",IDC_BORDER_CHK,"Button",BS_AUTOCHECKBOX | +WS_TABSTOP,149,7,66,10 +EDITTEXT IDC_BORDER_EDIT,7,28,76,13, +ES_AUTOHSCROLL + LTEXT +"Border Size",IDC_STATIC,86,28,60,13, +SS_CENTERIMAGE + CONTROL +"Align Top Edge",IDC_ALIGN_CHK,"Button",BS_AUTOCHECKBOX | +WS_TABSTOP,149,35,75,10 END -IDD_DOOR_DIALOG DIALOG DISCARDABLE 0, 0, 327, 119 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Door Builder" +IDD_DOOR_DIALOG +DIALOG DISCARDABLE +0, 0, 327, 119 +STYLE DS_MODALFRAME +| WS_POPUP | WS_CAPTION | +WS_SYSMENU + CAPTION +"Door Builder" FONT 8, "Arial" BEGIN - DEFPUSHBUTTON "OK",IDOK,270,7,50,14 - PUSHBUTTON "Cancel",IDCANCEL,270,24,50,14 - EDITTEXT IDC_FBTEXTURE_EDIT,7,7,125,14,ES_AUTOHSCROLL - LTEXT "Door Front/Back Texture",IDC_STATIC,137,7,86,14, - SS_CENTERIMAGE - EDITTEXT IDC_TRIMTEXTURE_EDIT,7,26,125,14,ES_AUTOHSCROLL - LTEXT "Door Trim Texture",IDC_STATIC,137,26,86,14, - SS_CENTERIMAGE - CONTROL "Scale Main Texture Horizontally",IDC_TEXSCALE1_CHECK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,46,115,10 - CONTROL "Scale Main Texture Vertically",IDC_TEXSCALE2_CHECK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,60,107,10 - CONTROL "Scale Trim Texture Horizontally",IDC_TEXSCALE3_CHECK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,46,113,10 - CONTROL "Scale Trim Texture Vertically",IDC_TEXSCALE4_CHECK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,60,105,10 - COMBOBOX IDC_MAINTEX_COMBO,7,76,126,30,CBS_DROPDOWN | CBS_SORT | - WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_TRIMTEX_COMBO,7,99,126,30,CBS_DROPDOWN | CBS_SORT | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Set As Main Texture",IDC_SET_MAINTEX_BTN,139,76,82,14 - PUSHBUTTON "Set As Trim Texture",IDC_SET_TRIMTEX_BTN,139,98,82,14 - GROUPBOX "Orientation",IDC_DIR_GROUP,225,72,95,40 - CONTROL "North - South",IDC_DIR_NS_RADIO,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,230,82,85,10 - CONTROL "East - West",IDC_DIR_EW_RADIO,"Button", - BS_AUTORADIOBUTTON,230,97,85,10 + DEFPUSHBUTTON +"OK",IDOK,270,7,50,14 +PUSHBUTTON "Cancel",IDCANCEL,270,24,50,14 +EDITTEXT IDC_FBTEXTURE_EDIT,7,7,125,14, +ES_AUTOHSCROLL + LTEXT +"Door Front/Back Texture",IDC_STATIC,137,7,86,14, +SS_CENTERIMAGE + EDITTEXT +IDC_TRIMTEXTURE_EDIT,7,26,125,14, +ES_AUTOHSCROLL + LTEXT +"Door Trim Texture",IDC_STATIC,137,26,86,14, +SS_CENTERIMAGE + CONTROL +"Scale Main Texture Horizontally",IDC_TEXSCALE1_CHECK, +"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,46,115,10 +CONTROL "Scale Main Texture Vertically",IDC_TEXSCALE2_CHECK, +"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,60,107,10 +CONTROL "Scale Trim Texture Horizontally",IDC_TEXSCALE3_CHECK, +"Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,46,113,10 +CONTROL "Scale Trim Texture Vertically",IDC_TEXSCALE4_CHECK, +"Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,60,105,10 +COMBOBOX IDC_MAINTEX_COMBO,7,76,126,30,CBS_DROPDOWN | CBS_SORT | +WS_VSCROLL | +WS_TABSTOP + COMBOBOX +IDC_TRIMTEX_COMBO,7,99,126,30,CBS_DROPDOWN | CBS_SORT | +WS_VSCROLL | +WS_TABSTOP + PUSHBUTTON +"Set As Main Texture",IDC_SET_MAINTEX_BTN,139,76,82,14 +PUSHBUTTON "Set As Trim Texture",IDC_SET_TRIMTEX_BTN,139,98,82,14 +GROUPBOX "Orientation",IDC_DIR_GROUP,225,72,95,40 +CONTROL "North - South",IDC_DIR_NS_RADIO,"Button", +BS_AUTORADIOBUTTON | WS_GROUP,230,82,85,10 +CONTROL "East - West",IDC_DIR_EW_RADIO,"Button", +BS_AUTORADIOBUTTON,230,97,85,10 END -IDD_INTERSECT_DIALOG DIALOG DISCARDABLE 0, 0, 245, 58 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Intersecting Brush Finder" +IDD_INTERSECT_DIALOG +DIALOG DISCARDABLE +0, 0, 245, 58 +STYLE DS_MODALFRAME +| WS_POPUP | WS_CAPTION | +WS_SYSMENU + CAPTION +"Intersecting Brush Finder" FONT 8, "Arial" BEGIN - DEFPUSHBUTTON "OK",IDOK,130,40,50,14 - PUSHBUTTON "Cancel",IDCANCEL,185,40,50,14 - CONTROL "Include Detail Brushes",IDC_DETAIL_INCLUDE_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,130,10,111,10 - GROUPBOX "Brush Options",IDC_STATIC,10,5,111,45 - CONTROL "Use Whole Map",IDC_WHOLEMAP_RADIO,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,15,15,95,10 - CONTROL "Use Selected Brushes",IDC_SELECTED_RADIO,"Button", - BS_AUTORADIOBUTTON,15,30,95,10 - CONTROL "Only Select Duplicate Brushes",IDC_DUPLICATEONLY_CHECK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,25,113,10 + DEFPUSHBUTTON +"OK",IDOK,130,40,50,14 +PUSHBUTTON "Cancel",IDCANCEL,185,40,50,14 +CONTROL "Include Detail Brushes",IDC_DETAIL_INCLUDE_CHECK,"Button", +BS_AUTOCHECKBOX | WS_TABSTOP,130,10,111,10 +GROUPBOX "Brush Options",IDC_STATIC,10,5,111,45 +CONTROL "Use Whole Map",IDC_WHOLEMAP_RADIO,"Button", +BS_AUTORADIOBUTTON | WS_GROUP,15,15,95,10 +CONTROL "Use Selected Brushes",IDC_SELECTED_RADIO,"Button", +BS_AUTORADIOBUTTON,15,30,95,10 +CONTROL "Only Select Duplicate Brushes",IDC_DUPLICATEONLY_CHECK, +"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,25,113,10 END -IDD_INTERSECT_INFO_DIALOG DIALOG DISCARDABLE 0, 0, 187, 33 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE -FONT 8, "MS Sans Serif" +IDD_INTERSECT_INFO_DIALOG +DIALOG DISCARDABLE +0, 0, 187, 33 +STYLE DS_MODALFRAME +| WS_POPUP | +WS_VISIBLE + FONT +8, "MS Sans Serif" BEGIN - CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH, - 5,15,175,10 - CTEXT "Brush Loading",IDC_STATIC,5,5,175,10,SS_CENTERIMAGE -END + CONTROL +"Progress1",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH, +5,15,175,10 +CTEXT "Brush Loading",IDC_STATIC,5,5,175,10, +SS_CENTERIMAGE + END -IDD_BRUSHCHECKER_DIALOG DIALOG DISCARDABLE 0, 0, 182, 38 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE -FONT 8, "MS Sans Serif" +IDD_BRUSHCHECKER_DIALOG +DIALOG DISCARDABLE +0, 0, 182, 38 +STYLE DS_MODALFRAME +| WS_POPUP | +WS_VISIBLE + FONT +8, "MS Sans Serif" BEGIN - CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH, - 5,21,172,10 - CTEXT "Checking Brushes",IDC_STATIC,5,5,170,15,SS_CENTERIMAGE -END + CONTROL +"Progress1",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH, +5,21,172,10 +CTEXT "Checking Brushes",IDC_STATIC,5,5,170,15, +SS_CENTERIMAGE + END -IDD_AUTOCAULK_DIALOG DIALOG DISCARDABLE 0, 0, 187, 52 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE -FONT 8, "MS Sans Serif" +IDD_AUTOCAULK_DIALOG +DIALOG DISCARDABLE +0, 0, 187, 52 +STYLE DS_MODALFRAME +| WS_POPUP | +WS_VISIBLE + FONT +8, "MS Sans Serif" BEGIN - CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH, - 5,15,175,10 - CTEXT "Loading Portal Data",IDC_STATIC,5,5,175,10, - SS_CENTERIMAGE - CONTROL "Progress1",IDC_PROGRESS2,"msctls_progress32",PBS_SMOOTH, - 5,35,175,10 - CTEXT "Auto Caulking",IDC_STATIC,5,25,175,10,SS_CENTERIMAGE -END + CONTROL +"Progress1",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH, +5,15,175,10 +CTEXT "Loading Portal Data",IDC_STATIC,5,5,175,10, +SS_CENTERIMAGE + CONTROL +"Progress1",IDC_PROGRESS2,"msctls_progress32",PBS_SMOOTH, +5,35,175,10 +CTEXT "Auto Caulking",IDC_STATIC,5,25,175,10, +SS_CENTERIMAGE + END -IDD_AUTOCAULKSTART_DIALOG DIALOG DISCARDABLE 0, 0, 237, 83 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Auto Caulk" +IDD_AUTOCAULKSTART_DIALOG +DIALOG DISCARDABLE +0, 0, 237, 83 +STYLE DS_MODALFRAME +| WS_POPUP | WS_CAPTION | +WS_SYSMENU + CAPTION +"Auto Caulk" FONT 8, "Arial" BEGIN - DEFPUSHBUTTON "OK",IDOK,125,10,50,14 - PUSHBUTTON "Cancel",IDCANCEL,180,10,50,14 - CONTROL "Destroy Invisible Brushes",IDC_KILLBRUSHES_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,125,50,95,10 - LTEXT "",IDC_WARNING1_STATIC,5,65,223,11,NOT WS_GROUP - GROUPBOX "Static",IDC_STATIC,5,5,115,57 - CONTROL "Autocaulk",IDC_AC_NORMAL_RADIO,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,10,15,48,10 - CONTROL "Build Mini Prt",IDC_AC_BUILD_MINI_PRT_RADIO,"Button", - BS_AUTORADIOBUTTON,10,30,56,10 - CONTROL "Autocaulk+ (Detail Brushes)",IDC_AC_SUPER_RADIO,"Button", - BS_AUTORADIOBUTTON,10,45,106,10 + DEFPUSHBUTTON +"OK",IDOK,125,10,50,14 +PUSHBUTTON "Cancel",IDCANCEL,180,10,50,14 +CONTROL "Destroy Invisible Brushes",IDC_KILLBRUSHES_CHECK,"Button", +BS_AUTOCHECKBOX | WS_TABSTOP,125,50,95,10 +LTEXT "",IDC_WARNING1_STATIC,5,65,223,11, +NOT WS_GROUP +GROUPBOX "Static",IDC_STATIC,5,5,115,57 +CONTROL "Autocaulk",IDC_AC_NORMAL_RADIO,"Button", +BS_AUTORADIOBUTTON | WS_GROUP,10,15,48,10 +CONTROL "Build Mini Prt",IDC_AC_BUILD_MINI_PRT_RADIO,"Button", +BS_AUTORADIOBUTTON,10,30,56,10 +CONTROL "Autocaulk+ (Detail Brushes)",IDC_AC_SUPER_RADIO,"Button", +BS_AUTORADIOBUTTON,10,45,106,10 END -IDD_TEXTURE_RESET_DIALOG DIALOG DISCARDABLE 0, 0, 272, 107 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Texture Reset" +IDD_TEXTURE_RESET_DIALOG +DIALOG DISCARDABLE +0, 0, 272, 107 +STYLE DS_MODALFRAME +| WS_POPUP | WS_CAPTION | +WS_SYSMENU + CAPTION +"Texture Reset" FONT 8, "Arial" BEGIN - DEFPUSHBUTTON "OK",IDOK,160,85,50,14 - PUSHBUTTON "Cancel",IDCANCEL,215,85,50,14 - EDITTEXT IDC_RESET_TEXTURE_EDIT,5,5,118,14,ES_AUTOHSCROLL - EDITTEXT IDC_SCL_VERT_EDIT,85,45,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_SCL_HOR_EDIT,85,65,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_ROTATION_EDIT,85,85,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_SHFT_VER_EDIT,225,45,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_SHFT_HOR_EDIT,225,65,40,14,ES_AUTOHSCROLL - RTEXT "Scale::Vertical",IDC_STATIC,5,45,75,15,SS_CENTERIMAGE - RTEXT "Scale::Horizontal",IDC_STATIC,5,65,75,15,SS_CENTERIMAGE - RTEXT "Rotation",IDC_STATIC,5,85,75,15,SS_CENTERIMAGE - RTEXT "Shift::Horizontal",IDC_STATIC,160,65,60,15, - SS_CENTERIMAGE - RTEXT "Shift::Vertical",IDC_STATIC,160,45,60,15,SS_CENTERIMAGE - LTEXT "Texture To Reset",IDC_STATIC,128,5,62,15,SS_CENTERIMAGE - CONTROL "Reset All Textures",IDC_ALLTEXTURES_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,195,5,75,15 - EDITTEXT IDC_RESET_NEW_TEXTURE_EDIT,5,25,118,14,ES_AUTOHSCROLL - LTEXT "New Texture Name",IDC_STATIC,128,25,62,15, - SS_CENTERIMAGE - CONTROL "Reset Texture Only",IDC_ONLYTEXTURE_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,195,25,75,15 + DEFPUSHBUTTON +"OK",IDOK,160,85,50,14 +PUSHBUTTON "Cancel",IDCANCEL,215,85,50,14 +EDITTEXT IDC_RESET_TEXTURE_EDIT,5,5,118,14, +ES_AUTOHSCROLL + EDITTEXT +IDC_SCL_VERT_EDIT,85,45,40,14, +ES_AUTOHSCROLL + EDITTEXT +IDC_SCL_HOR_EDIT,85,65,40,14, +ES_AUTOHSCROLL + EDITTEXT +IDC_ROTATION_EDIT,85,85,40,14, +ES_AUTOHSCROLL + EDITTEXT +IDC_SHFT_VER_EDIT,225,45,40,14, +ES_AUTOHSCROLL + EDITTEXT +IDC_SHFT_HOR_EDIT,225,65,40,14, +ES_AUTOHSCROLL + RTEXT +"Scale::Vertical",IDC_STATIC,5,45,75,15, +SS_CENTERIMAGE + RTEXT +"Scale::Horizontal",IDC_STATIC,5,65,75,15, +SS_CENTERIMAGE + RTEXT +"Rotation",IDC_STATIC,5,85,75,15, +SS_CENTERIMAGE + RTEXT +"Shift::Horizontal",IDC_STATIC,160,65,60,15, +SS_CENTERIMAGE + RTEXT +"Shift::Vertical",IDC_STATIC,160,45,60,15, +SS_CENTERIMAGE + LTEXT +"Texture To Reset",IDC_STATIC,128,5,62,15, +SS_CENTERIMAGE + CONTROL +"Reset All Textures",IDC_ALLTEXTURES_CHECK,"Button", +BS_AUTOCHECKBOX | WS_TABSTOP,195,5,75,15 +EDITTEXT IDC_RESET_NEW_TEXTURE_EDIT,5,25,118,14, +ES_AUTOHSCROLL + LTEXT +"New Texture Name",IDC_STATIC,128,25,62,15, +SS_CENTERIMAGE + CONTROL +"Reset Texture Only",IDC_ONLYTEXTURE_CHECK,"Button", +BS_AUTOCHECKBOX | WS_TABSTOP,195,25,75,15 END -IDD_PATHPLOTTER_DIALOG DIALOG DISCARDABLE 0, 0, 172, 113 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Path Plotter" +IDD_PATHPLOTTER_DIALOG +DIALOG DISCARDABLE +0, 0, 172, 113 +STYLE DS_MODALFRAME +| WS_POPUP | WS_CAPTION | +WS_SYSMENU + CAPTION +"Path Plotter" FONT 8, "MS Sans Serif" BEGIN - DEFPUSHBUTTON "Enable",IDYES,5,92,50,14 - PUSHBUTTON "Cancel",IDCANCEL,115,92,50,14 - PUSHBUTTON "Disable",IDNO,60,92,50,14 - EDITTEXT IDC_POINTCOUNT_EDIT,5,5,80,14,ES_AUTOHSCROLL - EDITTEXT IDC_MULTIPLIER_EDIT,5,25,80,14,ES_AUTOHSCROLL - EDITTEXT IDC_GRAVITY_EDIT,5,45,80,14,ES_AUTOHSCROLL - LTEXT "Number Of Points",IDC_STATIC,90,5,60,15,SS_CENTERIMAGE - CONTROL "No Dynamic Update",IDC_NOUPDATE_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,65,80,10 - LTEXT "Multiplier",IDC_STATIC,90,25,60,15,SS_CENTERIMAGE - LTEXT "Gravity",IDC_STATIC,90,45,60,15,SS_CENTERIMAGE - CONTROL "Show Bounding Lines",IDC_SHOWEXTRA_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,79,85,10 + DEFPUSHBUTTON +"Enable",IDYES,5,92,50,14 +PUSHBUTTON "Cancel",IDCANCEL,115,92,50,14 +PUSHBUTTON "Disable",IDNO,60,92,50,14 +EDITTEXT IDC_POINTCOUNT_EDIT,5,5,80,14, +ES_AUTOHSCROLL + EDITTEXT +IDC_MULTIPLIER_EDIT,5,25,80,14, +ES_AUTOHSCROLL + EDITTEXT +IDC_GRAVITY_EDIT,5,45,80,14, +ES_AUTOHSCROLL + LTEXT +"Number Of Points",IDC_STATIC,90,5,60,15, +SS_CENTERIMAGE + CONTROL +"No Dynamic Update",IDC_NOUPDATE_CHECK,"Button", +BS_AUTOCHECKBOX | WS_TABSTOP,7,65,80,10 +LTEXT "Multiplier",IDC_STATIC,90,25,60,15, +SS_CENTERIMAGE + LTEXT +"Gravity",IDC_STATIC,90,45,60,15, +SS_CENTERIMAGE + CONTROL +"Show Bounding Lines",IDC_SHOWEXTRA_CHECK,"Button", +BS_AUTOCHECKBOX | WS_TABSTOP,7,79,85,10 END @@ -345,7 +488,7 @@ END // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE +GUIDELINES DESIGNINFO DISCARDABLE BEGIN IDD_STAIR_DIALOG, DIALOG BEGIN @@ -435,58 +578,59 @@ END // Dialog Info // -IDD_DOOR_DIALOG DLGINIT -BEGIN - IDC_MAINTEX_COMBO, 0x403, 25, 0 -0x6162, 0x6573, 0x645f, 0x6f6f, 0x2f72, 0x6873, 0x6e69, 0x6d79, 0x7465, -0x6c61, 0x6f64, 0x726f, "\000" - IDC_MAINTEX_COMBO, 0x403, 33, 0 -0x6162, 0x6573, 0x645f, 0x6f6f, 0x2f72, 0x6873, 0x6e69, 0x6d79, 0x7465, -0x6c61, 0x6f64, 0x726f, 0x6f5f, 0x7475, 0x6973, 0x6564, "\000" - IDC_MAINTEX_COMBO, 0x403, 36, 0 -0x6162, 0x6573, 0x645f, 0x6f6f, 0x2f72, 0x6873, 0x6e69, 0x6d79, 0x7465, -0x6c61, 0x6f64, 0x726f, 0x6f5f, 0x7475, 0x6973, 0x6564, 0x6133, 0x0032, - - IDC_MAINTEX_COMBO, 0x403, 24, 0 -0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, -0x625f, 0x6572, 0x0064, - IDC_MAINTEX_COMBO, 0x403, 31, 0 -0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, -0x625f, 0x6572, 0x3264, 0x735f, 0x6968, 0x796e, "\000" - IDC_MAINTEX_COMBO, 0x403, 32, 0 -0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, -0x655f, 0x6c62, 0x6575, 0x5f32, 0x6873, 0x6e69, 0x0079, - IDC_MAINTEX_COMBO, 0x403, 33, 0 -0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, -0x695f, 0x6f5f, 0x6e72, 0x7461, 0x3565, 0x665f, 0x6e69, "\000" - IDC_MAINTEX_COMBO, 0x403, 21, 0 -0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, -0x6a5f, "\000" - IDC_MAINTEX_COMBO, 0x403, 22, 0 -0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, -0x6a5f, 0x0033, - IDC_MAINTEX_COMBO, 0x403, 22, 0 -0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, -0x6a5f, 0x0034, - IDC_MAINTEX_COMBO, 0x403, 23, 0 -0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, -0x6b5f, 0x6232, "\000" - IDC_TRIMTEX_COMBO, 0x403, 26, 0 -0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x732f, 0x7075, 0x6f70, -0x7472, 0x7231, 0x7375, 0x0074, - IDC_TRIMTEX_COMBO, 0x403, 27, 0 -0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x732f, 0x7075, 0x6f70, -0x7472, 0x7331, 0x6968, 0x796e, "\000" - IDC_TRIMTEX_COMBO, 0x403, 26, 0 -0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x732f, 0x7075, 0x6f70, -0x7472, 0x7232, 0x7375, 0x0074, - IDC_TRIMTEX_COMBO, 0x403, 22, 0 -0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x772f, 0x6c70, 0x7461, -0x5f31, 0x0031, - IDC_TRIMTEX_COMBO, 0x403, 22, 0 -0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x702f, 0x616c, 0x6574, -0x5f32, 0x0035, - 0 +IDD_DOOR_DIALOG +DLGINIT + BEGIN +IDC_MAINTEX_COMBO, 0x403, 25, 0 +0x6162, 0x6573, 0x645f, 0x6f6f, 0x2f72, 0x6873, 0x6e69, 0x6d79, 0x7465, +0x6c61, 0x6f64, 0x726f, "\000" +IDC_MAINTEX_COMBO, 0x403, 33, 0 +0x6162, 0x6573, 0x645f, 0x6f6f, 0x2f72, 0x6873, 0x6e69, 0x6d79, 0x7465, +0x6c61, 0x6f64, 0x726f, 0x6f5f, 0x7475, 0x6973, 0x6564, "\000" +IDC_MAINTEX_COMBO, 0x403, 36, 0 +0x6162, 0x6573, 0x645f, 0x6f6f, 0x2f72, 0x6873, 0x6e69, 0x6d79, 0x7465, +0x6c61, 0x6f64, 0x726f, 0x6f5f, 0x7475, 0x6973, 0x6564, 0x6133, 0x0032, + +IDC_MAINTEX_COMBO, 0x403, 24, 0 +0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, +0x625f, 0x6572, 0x0064, +IDC_MAINTEX_COMBO, 0x403, 31, 0 +0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, +0x625f, 0x6572, 0x3264, 0x735f, 0x6968, 0x796e, "\000" +IDC_MAINTEX_COMBO, 0x403, 32, 0 +0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, +0x655f, 0x6c62, 0x6575, 0x5f32, 0x6873, 0x6e69, 0x0079, +IDC_MAINTEX_COMBO, 0x403, 33, 0 +0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, +0x695f, 0x6f5f, 0x6e72, 0x7461, 0x3565, 0x665f, 0x6e69, "\000" +IDC_MAINTEX_COMBO, 0x403, 21, 0 +0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, +0x6a5f, "\000" +IDC_MAINTEX_COMBO, 0x403, 22, 0 +0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, +0x6a5f, 0x0033, +IDC_MAINTEX_COMBO, 0x403, 22, 0 +0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, +0x6a5f, 0x0034, +IDC_MAINTEX_COMBO, 0x403, 23, 0 +0x6f67, 0x6874, 0x6369, 0x645f, 0x6f6f, 0x2f72, 0x6f64, 0x726f, 0x3230, +0x6b5f, 0x6232, "\000" +IDC_TRIMTEX_COMBO, 0x403, 26, 0 +0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x732f, 0x7075, 0x6f70, +0x7472, 0x7231, 0x7375, 0x0074, +IDC_TRIMTEX_COMBO, 0x403, 27, 0 +0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x732f, 0x7075, 0x6f70, +0x7472, 0x7331, 0x6968, 0x796e, "\000" +IDC_TRIMTEX_COMBO, 0x403, 26, 0 +0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x732f, 0x7075, 0x6f70, +0x7472, 0x7232, 0x7375, 0x0074, +IDC_TRIMTEX_COMBO, 0x403, 22, 0 +0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x772f, 0x6c70, 0x7461, +0x5f31, 0x0031, +IDC_TRIMTEX_COMBO, 0x403, 22, 0 +0x6162, 0x6573, 0x735f, 0x7075, 0x6f70, 0x7472, 0x702f, 0x616c, 0x6574, +0x5f32, 0x0035, +0 END diff --git a/contrib/bobtoolz/bsploader.cpp b/contrib/bobtoolz/bsploader.cpp index 0c442e16..020cf4d8 100644 --- a/contrib/bobtoolz/bsploader.cpp +++ b/contrib/bobtoolz/bsploader.cpp @@ -14,18 +14,18 @@ int numbrushes; int numbrushsides; int numleafbrushes; -byte *visBytes = NULL; -dnode_t *dnodes = NULL; -dplane_t *dplanes = NULL; -dleaf_t *dleafs = NULL; -qdrawVert_t *drawVerts = NULL; -dsurface_t *drawSurfaces = NULL; -int *dleafsurfaces = NULL; -dbrush_t *dbrushes = NULL; -dbrushside_t *dbrushsides = NULL; -int *dleafbrushes = NULL; - -const int BSP_IDENT = ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'B' << 8 ) + 'I' ); +byte *visBytes = NULL; +dnode_t *dnodes = NULL; +dplane_t *dplanes = NULL; +dleaf_t *dleafs = NULL; +qdrawVert_t *drawVerts = NULL; +dsurface_t *drawSurfaces = NULL; +int *dleafsurfaces = NULL; +dbrush_t *dbrushes = NULL; +dbrushside_t *dbrushsides = NULL; +int *dleafbrushes = NULL; + +const int BSP_IDENT = (('P' << 24) + ('S' << 16) + ('B' << 8) + 'I'); const int Q3_BSP_VERSION = 46; const int WOLF_BSP_VERSION = 47; @@ -34,16 +34,17 @@ const int WOLF_BSP_VERSION = 47; FileLength ================ */ -int FileLength( FILE *f ){ - int pos; - int end; +int FileLength(FILE *f) +{ + int pos; + int end; - pos = ftell( f ); - fseek( f, 0, SEEK_END ); - end = ftell( f ); - fseek( f, pos, SEEK_SET ); + pos = ftell(f); + fseek(f, 0, SEEK_END); + end = ftell(f); + fseek(f, pos, SEEK_SET); - return end; + return end; } /* @@ -51,38 +52,41 @@ int FileLength( FILE *f ){ LoadFile ============== */ -bool LoadFile( const char *filename, byte **bufferptr ){ - FILE *f; - int length; - byte *buffer; - - f = fopen( filename, "rb" ); - if ( !f ) { - return false; - } - - length = FileLength( f ); - buffer = new byte[length + 1]; - buffer[length] = 0; - fread( buffer, 1, length, f ); - fclose( f ); - - *bufferptr = buffer; - return true; +bool LoadFile(const char *filename, byte **bufferptr) +{ + FILE *f; + int length; + byte *buffer; + + f = fopen(filename, "rb"); + if (!f) { + return false; + } + + length = FileLength(f); + buffer = new byte[length + 1]; + buffer[length] = 0; + fread(buffer, 1, length, f); + fclose(f); + + *bufferptr = buffer; + return true; } -int LittleLong( int l ){ - if (GDEF_ARCH_ENDIAN_BIG) { - std::reverse(reinterpret_cast( &l ), reinterpret_cast( &l ) + sizeof(int)); - } - return l; +int LittleLong(int l) +{ + if (GDEF_ARCH_ENDIAN_BIG) { + std::reverse(reinterpret_cast( &l ), reinterpret_cast( &l ) + sizeof(int)); + } + return l; } -float LittleFloat( float l ){ - if (GDEF_ARCH_ENDIAN_BIG) { - std::reverse( reinterpret_cast( &l ), reinterpret_cast( &l ) + sizeof( float ) ); - } - return l; +float LittleFloat(float l) +{ + if (GDEF_ARCH_ENDIAN_BIG) { + std::reverse(reinterpret_cast( &l ), reinterpret_cast( &l ) + sizeof(float)); + } + return l; } /* @@ -92,13 +96,14 @@ float LittleFloat( float l ){ If all values are 32 bits, this can be used to swap everything ============= */ -void SwapBlock( int *block, int sizeOfBlock ) { - int i; - - sizeOfBlock >>= 2; - for ( i = 0 ; i < sizeOfBlock ; i++ ) { - block[i] = LittleLong( block[i] ); - } +void SwapBlock(int *block, int sizeOfBlock) +{ + int i; + + sizeOfBlock >>= 2; + for (i = 0; i < sizeOfBlock; i++) { + block[i] = LittleLong(block[i]); + } } /* @@ -108,64 +113,65 @@ void SwapBlock( int *block, int sizeOfBlock ) { Byte swaps all data in a bsp file. ============= */ -void SwapBSPFile( void ) { - int i; +void SwapBSPFile(void) +{ + int i; - // models + // models // SwapBlock( (int *)dmodels, nummodels * sizeof( dmodels[0] ) ); - // shaders (don't swap the name) + // shaders (don't swap the name) // for ( i = 0 ; i < numShaders ; i++ ) { // dshaders[i].contentFlags = LittleLong( dshaders[i].contentFlags ); // dshaders[i].surfaceFlags = LittleLong( dshaders[i].surfaceFlags ); // } - // planes - SwapBlock( (int *)dplanes, numplanes * sizeof( dplanes[0] ) ); + // planes + SwapBlock((int *) dplanes, numplanes * sizeof(dplanes[0])); - // nodes - SwapBlock( (int *)dnodes, numnodes * sizeof( dnodes[0] ) ); + // nodes + SwapBlock((int *) dnodes, numnodes * sizeof(dnodes[0])); - // leafs - SwapBlock( (int *)dleafs, numleafs * sizeof( dleafs[0] ) ); + // leafs + SwapBlock((int *) dleafs, numleafs * sizeof(dleafs[0])); - // leaffaces - SwapBlock( (int *)dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) ); + // leaffaces + SwapBlock((int *) dleafsurfaces, numleafsurfaces * sizeof(dleafsurfaces[0])); - // leafbrushes - SwapBlock( (int *)dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) ); + // leafbrushes + SwapBlock((int *) dleafbrushes, numleafbrushes * sizeof(dleafbrushes[0])); - // brushes - SwapBlock( (int *)dbrushes, numbrushes * sizeof( dbrushes[0] ) ); + // brushes + SwapBlock((int *) dbrushes, numbrushes * sizeof(dbrushes[0])); - // brushsides - SwapBlock( (int *)dbrushsides, numbrushsides * sizeof( dbrushsides[0] ) ); + // brushsides + SwapBlock((int *) dbrushsides, numbrushsides * sizeof(dbrushsides[0])); - // vis - ( (int *)&visBytes )[0] = LittleLong( ( (int *)&visBytes )[0] ); - ( (int *)&visBytes )[1] = LittleLong( ( (int *)&visBytes )[1] ); + // vis + ((int *) &visBytes)[0] = LittleLong(((int *) &visBytes)[0]); + ((int *) &visBytes)[1] = LittleLong(((int *) &visBytes)[1]); - // drawverts (don't swap colors ) - for ( i = 0 ; i < numDrawVerts ; i++ ) { - drawVerts[i].lightmap[0] = LittleFloat( drawVerts[i].lightmap[0] ); - drawVerts[i].lightmap[1] = LittleFloat( drawVerts[i].lightmap[1] ); - drawVerts[i].st[0] = LittleFloat( drawVerts[i].st[0] ); - drawVerts[i].st[1] = LittleFloat( drawVerts[i].st[1] ); - drawVerts[i].xyz[0] = LittleFloat( drawVerts[i].xyz[0] ); - drawVerts[i].xyz[1] = LittleFloat( drawVerts[i].xyz[1] ); - drawVerts[i].xyz[2] = LittleFloat( drawVerts[i].xyz[2] ); - drawVerts[i].normal[0] = LittleFloat( drawVerts[i].normal[0] ); - drawVerts[i].normal[1] = LittleFloat( drawVerts[i].normal[1] ); - drawVerts[i].normal[2] = LittleFloat( drawVerts[i].normal[2] ); - } + // drawverts (don't swap colors ) + for (i = 0; i < numDrawVerts; i++) { + drawVerts[i].lightmap[0] = LittleFloat(drawVerts[i].lightmap[0]); + drawVerts[i].lightmap[1] = LittleFloat(drawVerts[i].lightmap[1]); + drawVerts[i].st[0] = LittleFloat(drawVerts[i].st[0]); + drawVerts[i].st[1] = LittleFloat(drawVerts[i].st[1]); + drawVerts[i].xyz[0] = LittleFloat(drawVerts[i].xyz[0]); + drawVerts[i].xyz[1] = LittleFloat(drawVerts[i].xyz[1]); + drawVerts[i].xyz[2] = LittleFloat(drawVerts[i].xyz[2]); + drawVerts[i].normal[0] = LittleFloat(drawVerts[i].normal[0]); + drawVerts[i].normal[1] = LittleFloat(drawVerts[i].normal[1]); + drawVerts[i].normal[2] = LittleFloat(drawVerts[i].normal[2]); + } - // drawindexes + // drawindexes // SwapBlock( (int *)drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) ); - // drawsurfs - SwapBlock( (int *)drawSurfaces, numDrawSurfaces * sizeof( drawSurfaces[0] ) ); + // drawsurfs + SwapBlock((int *) drawSurfaces, numDrawSurfaces * sizeof(drawSurfaces[0])); - // fogs + // fogs // for ( i = 0 ; i < numFogs ; i++ ) { // dfogs[i].brushNum = LittleLong( dfogs[i].brushNum ); // dfogs[i].visibleSide = LittleLong( dfogs[i].visibleSide ); @@ -177,20 +183,21 @@ void SwapBSPFile( void ) { CopyLump ============= */ -int CopyLump( dheader_t *header, int lump, void **dest, int size ) { - int length, ofs; +int CopyLump(dheader_t *header, int lump, void **dest, int size) +{ + int length, ofs; - length = header->lumps[lump].filelen; - ofs = header->lumps[lump].fileofs; + length = header->lumps[lump].filelen; + ofs = header->lumps[lump].fileofs; - if ( length == 0 ) { - return 0; - } + if (length == 0) { + return 0; + } - *dest = new byte[length]; - memcpy( *dest, (byte *)header + ofs, length ); + *dest = new byte[length]; + memcpy(*dest, (byte *) header + ofs, length); - return length / size; + return length / size; } /* @@ -198,75 +205,77 @@ int CopyLump( dheader_t *header, int lump, void **dest, int size ) { LoadBSPFile ============= */ -bool LoadBSPFile( const char *filename ) { - dheader_t *header; - - // load the file header - if ( !LoadFile( filename, (byte **)&header ) ) { - return false; - } - - // swap the header - SwapBlock( (int *)header, sizeof( *header ) ); - - if ( header->ident != BSP_IDENT ) { - DoMessageBox( "Cant find a valid IBSP file", "Error", eMB_OK ); - return false; - } - if ( ( header->version != Q3_BSP_VERSION ) && - ( header->version != WOLF_BSP_VERSION ) ) { - DoMessageBox( "File is incorrect version", "Error", eMB_OK ); - return false; - } - - numbrushsides = CopyLump( header, LUMP_BRUSHES, (void**)&dbrushsides, sizeof( dbrushside_t ) ); - numbrushes = CopyLump( header, LUMP_BRUSHES, (void**)&dbrushes, sizeof( dbrush_t ) ); - numplanes = CopyLump( header, LUMP_PLANES, (void**)&dplanes, sizeof( dplane_t ) ); - numleafs = CopyLump( header, LUMP_LEAFS, (void**)&dleafs, sizeof( dleaf_t ) ); - numnodes = CopyLump( header, LUMP_NODES, (void**)&dnodes, sizeof( dnode_t ) ); - numDrawVerts = CopyLump( header, LUMP_DRAWVERTS, (void**)&drawVerts, sizeof( qdrawVert_t ) ); - numDrawSurfaces = CopyLump( header, LUMP_SURFACES, (void**)&drawSurfaces, sizeof( dsurface_t ) ); - numleafsurfaces = CopyLump( header, LUMP_LEAFSURFACES, (void**)&dleafsurfaces, sizeof( int ) ); - numVisBytes = CopyLump( header, LUMP_VISIBILITY, (void**)&visBytes, 1 ); - numleafbrushes = CopyLump( header, LUMP_LEAFBRUSHES, (void**)&dleafbrushes, sizeof( int ) ); - - delete header; // everything has been copied out - - // swap everything - SwapBSPFile(); - - return true; +bool LoadBSPFile(const char *filename) +{ + dheader_t *header; + + // load the file header + if (!LoadFile(filename, (byte **) &header)) { + return false; + } + + // swap the header + SwapBlock((int *) header, sizeof(*header)); + + if (header->ident != BSP_IDENT) { + DoMessageBox("Cant find a valid IBSP file", "Error", eMB_OK); + return false; + } + if ((header->version != Q3_BSP_VERSION) && + (header->version != WOLF_BSP_VERSION)) { + DoMessageBox("File is incorrect version", "Error", eMB_OK); + return false; + } + + numbrushsides = CopyLump(header, LUMP_BRUSHES, (void **) &dbrushsides, sizeof(dbrushside_t)); + numbrushes = CopyLump(header, LUMP_BRUSHES, (void **) &dbrushes, sizeof(dbrush_t)); + numplanes = CopyLump(header, LUMP_PLANES, (void **) &dplanes, sizeof(dplane_t)); + numleafs = CopyLump(header, LUMP_LEAFS, (void **) &dleafs, sizeof(dleaf_t)); + numnodes = CopyLump(header, LUMP_NODES, (void **) &dnodes, sizeof(dnode_t)); + numDrawVerts = CopyLump(header, LUMP_DRAWVERTS, (void **) &drawVerts, sizeof(qdrawVert_t)); + numDrawSurfaces = CopyLump(header, LUMP_SURFACES, (void **) &drawSurfaces, sizeof(dsurface_t)); + numleafsurfaces = CopyLump(header, LUMP_LEAFSURFACES, (void **) &dleafsurfaces, sizeof(int)); + numVisBytes = CopyLump(header, LUMP_VISIBILITY, (void **) &visBytes, 1); + numleafbrushes = CopyLump(header, LUMP_LEAFBRUSHES, (void **) &dleafbrushes, sizeof(int)); + + delete header; // everything has been copied out + + // swap everything + SwapBSPFile(); + + return true; } -void FreeBSPData(){ - if ( visBytes ) { - delete visBytes; - } - if ( dnodes ) { - delete dnodes; - } - if ( dplanes ) { - delete dplanes; - } - if ( dleafs ) { - delete dleafs; - } - if ( drawVerts ) { - delete drawVerts; - } - if ( drawSurfaces ) { - delete drawSurfaces; - } - if ( dleafsurfaces ) { - delete dleafsurfaces; - } - if ( dleafbrushes ) { - delete dleafbrushes; - } - if ( dbrushes ) { - delete dbrushes; - } - if ( dbrushsides ) { - delete dbrushsides; - } +void FreeBSPData() +{ + if (visBytes) { + delete visBytes; + } + if (dnodes) { + delete dnodes; + } + if (dplanes) { + delete dplanes; + } + if (dleafs) { + delete dleafs; + } + if (drawVerts) { + delete drawVerts; + } + if (drawSurfaces) { + delete drawSurfaces; + } + if (dleafsurfaces) { + delete dleafsurfaces; + } + if (dleafbrushes) { + delete dleafbrushes; + } + if (dbrushes) { + delete dbrushes; + } + if (dbrushsides) { + delete dbrushsides; + } } diff --git a/contrib/bobtoolz/bsploader.h b/contrib/bobtoolz/bsploader.h index 47e9f5a3..de22e7b7 100644 --- a/contrib/bobtoolz/bsploader.h +++ b/contrib/bobtoolz/bsploader.h @@ -1,115 +1,115 @@ #include "mathlib.h" -const int LUMP_ENTITIES = 0; -const int LUMP_SHADERS = 1; -const int LUMP_PLANES = 2; -const int LUMP_NODES = 3; -const int LUMP_LEAFS = 4; -const int LUMP_LEAFSURFACES = 5; -const int LUMP_LEAFBRUSHES = 6; -const int LUMP_MODELS = 7; -const int LUMP_BRUSHES = 8; -const int LUMP_BRUSHSIDES = 9; -const int LUMP_DRAWVERTS = 10; -const int LUMP_DRAWINDEXES = 11; -const int LUMP_FOGS = 12; -const int LUMP_SURFACES = 13; -const int LUMP_LIGHTMAPS = 14; -const int LUMP_LIGHTGRID = 15; -const int LUMP_VISIBILITY = 16; -const int HEADER_LUMPS = 17; +const int LUMP_ENTITIES = 0; +const int LUMP_SHADERS = 1; +const int LUMP_PLANES = 2; +const int LUMP_NODES = 3; +const int LUMP_LEAFS = 4; +const int LUMP_LEAFSURFACES = 5; +const int LUMP_LEAFBRUSHES = 6; +const int LUMP_MODELS = 7; +const int LUMP_BRUSHES = 8; +const int LUMP_BRUSHSIDES = 9; +const int LUMP_DRAWVERTS = 10; +const int LUMP_DRAWINDEXES = 11; +const int LUMP_FOGS = 12; +const int LUMP_SURFACES = 13; +const int LUMP_LIGHTMAPS = 14; +const int LUMP_LIGHTGRID = 15; +const int LUMP_VISIBILITY = 16; +const int HEADER_LUMPS = 17; typedef struct { - int fileofs, filelen; + int fileofs, filelen; } lump_t; typedef struct { - int ident; - int version; + int ident; + int version; - lump_t lumps[HEADER_LUMPS]; + lump_t lumps[HEADER_LUMPS]; } dheader_t; typedef struct { - float normal[3]; - float dist; + float normal[3]; + float dist; } dplane_t; typedef struct { - int planeNum; - int children[2]; // negative numbers are -(leafs+1), not nodes - int mins[3]; // for frustom culling - int maxs[3]; + int planeNum; + int children[2]; // negative numbers are -(leafs+1), not nodes + int mins[3]; // for frustom culling + int maxs[3]; } dnode_t; typedef struct { - int cluster; // -1 = opaque cluster (do I still store these?) - int area; + int cluster; // -1 = opaque cluster (do I still store these?) + int area; - int mins[3]; // for frustum culling - int maxs[3]; + int mins[3]; // for frustum culling + int maxs[3]; - int firstLeafSurface; - int numLeafSurfaces; + int firstLeafSurface; + int numLeafSurfaces; - int firstLeafBrush; - int numLeafBrushes; + int firstLeafBrush; + int numLeafBrushes; } dleaf_t; typedef struct { - vec3_t xyz; - float st[2]; - float lightmap[2]; - vec3_t normal; - byte color[4]; + vec3_t xyz; + float st[2]; + float lightmap[2]; + vec3_t normal; + byte color[4]; } qdrawVert_t; typedef struct { - int shaderNum; - int fogNum; - int surfaceType; + int shaderNum; + int fogNum; + int surfaceType; - int firstVert; - int numVerts; + int firstVert; + int numVerts; - int firstIndex; - int numIndexes; + int firstIndex; + int numIndexes; - int lightmapNum; - int lightmapX, lightmapY; - int lightmapWidth, lightmapHeight; + int lightmapNum; + int lightmapX, lightmapY; + int lightmapWidth, lightmapHeight; - vec3_t lightmapOrigin; - vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds + vec3_t lightmapOrigin; + vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds - int patchWidth; - int patchHeight; + int patchWidth; + int patchHeight; } dsurface_t; typedef struct { - int planeNum; // positive plane side faces out of the leaf - int shaderNum; + int planeNum; // positive plane side faces out of the leaf + int shaderNum; } dbrushside_t; typedef struct { - int firstSide; - int numSides; - int shaderNum; // the shader that determines the contents flags + int firstSide; + int numSides; + int shaderNum; // the shader that determines the contents flags } dbrush_t; typedef enum { - MST_BAD, - MST_PLANAR, - MST_PATCH, - MST_TRIANGLE_SOUP, - MST_FLARE + MST_BAD, + MST_PLANAR, + MST_PATCH, + MST_TRIANGLE_SOUP, + MST_FLARE } mapSurfaceType_t; -const int MAX_MAP_VISIBILITY = 0x200000; -const int MAX_MAP_NODES = 0x20000; -const int MAX_MAP_PLANES = 0x20000; -const int MAX_MAP_LEAFS = 0x20000; +const int MAX_MAP_VISIBILITY = 0x200000; +const int MAX_MAP_NODES = 0x20000; +const int MAX_MAP_PLANES = 0x20000; +const int MAX_MAP_LEAFS = 0x20000; extern int numVisBytes; extern int numleafs; @@ -122,16 +122,17 @@ extern int numbrushes; extern int numbrushsides; extern int numleafbrushes; -extern dnode_t *dnodes; -extern dplane_t *dplanes; -extern dleaf_t *dleafs; -extern byte *visBytes; -extern qdrawVert_t *drawVerts; -extern dsurface_t *drawSurfaces; -extern int *dleafsurfaces; -extern dbrush_t *dbrushes; -extern dbrushside_t *dbrushsides; -extern int *dleafbrushes; - -bool LoadBSPFile( const char *filename ); +extern dnode_t *dnodes; +extern dplane_t *dplanes; +extern dleaf_t *dleafs; +extern byte *visBytes; +extern qdrawVert_t *drawVerts; +extern dsurface_t *drawSurfaces; +extern int *dleafsurfaces; +extern dbrush_t *dbrushes; +extern dbrushside_t *dbrushsides; +extern int *dleafbrushes; + +bool LoadBSPFile(const char *filename); + void FreeBSPData(); diff --git a/contrib/bobtoolz/cportals.cpp b/contrib/bobtoolz/cportals.cpp index d8ec2a60..ab944ed8 100644 --- a/contrib/bobtoolz/cportals.cpp +++ b/contrib/bobtoolz/cportals.cpp @@ -30,298 +30,309 @@ const char *MSG_PREFIX = "bobToolz plugin: "; // these classes are far less of a mess than my code was, // thanq to G.DeWan 4 the prtview source on which it was based -CBspPortal::CBspPortal(){ - memset( this, 0, sizeof( CBspPortal ) ); +CBspPortal::CBspPortal() +{ + memset(this, 0, sizeof(CBspPortal)); } -CBspPortal::~CBspPortal(){ - delete[] point; +CBspPortal::~CBspPortal() +{ + delete[] point; } -void ClampFloat( float* p ){ - double i; - double frac = modf( *p, &i ); +void ClampFloat(float *p) +{ + double i; + double frac = modf(*p, &i); - if ( !frac ) { - return; - } + if (!frac) { + return; + } - if ( fabs( *p - ceil( *p ) ) < MAX_ROUND_ERROR ) { - *p = static_cast( ceil( *p ) ); - } + if (fabs(*p - ceil(*p)) < MAX_ROUND_ERROR) { + *p = static_cast( ceil(*p)); + } - if ( fabs( *p - floor( *p ) ) < MAX_ROUND_ERROR ) { - *p = static_cast( floor( *p ) ); - } + if (fabs(*p - floor(*p)) < MAX_ROUND_ERROR) { + *p = static_cast( floor(*p)); + } } -bool CBspPortal::Build( char *def, unsigned int pointCnt, bool bInverse ){ - char *c = def; - unsigned int n; +bool CBspPortal::Build(char *def, unsigned int pointCnt, bool bInverse) +{ + char *c = def; + unsigned int n; - point_count = pointCnt; + point_count = pointCnt; - if ( point_count < 3 ) { - return false; - } + if (point_count < 3) { + return false; + } - point = new CBspPoint[point_count]; + point = new CBspPoint[point_count]; - for ( n = 0; n < point_count; n++ ) - { - for (; *c != 0 && *c != '('; c++ ) ; + for (n = 0; n < point_count; n++) { + for (; *c != 0 && *c != '('; c++) {} - if ( *c == 0 ) { - return false; - } + if (*c == 0) { + return false; + } - c++; + c++; - int x; - if ( bInverse ) { - x = point_count - n - 1; - } - else{ - x = n; - } + int x; + if (bInverse) { + x = point_count - n - 1; + } else { + x = n; + } - sscanf( c, "%f %f %f", &point[x].p[0], &point[x].p[1], &point[x].p[2] ); + sscanf(c, "%f %f %f", &point[x].p[0], &point[x].p[1], &point[x].p[2]); - ClampFloat( &point[x].p[0] ); - ClampFloat( &point[x].p[1] ); - ClampFloat( &point[x].p[2] ); - } + ClampFloat(&point[x].p[0]); + ClampFloat(&point[x].p[1]); + ClampFloat(&point[x].p[2]); + } - return true; + return true; } -CPortals::CPortals(){ - memset( this, 0, sizeof( CPortals ) ); +CPortals::CPortals() +{ + memset(this, 0, sizeof(CPortals)); } -CPortals::~CPortals(){ - Purge(); +CPortals::~CPortals() +{ + Purge(); } -void CPortals::Purge(){ - if ( node ) { - delete[] node; - } - node = NULL; - node_count = 0; +void CPortals::Purge() +{ + if (node) { + delete[] node; + } + node = NULL; + node_count = 0; } -void CPortals::Load(){ - char buf[LINE_BUF + 1]; +void CPortals::Load() +{ + char buf[LINE_BUF + 1]; - memset( buf, 0, LINE_BUF + 1 ); + memset(buf, 0, LINE_BUF + 1); - Purge(); + Purge(); - globalOutputStream() << MSG_PREFIX << "Loading portal file " << fn << ".\n"; + globalOutputStream() << MSG_PREFIX << "Loading portal file " << fn << ".\n"; - FILE *in; + FILE *in; - in = fopen( fn, "rt" ); + in = fopen(fn, "rt"); - if ( in == NULL ) { - globalOutputStream() << " ERROR - could not open file.\n"; + if (in == NULL) { + globalOutputStream() << " ERROR - could not open file.\n"; - return; - } + return; + } - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - globalOutputStream() << " ERROR - File ended prematurely.\n"; + globalOutputStream() << " ERROR - File ended prematurely.\n"; - return; - } + return; + } - if ( strncmp( "PRT1", buf, 4 ) != 0 ) { - fclose( in ); + if (strncmp("PRT1", buf, 4) != 0) { + fclose(in); - globalOutputStream() << " ERROR - File header indicates wrong file type (should be \"PRT1\").\n"; + globalOutputStream() << " ERROR - File header indicates wrong file type (should be \"PRT1\").\n"; - return; - } + return; + } - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - globalOutputStream() << " ERROR - File ended prematurely.\n"; + globalOutputStream() << " ERROR - File ended prematurely.\n"; - return; - } + return; + } - sscanf( buf, "%u", &node_count ); + sscanf(buf, "%u", &node_count); - if ( node_count > 0xFFFF ) { - fclose( in ); + if (node_count > 0xFFFF) { + fclose(in); - node_count = 0; + node_count = 0; - globalOutputStream() << " ERROR - Extreme number of nodes, aborting.\n"; + globalOutputStream() << " ERROR - Extreme number of nodes, aborting.\n"; - return; - } + return; + } - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - node_count = 0; + node_count = 0; - globalOutputStream() << " ERROR - File ended prematurely.\n"; + globalOutputStream() << " ERROR - File ended prematurely.\n"; - return; - } + return; + } - unsigned int p_count; - sscanf( buf, "%u", &p_count ); + unsigned int p_count; + sscanf(buf, "%u", &p_count); - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - node_count = 0; + node_count = 0; - globalOutputStream() << " ERROR - File ended prematurely.\n"; + globalOutputStream() << " ERROR - File ended prematurely.\n"; - return; - } + return; + } - unsigned int p_count2; - sscanf( buf, "%u", &p_count2 ); + unsigned int p_count2; + sscanf(buf, "%u", &p_count2); - node = new CBspNode[node_count]; + node = new CBspNode[node_count]; - unsigned int i; - for ( i = 0; i < p_count; i++ ) - { - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + unsigned int i; + for (i = 0; i < p_count; i++) { + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - node_count = 0; + node_count = 0; - globalOutputStream() << " ERROR - File ended prematurely.\n"; + globalOutputStream() << " ERROR - File ended prematurely.\n"; - return; - } + return; + } - unsigned int dummy, node1, node2; - sscanf( buf, "%u %u %u", &dummy, &node1, &node2 ); + unsigned int dummy, node1, node2; + sscanf(buf, "%u %u %u", &dummy, &node1, &node2); - node[node1].portal_count++; - node[node2].portal_count++; - } + node[node1].portal_count++; + node[node2].portal_count++; + } - for ( i = 0; i < p_count2; i++ ) - { - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + for (i = 0; i < p_count2; i++) { + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - node_count = 0; + node_count = 0; - globalOutputStream() << " ERROR - File ended prematurely.\n"; + globalOutputStream() << " ERROR - File ended prematurely.\n"; - return; - } + return; + } - unsigned int dummy, node1; - sscanf( buf, "%u %u", &dummy, &node1 ); + unsigned int dummy, node1; + sscanf(buf, "%u %u", &dummy, &node1); - node[node1].portal_count++; - } + node[node1].portal_count++; + } - for ( i = 0; i < node_count; i++ ) - node[i].portal = new CBspPortal[node[i].portal_count]; + for (i = 0; i < node_count; i++) { + node[i].portal = new CBspPortal[node[i].portal_count]; + } - fclose( in ); + fclose(in); - in = fopen( fn, "rt" ); + in = fopen(fn, "rt"); - fgets( buf, LINE_BUF, in ); - fgets( buf, LINE_BUF, in ); - fgets( buf, LINE_BUF, in ); - fgets( buf, LINE_BUF, in ); + fgets(buf, LINE_BUF, in); + fgets(buf, LINE_BUF, in); + fgets(buf, LINE_BUF, in); + fgets(buf, LINE_BUF, in); - unsigned int n; - for ( n = 0; n < p_count; n++ ) - { - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + unsigned int n; + for (n = 0; n < p_count; n++) { + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - Purge(); + Purge(); - globalOutputStream() << " ERROR - Could not find information for portal number " << n + 1 << " of " << p_count << ".\n"; + globalOutputStream() << " ERROR - Could not find information for portal number " << n + 1 << " of " + << p_count << ".\n"; - return; - } + return; + } - unsigned int pCount, node1, node2; - sscanf( buf, "%u %u %u", &pCount, &node1, &node2 ); + unsigned int pCount, node1, node2; + sscanf(buf, "%u %u %u", &pCount, &node1, &node2); - if ( !node[node1].AddPortal( buf, pCount, false ) ) { - fclose( in ); + if (!node[node1].AddPortal(buf, pCount, false)) { + fclose(in); - Purge(); + Purge(); - globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n"; + globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << p_count + << " is not formatted correctly.\n"; - return; - } + return; + } - if ( !node[node2].AddPortal( buf, pCount, true ) ) { - fclose( in ); + if (!node[node2].AddPortal(buf, pCount, true)) { + fclose(in); - Purge(); + Purge(); - globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n"; + globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << p_count + << " is not formatted correctly.\n"; - return; - } - } + return; + } + } - for ( n = 0; n < p_count2; n++ ) - { - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + for (n = 0; n < p_count2; n++) { + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - Purge(); + Purge(); - globalOutputStream() << " ERROR - Could not find information for portal number " << n + 1 << " of " << p_count << ".\n"; + globalOutputStream() << " ERROR - Could not find information for portal number " << n + 1 << " of " + << p_count << ".\n"; - return; - } + return; + } - unsigned int pCount, node1; - sscanf( buf, "%u %u", &pCount, &node1 ); + unsigned int pCount, node1; + sscanf(buf, "%u %u", &pCount, &node1); - if ( !node[node1].AddPortal( buf, pCount, false ) ) { - fclose( in ); + if (!node[node1].AddPortal(buf, pCount, false)) { + fclose(in); - Purge(); + Purge(); - globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n"; + globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << p_count + << " is not formatted correctly.\n"; - return; - } - } + return; + } + } - fclose( in ); + fclose(in); } -CBspNode::CBspNode(){ - portal = NULL; - portal_count = 0; - portal_next = 0; +CBspNode::CBspNode() +{ + portal = NULL; + portal_count = 0; + portal_next = 0; } -CBspNode::~CBspNode(){ - if ( portal != NULL ) { - delete[] portal; - } +CBspNode::~CBspNode() +{ + if (portal != NULL) { + delete[] portal; + } } -bool CBspNode::AddPortal( char *def, unsigned int pointCnt, bool bInverse ){ - return portal[portal_next++].Build( def, pointCnt, bInverse ); +bool CBspNode::AddPortal(char *def, unsigned int pointCnt, bool bInverse) +{ + return portal[portal_next++].Build(def, pointCnt, bInverse); } diff --git a/contrib/bobtoolz/ctfToolz-GTK.cpp b/contrib/bobtoolz/ctfToolz-GTK.cpp index 4e5231d1..218ec195 100644 --- a/contrib/bobtoolz/ctfToolz-GTK.cpp +++ b/contrib/bobtoolz/ctfToolz-GTK.cpp @@ -28,7 +28,7 @@ _QERFuncTable_1 g_FuncTable; _QERAppBSPFrontendTable g_BSPTable; // for map name -BOOL g_bBSPInitDone = FALSE; +BOOL g_bBSPInitDone = FALSE; // plugin name static const char *PLUGIN_NAME = "ctfToolz"; @@ -40,58 +40,100 @@ static const char *PLUGIN_COMMANDS = "About...,Colour Changer...,Swap Light Colo GtkWidget *g_pRadiantWnd = NULL; static const char *PLUGIN_ABOUT = "ctfToolz for NetRadiant\n" - "by djbob\n" - "http://www.planetquake.com/toolz\n\n"; + "by djbob\n" + "http://www.planetquake.com/toolz\n\n"; -extern "C" LPVOID WINAPI QERPlug_GetFuncTable(){ - return &g_FuncTable; +extern "C" LPVOID WINAPI + +QERPlug_GetFuncTable() +{ + return &g_FuncTable; +} + +extern "C" LPCSTR WINAPI +QERPlug_Init( HMODULE +hApp, +GtkWidget *pMainWidget +){ +g_pRadiantWnd = pMainWidget; +memset( &g_FuncTable, +0, sizeof( _QERFuncTable_1 )); +g_FuncTable. +m_fVersion = QER_PLUG_VERSION; +g_FuncTable. +m_nSize = sizeof(_QERFuncTable_1); + +return "ctfToolz for GTKradiant"; +} + +extern "C" LPCSTR WINAPI + +QERPlug_GetName() +{ + return (char *) PLUGIN_NAME; } -extern "C" LPCSTR WINAPI QERPlug_Init( HMODULE hApp, GtkWidget* pMainWidget ){ - g_pRadiantWnd = pMainWidget; - memset( &g_FuncTable, 0, sizeof( _QERFuncTable_1 ) ); - g_FuncTable.m_fVersion = QER_PLUG_VERSION; - g_FuncTable.m_nSize = sizeof( _QERFuncTable_1 ); +extern "C" LPCSTR WINAPI - return "ctfToolz for GTKradiant"; +QERPlug_GetCommandList() +{ + return (char *) PLUGIN_COMMANDS; } -extern "C" LPCSTR WINAPI QERPlug_GetName(){ - return (char*)PLUGIN_NAME; +extern "C" void WINAPI +QERPlug_Dispatch( LPCSTR +p, +vec3_t vMin, vec3_t +vMax, +bool bSingleBrush +){ +LoadLists(); + +if ( !g_bBSPInitDone ) { +g_BSPTable. +m_nSize = sizeof(_QERAppBSPFrontendTable); +if ( g_FuncTable. +m_pfnRequestInterface( QERAppBSPFrontendTable_GUID, +static_cast +( &g_BSPTable ) +)) { +g_bBSPInitDone = TRUE; +} +else +{ +Sys_ERROR( "_QERAppBSPFrontendTable interface request failed\n" ); +return; +} } -extern "C" LPCSTR WINAPI QERPlug_GetCommandList(){ - return (char*)PLUGIN_COMMANDS; +if ( ! +strcmp( p, +"About..." )) { +DoMessageBox( PLUGIN_ABOUT, +"About", IDOK ); } +else if ( ! +strcmp( p, +"Colour Changer..." )) { +DoCTFColourChanger(); -extern "C" void WINAPI QERPlug_Dispatch( LPCSTR p, vec3_t vMin, vec3_t vMax, bool bSingleBrush ){ - LoadLists(); - - if ( !g_bBSPInitDone ) { - g_BSPTable.m_nSize = sizeof( _QERAppBSPFrontendTable ); - if ( g_FuncTable.m_pfnRequestInterface( QERAppBSPFrontendTable_GUID, static_cast( &g_BSPTable ) ) ) { - g_bBSPInitDone = TRUE; - } - else - { - Sys_ERROR( "_QERAppBSPFrontendTable interface request failed\n" ); - return; - } - } - - if ( !strcmp( p, "About..." ) ) { - DoMessageBox( PLUGIN_ABOUT, "About", IDOK ); - } - else if ( !strcmp( p, "Colour Changer..." ) ) { - DoCTFColourChanger(); - } - else if ( !strcmp( p, "Swap Light Colours" ) ) { - DoSwapLights(); - } - else if ( !strcmp( p, "Change Angles 180" ) ) { - DoChangeAngles(); - } - else if ( !strcmp( p, "Swap Spawn Points" ) ) { - DoSwapSpawns(); - } +} +else if ( ! +strcmp( p, +"Swap Light Colours" )) { +DoSwapLights(); + +} +else if ( ! +strcmp( p, +"Change Angles 180" )) { +DoChangeAngles(); + +} +else if ( ! +strcmp( p, +"Swap Spawn Points" )) { +DoSwapSpawns(); + +} } diff --git a/contrib/bobtoolz/dialogs/AboutDialog.cpp b/contrib/bobtoolz/dialogs/AboutDialog.cpp index 0f5ef44f..6c43cd24 100644 --- a/contrib/bobtoolz/dialogs/AboutDialog.cpp +++ b/contrib/bobtoolz/dialogs/AboutDialog.cpp @@ -27,23 +27,27 @@ // CAboutDialog dialog -CAboutDialog::CAboutDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CAboutDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CAboutDialog) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT +CAboutDialog::CAboutDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CAboutDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAboutDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT } -void CAboutDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CAboutDialog) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP +void CAboutDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDialog) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CAboutDialog, CDialog ) +BEGIN_MESSAGE_MAP( CAboutDialog, CDialog +) + //{{AFX_MSG_MAP(CAboutDialog) // NOTE: the ClassWizard will add message map macros here //}}AFX_MSG_MAP diff --git a/contrib/bobtoolz/dialogs/AboutDialog.h b/contrib/bobtoolz/dialogs/AboutDialog.h index 64b4eb2c..253e8a7c 100644 --- a/contrib/bobtoolz/dialogs/AboutDialog.h +++ b/contrib/bobtoolz/dialogs/AboutDialog.h @@ -29,15 +29,14 @@ ///////////////////////////////////////////////////////////////////////////// // CAboutDialog dialog -class CAboutDialog : public CDialog -{ +class CAboutDialog : public CDialog { // Construction public: -CAboutDialog( CWnd* pParent = NULL ); // standard constructor + CAboutDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CAboutDialog) -enum { IDD = IDD_ABOUT }; + enum { IDD = IDD_ABOUT }; //}}AFX_DATA @@ -45,7 +44,7 @@ enum { IDD = IDD_ABOUT }; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -55,7 +54,7 @@ protected: //{{AFX_MSG(CAboutDialog) // NOTE: the ClassWizard will add member functions here //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/AutoCaulkDialog.cpp b/contrib/bobtoolz/dialogs/AutoCaulkDialog.cpp index a04c604c..c6a2c585 100644 --- a/contrib/bobtoolz/dialogs/AutoCaulkDialog.cpp +++ b/contrib/bobtoolz/dialogs/AutoCaulkDialog.cpp @@ -28,24 +28,28 @@ // CAutoCaulkDialog dialog -CAutoCaulkDialog::CAutoCaulkDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CAutoCaulkDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CAutoCaulkDialog) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT +CAutoCaulkDialog::CAutoCaulkDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CAutoCaulkDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAutoCaulkDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT } -void CAutoCaulkDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CAutoCaulkDialog) - DDX_Control( pDX, IDC_PROGRESS2, m_prog2 ); - DDX_Control( pDX, IDC_PROGRESS1, m_prog1 ); - //}}AFX_DATA_MAP +void CAutoCaulkDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAutoCaulkDialog) + DDX_Control(pDX, IDC_PROGRESS2, m_prog2); + DDX_Control(pDX, IDC_PROGRESS1, m_prog1); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CAutoCaulkDialog, CDialog ) +BEGIN_MESSAGE_MAP( CAutoCaulkDialog, CDialog +) + //{{AFX_MSG_MAP(CAutoCaulkDialog) // NOTE: the ClassWizard will add message map macros here //}}AFX_MSG_MAP diff --git a/contrib/bobtoolz/dialogs/AutoCaulkDialog.h b/contrib/bobtoolz/dialogs/AutoCaulkDialog.h index 30ca2e75..c8ff6040 100644 --- a/contrib/bobtoolz/dialogs/AutoCaulkDialog.h +++ b/contrib/bobtoolz/dialogs/AutoCaulkDialog.h @@ -29,17 +29,16 @@ ///////////////////////////////////////////////////////////////////////////// // CAutoCaulkDialog dialog -class CAutoCaulkDialog : public CDialog -{ +class CAutoCaulkDialog : public CDialog { // Construction public: -CAutoCaulkDialog( CWnd* pParent = NULL ); // standard constructor + CAutoCaulkDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CAutoCaulkDialog) -enum { IDD = IDD_AUTOCAULK_DIALOG }; -CProgressCtrl m_prog2; -CProgressCtrl m_prog1; + enum { IDD = IDD_AUTOCAULK_DIALOG }; + CProgressCtrl m_prog2; + CProgressCtrl m_prog1; //}}AFX_DATA @@ -47,7 +46,7 @@ CProgressCtrl m_prog1; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAutoCaulkDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -57,7 +56,7 @@ protected: //{{AFX_MSG(CAutoCaulkDialog) // NOTE: the ClassWizard will add member functions here //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.cpp b/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.cpp index f112f02b..ac7b85d3 100644 --- a/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.cpp +++ b/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.cpp @@ -28,27 +28,31 @@ // CAutoCaulkStartDialog dialog -CAutoCaulkStartDialog::CAutoCaulkStartDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CAutoCaulkStartDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CAutoCaulkStartDialog) - m_bAllowDestruction = FALSE; - m_Warning1 = _T( "" ); - m_nMode = 0; - //}}AFX_DATA_INIT +CAutoCaulkStartDialog::CAutoCaulkStartDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CAutoCaulkStartDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAutoCaulkStartDialog) + m_bAllowDestruction = FALSE; + m_Warning1 = _T(""); + m_nMode = 0; + //}}AFX_DATA_INIT } -void CAutoCaulkStartDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CAutoCaulkStartDialog) - DDX_Check( pDX, IDC_KILLBRUSHES_CHECK, m_bAllowDestruction ); - DDX_Text( pDX, IDC_WARNING1_STATIC, m_Warning1 ); - DDX_Radio( pDX, IDC_AC_NORMAL_RADIO, m_nMode ); - //}}AFX_DATA_MAP +void CAutoCaulkStartDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAutoCaulkStartDialog) + DDX_Check(pDX, IDC_KILLBRUSHES_CHECK, m_bAllowDestruction); + DDX_Text(pDX, IDC_WARNING1_STATIC, m_Warning1); + DDX_Radio(pDX, IDC_AC_NORMAL_RADIO, m_nMode); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CAutoCaulkStartDialog, CDialog ) +BEGIN_MESSAGE_MAP( CAutoCaulkStartDialog, CDialog +) + //{{AFX_MSG_MAP(CAutoCaulkStartDialog) // NOTE: the ClassWizard will add message map macros here //}}AFX_MSG_MAP diff --git a/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.h b/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.h index 73e265f4..a29c12b6 100644 --- a/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.h +++ b/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.h @@ -26,25 +26,24 @@ // AutoCaulkStartDialog.h : header file // -const int MODE_AC_NORMAL = 0; -const int MODE_AC_BUILD_MINI_PRT = 1; -const int MODE_AC_SUPER = 2; +const int MODE_AC_NORMAL = 0; +const int MODE_AC_BUILD_MINI_PRT = 1; +const int MODE_AC_SUPER = 2; ///////////////////////////////////////////////////////////////////////////// // CAutoCaulkStartDialog dialog -class CAutoCaulkStartDialog : public CDialog -{ +class CAutoCaulkStartDialog : public CDialog { // Construction public: -CAutoCaulkStartDialog( CWnd* pParent = NULL ); // standard constructor + CAutoCaulkStartDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CAutoCaulkStartDialog) -enum { IDD = IDD_AUTOCAULKSTART_DIALOG }; -BOOL m_bAllowDestruction; -CString m_Warning1; -int m_nMode; + enum { IDD = IDD_AUTOCAULKSTART_DIALOG }; + BOOL m_bAllowDestruction; + CString m_Warning1; + int m_nMode; //}}AFX_DATA @@ -52,7 +51,7 @@ int m_nMode; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAutoCaulkStartDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -62,7 +61,7 @@ protected: //{{AFX_MSG(CAutoCaulkStartDialog) // NOTE: the ClassWizard will add member functions here //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/BrushCheckDialog.h b/contrib/bobtoolz/dialogs/BrushCheckDialog.h index c232657b..19b420c0 100644 --- a/contrib/bobtoolz/dialogs/BrushCheckDialog.h +++ b/contrib/bobtoolz/dialogs/BrushCheckDialog.h @@ -29,16 +29,15 @@ ///////////////////////////////////////////////////////////////////////////// // CBrushCheckDialog dialog -class CBrushCheckDialog : public CDialog -{ +class CBrushCheckDialog : public CDialog { // Construction public: -CBrushCheckDialog( CWnd* pParent = NULL ); // standard constructor + CBrushCheckDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CBrushCheckDialog) -enum { IDD = IDD_BRUSHCHECKER_DIALOG }; -CProgressCtrl m_prog1; + enum { IDD = IDD_BRUSHCHECKER_DIALOG }; + CProgressCtrl m_prog1; //}}AFX_DATA @@ -46,7 +45,7 @@ CProgressCtrl m_prog1; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CBrushCheckDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -56,7 +55,7 @@ protected: //{{AFX_MSG(CBrushCheckDialog) // NOTE: the ClassWizard will add member functions here //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/DoorDialog.cpp b/contrib/bobtoolz/dialogs/DoorDialog.cpp index 50e7ef76..4660ebba 100644 --- a/contrib/bobtoolz/dialogs/DoorDialog.cpp +++ b/contrib/bobtoolz/dialogs/DoorDialog.cpp @@ -27,56 +27,64 @@ // CDoorDialog dialog -CDoorDialog::CDoorDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CDoorDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CDoorDialog) - m_fbTextureName = _T( "" ); - m_bSclMainHor = TRUE; - m_bSclMainVert = TRUE; - m_bSclTrimHor = TRUE; - m_bSclTrimVert = FALSE; - m_trimTextureName = _T( "" ); - m_trimTexSetBox = _T( "" ); - m_mainTexSetBox = _T( "" ); - m_doorDirection = -1; - //}}AFX_DATA_INIT +CDoorDialog::CDoorDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CDoorDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDoorDialog) + m_fbTextureName = _T(""); + m_bSclMainHor = TRUE; + m_bSclMainVert = TRUE; + m_bSclTrimHor = TRUE; + m_bSclTrimVert = FALSE; + m_trimTextureName = _T(""); + m_trimTexSetBox = _T(""); + m_mainTexSetBox = _T(""); + m_doorDirection = -1; + //}}AFX_DATA_INIT } -void CDoorDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CDoorDialog) - DDX_Text( pDX, IDC_FBTEXTURE_EDIT, m_fbTextureName ); - DDX_Check( pDX, IDC_TEXSCALE1_CHECK, m_bSclMainHor ); - DDX_Check( pDX, IDC_TEXSCALE2_CHECK, m_bSclMainVert ); - DDX_Check( pDX, IDC_TEXSCALE3_CHECK, m_bSclTrimHor ); - DDX_Check( pDX, IDC_TEXSCALE4_CHECK, m_bSclTrimVert ); - DDX_Text( pDX, IDC_TRIMTEXTURE_EDIT, m_trimTextureName ); - DDX_CBString( pDX, IDC_TRIMTEX_COMBO, m_trimTexSetBox ); - DDX_CBString( pDX, IDC_MAINTEX_COMBO, m_mainTexSetBox ); - DDX_Radio( pDX, IDC_DIR_NS_RADIO, m_doorDirection ); - //}}AFX_DATA_MAP +void CDoorDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDoorDialog) + DDX_Text(pDX, IDC_FBTEXTURE_EDIT, m_fbTextureName); + DDX_Check(pDX, IDC_TEXSCALE1_CHECK, m_bSclMainHor); + DDX_Check(pDX, IDC_TEXSCALE2_CHECK, m_bSclMainVert); + DDX_Check(pDX, IDC_TEXSCALE3_CHECK, m_bSclTrimHor); + DDX_Check(pDX, IDC_TEXSCALE4_CHECK, m_bSclTrimVert); + DDX_Text(pDX, IDC_TRIMTEXTURE_EDIT, m_trimTextureName); + DDX_CBString(pDX, IDC_TRIMTEX_COMBO, m_trimTexSetBox); + DDX_CBString(pDX, IDC_MAINTEX_COMBO, m_mainTexSetBox); + DDX_Radio(pDX, IDC_DIR_NS_RADIO, m_doorDirection); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CDoorDialog, CDialog ) +BEGIN_MESSAGE_MAP( CDoorDialog, CDialog +) //{{AFX_MSG_MAP(CDoorDialog) -ON_BN_CLICKED( IDC_SET_MAINTEX_BTN, OnSetMaintexBtn ) -ON_BN_CLICKED( IDC_SET_TRIMTEX_BTN, OnSetTrimtexBtn ) +ON_BN_CLICKED( IDC_SET_MAINTEX_BTN, OnSetMaintexBtn +) +ON_BN_CLICKED( IDC_SET_TRIMTEX_BTN, OnSetTrimtexBtn +) + //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDoorDialog message handlers -void CDoorDialog::OnSetMaintexBtn(){ - UpdateData( TRUE ); - m_fbTextureName = m_mainTexSetBox; - UpdateData( FALSE ); +void CDoorDialog::OnSetMaintexBtn() +{ + UpdateData(TRUE); + m_fbTextureName = m_mainTexSetBox; + UpdateData(FALSE); } -void CDoorDialog::OnSetTrimtexBtn(){ - UpdateData( TRUE ); - m_trimTextureName = m_trimTexSetBox; - UpdateData( FALSE ); +void CDoorDialog::OnSetTrimtexBtn() +{ + UpdateData(TRUE); + m_trimTextureName = m_trimTexSetBox; + UpdateData(FALSE); } diff --git a/contrib/bobtoolz/dialogs/DoorDialog.h b/contrib/bobtoolz/dialogs/DoorDialog.h index 94242aff..39e60630 100644 --- a/contrib/bobtoolz/dialogs/DoorDialog.h +++ b/contrib/bobtoolz/dialogs/DoorDialog.h @@ -29,24 +29,23 @@ ///////////////////////////////////////////////////////////////////////////// // CDoorDialog dialog -class CDoorDialog : public CDialog -{ +class CDoorDialog : public CDialog { // Construction public: -CDoorDialog( CWnd* pParent = NULL ); // standard constructor + CDoorDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CDoorDialog) -enum { IDD = IDD_DOOR_DIALOG }; -CString m_fbTextureName; -BOOL m_bSclMainHor; -BOOL m_bSclMainVert; -BOOL m_bSclTrimHor; -BOOL m_bSclTrimVert; -CString m_trimTextureName; -CString m_trimTexSetBox; -CString m_mainTexSetBox; -int m_doorDirection; + enum { IDD = IDD_DOOR_DIALOG }; + CString m_fbTextureName; + BOOL m_bSclMainHor; + BOOL m_bSclMainVert; + BOOL m_bSclTrimHor; + BOOL m_bSclTrimVert; + CString m_trimTextureName; + CString m_trimTexSetBox; + CString m_mainTexSetBox; + int m_doorDirection; //}}AFX_DATA @@ -54,7 +53,7 @@ int m_doorDirection; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CDoorDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -62,10 +61,12 @@ protected: // Generated message map functions //{{AFX_MSG(CDoorDialog) -afx_msg void OnSetMaintexBtn(); -afx_msg void OnSetTrimtexBtn(); + afx_msg void OnSetMaintexBtn(); + + afx_msg void OnSetTrimtexBtn(); + //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/IntersectDialog.cpp b/contrib/bobtoolz/dialogs/IntersectDialog.cpp index 8b2a0c72..ae564c1a 100644 --- a/contrib/bobtoolz/dialogs/IntersectDialog.cpp +++ b/contrib/bobtoolz/dialogs/IntersectDialog.cpp @@ -27,27 +27,31 @@ // CIntersectDialog dialog -CIntersectDialog::CIntersectDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CIntersectDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CIntersectDialog) - m_nBrushOptions = 1; - m_bUseDetail = FALSE; - m_bDuplicateOnly = FALSE; - //}}AFX_DATA_INIT +CIntersectDialog::CIntersectDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CIntersectDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CIntersectDialog) + m_nBrushOptions = 1; + m_bUseDetail = FALSE; + m_bDuplicateOnly = FALSE; + //}}AFX_DATA_INIT } -void CIntersectDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CIntersectDialog) - DDX_Radio( pDX, IDC_WHOLEMAP_RADIO, m_nBrushOptions ); - DDX_Check( pDX, IDC_DETAIL_INCLUDE_CHECK, m_bUseDetail ); - DDX_Check( pDX, IDC_DUPLICATEONLY_CHECK, m_bDuplicateOnly ); - //}}AFX_DATA_MAP +void CIntersectDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CIntersectDialog) + DDX_Radio(pDX, IDC_WHOLEMAP_RADIO, m_nBrushOptions); + DDX_Check(pDX, IDC_DETAIL_INCLUDE_CHECK, m_bUseDetail); + DDX_Check(pDX, IDC_DUPLICATEONLY_CHECK, m_bDuplicateOnly); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CIntersectDialog, CDialog ) +BEGIN_MESSAGE_MAP( CIntersectDialog, CDialog +) + //{{AFX_MSG_MAP(CIntersectDialog) // NOTE: the ClassWizard will add message map macros here //}}AFX_MSG_MAP diff --git a/contrib/bobtoolz/dialogs/IntersectDialog.h b/contrib/bobtoolz/dialogs/IntersectDialog.h index b9c342b4..339ea7f2 100644 --- a/contrib/bobtoolz/dialogs/IntersectDialog.h +++ b/contrib/bobtoolz/dialogs/IntersectDialog.h @@ -27,23 +27,22 @@ // const int BRUSH_OPT_WHOLE_MAP = 0; -const int BRUSH_OPT_SELECTED = 1; +const int BRUSH_OPT_SELECTED = 1; ///////////////////////////////////////////////////////////////////////////// // CIntersectDialog dialog -class CIntersectDialog : public CDialog -{ +class CIntersectDialog : public CDialog { // Construction public: -CIntersectDialog( CWnd* pParent = NULL ); // standard constructor + CIntersectDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CIntersectDialog) -enum { IDD = IDD_INTERSECT_DIALOG }; -int m_nBrushOptions; -BOOL m_bUseDetail; -BOOL m_bDuplicateOnly; + enum { IDD = IDD_INTERSECT_DIALOG }; + int m_nBrushOptions; + BOOL m_bUseDetail; + BOOL m_bDuplicateOnly; //}}AFX_DATA @@ -51,7 +50,7 @@ BOOL m_bDuplicateOnly; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CIntersectDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -61,7 +60,7 @@ protected: //{{AFX_MSG(CIntersectDialog) // NOTE: the ClassWizard will add member functions here //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/IntersectInfoDialog.cpp b/contrib/bobtoolz/dialogs/IntersectInfoDialog.cpp index 6d61f6ce..fdb540cc 100644 --- a/contrib/bobtoolz/dialogs/IntersectInfoDialog.cpp +++ b/contrib/bobtoolz/dialogs/IntersectInfoDialog.cpp @@ -28,22 +28,26 @@ // CIntersectInfoDialog dialog -CIntersectInfoDialog::CIntersectInfoDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CIntersectInfoDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CIntersectInfoDialog) - //}}AFX_DATA_INIT +CIntersectInfoDialog::CIntersectInfoDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CIntersectInfoDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CIntersectInfoDialog) + //}}AFX_DATA_INIT } -void CIntersectInfoDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CIntersectInfoDialog) - DDX_Control( pDX, IDC_PROGRESS1, m_prog1 ); - //}}AFX_DATA_MAP +void CIntersectInfoDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CIntersectInfoDialog) + DDX_Control(pDX, IDC_PROGRESS1, m_prog1); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CIntersectInfoDialog, CDialog ) +BEGIN_MESSAGE_MAP( CIntersectInfoDialog, CDialog +) + //{{AFX_MSG_MAP(CIntersectInfoDialog) // NOTE: the ClassWizard will add message map macros here //}}AFX_MSG_MAP diff --git a/contrib/bobtoolz/dialogs/IntersectInfoDialog.h b/contrib/bobtoolz/dialogs/IntersectInfoDialog.h index 58553d1e..3c3300c8 100644 --- a/contrib/bobtoolz/dialogs/IntersectInfoDialog.h +++ b/contrib/bobtoolz/dialogs/IntersectInfoDialog.h @@ -29,16 +29,15 @@ ///////////////////////////////////////////////////////////////////////////// // CIntersectInfoDialog dialog -class CIntersectInfoDialog : public CDialog -{ +class CIntersectInfoDialog : public CDialog { // Construction public: -CIntersectInfoDialog( CWnd* pParent = NULL ); // standard constructor + CIntersectInfoDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CIntersectInfoDialog) -enum { IDD = IDD_INTERSECT_INFO_DIALOG }; -CProgressCtrl m_prog1; + enum { IDD = IDD_INTERSECT_INFO_DIALOG }; + CProgressCtrl m_prog1; //}}AFX_DATA @@ -46,7 +45,7 @@ CProgressCtrl m_prog1; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CIntersectInfoDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -56,7 +55,7 @@ protected: //{{AFX_MSG(CIntersectInfoDialog) // NOTE: the ClassWizard will add member functions here //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/PolygonDialog.cpp b/contrib/bobtoolz/dialogs/PolygonDialog.cpp index ec7ee2cd..a2e1d424 100644 --- a/contrib/bobtoolz/dialogs/PolygonDialog.cpp +++ b/contrib/bobtoolz/dialogs/PolygonDialog.cpp @@ -28,78 +28,90 @@ // CPolygonDialog dialog -CPolygonDialog::CPolygonDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CPolygonDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CPolygonDialog) - m_nSideCount = 3; - m_bInverse = FALSE; - m_bBorder = FALSE; - m_nBorderSize = 8; - m_bAlignTop = FALSE; - //}}AFX_DATA_INIT +CPolygonDialog::CPolygonDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CPolygonDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPolygonDialog) + m_nSideCount = 3; + m_bInverse = FALSE; + m_bBorder = FALSE; + m_nBorderSize = 8; + m_bAlignTop = FALSE; + //}}AFX_DATA_INIT } -void CPolygonDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CPolygonDialog) - DDX_Text( pDX, IDC_EDIT1, m_nSideCount ); - DDV_MinMaxUInt( pDX, m_nSideCount, 3, MAX_POLYGON_FACES ); - DDX_Check( pDX, IDC_INVERSE_CHK, m_bInverse ); - DDX_Check( pDX, IDC_BORDER_CHK, m_bBorder ); - DDX_Text( pDX, IDC_BORDER_EDIT, m_nBorderSize ); - DDV_MinMaxUInt( pDX, m_nBorderSize, 1, 1024 ); - DDX_Check( pDX, IDC_ALIGN_CHK, m_bAlignTop ); - //}}AFX_DATA_MAP +void CPolygonDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPolygonDialog) + DDX_Text(pDX, IDC_EDIT1, m_nSideCount); + DDV_MinMaxUInt(pDX, m_nSideCount, 3, MAX_POLYGON_FACES); + DDX_Check(pDX, IDC_INVERSE_CHK, m_bInverse); + DDX_Check(pDX, IDC_BORDER_CHK, m_bBorder); + DDX_Text(pDX, IDC_BORDER_EDIT, m_nBorderSize); + DDV_MinMaxUInt(pDX, m_nBorderSize, 1, 1024); + DDX_Check(pDX, IDC_ALIGN_CHK, m_bAlignTop); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CPolygonDialog, CDialog ) +BEGIN_MESSAGE_MAP( CPolygonDialog, CDialog +) //{{AFX_MSG_MAP(CPolygonDialog) -ON_BN_CLICKED( IDC_BORDER_CHK, OnBorderChkClicked ) -ON_BN_CLICKED( IDC_INVERSE_CHK, OnInverseChkClickrd ) +ON_BN_CLICKED( IDC_BORDER_CHK, OnBorderChkClicked +) +ON_BN_CLICKED( IDC_INVERSE_CHK, OnInverseChkClickrd +) + //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPolygonDialog message handlers -BOOL CPolygonDialog::OnInitDialog(){ - CDialog::OnInitDialog(); +BOOL CPolygonDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); - EnableBordered( !GetChkBool( IDC_INVERSE_CHK ) ); - EnableBorderEdit( !GetChkBool( IDC_INVERSE_CHK ) && GetChkBool( IDC_BORDER_CHK ) ); + EnableBordered(!GetChkBool(IDC_INVERSE_CHK)); + EnableBorderEdit(!GetChkBool(IDC_INVERSE_CHK) && GetChkBool(IDC_BORDER_CHK)); - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE } -void CPolygonDialog::EnableBordered( BOOL bEnable ){ - CWnd* dtlChk = GetDlgItem( IDC_BORDER_CHK ); - if ( dtlChk ) { - dtlChk->EnableWindow( bEnable ); - } +void CPolygonDialog::EnableBordered(BOOL bEnable) +{ + CWnd *dtlChk = GetDlgItem(IDC_BORDER_CHK); + if (dtlChk) { + dtlChk->EnableWindow(bEnable); + } } -void CPolygonDialog::EnableBorderEdit( BOOL bEnable ){ - CWnd* dtlChk = GetDlgItem( IDC_BORDER_EDIT ); - if ( dtlChk ) { - dtlChk->EnableWindow( bEnable ); - } +void CPolygonDialog::EnableBorderEdit(BOOL bEnable) +{ + CWnd *dtlChk = GetDlgItem(IDC_BORDER_EDIT); + if (dtlChk) { + dtlChk->EnableWindow(bEnable); + } } -void CPolygonDialog::OnBorderChkClicked(){ - EnableBorderEdit( !GetChkBool( IDC_INVERSE_CHK ) && GetChkBool( IDC_BORDER_CHK ) ); +void CPolygonDialog::OnBorderChkClicked() +{ + EnableBorderEdit(!GetChkBool(IDC_INVERSE_CHK) && GetChkBool(IDC_BORDER_CHK)); } -void CPolygonDialog::OnInverseChkClickrd(){ - EnableBordered( !GetChkBool( IDC_INVERSE_CHK ) ); - EnableBorderEdit( !GetChkBool( IDC_INVERSE_CHK ) && GetChkBool( IDC_BORDER_CHK ) ); +void CPolygonDialog::OnInverseChkClickrd() +{ + EnableBordered(!GetChkBool(IDC_INVERSE_CHK)); + EnableBorderEdit(!GetChkBool(IDC_INVERSE_CHK) && GetChkBool(IDC_BORDER_CHK)); } -BOOL CPolygonDialog::GetChkBool( int nID ){ - CButton* btn = (CButton*)GetDlgItem( nID ); - if ( btn ) { - return btn->GetCheck(); - } - return FALSE; +BOOL CPolygonDialog::GetChkBool(int nID) +{ + CButton *btn = (CButton *) GetDlgItem(nID); + if (btn) { + return btn->GetCheck(); + } + return FALSE; } diff --git a/contrib/bobtoolz/dialogs/PolygonDialog.h b/contrib/bobtoolz/dialogs/PolygonDialog.h index 8774e1f0..e6a29fb4 100644 --- a/contrib/bobtoolz/dialogs/PolygonDialog.h +++ b/contrib/bobtoolz/dialogs/PolygonDialog.h @@ -29,23 +29,25 @@ ///////////////////////////////////////////////////////////////////////////// // CPolygonDialog dialog -class CPolygonDialog : public CDialog -{ +class CPolygonDialog : public CDialog { // Construction public: -BOOL GetChkBool( int nID ); -void EnableBorderEdit( BOOL bEnable ); -void EnableBordered( BOOL bEnable ); -CPolygonDialog( CWnd* pParent = NULL ); // standard constructor + BOOL GetChkBool(int nID); + + void EnableBorderEdit(BOOL bEnable); + + void EnableBordered(BOOL bEnable); + + CPolygonDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CPolygonDialog) -enum { IDD = IDD_POLYGON_DIALOG }; -UINT m_nSideCount; -BOOL m_bInverse; -BOOL m_bBorder; -UINT m_nBorderSize; -BOOL m_bAlignTop; + enum { IDD = IDD_POLYGON_DIALOG }; + UINT m_nSideCount; + BOOL m_bInverse; + BOOL m_bBorder; + UINT m_nBorderSize; + BOOL m_bAlignTop; //}}AFX_DATA @@ -53,7 +55,7 @@ BOOL m_bAlignTop; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CPolygonDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -61,11 +63,14 @@ protected: // Generated message map functions //{{AFX_MSG(CPolygonDialog) -virtual BOOL OnInitDialog(); -afx_msg void OnBorderChkClicked(); -afx_msg void OnInverseChkClickrd(); + virtual BOOL OnInitDialog(); + + afx_msg void OnBorderChkClicked(); + + afx_msg void OnInverseChkClickrd(); + //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/StairDialog.cpp b/contrib/bobtoolz/dialogs/StairDialog.cpp index e0cd2f14..73bc10f6 100644 --- a/contrib/bobtoolz/dialogs/StairDialog.cpp +++ b/contrib/bobtoolz/dialogs/StairDialog.cpp @@ -27,67 +27,79 @@ // CStairDialog dialog -CStairDialog::CStairDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CStairDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CStairDialog) - m_nStairHeight = 8; - m_StairDir = 0; - m_StairStyle = 0; - m_riserTexture = _T( "" ); - m_bDetail = TRUE; - //}}AFX_DATA_INIT +CStairDialog::CStairDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CStairDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CStairDialog) + m_nStairHeight = 8; + m_StairDir = 0; + m_StairStyle = 0; + m_riserTexture = _T(""); + m_bDetail = TRUE; + //}}AFX_DATA_INIT } -void CStairDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CStairDialog) - DDX_Text( pDX, IDC_EDIT1, m_nStairHeight ); - DDV_MinMaxUInt( pDX, m_nStairHeight, 1, 256 ); - DDX_Radio( pDX, IDC_DIR_N_RADIO, m_StairDir ); - DDX_Radio( pDX, IDC_STYLE_ORIG_RADIO, m_StairStyle ); - DDX_Text( pDX, IDC_RISER_EDIT, m_riserTexture ); - DDV_MaxChars( pDX, m_riserTexture, 256 ); - DDX_Check( pDX, IDC_DETAIL_CHK, m_bDetail ); - //}}AFX_DATA_MAP +void CStairDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CStairDialog) + DDX_Text(pDX, IDC_EDIT1, m_nStairHeight); + DDV_MinMaxUInt(pDX, m_nStairHeight, 1, 256); + DDX_Radio(pDX, IDC_DIR_N_RADIO, m_StairDir); + DDX_Radio(pDX, IDC_STYLE_ORIG_RADIO, m_StairStyle); + DDX_Text(pDX, IDC_RISER_EDIT, m_riserTexture); + DDV_MaxChars(pDX, m_riserTexture, 256); + DDX_Check(pDX, IDC_DETAIL_CHK, m_bDetail); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CStairDialog, CDialog ) +BEGIN_MESSAGE_MAP( CStairDialog, CDialog +) //{{AFX_MSG_MAP(CStairDialog) -ON_BN_CLICKED( IDC_STYLE_BOB_RADIO, OnStyleBobClicked ) -ON_BN_CLICKED( IDC_STYLE_ORIG_RADIO, OnStyleOrigClicked ) -ON_BN_CLICKED( IDC_STYLE_CORNER_RADIO, OnStyleCornerClicked ) +ON_BN_CLICKED( IDC_STYLE_BOB_RADIO, OnStyleBobClicked +) +ON_BN_CLICKED( IDC_STYLE_ORIG_RADIO, OnStyleOrigClicked +) +ON_BN_CLICKED( IDC_STYLE_CORNER_RADIO, OnStyleCornerClicked +) + //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CStairDialog message handlers -void CStairDialog::OnStyleBobClicked(){ - EnableDetail( TRUE ); +void CStairDialog::OnStyleBobClicked() +{ + EnableDetail(TRUE); } -void CStairDialog::OnStyleOrigClicked(){ - EnableDetail( FALSE ); +void CStairDialog::OnStyleOrigClicked() +{ + EnableDetail(FALSE); } -void CStairDialog::EnableDetail( BOOL bEnable ){ - CWnd* dtlChk = GetDlgItem( IDC_DETAIL_CHK ); - if ( dtlChk ) { - dtlChk->EnableWindow( bEnable ); - } +void CStairDialog::EnableDetail(BOOL bEnable) +{ + CWnd *dtlChk = GetDlgItem(IDC_DETAIL_CHK); + if (dtlChk) { + dtlChk->EnableWindow(bEnable); + } } -BOOL CStairDialog::OnInitDialog(){ - CDialog::OnInitDialog(); +BOOL CStairDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); - EnableDetail( m_StairStyle == 1 ); + EnableDetail(m_StairStyle == 1); - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE } -void CStairDialog::OnStyleCornerClicked(){ - EnableDetail( FALSE ); +void CStairDialog::OnStyleCornerClicked() +{ + EnableDetail(FALSE); } diff --git a/contrib/bobtoolz/dialogs/StairDialog.h b/contrib/bobtoolz/dialogs/StairDialog.h index 0be13e67..0eb60c62 100644 --- a/contrib/bobtoolz/dialogs/StairDialog.h +++ b/contrib/bobtoolz/dialogs/StairDialog.h @@ -29,20 +29,19 @@ ///////////////////////////////////////////////////////////////////////////// // CStairDialog dialog -class CStairDialog : public CDialog -{ +class CStairDialog : public CDialog { // Construction public: -CStairDialog( CWnd* pParent = NULL ); // standard constructor + CStairDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CStairDialog) -enum { IDD = IDD_STAIR_DIALOG }; -UINT m_nStairHeight; -int m_StairDir; -int m_StairStyle; -CString m_riserTexture; -BOOL m_bDetail; + enum { IDD = IDD_STAIR_DIALOG }; + UINT m_nStairHeight; + int m_StairDir; + int m_StairStyle; + CString m_riserTexture; + BOOL m_bDetail; //}}AFX_DATA @@ -50,7 +49,7 @@ BOOL m_bDetail; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CStairDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -58,14 +57,19 @@ protected: // Generated message map functions //{{AFX_MSG(CStairDialog) -afx_msg void OnStyleBobClicked(); -afx_msg void OnStyleOrigClicked(); -virtual BOOL OnInitDialog(); -afx_msg void OnStyleCornerClicked(); + afx_msg void OnStyleBobClicked(); + + afx_msg void OnStyleOrigClicked(); + + virtual BOOL OnInitDialog(); + + afx_msg void OnStyleCornerClicked(); + //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() + private: -void EnableDetail( BOOL bEnable ); + void EnableDetail(BOOL bEnable); }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/TextureResetDialog.cpp b/contrib/bobtoolz/dialogs/TextureResetDialog.cpp index 4b9991a0..1512018c 100644 --- a/contrib/bobtoolz/dialogs/TextureResetDialog.cpp +++ b/contrib/bobtoolz/dialogs/TextureResetDialog.cpp @@ -28,42 +28,46 @@ // CTextureResetDialog dialog -CTextureResetDialog::CTextureResetDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CTextureResetDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CTextureResetDialog) - m_bAllTextures = FALSE; - m_TextureName = _T( "" ); - m_nRotation = 0; - m_fScaleHorizontal = 0.5f; - m_fScaleVertical = 0.5f; - m_nShiftHorizontal = 0; - m_nShiftVertical = 0; - m_bOnlyTexture = FALSE; - m_NewTextureName = _T( "" ); - //}}AFX_DATA_INIT +CTextureResetDialog::CTextureResetDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CTextureResetDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTextureResetDialog) + m_bAllTextures = FALSE; + m_TextureName = _T(""); + m_nRotation = 0; + m_fScaleHorizontal = 0.5f; + m_fScaleVertical = 0.5f; + m_nShiftHorizontal = 0; + m_nShiftVertical = 0; + m_bOnlyTexture = FALSE; + m_NewTextureName = _T(""); + //}}AFX_DATA_INIT } -void CTextureResetDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CTextureResetDialog) - DDX_Check( pDX, IDC_ALLTEXTURES_CHECK, m_bAllTextures ); - DDX_Text( pDX, IDC_RESET_TEXTURE_EDIT, m_TextureName ); - DDV_MaxChars( pDX, m_TextureName, 256 ); - DDX_Text( pDX, IDC_ROTATION_EDIT, m_nRotation ); - DDV_MinMaxInt( pDX, m_nRotation, 0, 360 ); - DDX_Text( pDX, IDC_SCL_HOR_EDIT, m_fScaleHorizontal ); - DDX_Text( pDX, IDC_SCL_VERT_EDIT, m_fScaleVertical ); - DDX_Text( pDX, IDC_SHFT_HOR_EDIT, m_nShiftHorizontal ); - DDX_Text( pDX, IDC_SHFT_VER_EDIT, m_nShiftVertical ); - DDX_Check( pDX, IDC_ONLYTEXTURE_CHECK, m_bOnlyTexture ); - DDX_Text( pDX, IDC_RESET_NEW_TEXTURE_EDIT, m_NewTextureName ); - DDV_MaxChars( pDX, m_NewTextureName, 256 ); - //}}AFX_DATA_MAP +void CTextureResetDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTextureResetDialog) + DDX_Check(pDX, IDC_ALLTEXTURES_CHECK, m_bAllTextures); + DDX_Text(pDX, IDC_RESET_TEXTURE_EDIT, m_TextureName); + DDV_MaxChars(pDX, m_TextureName, 256); + DDX_Text(pDX, IDC_ROTATION_EDIT, m_nRotation); + DDV_MinMaxInt(pDX, m_nRotation, 0, 360); + DDX_Text(pDX, IDC_SCL_HOR_EDIT, m_fScaleHorizontal); + DDX_Text(pDX, IDC_SCL_VERT_EDIT, m_fScaleVertical); + DDX_Text(pDX, IDC_SHFT_HOR_EDIT, m_nShiftHorizontal); + DDX_Text(pDX, IDC_SHFT_VER_EDIT, m_nShiftVertical); + DDX_Check(pDX, IDC_ONLYTEXTURE_CHECK, m_bOnlyTexture); + DDX_Text(pDX, IDC_RESET_NEW_TEXTURE_EDIT, m_NewTextureName); + DDV_MaxChars(pDX, m_NewTextureName, 256); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CTextureResetDialog, CDialog ) +BEGIN_MESSAGE_MAP( CTextureResetDialog, CDialog +) + //{{AFX_MSG_MAP(CTextureResetDialog) // NOTE: the ClassWizard will add message map macros here //}}AFX_MSG_MAP diff --git a/contrib/bobtoolz/dialogs/TextureResetDialog.h b/contrib/bobtoolz/dialogs/TextureResetDialog.h index 40260735..793c101a 100644 --- a/contrib/bobtoolz/dialogs/TextureResetDialog.h +++ b/contrib/bobtoolz/dialogs/TextureResetDialog.h @@ -29,24 +29,23 @@ ///////////////////////////////////////////////////////////////////////////// // CTextureResetDialog dialog -class CTextureResetDialog : public CDialog -{ +class CTextureResetDialog : public CDialog { // Construction public: -CTextureResetDialog( CWnd* pParent = NULL ); // standard constructor + CTextureResetDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CTextureResetDialog) -enum { IDD = IDD_TEXTURE_RESET_DIALOG }; -BOOL m_bAllTextures; -CString m_TextureName; -int m_nRotation; -float m_fScaleHorizontal; -float m_fScaleVertical; -int m_nShiftHorizontal; -int m_nShiftVertical; -BOOL m_bOnlyTexture; -CString m_NewTextureName; + enum { IDD = IDD_TEXTURE_RESET_DIALOG }; + BOOL m_bAllTextures; + CString m_TextureName; + int m_nRotation; + float m_fScaleHorizontal; + float m_fScaleVertical; + int m_nShiftHorizontal; + int m_nShiftVertical; + BOOL m_bOnlyTexture; + CString m_NewTextureName; //}}AFX_DATA @@ -54,7 +53,7 @@ CString m_NewTextureName; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CTextureResetDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -64,7 +63,7 @@ protected: //{{AFX_MSG(CTextureResetDialog) // NOTE: the ClassWizard will add member functions here //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/dialogs/brushcheckdialog.cpp b/contrib/bobtoolz/dialogs/brushcheckdialog.cpp index 0b36f21f..948575d5 100644 --- a/contrib/bobtoolz/dialogs/brushcheckdialog.cpp +++ b/contrib/bobtoolz/dialogs/brushcheckdialog.cpp @@ -28,22 +28,26 @@ // CBrushCheckDialog dialog -CBrushCheckDialog::CBrushCheckDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CBrushCheckDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CBrushCheckDialog) - //}}AFX_DATA_INIT +CBrushCheckDialog::CBrushCheckDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CBrushCheckDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBrushCheckDialog) + //}}AFX_DATA_INIT } -void CBrushCheckDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CBrushCheckDialog) - DDX_Control( pDX, IDC_PROGRESS1, m_prog1 ); - //}}AFX_DATA_MAP +void CBrushCheckDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBrushCheckDialog) + DDX_Control(pDX, IDC_PROGRESS1, m_prog1); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CBrushCheckDialog, CDialog ) +BEGIN_MESSAGE_MAP( CBrushCheckDialog, CDialog +) + //{{AFX_MSG_MAP(CBrushCheckDialog) // NOTE: the ClassWizard will add message map macros here //}}AFX_MSG_MAP diff --git a/contrib/bobtoolz/dialogs/dialogs-gtk.cpp b/contrib/bobtoolz/dialogs/dialogs-gtk.cpp index 9329f306..efe52072 100644 --- a/contrib/bobtoolz/dialogs/dialogs-gtk.cpp +++ b/contrib/bobtoolz/dialogs/dialogs-gtk.cpp @@ -34,163 +34,164 @@ ---------------------------------*/ typedef struct { - ui::Widget cbTexChange{ui::null}; - ui::Widget editTexOld{ui::null}, editTexNew{ui::null}; + ui::Widget cbTexChange{ui::null}; + ui::Widget editTexOld{ui::null}, editTexNew{ui::null}; - ui::Widget cbScaleHor{ui::null}, cbScaleVert{ui::null}; - ui::Widget editScaleHor{ui::null}, editScaleVert{ui::null}; + ui::Widget cbScaleHor{ui::null}, cbScaleVert{ui::null}; + ui::Widget editScaleHor{ui::null}, editScaleVert{ui::null}; - ui::Widget cbShiftHor{ui::null}, cbShiftVert{ui::null}; - ui::Widget editShiftHor{ui::null}, editShiftVert{ui::null}; + ui::Widget cbShiftHor{ui::null}, cbShiftVert{ui::null}; + ui::Widget editShiftHor{ui::null}, editShiftVert{ui::null}; - ui::Widget cbRotation{ui::null}; - ui::Widget editRotation{ui::null}; -}dlg_texReset_t; + ui::Widget cbRotation{ui::null}; + ui::Widget editRotation{ui::null}; +} dlg_texReset_t; dlg_texReset_t dlgTexReset; void Update_TextureReseter(); -static void dialog_button_callback_texreset_update(ui::Widget widget, gpointer data ){ - Update_TextureReseter(); +static void dialog_button_callback_texreset_update(ui::Widget widget, gpointer data) +{ + Update_TextureReseter(); } -void Update_TextureReseter(){ - gboolean check; +void Update_TextureReseter() +{ + gboolean check; - check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbTexChange ) ); - gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editTexNew ), check ); - gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editTexOld ), check ); + check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbTexChange)); + gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editTexNew), check); + gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editTexOld), check); - check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleHor ) ); - gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editScaleHor ), check ); + check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbScaleHor)); + gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editScaleHor), check); - check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleVert ) ); - gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editScaleVert ), check ); + check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbScaleVert)); + gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editScaleVert), check); - check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftHor ) ); - gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editShiftHor ), check ); + check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbShiftHor)); + gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editShiftHor), check); - check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftVert ) ); - gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editShiftVert ), check ); + check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbShiftVert)); + gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editShiftVert), check); - check = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbRotation ) ); - gtk_editable_set_editable( GTK_EDITABLE( dlgTexReset.editRotation ), check ); + check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbRotation)); + gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editRotation), check); } -static void dialog_button_callback( ui::Widget widget, gpointer data ){ - int *loop; - EMessageBoxReturn *ret; +static void dialog_button_callback(ui::Widget widget, gpointer data) +{ + int *loop; + EMessageBoxReturn *ret; - auto parent = widget.window(); - loop = (int*)g_object_get_data( G_OBJECT( parent ), "loop" ); - ret = (EMessageBoxReturn*)g_object_get_data( G_OBJECT( parent ), "ret" ); + auto parent = widget.window(); + loop = (int *) g_object_get_data(G_OBJECT(parent), "loop"); + ret = (EMessageBoxReturn *) g_object_get_data(G_OBJECT(parent), "ret"); - *loop = 0; - *ret = (EMessageBoxReturn)gpointer_to_int( data ); + *loop = 0; + *ret = (EMessageBoxReturn) gpointer_to_int(data); } -static gint dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){ - widget.hide(); - int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); - *loop = 0; - return TRUE; +static gint dialog_delete_callback(ui::Widget widget, GdkEvent *event, gpointer data) +{ + widget.hide(); + int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); + *loop = 0; + return TRUE; } -static void dialog_button_callback_settex(ui::Widget widget, gpointer data ){ - TwinWidget* tw = (TwinWidget*)data; +static void dialog_button_callback_settex(ui::Widget widget, gpointer data) +{ + TwinWidget *tw = (TwinWidget *) data; - auto entry = ui::Entry::from( tw->one ); - auto combo = tw->two; + auto entry = ui::Entry::from(tw->one); + auto combo = tw->two; - const gchar *tex = gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(combo))); - gtk_entry_set_text( entry, tex ); + const gchar *tex = gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(combo))); + gtk_entry_set_text(entry, tex); } /*-------------------------------- Data validation Routines ---------------------------------*/ -bool ValidateTextFloat( const char* pData, const char* error_title, float* value ){ - if ( pData ) { - float testNum = (float)atof( pData ); - - if ( ( testNum == 0.0f ) && strcmp( pData, "0" ) ) { - DoMessageBox( "Please Enter A Floating Point Number", error_title, eMB_OK ); - return FALSE; - } - else - { - *value = testNum; - return TRUE; - } - } - - DoMessageBox( "Please Enter A Floating Point Number", error_title, eMB_OK ); - return FALSE; +bool ValidateTextFloat(const char *pData, const char *error_title, float *value) +{ + if (pData) { + float testNum = (float) atof(pData); + + if ((testNum == 0.0f) && strcmp(pData, "0")) { + DoMessageBox("Please Enter A Floating Point Number", error_title, eMB_OK); + return FALSE; + } else { + *value = testNum; + return TRUE; + } + } + + DoMessageBox("Please Enter A Floating Point Number", error_title, eMB_OK); + return FALSE; } -bool ValidateTextFloatRange( const char* pData, float min, float max, const char* error_title, float* value ){ - char error_buffer[256]; - sprintf( error_buffer, "Please Enter A Floating Point Number Between %.3f and %.3f", min, max ); - - if ( pData ) { - float testNum = (float)atof( pData ); - - if ( ( testNum < min ) || ( testNum > max ) ) { - DoMessageBox( error_buffer, error_title, eMB_OK ); - return FALSE; - } - else - { - *value = testNum; - return TRUE; - } - } - - DoMessageBox( error_buffer, error_title, eMB_OK ); - return FALSE; +bool ValidateTextFloatRange(const char *pData, float min, float max, const char *error_title, float *value) +{ + char error_buffer[256]; + sprintf(error_buffer, "Please Enter A Floating Point Number Between %.3f and %.3f", min, max); + + if (pData) { + float testNum = (float) atof(pData); + + if ((testNum < min) || (testNum > max)) { + DoMessageBox(error_buffer, error_title, eMB_OK); + return FALSE; + } else { + *value = testNum; + return TRUE; + } + } + + DoMessageBox(error_buffer, error_title, eMB_OK); + return FALSE; } -bool ValidateTextIntRange( const char* pData, int min, int max, const char* error_title, int* value ){ - char error_buffer[256]; - sprintf( error_buffer, "Please Enter An Integer Between %i and %i", min, max ); - - if ( pData ) { - int testNum = atoi( pData ); - - if ( ( testNum < min ) || ( testNum > max ) ) { - DoMessageBox( error_buffer, error_title, eMB_OK ); - return FALSE; - } - else - { - *value = testNum; - return TRUE; - } - } - - DoMessageBox( error_buffer, error_title, eMB_OK ); - return FALSE; +bool ValidateTextIntRange(const char *pData, int min, int max, const char *error_title, int *value) +{ + char error_buffer[256]; + sprintf(error_buffer, "Please Enter An Integer Between %i and %i", min, max); + + if (pData) { + int testNum = atoi(pData); + + if ((testNum < min) || (testNum > max)) { + DoMessageBox(error_buffer, error_title, eMB_OK); + return FALSE; + } else { + *value = testNum; + return TRUE; + } + } + + DoMessageBox(error_buffer, error_title, eMB_OK); + return FALSE; } -bool ValidateTextInt( const char* pData, const char* error_title, int* value ){ - if ( pData ) { - int testNum = atoi( pData ); - - if ( ( testNum == 0 ) && strcmp( pData, "0" ) ) { - DoMessageBox( "Please Enter An Integer", error_title, eMB_OK ); - return FALSE; - } - else - { - *value = testNum; - return TRUE; - } - } - - DoMessageBox( "Please Enter An Integer", error_title, eMB_OK ); - return FALSE; +bool ValidateTextInt(const char *pData, const char *error_title, int *value) +{ + if (pData) { + int testNum = atoi(pData); + + if ((testNum == 0) && strcmp(pData, "0")) { + DoMessageBox("Please Enter An Integer", error_title, eMB_OK); + return FALSE; + } else { + *value = testNum; + return TRUE; + } + } + + DoMessageBox("Please Enter An Integer", error_title, eMB_OK); + return FALSE; } /*-------------------------------- @@ -204,1705 +205,1709 @@ bool ValidateTextInt( const char* pData, const char* error_title, int* value ){ */ -EMessageBoxReturn DoMessageBox( const char* lpText, const char* lpCaption, EMessageBoxType type ){ - ui::Widget w{ui::null}; - EMessageBoxReturn ret; - int loop = 1; - - auto window = ui::Window( ui::window_type::TOP ); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); - gtk_window_set_title( window, lpCaption ); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); - gtk_widget_realize( window ); - - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); - - w = ui::Label( lpText ); - vbox.pack_start( w, FALSE, FALSE, 2 ); - gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT ); - w.show(); - - w = ui::Widget::from(gtk_hseparator_new()); - vbox.pack_start( w, FALSE, FALSE, 2 ); - w.show(); - - auto hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); - - if ( type == eMB_OK ) { - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - gtk_widget_set_can_default(w, true); - gtk_widget_grab_default( w ); - w.show(); - ret = eIDOK; - } - else if ( type == eMB_OKCANCEL ) { - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; - } - else if ( type == eMB_YESNOCANCEL ) { - w = ui::Button( "Yes" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "No" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDNO ) ); - w.show(); - - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; - } - else /* if (mode == MB_YESNO) */ - { - w = ui::Button( "Yes" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "No" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDNO ) ); - w.show(); - ret = eIDNO; - } - - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); - - while ( loop ) - gtk_main_iteration(); - - gtk_grab_remove( window ); - window.destroy(); - - return ret; +EMessageBoxReturn DoMessageBox(const char *lpText, const char *lpCaption, EMessageBoxType type) +{ + ui::Widget w{ui::null}; + EMessageBoxReturn ret; + int loop = 1; + + auto window = ui::Window(ui::window_type::TOP); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_window_set_title(window, lpCaption); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); + gtk_widget_realize(window); + + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); + + w = ui::Label(lpText); + vbox.pack_start(w, FALSE, FALSE, 2); + gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT); + w.show(); + + w = ui::Widget::from(gtk_hseparator_new()); + vbox.pack_start(w, FALSE, FALSE, 2); + w.show(); + + auto hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); + + if (type == eMB_OK) { + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + ret = eIDOK; + } else if (type == eMB_OKCANCEL) { + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; + } else if (type == eMB_YESNOCANCEL) { + w = ui::Button("Yes"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("No"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDNO)); + w.show(); + + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; + } else /* if (mode == MB_YESNO) */ + { + w = ui::Button("Yes"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("No"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDNO)); + w.show(); + ret = eIDNO; + } + + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); + + while (loop) { + gtk_main_iteration(); + } + + gtk_grab_remove(window); + window.destroy(); + + return ret; } -EMessageBoxReturn DoIntersectBox( IntersectRS* rs ){ - EMessageBoxReturn ret; - int loop = 1; +EMessageBoxReturn DoIntersectBox(IntersectRS *rs) +{ + EMessageBoxReturn ret; + int loop = 1; - auto window = ui::Window( ui::window_type::TOP ); + auto window = ui::Window(ui::window_type::TOP); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - gtk_window_set_title( window, "Intersect" ); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); + gtk_window_set_title(window, "Intersect"); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - gtk_widget_realize( window ); + gtk_widget_realize(window); + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); + // ---- vbox ---- - // ---- vbox ---- + auto radio1 = ui::Widget::from(gtk_radio_button_new_with_label(NULL, "Use Whole Map")); + vbox.pack_start(radio1, FALSE, FALSE, 2); + radio1.show(); - auto radio1 = ui::Widget::from(gtk_radio_button_new_with_label( NULL, "Use Whole Map" )); - vbox.pack_start( radio1, FALSE, FALSE, 2 ); - radio1.show(); + auto radio2 = ui::Widget::from(gtk_radio_button_new_with_label(gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio1)), + "Use Selected Brushes")); + vbox.pack_start(radio2, FALSE, FALSE, 2); + radio2.show(); - auto radio2 = ui::Widget::from(gtk_radio_button_new_with_label( gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio1)), "Use Selected Brushes" )); - vbox.pack_start( radio2, FALSE, FALSE, 2 ); - radio2.show(); + auto hsep = ui::Widget::from(gtk_hseparator_new()); + vbox.pack_start(hsep, FALSE, FALSE, 2); + hsep.show(); - auto hsep = ui::Widget::from(gtk_hseparator_new()); - vbox.pack_start( hsep, FALSE, FALSE, 2 ); - hsep.show(); + auto check1 = ui::CheckButton("Include Detail Brushes"); + vbox.pack_start(check1, FALSE, FALSE, 0); + check1.show(); - auto check1 = ui::CheckButton( "Include Detail Brushes" ); - vbox.pack_start( check1, FALSE, FALSE, 0 ); - check1.show(); + auto check2 = ui::CheckButton("Select Duplicate Brushes Only"); + vbox.pack_start(check2, FALSE, FALSE, 0); + check2.show(); - auto check2 = ui::CheckButton( "Select Duplicate Brushes Only" ); - vbox.pack_start( check2, FALSE, FALSE, 0 ); - check2.show(); + auto hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); - auto hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); + // ---- hbox ---- ok/cancel buttons - // ---- hbox ---- ok/cancel buttons + auto w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); - auto w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; + // ---- /hbox ---- - // ---- /hbox ---- + // ---- /vbox ---- - // ---- /vbox ---- + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + while (loop) { + gtk_main_iteration(); + } - while ( loop ) - gtk_main_iteration(); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio1))) { + rs->nBrushOptions = BRUSH_OPT_WHOLE_MAP; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio2))) { + rs->nBrushOptions = BRUSH_OPT_SELECTED; + } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radio1) ) ) { - rs->nBrushOptions = BRUSH_OPT_WHOLE_MAP; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radio2) ) ) { - rs->nBrushOptions = BRUSH_OPT_SELECTED; - } + rs->bUseDetail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check1)) ? true : false; + rs->bDuplicateOnly = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check2)) ? true : false; - rs->bUseDetail = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check1) ) ? true : false; - rs->bDuplicateOnly = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check2) ) ? true : false; + gtk_grab_remove(window); + window.destroy(); - gtk_grab_remove( window ); - window.destroy(); - - return ret; + return ret; } -EMessageBoxReturn DoPolygonBox( PolygonRS* rs ){ - EMessageBoxReturn ret; - int loop = 1; - - auto window = ui::Window( ui::window_type::TOP ); +EMessageBoxReturn DoPolygonBox(PolygonRS *rs) +{ + EMessageBoxReturn ret; + int loop = 1; - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + auto window = ui::Window(ui::window_type::TOP); - gtk_window_set_title( window, "Polygon Builder" ); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + gtk_window_set_title(window, "Polygon Builder"); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); - gtk_widget_realize( window ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); + gtk_widget_realize(window); - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); - // ---- vbox ---- + // ---- vbox ---- - auto hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); + auto hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); - // ---- hbox ---- + // ---- hbox ---- - auto vbox2 = ui::VBox( FALSE, 10 ); - hbox.pack_start( vbox2, FALSE, FALSE, 2 ); - vbox2.show(); + auto vbox2 = ui::VBox(FALSE, 10); + hbox.pack_start(vbox2, FALSE, FALSE, 2); + vbox2.show(); - // ---- vbox2 ---- + // ---- vbox2 ---- - auto hbox2 = ui::HBox( FALSE, 10 ); - vbox2.pack_start( hbox2, FALSE, FALSE, 2 ); - hbox2.show(); + auto hbox2 = ui::HBox(FALSE, 10); + vbox2.pack_start(hbox2, FALSE, FALSE, 2); + hbox2.show(); - // ---- hbox2 ---- + // ---- hbox2 ---- - auto text1 = ui::Entry( 256 ); - gtk_entry_set_text( text1, "3" ); - hbox2.pack_start( text1, FALSE, FALSE, 2 ); - text1.show(); + auto text1 = ui::Entry(256); + gtk_entry_set_text(text1, "3"); + hbox2.pack_start(text1, FALSE, FALSE, 2); + text1.show(); - auto l = ui::Label( "Number Of Sides" ); - hbox2.pack_start( l, FALSE, FALSE, 2 ); - gtk_label_set_justify( GTK_LABEL( l ), GTK_JUSTIFY_LEFT ); - l.show(); + auto l = ui::Label("Number Of Sides"); + hbox2.pack_start(l, FALSE, FALSE, 2); + gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_LEFT); + l.show(); - // ---- /hbox2 ---- + // ---- /hbox2 ---- - hbox2 = ui::HBox( FALSE, 10 ); - vbox2.pack_start( hbox2, FALSE, FALSE, 2 ); - hbox2.show(); + hbox2 = ui::HBox(FALSE, 10); + vbox2.pack_start(hbox2, FALSE, FALSE, 2); + hbox2.show(); - // ---- hbox2 ---- + // ---- hbox2 ---- - auto text2 = ui::Entry( 256 ); - gtk_entry_set_text( text2, "8" ); - hbox2.pack_start( text2, FALSE, FALSE, 2 ); - text2.show(); + auto text2 = ui::Entry(256); + gtk_entry_set_text(text2, "8"); + hbox2.pack_start(text2, FALSE, FALSE, 2); + text2.show(); - l = ui::Label( "Border Width" ); - hbox2.pack_start( l, FALSE, FALSE, 2 ); - gtk_label_set_justify( GTK_LABEL( l ), GTK_JUSTIFY_LEFT ); - l.show(); + l = ui::Label("Border Width"); + hbox2.pack_start(l, FALSE, FALSE, 2); + gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_LEFT); + l.show(); - // ---- /hbox2 ---- + // ---- /hbox2 ---- - // ---- /vbox2 ---- + // ---- /vbox2 ---- - vbox2 = ui::VBox( FALSE, 10 ); - hbox.pack_start( vbox2, FALSE, FALSE, 2 ); - vbox2.show(); + vbox2 = ui::VBox(FALSE, 10); + hbox.pack_start(vbox2, FALSE, FALSE, 2); + vbox2.show(); - // ---- vbox2 ---- + // ---- vbox2 ---- - auto check1 = ui::CheckButton( "Use Border" ); - vbox2.pack_start( check1, FALSE, FALSE, 0 ); - check1.show(); + auto check1 = ui::CheckButton("Use Border"); + vbox2.pack_start(check1, FALSE, FALSE, 0); + check1.show(); - auto check2 = ui::CheckButton( "Inverse Polygon" ); - vbox2.pack_start( check2, FALSE, FALSE, 0 ); - check2.show(); + auto check2 = ui::CheckButton("Inverse Polygon"); + vbox2.pack_start(check2, FALSE, FALSE, 0); + check2.show(); - auto check3 = ui::CheckButton( "Align Top Edge" ); - vbox2.pack_start( check3, FALSE, FALSE, 0 ); - check3.show(); + auto check3 = ui::CheckButton("Align Top Edge"); + vbox2.pack_start(check3, FALSE, FALSE, 0); + check3.show(); - // ---- /vbox2 ---- + // ---- /vbox2 ---- - // ---- /hbox ---- + // ---- /hbox ---- - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); - // ---- hbox ---- + // ---- hbox ---- - auto w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); + auto w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; - // ---- /hbox ---- + // ---- /hbox ---- - // ---- /vbox ---- + // ---- /vbox ---- - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - bool dialogError = TRUE; - while ( dialogError ) - { - loop = 1; - while ( loop ) - gtk_main_iteration(); + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } - dialogError = FALSE; + dialogError = FALSE; - if ( ret == eIDOK ) { - rs->bUseBorder = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check1) ) ? true : false; - rs->bInverse = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check2) ) ? true : false; - rs->bAlignTop = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(check3) ) ? true : false; + if (ret == eIDOK) { + rs->bUseBorder = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check1)) ? true : false; + rs->bInverse = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check2)) ? true : false; + rs->bAlignTop = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check3)) ? true : false; - if ( !ValidateTextIntRange( gtk_entry_get_text( text1 ), 3, 32, "Number Of Sides", &rs->nSides ) ) { - dialogError = TRUE; - } + if (!ValidateTextIntRange(gtk_entry_get_text(text1), 3, 32, "Number Of Sides", &rs->nSides)) { + dialogError = TRUE; + } - if ( rs->bUseBorder ) { - if ( !ValidateTextIntRange( gtk_entry_get_text( text2 ), 8, 256, "Border Width", &rs->nBorderWidth ) ) { - dialogError = TRUE; - } - } - } - } + if (rs->bUseBorder) { + if (!ValidateTextIntRange(gtk_entry_get_text(text2), 8, 256, "Border Width", &rs->nBorderWidth)) { + dialogError = TRUE; + } + } + } + } - gtk_grab_remove( window ); - window.destroy(); + gtk_grab_remove(window); + window.destroy(); - return ret; + return ret; } // mars // for stair builder stuck as close as i could to the MFC version // obviously feel free to change it at will :) -EMessageBoxReturn DoBuildStairsBox( BuildStairsRS* rs ){ - GSList *radioDirection, *radioStyle; - EMessageBoxReturn ret; - int loop = 1; +EMessageBoxReturn DoBuildStairsBox(BuildStairsRS *rs) +{ + GSList *radioDirection, *radioStyle; + EMessageBoxReturn ret; + int loop = 1; - const char *text = "Please set a value in the boxes below and press 'OK' to build the stairs"; + const char *text = "Please set a value in the boxes below and press 'OK' to build the stairs"; - auto window = ui::Window( ui::window_type::TOP ); + auto window = ui::Window(ui::window_type::TOP); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - gtk_window_set_title( window, "Stair Builder" ); + gtk_window_set_title(window, "Stair Builder"); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - gtk_widget_realize( window ); + gtk_widget_realize(window); - // new vbox - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); + // new vbox + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); - auto hbox = ui::HBox( FALSE, 10 ); - vbox.add(hbox); - hbox.show(); + auto hbox = ui::HBox(FALSE, 10); + vbox.add(hbox); + hbox.show(); - // dunno if you want this text or not ... - ui::Widget w = ui::Label( text ); - hbox.pack_start( w, FALSE, FALSE, 0 ); // not entirely sure on all the parameters / what they do ... - w.show(); + // dunno if you want this text or not ... + ui::Widget w = ui::Label(text); + hbox.pack_start(w, FALSE, FALSE, 0); // not entirely sure on all the parameters / what they do ... + w.show(); - w = ui::Widget::from(gtk_hseparator_new()); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Widget::from(gtk_hseparator_new()); + vbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - // ------------------------- // indenting == good way of keeping track of lines :) + // ------------------------- // indenting == good way of keeping track of lines :) - // new hbox - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + // new hbox + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto textStairHeight = ui::Entry( 256 ); - hbox.pack_start( textStairHeight, FALSE, FALSE, 1 ); - textStairHeight.show(); + auto textStairHeight = ui::Entry(256); + hbox.pack_start(textStairHeight, FALSE, FALSE, 1); + textStairHeight.show(); - w = ui::Label( "Stair Height" ); - hbox.pack_start( w, FALSE, FALSE, 1 ); - w.show(); + w = ui::Label("Stair Height"); + hbox.pack_start(w, FALSE, FALSE, 1); + w.show(); - // ------------------------- // + // ------------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Label( "Direction:" ); - hbox.pack_start( w, FALSE, FALSE, 5 ); - w.show(); + w = ui::Label("Direction:"); + hbox.pack_start(w, FALSE, FALSE, 5); + w.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - // radio buttons confuse me ... - // but this _looks_ right + // radio buttons confuse me ... + // but this _looks_ right - // djbob: actually it looks very nice :), slightly better than the way i did it - // edit: actually it doesn't work :P, you must pass the last radio item each time, ugh + // djbob: actually it looks very nice :), slightly better than the way i did it + // edit: actually it doesn't work :P, you must pass the last radio item each time, ugh - auto radioNorth = ui::Widget::from(gtk_radio_button_new_with_label( NULL, "North" )); - hbox.pack_start( radioNorth, FALSE, FALSE, 3 ); - radioNorth.show(); + auto radioNorth = ui::Widget::from(gtk_radio_button_new_with_label(NULL, "North")); + hbox.pack_start(radioNorth, FALSE, FALSE, 3); + radioNorth.show(); - radioDirection = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioNorth ) ); + radioDirection = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioNorth)); - auto radioSouth = ui::Widget::from(gtk_radio_button_new_with_label( radioDirection, "South" )); - hbox.pack_start( radioSouth, FALSE, FALSE, 2 ); - radioSouth.show(); + auto radioSouth = ui::Widget::from(gtk_radio_button_new_with_label(radioDirection, "South")); + hbox.pack_start(radioSouth, FALSE, FALSE, 2); + radioSouth.show(); - radioDirection = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioSouth ) ); + radioDirection = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioSouth)); - auto radioEast = ui::Widget::from(gtk_radio_button_new_with_label( radioDirection, "East" )); - hbox.pack_start( radioEast, FALSE, FALSE, 1 ); - radioEast.show(); + auto radioEast = ui::Widget::from(gtk_radio_button_new_with_label(radioDirection, "East")); + hbox.pack_start(radioEast, FALSE, FALSE, 1); + radioEast.show(); - radioDirection = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioEast ) ); + radioDirection = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioEast)); - auto radioWest = ui::Widget::from(gtk_radio_button_new_with_label( radioDirection, "West" )); - hbox.pack_start( radioWest, FALSE, FALSE, 0 ); - radioWest.show(); + auto radioWest = ui::Widget::from(gtk_radio_button_new_with_label(radioDirection, "West")); + hbox.pack_start(radioWest, FALSE, FALSE, 0); + radioWest.show(); - // --------------------------- // + // --------------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Label( "Style:" ); - hbox.pack_start( w, FALSE, FALSE, 5 ); - w.show(); + w = ui::Label("Style:"); + hbox.pack_start(w, FALSE, FALSE, 5); + w.show(); - // --------------------------- // + // --------------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto radioOldStyle = ui::Widget::from(gtk_radio_button_new_with_label( NULL, "Original" )); - hbox.pack_start( radioOldStyle, FALSE, FALSE, 0 ); - radioOldStyle.show(); + auto radioOldStyle = ui::Widget::from(gtk_radio_button_new_with_label(NULL, "Original")); + hbox.pack_start(radioOldStyle, FALSE, FALSE, 0); + radioOldStyle.show(); - radioStyle = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioOldStyle ) ); + radioStyle = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioOldStyle)); - auto radioBobStyle = ui::Widget::from(gtk_radio_button_new_with_label( radioStyle, "Bob's Style" )); - hbox.pack_start( radioBobStyle, FALSE, FALSE, 0 ); - radioBobStyle.show(); + auto radioBobStyle = ui::Widget::from(gtk_radio_button_new_with_label(radioStyle, "Bob's Style")); + hbox.pack_start(radioBobStyle, FALSE, FALSE, 0); + radioBobStyle.show(); - radioStyle = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioBobStyle ) ); + radioStyle = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioBobStyle)); - auto radioCornerStyle = ui::Widget::from(gtk_radio_button_new_with_label( radioStyle, "Corner Style" )); - hbox.pack_start( radioCornerStyle, FALSE, FALSE, 0 ); - radioCornerStyle.show(); + auto radioCornerStyle = ui::Widget::from(gtk_radio_button_new_with_label(radioStyle, "Corner Style")); + hbox.pack_start(radioCornerStyle, FALSE, FALSE, 0); + radioCornerStyle.show(); - // err, the q3r has an if or something so you need bob style checked before this - // is "ungreyed out" but you'll need to do that, as i suck :) + // err, the q3r has an if or something so you need bob style checked before this + // is "ungreyed out" but you'll need to do that, as i suck :) - // djbob: er.... yeah um, im not at all sure how i'm gonna sort this - // djbob: think we need some button callback functions or smuffin - // FIXME: actually get around to doing what i suggested!!!! + // djbob: er.... yeah um, im not at all sure how i'm gonna sort this + // djbob: think we need some button callback functions or smuffin + // FIXME: actually get around to doing what i suggested!!!! - auto checkUseDetail = ui::CheckButton( "Use Detail Brushes" ); - hbox.pack_start( checkUseDetail, FALSE, FALSE, 0 ); - checkUseDetail.show(); + auto checkUseDetail = ui::CheckButton("Use Detail Brushes"); + hbox.pack_start(checkUseDetail, FALSE, FALSE, 0); + checkUseDetail.show(); - // --------------------------- // + // --------------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto textMainTex = ui::Entry( 512 ); - gtk_entry_set_text( GTK_ENTRY( textMainTex ), rs->mainTexture ); - hbox.pack_start( textMainTex, FALSE, FALSE, 0 ); - textMainTex.show(); + auto textMainTex = ui::Entry(512); + gtk_entry_set_text(GTK_ENTRY(textMainTex), rs->mainTexture); + hbox.pack_start(textMainTex, FALSE, FALSE, 0); + textMainTex.show(); - w = ui::Label( "Main Texture" ); - hbox.pack_start( w, FALSE, FALSE, 1 ); - w.show(); + w = ui::Label("Main Texture"); + hbox.pack_start(w, FALSE, FALSE, 1); + w.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto textRiserTex = ui::Entry( 512 ); - hbox.pack_start( textRiserTex, FALSE, FALSE, 0 ); - textRiserTex.show(); + auto textRiserTex = ui::Entry(512); + hbox.pack_start(textRiserTex, FALSE, FALSE, 0); + textRiserTex.show(); - w = ui::Label( "Riser Texture" ); - hbox.pack_start( w, FALSE, FALSE, 1 ); - w.show(); + w = ui::Label("Riser Texture"); + hbox.pack_start(w, FALSE, FALSE, 1); + w.show(); - // -------------------------- // - w = ui::Widget::from(gtk_hseparator_new()); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + // -------------------------- // + w = ui::Widget::from(gtk_hseparator_new()); + vbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Button( "OK" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); + w = ui::Button("OK"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); - ret = eIDCANCEL; + ret = eIDCANCEL; // +djbob: need our "little" modal loop mars :P - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); - - bool dialogError = TRUE; - while ( dialogError ) - { - loop = 1; - while ( loop ) - gtk_main_iteration(); - - dialogError = FALSE; - - if ( ret == eIDOK ) { - rs->bUseDetail = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(checkUseDetail) ) ? true : false; - - strcpy( rs->riserTexture, gtk_entry_get_text( textRiserTex ) ); - strcpy( rs->mainTexture, gtk_entry_get_text( textMainTex ) ); - - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioNorth) ) ) { - rs->direction = MOVE_NORTH; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioSouth) ) ) { - rs->direction = MOVE_SOUTH; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioEast) ) ) { - rs->direction = MOVE_EAST; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioWest) ) ) { - rs->direction = MOVE_WEST; - } - - if ( !ValidateTextInt( gtk_entry_get_text( textStairHeight ), "Stair Height", &rs->stairHeight ) ) { - dialogError = TRUE; - } - - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioOldStyle) ) ) { - rs->style = STYLE_ORIGINAL; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioBobStyle) ) ) { - rs->style = STYLE_BOB; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radioCornerStyle) ) ) { - rs->style = STYLE_CORNER; - } - } - } - - gtk_grab_remove( window ); - window.destroy(); - - return ret; + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); + + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } + + dialogError = FALSE; + + if (ret == eIDOK) { + rs->bUseDetail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkUseDetail)) ? true : false; + + strcpy(rs->riserTexture, gtk_entry_get_text(textRiserTex)); + strcpy(rs->mainTexture, gtk_entry_get_text(textMainTex)); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioNorth))) { + rs->direction = MOVE_NORTH; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioSouth))) { + rs->direction = MOVE_SOUTH; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioEast))) { + rs->direction = MOVE_EAST; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioWest))) { + rs->direction = MOVE_WEST; + } + + if (!ValidateTextInt(gtk_entry_get_text(textStairHeight), "Stair Height", &rs->stairHeight)) { + dialogError = TRUE; + } + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioOldStyle))) { + rs->style = STYLE_ORIGINAL; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioBobStyle))) { + rs->style = STYLE_BOB; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioCornerStyle))) { + rs->style = STYLE_CORNER; + } + } + } + + gtk_grab_remove(window); + window.destroy(); + + return ret; // -djbob - // there we go, all done ... on my end at least, not bad for a night's work + // there we go, all done ... on my end at least, not bad for a night's work } -EMessageBoxReturn DoDoorsBox( DoorRS* rs ){ - GSList *radioOrientation; - TwinWidget tw1, tw2; - EMessageBoxReturn ret; - int loop = 1; +EMessageBoxReturn DoDoorsBox(DoorRS *rs) +{ + GSList *radioOrientation; + TwinWidget tw1, tw2; + EMessageBoxReturn ret; + int loop = 1; - auto window = ui::Window( ui::window_type::TOP ); + auto window = ui::Window(ui::window_type::TOP); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - gtk_window_set_title( window, "Door Builder" ); + gtk_window_set_title(window, "Door Builder"); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - gtk_widget_realize( window ); + gtk_widget_realize(window); - char buffer[256]; - auto listMainTextures = ui::ListStore::from(gtk_list_store_new( 1, G_TYPE_STRING )); - auto listTrimTextures = ui::ListStore::from(gtk_list_store_new( 1, G_TYPE_STRING )); - LoadGList( GetFilename( buffer, "plugins/bt/door-tex.txt" ), listMainTextures ); - LoadGList( GetFilename( buffer, "plugins/bt/door-tex-trim.txt" ), listTrimTextures ); + char buffer[256]; + auto listMainTextures = ui::ListStore::from(gtk_list_store_new(1, G_TYPE_STRING)); + auto listTrimTextures = ui::ListStore::from(gtk_list_store_new(1, G_TYPE_STRING)); + LoadGList(GetFilename(buffer, "plugins/bt/door-tex.txt"), listMainTextures); + LoadGList(GetFilename(buffer, "plugins/bt/door-tex-trim.txt"), listTrimTextures); - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); - // -------------------------- // + // -------------------------- // - auto hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + auto hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto textFrontBackTex = ui::Entry( 512 ); - gtk_entry_set_text( GTK_ENTRY( textFrontBackTex ), rs->mainTexture ); - hbox.pack_start( textFrontBackTex, FALSE, FALSE, 0 ); - textFrontBackTex.show(); + auto textFrontBackTex = ui::Entry(512); + gtk_entry_set_text(GTK_ENTRY(textFrontBackTex), rs->mainTexture); + hbox.pack_start(textFrontBackTex, FALSE, FALSE, 0); + textFrontBackTex.show(); - ui::Widget w = ui::Label( "Door Front/Back Texture" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + ui::Widget w = ui::Label("Door Front/Back Texture"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - // ------------------------ // + // ------------------------ // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto textTrimTex = ui::Entry( 512 ); - hbox.pack_start( textTrimTex, FALSE, FALSE, 0 ); - textTrimTex.show(); + auto textTrimTex = ui::Entry(512); + hbox.pack_start(textTrimTex, FALSE, FALSE, 0); + textTrimTex.show(); - w = ui::Label( "Door Trim Texture" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("Door Trim Texture"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - // ----------------------- // + // ----------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - // sp: horizontally ???? - // djbob: yes mars, u can spell :] - auto checkScaleMainH = ui::CheckButton( "Scale Main Texture Horizontally" ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( checkScaleMainH ), TRUE ); - hbox.pack_start( checkScaleMainH, FALSE, FALSE, 0 ); - checkScaleMainH.show(); + // sp: horizontally ???? + // djbob: yes mars, u can spell :] + auto checkScaleMainH = ui::CheckButton("Scale Main Texture Horizontally"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkScaleMainH), TRUE); + hbox.pack_start(checkScaleMainH, FALSE, FALSE, 0); + checkScaleMainH.show(); - auto checkScaleTrimH = ui::CheckButton( "Scale Trim Texture Horizontally" ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( checkScaleTrimH ), TRUE ); - hbox.pack_start( checkScaleTrimH, FALSE, FALSE, 0 ); - checkScaleTrimH.show(); + auto checkScaleTrimH = ui::CheckButton("Scale Trim Texture Horizontally"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkScaleTrimH), TRUE); + hbox.pack_start(checkScaleTrimH, FALSE, FALSE, 0); + checkScaleTrimH.show(); - // ---------------------- // + // ---------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto checkScaleMainV = ui::CheckButton( "Scale Main Texture Vertically" ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( checkScaleMainV ), TRUE ); - hbox.pack_start( checkScaleMainV, FALSE, FALSE, 0 ); - checkScaleMainV.show(); + auto checkScaleMainV = ui::CheckButton("Scale Main Texture Vertically"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkScaleMainV), TRUE); + hbox.pack_start(checkScaleMainV, FALSE, FALSE, 0); + checkScaleMainV.show(); - auto checkScaleTrimV = ui::CheckButton( "Scale Trim Texture Vertically" ); - hbox.pack_start( checkScaleTrimV, FALSE, FALSE, 0 ); - checkScaleTrimV.show(); + auto checkScaleTrimV = ui::CheckButton("Scale Trim Texture Vertically"); + hbox.pack_start(checkScaleTrimV, FALSE, FALSE, 0); + checkScaleTrimV.show(); - // --------------------- // + // --------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - // djbob: lists added + // djbob: lists added - auto comboMain = ui::ComboBox::from(gtk_combo_box_new_with_model_and_entry(listMainTextures)); - gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(comboMain), 0); - hbox.pack_start( comboMain, FALSE, FALSE, 0 ); - comboMain.show(); + auto comboMain = ui::ComboBox::from(gtk_combo_box_new_with_model_and_entry(listMainTextures)); + gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(comboMain), 0); + hbox.pack_start(comboMain, FALSE, FALSE, 0); + comboMain.show(); - tw1.one = textFrontBackTex; - tw1.two = comboMain; + tw1.one = textFrontBackTex; + tw1.two = comboMain; - auto buttonSetMain = ui::Button( "Set As Main Texture" ); - buttonSetMain.connect( "clicked", G_CALLBACK( dialog_button_callback_settex ), &tw1 ); - hbox.pack_start( buttonSetMain, FALSE, FALSE, 0 ); - buttonSetMain.show(); + auto buttonSetMain = ui::Button("Set As Main Texture"); + buttonSetMain.connect("clicked", G_CALLBACK(dialog_button_callback_settex), &tw1); + hbox.pack_start(buttonSetMain, FALSE, FALSE, 0); + buttonSetMain.show(); - // ------------------- // + // ------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto comboTrim = ui::ComboBox::from(gtk_combo_box_new_with_model_and_entry(listTrimTextures)); - gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(comboMain), 0); - hbox.pack_start( comboTrim, FALSE, FALSE, 0 ); - comboTrim.show(); + auto comboTrim = ui::ComboBox::from(gtk_combo_box_new_with_model_and_entry(listTrimTextures)); + gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(comboMain), 0); + hbox.pack_start(comboTrim, FALSE, FALSE, 0); + comboTrim.show(); - tw2.one = textTrimTex; - tw2.two = comboTrim; + tw2.one = textTrimTex; + tw2.two = comboTrim; - auto buttonSetTrim = ui::Button( "Set As Trim Texture" ); - buttonSetTrim.connect( "clicked", G_CALLBACK( dialog_button_callback_settex ), &tw2 ); - hbox.pack_start( buttonSetTrim, FALSE, FALSE, 0 ); - buttonSetTrim.show(); + auto buttonSetTrim = ui::Button("Set As Trim Texture"); + buttonSetTrim.connect("clicked", G_CALLBACK(dialog_button_callback_settex), &tw2); + hbox.pack_start(buttonSetTrim, FALSE, FALSE, 0); + buttonSetTrim.show(); - // ------------------ // + // ------------------ // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Label( "Orientation" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("Orientation"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - // argh more radio buttons! - auto radioNS = ui::Widget::from(gtk_radio_button_new_with_label( NULL, "North - South" )); - hbox.pack_start( radioNS, FALSE, FALSE, 0 ); - radioNS.show(); + // argh more radio buttons! + auto radioNS = ui::Widget::from(gtk_radio_button_new_with_label(NULL, "North - South")); + hbox.pack_start(radioNS, FALSE, FALSE, 0); + radioNS.show(); - radioOrientation = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radioNS ) ); + radioOrientation = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioNS)); - auto radioEW = ui::Widget::from(gtk_radio_button_new_with_label( radioOrientation, "East - West" )); - hbox.pack_start( radioEW, FALSE, FALSE, 0 ); - radioEW.show(); + auto radioEW = ui::Widget::from(gtk_radio_button_new_with_label(radioOrientation, "East - West")); + hbox.pack_start(radioEW, FALSE, FALSE, 0); + radioEW.show(); - // ----------------- // + // ----------------- // - w = ui::Widget::from(gtk_hseparator_new()); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Widget::from(gtk_hseparator_new()); + vbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - // ----------------- // + // ----------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Button( "OK" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); + w = ui::Button("OK"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; - // ----------------- // + // ----------------- // //+djbob - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - while ( loop ) - gtk_main_iteration(); + while (loop) { + gtk_main_iteration(); + } - strcpy( rs->mainTexture, gtk_entry_get_text( GTK_ENTRY( textFrontBackTex ) ) ); - strcpy( rs->trimTexture, gtk_entry_get_text( GTK_ENTRY( textTrimTex ) ) ); + strcpy(rs->mainTexture, gtk_entry_get_text(GTK_ENTRY(textFrontBackTex))); + strcpy(rs->trimTexture, gtk_entry_get_text(GTK_ENTRY(textTrimTex))); - rs->bScaleMainH = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( checkScaleMainH ) ) ? true : false; - rs->bScaleMainV = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( checkScaleMainV ) ) ? true : false; - rs->bScaleTrimH = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( checkScaleTrimH ) ) ? true : false; - rs->bScaleTrimV = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( checkScaleTrimV ) ) ? true : false; + rs->bScaleMainH = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkScaleMainH)) ? true : false; + rs->bScaleMainV = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkScaleMainV)) ? true : false; + rs->bScaleTrimH = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkScaleTrimH)) ? true : false; + rs->bScaleTrimV = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkScaleTrimV)) ? true : false; - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radioNS ) ) ) { - rs->nOrientation = DIRECTION_NS; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radioEW ) ) ) { - rs->nOrientation = DIRECTION_EW; - } + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioNS))) { + rs->nOrientation = DIRECTION_NS; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioEW))) { + rs->nOrientation = DIRECTION_EW; + } - gtk_grab_remove( window ); - window.destroy(); + gtk_grab_remove(window); + window.destroy(); - return ret; + return ret; //-djbob } -EMessageBoxReturn DoPathPlotterBox( PathPlotterRS* rs ){ - ui::Widget w{ui::null}; - - EMessageBoxReturn ret; - int loop = 1; +EMessageBoxReturn DoPathPlotterBox(PathPlotterRS *rs) +{ + ui::Widget w{ui::null}; - auto window = ui::Window( ui::window_type::TOP ); + EMessageBoxReturn ret; + int loop = 1; - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + auto window = ui::Window(ui::window_type::TOP); - gtk_window_set_title( window, "Texture Reset" ); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + gtk_window_set_title(window, "Texture Reset"); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); - gtk_widget_realize( window ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); + gtk_widget_realize(window); - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); - // ---- vbox ---- + // ---- vbox ---- - auto hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); + auto hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); - // ---- hbox ---- + // ---- hbox ---- - auto text1 = ui::Entry( 256 ); - gtk_entry_set_text( text1, "25" ); - hbox.pack_start( text1, FALSE, FALSE, 2 ); - text1.show(); + auto text1 = ui::Entry(256); + gtk_entry_set_text(text1, "25"); + hbox.pack_start(text1, FALSE, FALSE, 2); + text1.show(); - w = ui::Label( "Number Of Points" ); - hbox.pack_start( w, FALSE, FALSE, 2 ); - gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT ); - w.show(); + w = ui::Label("Number Of Points"); + hbox.pack_start(w, FALSE, FALSE, 2); + gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT); + w.show(); - // ---- /hbox ---- + // ---- /hbox ---- - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); - // ---- hbox ---- + // ---- hbox ---- - auto text2 = ui::Entry( 256 ); - gtk_entry_set_text( text2, "3" ); - hbox.pack_start( text2, FALSE, FALSE, 2 ); - text2.show(); + auto text2 = ui::Entry(256); + gtk_entry_set_text(text2, "3"); + hbox.pack_start(text2, FALSE, FALSE, 2); + text2.show(); - w = ui::Label( "Multipler" ); - hbox.pack_start( w, FALSE, FALSE, 2 ); - gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT ); - w.show(); + w = ui::Label("Multipler"); + hbox.pack_start(w, FALSE, FALSE, 2); + gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT); + w.show(); - // ---- /hbox ---- + // ---- /hbox ---- - w = ui::Label( "Path Distance = dist(start -> apex) * multiplier" ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT ); - w.show(); + w = ui::Label("Path Distance = dist(start -> apex) * multiplier"); + vbox.pack_start(w, FALSE, FALSE, 0); + gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT); + w.show(); - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); - // ---- hbox ---- + // ---- hbox ---- - auto text3 = ui::Entry( 256 ); - gtk_entry_set_text( text3, "-800" ); - hbox.pack_start( text3, FALSE, FALSE, 2 ); - text3.show(); + auto text3 = ui::Entry(256); + gtk_entry_set_text(text3, "-800"); + hbox.pack_start(text3, FALSE, FALSE, 2); + text3.show(); - w = ui::Label( "Gravity" ); - hbox.pack_start( w, FALSE, FALSE, 2 ); - gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT ); - w.show(); + w = ui::Label("Gravity"); + hbox.pack_start(w, FALSE, FALSE, 2); + gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT); + w.show(); - // ---- /hbox ---- + // ---- /hbox ---- - w = ui::Widget::from(gtk_hseparator_new()); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Widget::from(gtk_hseparator_new()); + vbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - auto check1 = ui::CheckButton( "No Dynamic Update" ); - vbox.pack_start( check1, FALSE, FALSE, 0 ); - check1.show(); + auto check1 = ui::CheckButton("No Dynamic Update"); + vbox.pack_start(check1, FALSE, FALSE, 0); + check1.show(); - auto check2 = ui::CheckButton( "Show Bounding Lines" ); - vbox.pack_start( check2, FALSE, FALSE, 0 ); - check2.show(); + auto check2 = ui::CheckButton("Show Bounding Lines"); + vbox.pack_start(check2, FALSE, FALSE, 0); + check2.show(); - // ---- /vbox ---- + // ---- /vbox ---- - // ----------------- // + // ----------------- // - w = ui::Widget::from(gtk_hseparator_new()); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Widget::from(gtk_hseparator_new()); + vbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - // ----------------- // + // ----------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Button( "Enable" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) ); - w.show(); + w = ui::Button("Enable"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES)); + w.show(); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); - w = ui::Button( "Disable" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDNO ) ); - w.show(); + w = ui::Button("Disable"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDNO)); + w.show(); - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); - ret = eIDCANCEL; + ret = eIDCANCEL; - // ----------------- // + // ----------------- // - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - bool dialogError = TRUE; - while ( dialogError ) - { - loop = 1; - while ( loop ) - gtk_main_iteration(); + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } - dialogError = FALSE; + dialogError = FALSE; - if ( ret == eIDYES ) { - if ( !ValidateTextIntRange( gtk_entry_get_text( GTK_ENTRY( text1 ) ), 1, 200, "Number Of Points", &rs->nPoints ) ) { - dialogError = TRUE; - } + if (ret == eIDYES) { + if (!ValidateTextIntRange(gtk_entry_get_text(GTK_ENTRY(text1)), 1, 200, "Number Of Points", &rs->nPoints)) { + dialogError = TRUE; + } - if ( !ValidateTextFloatRange( gtk_entry_get_text( GTK_ENTRY( text2 ) ), 1.0f, 10.0f, "Multiplier", &rs->fMultiplier ) ) { - dialogError = TRUE; - } + if (!ValidateTextFloatRange(gtk_entry_get_text(GTK_ENTRY(text2)), 1.0f, 10.0f, "Multiplier", + &rs->fMultiplier)) { + dialogError = TRUE; + } - if ( !ValidateTextFloatRange( gtk_entry_get_text( GTK_ENTRY( text3 ) ), -10000.0f, -1.0f, "Gravity", &rs->fGravity ) ) { - dialogError = TRUE; - } + if (!ValidateTextFloatRange(gtk_entry_get_text(GTK_ENTRY(text3)), -10000.0f, -1.0f, "Gravity", + &rs->fGravity)) { + dialogError = TRUE; + } - rs->bNoUpdate = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check1 ) ) ? true : false; - rs->bShowExtra = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check2 ) ) ? true : false; - } - } + rs->bNoUpdate = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check1)) ? true : false; + rs->bShowExtra = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check2)) ? true : false; + } + } - gtk_grab_remove( window ); - window.destroy(); + gtk_grab_remove(window); + window.destroy(); - return ret; + return ret; } -EMessageBoxReturn DoCTFColourChangeBox(){ - ui::Widget w{ui::null}; - EMessageBoxReturn ret; - int loop = 1; +EMessageBoxReturn DoCTFColourChangeBox() +{ + ui::Widget w{ui::null}; + EMessageBoxReturn ret; + int loop = 1; - auto window = ui::Window( ui::window_type::TOP ); + auto window = ui::Window(ui::window_type::TOP); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - gtk_window_set_title( window, "CTF Colour Changer" ); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); + gtk_window_set_title(window, "CTF Colour Changer"); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - gtk_widget_realize( window ); + gtk_widget_realize(window); + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); + // ---- vbox ---- - // ---- vbox ---- + auto hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, TRUE, TRUE, 0); + hbox.show(); - auto hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, TRUE, TRUE, 0 ); - hbox.show(); + // ---- hbox ---- ok/cancel buttons - // ---- hbox ---- ok/cancel buttons + w = ui::Button("Red->Blue"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); - w = ui::Button( "Red->Blue" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); + w = ui::Button("Blue->Red"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES)); + w.show(); - w = ui::Button( "Blue->Red" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) ); - w.show(); + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; + // ---- /hbox ---- - // ---- /hbox ---- + // ---- /vbox ---- - // ---- /vbox ---- + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + while (loop) { + gtk_main_iteration(); + } - while ( loop ) - gtk_main_iteration(); + gtk_grab_remove(window); + window.destroy(); - gtk_grab_remove( window ); - window.destroy(); - - return ret; + return ret; } -EMessageBoxReturn DoResetTextureBox( ResetTextureRS* rs ){ - Str texSelected; +EMessageBoxReturn DoResetTextureBox(ResetTextureRS *rs) +{ + Str texSelected; - ui::Widget w{ui::null}; + ui::Widget w{ui::null}; - EMessageBoxReturn ret; - int loop = 1; + EMessageBoxReturn ret; + int loop = 1; - auto window = ui::Window( ui::window_type::TOP ); + auto window = ui::Window(ui::window_type::TOP); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - gtk_window_set_title( window, "Texture Reset" ); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); + gtk_window_set_title(window, "Texture Reset"); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - gtk_widget_realize( window ); + gtk_widget_realize(window); - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); - // ---- vbox ---- + // ---- vbox ---- - auto hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); + auto hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); - // ---- hbox ---- + // ---- hbox ---- - texSelected = "Currently Selected Texture: "; - texSelected += GetCurrentTexture(); + texSelected = "Currently Selected Texture: "; + texSelected += GetCurrentTexture(); - w = ui::Label( texSelected ); - hbox.pack_start( w, FALSE, FALSE, 2 ); - gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT ); - w.show(); + w = ui::Label(texSelected); + hbox.pack_start(w, FALSE, FALSE, 2); + gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT); + w.show(); - // ---- /hbox ---- + // ---- /hbox ---- - auto frame = ui::Frame( "Reset Texture Names" ); - frame.show(); - vbox.pack_start( frame, FALSE, TRUE, 0 ); + auto frame = ui::Frame("Reset Texture Names"); + frame.show(); + vbox.pack_start(frame, FALSE, TRUE, 0); - auto table = ui::Table( 2, 3, TRUE ); - table.show(); - frame.add(table); - gtk_table_set_row_spacings(table, 5); - gtk_table_set_col_spacings(table, 5); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); + auto table = ui::Table(2, 3, TRUE); + table.show(); + frame.add(table); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); - // ---- frame ---- + // ---- frame ---- - dlgTexReset.cbTexChange = ui::CheckButton( "Enabled" ); - dlgTexReset.cbTexChange.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL ); - dlgTexReset.cbTexChange.show(); - table.attach(dlgTexReset.cbTexChange, {0, 1, 0, 1}, {GTK_FILL, 0}); + dlgTexReset.cbTexChange = ui::CheckButton("Enabled"); + dlgTexReset.cbTexChange.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL); + dlgTexReset.cbTexChange.show(); + table.attach(dlgTexReset.cbTexChange, {0, 1, 0, 1}, {GTK_FILL, 0}); - w = ui::Label( "Old Name: " ); - table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0}); - w.show(); + w = ui::Label("Old Name: "); + table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0}); + w.show(); - dlgTexReset.editTexOld = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editTexOld ), rs->textureName ); - table.attach(dlgTexReset.editTexOld, {2, 3, 0, 1}, {GTK_FILL, 0}); - dlgTexReset.editTexOld.show(); + dlgTexReset.editTexOld = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editTexOld), rs->textureName); + table.attach(dlgTexReset.editTexOld, {2, 3, 0, 1}, {GTK_FILL, 0}); + dlgTexReset.editTexOld.show(); - w = ui::Label( "New Name: " ); - table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0}); - w.show(); + w = ui::Label("New Name: "); + table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0}); + w.show(); - dlgTexReset.editTexNew = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editTexNew ), rs->textureName ); - table.attach(dlgTexReset.editTexNew, {2, 3, 1, 2}, {GTK_FILL, 0}); - dlgTexReset.editTexNew.show(); + dlgTexReset.editTexNew = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editTexNew), rs->textureName); + table.attach(dlgTexReset.editTexNew, {2, 3, 1, 2}, {GTK_FILL, 0}); + dlgTexReset.editTexNew.show(); - // ---- /frame ---- + // ---- /frame ---- - frame = ui::Frame( "Reset Scales" ); - frame.show(); - vbox.pack_start( frame, FALSE, TRUE, 0 ); + frame = ui::Frame("Reset Scales"); + frame.show(); + vbox.pack_start(frame, FALSE, TRUE, 0); - table = ui::Table( 2, 3, TRUE ); - table.show(); - frame.add(table); - gtk_table_set_row_spacings(table, 5); - gtk_table_set_col_spacings(table, 5); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); + table = ui::Table(2, 3, TRUE); + table.show(); + frame.add(table); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); - // ---- frame ---- + // ---- frame ---- - dlgTexReset.cbScaleHor = ui::CheckButton( "Enabled" ); - dlgTexReset.cbScaleHor.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL ); - dlgTexReset.cbScaleHor.show(); - table.attach(dlgTexReset.cbScaleHor, {0, 1, 0, 1}, {GTK_FILL, 0}); + dlgTexReset.cbScaleHor = ui::CheckButton("Enabled"); + dlgTexReset.cbScaleHor.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL); + dlgTexReset.cbScaleHor.show(); + table.attach(dlgTexReset.cbScaleHor, {0, 1, 0, 1}, {GTK_FILL, 0}); - w = ui::Label( "New Horizontal Scale: " ); - table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0}); - w.show(); + w = ui::Label("New Horizontal Scale: "); + table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0}); + w.show(); - dlgTexReset.editScaleHor = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editScaleHor ), "0.5" ); - table.attach(dlgTexReset.editScaleHor, {2, 3, 0, 1}, {GTK_FILL, 0}); - dlgTexReset.editScaleHor.show(); + dlgTexReset.editScaleHor = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editScaleHor), "0.5"); + table.attach(dlgTexReset.editScaleHor, {2, 3, 0, 1}, {GTK_FILL, 0}); + dlgTexReset.editScaleHor.show(); - dlgTexReset.cbScaleVert = ui::CheckButton( "Enabled" ); - dlgTexReset.cbScaleVert.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL ); - dlgTexReset.cbScaleVert.show(); - table.attach(dlgTexReset.cbScaleVert, {0, 1, 1, 2}, {GTK_FILL, 0}); + dlgTexReset.cbScaleVert = ui::CheckButton("Enabled"); + dlgTexReset.cbScaleVert.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL); + dlgTexReset.cbScaleVert.show(); + table.attach(dlgTexReset.cbScaleVert, {0, 1, 1, 2}, {GTK_FILL, 0}); - w = ui::Label( "New Vertical Scale: " ); - table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0}); - w.show(); + w = ui::Label("New Vertical Scale: "); + table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0}); + w.show(); - dlgTexReset.editScaleVert = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editScaleVert ), "0.5" ); - table.attach(dlgTexReset.editScaleVert, {2, 3, 1, 2}, {GTK_FILL, 0}); - dlgTexReset.editScaleVert.show(); + dlgTexReset.editScaleVert = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editScaleVert), "0.5"); + table.attach(dlgTexReset.editScaleVert, {2, 3, 1, 2}, {GTK_FILL, 0}); + dlgTexReset.editScaleVert.show(); - // ---- /frame ---- + // ---- /frame ---- - frame = ui::Frame( "Reset Shift" ); - frame.show(); - vbox.pack_start( frame, FALSE, TRUE, 0 ); + frame = ui::Frame("Reset Shift"); + frame.show(); + vbox.pack_start(frame, FALSE, TRUE, 0); - table = ui::Table( 2, 3, TRUE ); - table.show(); - frame.add(table); - gtk_table_set_row_spacings(table, 5); - gtk_table_set_col_spacings(table, 5); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); + table = ui::Table(2, 3, TRUE); + table.show(); + frame.add(table); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); - // ---- frame ---- + // ---- frame ---- - dlgTexReset.cbShiftHor = ui::CheckButton( "Enabled" ); - dlgTexReset.cbShiftHor.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL ); - dlgTexReset.cbShiftHor.show(); - table.attach(dlgTexReset.cbShiftHor, {0, 1, 0, 1}, {GTK_FILL, 0}); + dlgTexReset.cbShiftHor = ui::CheckButton("Enabled"); + dlgTexReset.cbShiftHor.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL); + dlgTexReset.cbShiftHor.show(); + table.attach(dlgTexReset.cbShiftHor, {0, 1, 0, 1}, {GTK_FILL, 0}); - w = ui::Label( "New Horizontal Shift: " ); - table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0}); - w.show(); + w = ui::Label("New Horizontal Shift: "); + table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0}); + w.show(); - dlgTexReset.editShiftHor = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editShiftHor ), "0" ); - table.attach(dlgTexReset.editShiftHor, {2, 3, 0, 1}, {GTK_FILL, 0}); - dlgTexReset.editShiftHor.show(); + dlgTexReset.editShiftHor = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editShiftHor), "0"); + table.attach(dlgTexReset.editShiftHor, {2, 3, 0, 1}, {GTK_FILL, 0}); + dlgTexReset.editShiftHor.show(); - dlgTexReset.cbShiftVert = ui::CheckButton( "Enabled" ); - dlgTexReset.cbShiftVert.connect( "toggled", G_CALLBACK( dialog_button_callback_texreset_update ), NULL ); - dlgTexReset.cbShiftVert.show(); - table.attach(dlgTexReset.cbShiftVert, {0, 1, 1, 2}, {GTK_FILL, 0}); - - w = ui::Label( "New Vertical Shift: " ); - table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0}); - w.show(); - - dlgTexReset.editShiftVert = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editShiftVert ), "0" ); - table.attach(dlgTexReset.editShiftVert, {2, 3, 1, 2}, {GTK_FILL, 0}); - dlgTexReset.editShiftVert.show(); - - // ---- /frame ---- - - frame = ui::Frame( "Reset Rotation" ); - frame.show(); - vbox.pack_start( frame, FALSE, TRUE, 0 ); - - table = ui::Table( 1, 3, TRUE ); - table.show(); - frame.add(table); - gtk_table_set_row_spacings(table, 5); - gtk_table_set_col_spacings(table, 5); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); - - // ---- frame ---- - - dlgTexReset.cbRotation = ui::CheckButton( "Enabled" ); - dlgTexReset.cbRotation.show(); - table.attach(dlgTexReset.cbRotation, {0, 1, 0, 1}, {GTK_FILL, 0}); - - w = ui::Label( "New Rotation Value: " ); - table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0}); - w.show(); - - dlgTexReset.editRotation = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( dlgTexReset.editRotation ), "0" ); - table.attach(dlgTexReset.editRotation, {2, 3, 0, 1}, {GTK_FILL, 0}); - dlgTexReset.editRotation.show(); - - // ---- /frame ---- - - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); - - // ---- hbox ---- - - w = ui::Button( "Use Selected Brushes" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "Use All Brushes" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDYES ) ); - w.show(); - - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; - - // ---- /hbox ---- - - // ---- /vbox ---- - - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); - - Update_TextureReseter(); - - bool dialogError = TRUE; - while ( dialogError ) - { - loop = 1; - while ( loop ) - gtk_main_iteration(); - - dialogError = FALSE; - - if ( ret != eIDCANCEL ) { - rs->bResetRotation = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbRotation ) ); - if ( rs->bResetRotation ) { - if ( !ValidateTextInt( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editRotation ) ), "Rotation", &rs->rotation ) ) { - dialogError = TRUE; - } - } - - rs->bResetScale[0] = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleHor ) ); - if ( rs->bResetScale[0] ) { - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editScaleHor ) ), "Horizontal Scale", &rs->fScale[0] ) ) { - dialogError = TRUE; - } - } - - rs->bResetScale[1] = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbScaleVert ) ); - if ( rs->bResetScale[1] ) { - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editScaleVert ) ), "Vertical Scale", &rs->fScale[1] ) ) { - dialogError = TRUE; - } - } - - rs->bResetShift[0] = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftHor ) ); - if ( rs->bResetShift[0] ) { - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editShiftHor ) ), "Horizontal Shift", &rs->fShift[0] ) ) { - dialogError = TRUE; - } - } - - rs->bResetShift[1] = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbShiftVert ) ); - if ( rs->bResetShift[1] ) { - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editShiftVert ) ), "Vertical Shift", &rs->fShift[1] ) ) { - dialogError = TRUE; - } - } - - rs->bResetTextureName = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dlgTexReset.cbTexChange ) ); - if ( rs->bResetTextureName ) { - strcpy( rs->textureName, gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editTexOld ) ) ); - strcpy( rs->newTextureName, gtk_entry_get_text( GTK_ENTRY( dlgTexReset.editTexNew ) ) ); - } - } - } - - gtk_grab_remove( window ); - window.destroy(); - - return ret; + dlgTexReset.cbShiftVert = ui::CheckButton("Enabled"); + dlgTexReset.cbShiftVert.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL); + dlgTexReset.cbShiftVert.show(); + table.attach(dlgTexReset.cbShiftVert, {0, 1, 1, 2}, {GTK_FILL, 0}); + + w = ui::Label("New Vertical Shift: "); + table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0}); + w.show(); + + dlgTexReset.editShiftVert = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editShiftVert), "0"); + table.attach(dlgTexReset.editShiftVert, {2, 3, 1, 2}, {GTK_FILL, 0}); + dlgTexReset.editShiftVert.show(); + + // ---- /frame ---- + + frame = ui::Frame("Reset Rotation"); + frame.show(); + vbox.pack_start(frame, FALSE, TRUE, 0); + + table = ui::Table(1, 3, TRUE); + table.show(); + frame.add(table); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + + // ---- frame ---- + + dlgTexReset.cbRotation = ui::CheckButton("Enabled"); + dlgTexReset.cbRotation.show(); + table.attach(dlgTexReset.cbRotation, {0, 1, 0, 1}, {GTK_FILL, 0}); + + w = ui::Label("New Rotation Value: "); + table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0}); + w.show(); + + dlgTexReset.editRotation = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editRotation), "0"); + table.attach(dlgTexReset.editRotation, {2, 3, 0, 1}, {GTK_FILL, 0}); + dlgTexReset.editRotation.show(); + + // ---- /frame ---- + + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); + + // ---- hbox ---- + + w = ui::Button("Use Selected Brushes"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("Use All Brushes"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES)); + w.show(); + + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; + + // ---- /hbox ---- + + // ---- /vbox ---- + + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); + + Update_TextureReseter(); + + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } + + dialogError = FALSE; + + if (ret != eIDCANCEL) { + rs->bResetRotation = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbRotation)); + if (rs->bResetRotation) { + if (!ValidateTextInt(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editRotation)), "Rotation", + &rs->rotation)) { + dialogError = TRUE; + } + } + + rs->bResetScale[0] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbScaleHor)); + if (rs->bResetScale[0]) { + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editScaleHor)), "Horizontal Scale", + &rs->fScale[0])) { + dialogError = TRUE; + } + } + + rs->bResetScale[1] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbScaleVert)); + if (rs->bResetScale[1]) { + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editScaleVert)), "Vertical Scale", + &rs->fScale[1])) { + dialogError = TRUE; + } + } + + rs->bResetShift[0] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbShiftHor)); + if (rs->bResetShift[0]) { + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editShiftHor)), "Horizontal Shift", + &rs->fShift[0])) { + dialogError = TRUE; + } + } + + rs->bResetShift[1] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbShiftVert)); + if (rs->bResetShift[1]) { + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editShiftVert)), "Vertical Shift", + &rs->fShift[1])) { + dialogError = TRUE; + } + } + + rs->bResetTextureName = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbTexChange)); + if (rs->bResetTextureName) { + strcpy(rs->textureName, gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editTexOld))); + strcpy(rs->newTextureName, gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editTexNew))); + } + } + } + + gtk_grab_remove(window); + window.destroy(); + + return ret; } -EMessageBoxReturn DoTrainThingBox( TrainThingRS* rs ){ - Str texSelected; - - ui::Widget w{ui::null}; +EMessageBoxReturn DoTrainThingBox(TrainThingRS *rs) +{ + Str texSelected; - ui::Widget radiusX{ui::null}, radiusY{ui::null}; - ui::Widget angleStart{ui::null}, angleEnd{ui::null}; - ui::Widget heightStart{ui::null}, heightEnd{ui::null}; - ui::Widget numPoints{ui::null}; + ui::Widget w{ui::null}; - EMessageBoxReturn ret; - int loop = 1; + ui::Widget radiusX{ui::null}, radiusY{ui::null}; + ui::Widget angleStart{ui::null}, angleEnd{ui::null}; + ui::Widget heightStart{ui::null}, heightEnd{ui::null}; + ui::Widget numPoints{ui::null}; - auto window = ui::Window( ui::window_type::TOP ); + EMessageBoxReturn ret; + int loop = 1; - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + auto window = ui::Window(ui::window_type::TOP); - gtk_window_set_title( window, "Train Thing" ); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + gtk_window_set_title(window, "Train Thing"); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); - gtk_widget_realize( window ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); + gtk_widget_realize(window); - // ---- vbox ---- + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); - auto hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); + // ---- vbox ---- - // ---- /hbox ---- + auto hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); - auto frame = ui::Frame( "Radii" ); - frame.show(); - vbox.pack_start( frame, FALSE, TRUE, 0 ); + // ---- /hbox ---- - auto table = ui::Table( 2, 3, TRUE ); - table.show(); - frame.add(table); - gtk_table_set_row_spacings(table, 5); - gtk_table_set_col_spacings(table, 5); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); + auto frame = ui::Frame("Radii"); + frame.show(); + vbox.pack_start(frame, FALSE, TRUE, 0); - // ---- frame ---- + auto table = ui::Table(2, 3, TRUE); + table.show(); + frame.add(table); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); - w = ui::Label( "X: " ); - table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0}); - w.show(); + // ---- frame ---- - radiusX = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( radiusX ), "100" ); - table.attach(radiusX, {1, 2, 0, 1}, {GTK_FILL, 0}); - radiusX.show(); + w = ui::Label("X: "); + table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0}); + w.show(); + radiusX = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(radiusX), "100"); + table.attach(radiusX, {1, 2, 0, 1}, {GTK_FILL, 0}); + radiusX.show(); - w = ui::Label( "Y: " ); - table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0}); - w.show(); + w = ui::Label("Y: "); + table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0}); + w.show(); - radiusY = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( radiusY ), "100" ); - table.attach(radiusY, {1, 2, 1, 2}, {GTK_FILL, 0}); - radiusY.show(); + radiusY = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(radiusY), "100"); + table.attach(radiusY, {1, 2, 1, 2}, {GTK_FILL, 0}); + radiusY.show(); + frame = ui::Frame("Angles"); + frame.show(); + vbox.pack_start(frame, FALSE, TRUE, 0); - frame = ui::Frame( "Angles" ); - frame.show(); - vbox.pack_start( frame, FALSE, TRUE, 0 ); + table = ui::Table(2, 3, TRUE); + table.show(); + frame.add(table); + gtk_table_set_row_spacings((table), 5); + gtk_table_set_col_spacings((table), 5); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); - table = ui::Table( 2, 3, TRUE ); - table.show(); - frame.add(table); - gtk_table_set_row_spacings((table), 5); - gtk_table_set_col_spacings((table), 5); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); + // ---- frame ---- - // ---- frame ---- + w = ui::Label("Start: "); + table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0}); + w.show(); - w = ui::Label( "Start: " ); - table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0}); - w.show(); + angleStart = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(angleStart), "0"); + table.attach(angleStart, {1, 2, 0, 1}, {GTK_FILL, 0}); + angleStart.show(); - angleStart = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( angleStart ), "0" ); - table.attach(angleStart, {1, 2, 0, 1}, {GTK_FILL, 0}); - angleStart.show(); + w = ui::Label("End: "); + table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0}); + w.show(); + angleEnd = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(angleEnd), "90"); + table.attach(angleEnd, {1, 2, 1, 2}, {GTK_FILL, 0}); + angleEnd.show(); - w = ui::Label( "End: " ); - table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0}); - w.show(); - angleEnd = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( angleEnd ), "90" ); - table.attach(angleEnd, {1, 2, 1, 2}, {GTK_FILL, 0}); - angleEnd.show(); + frame = ui::Frame("Height"); + frame.show(); + vbox.pack_start(frame, FALSE, TRUE, 0); + table = ui::Table(2, 3, TRUE); + table.show(); + frame.add(table); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); - frame = ui::Frame( "Height" ); - frame.show(); - vbox.pack_start( frame, FALSE, TRUE, 0 ); + // ---- frame ---- - table = ui::Table( 2, 3, TRUE ); - table.show(); - frame.add(table); - gtk_table_set_row_spacings(table, 5); - gtk_table_set_col_spacings(table, 5); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); + w = ui::Label("Start: "); + table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0}); + w.show(); - // ---- frame ---- + heightStart = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(heightStart), "0"); + table.attach(heightStart, {1, 2, 0, 1}, {GTK_FILL, 0}); + heightStart.show(); - w = ui::Label( "Start: " ); - table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0}); - w.show(); - heightStart = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( heightStart ), "0" ); - table.attach(heightStart, {1, 2, 0, 1}, {GTK_FILL, 0}); - heightStart.show(); + w = ui::Label("End: "); + table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0}); + w.show(); + heightEnd = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(heightEnd), "0"); + table.attach(heightEnd, {1, 2, 1, 2}, {GTK_FILL, 0}); + heightEnd.show(); - w = ui::Label( "End: " ); - table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0}); - w.show(); + frame = ui::Frame("Points"); + frame.show(); + vbox.pack_start(frame, FALSE, TRUE, 0); - heightEnd = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( heightEnd ), "0" ); - table.attach(heightEnd, {1, 2, 1, 2}, {GTK_FILL, 0}); - heightEnd.show(); + table = ui::Table(2, 3, TRUE); + table.show(); + frame.add(table); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + // ---- frame ---- + w = ui::Label("Number: "); + table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0}); + w.show(); - frame = ui::Frame( "Points" ); - frame.show(); - vbox.pack_start( frame, FALSE, TRUE, 0 ); + numPoints = ui::Entry(256); + gtk_entry_set_text(GTK_ENTRY(numPoints), "0"); + table.attach(numPoints, {1, 2, 0, 1}, {GTK_FILL, 0}); + numPoints.show(); - table = ui::Table( 2, 3, TRUE ); - table.show(); - frame.add(table); - gtk_table_set_row_spacings(table, 5); - gtk_table_set_col_spacings(table, 5); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); - // ---- frame ---- + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); - w = ui::Label( "Number: " ); - table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0}); - w.show(); + // ---- hbox ---- - numPoints = ui::Entry( 256 ); - gtk_entry_set_text( GTK_ENTRY( numPoints ), "0" ); - table.attach(numPoints, {1, 2, 0, 1}, {GTK_FILL, 0}); - numPoints.show(); + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; - // ---- hbox ---- + // ---- /hbox ---- - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - // ---- /hbox ---- + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } + dialogError = FALSE; + if (ret != eIDCANCEL) { + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(radiusX)), "Radius (X)", &rs->fRadiusX)) { + dialogError = TRUE; + } - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(radiusY)), "Radius (Y)", &rs->fRadiusY)) { + dialogError = TRUE; + } - bool dialogError = TRUE; - while ( dialogError ) - { - loop = 1; - while ( loop ) - gtk_main_iteration(); + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(angleStart)), "Angle (Start)", &rs->fStartAngle)) { + dialogError = TRUE; + } - dialogError = FALSE; + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(angleEnd)), "Angle (End)", &rs->fEndAngle)) { + dialogError = TRUE; + } - if ( ret != eIDCANCEL ) { - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( radiusX ) ), "Radius (X)", &rs->fRadiusX ) ) { - dialogError = TRUE; - } + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(heightStart)), "Height (Start)", &rs->fStartHeight)) { + dialogError = TRUE; + } - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( radiusY ) ), "Radius (Y)", &rs->fRadiusY ) ) { - dialogError = TRUE; - } + if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(heightEnd)), "Height (End)", &rs->fEndHeight)) { + dialogError = TRUE; + } - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( angleStart ) ), "Angle (Start)", &rs->fStartAngle ) ) { - dialogError = TRUE; - } + if (!ValidateTextInt(gtk_entry_get_text(GTK_ENTRY(numPoints)), "Num Points", &rs->iNumPoints)) { + dialogError = TRUE; + } + } + } - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( angleEnd ) ), "Angle (End)", &rs->fEndAngle ) ) { - dialogError = TRUE; - } + gtk_grab_remove(window); + window.destroy(); - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( heightStart ) ), "Height (Start)", &rs->fStartHeight ) ) { - dialogError = TRUE; - } - - if ( !ValidateTextFloat( gtk_entry_get_text( GTK_ENTRY( heightEnd ) ), "Height (End)", &rs->fEndHeight ) ) { - dialogError = TRUE; - } - - if ( !ValidateTextInt( gtk_entry_get_text( GTK_ENTRY( numPoints ) ), "Num Points", &rs->iNumPoints ) ) { - dialogError = TRUE; - } - } - } - - gtk_grab_remove( window ); - window.destroy(); - - return ret; + return ret; } + // ailmanki // add a simple input for the MakeChain thing.. -EMessageBoxReturn DoMakeChainBox( MakeChainRS* rs ){ - ui::Widget w{ui::null}; - ui::Entry textlinkNum{ui::null}, textlinkName{ui::null}; - EMessageBoxReturn ret; - int loop = 1; +EMessageBoxReturn DoMakeChainBox(MakeChainRS *rs) +{ + ui::Widget w{ui::null}; + ui::Entry textlinkNum{ui::null}, textlinkName{ui::null}; + EMessageBoxReturn ret; + int loop = 1; - const char *text = "Please set a value in the boxes below and press 'OK' to make a chain"; + const char *text = "Please set a value in the boxes below and press 'OK' to make a chain"; - auto window = ui::Window( ui::window_type::TOP ); + auto window = ui::Window(ui::window_type::TOP); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - gtk_window_set_title( window, "Make Chain" ); + gtk_window_set_title(window, "Make Chain"); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - gtk_widget_realize( window ); + gtk_widget_realize(window); - // new vbox - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); + // new vbox + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); - auto hbox = ui::HBox( FALSE, 10 ); - vbox.add(hbox); - hbox.show(); + auto hbox = ui::HBox(FALSE, 10); + vbox.add(hbox); + hbox.show(); - // dunno if you want this text or not ... - w = ui::Label( text ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + // dunno if you want this text or not ... + w = ui::Label(text); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - w = ui::Widget::from(gtk_hseparator_new()); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Widget::from(gtk_hseparator_new()); + vbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - // ------------------------- // + // ------------------------- // - // new hbox - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + // new hbox + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - textlinkNum = ui::Entry( 256 ); - hbox.pack_start( textlinkNum, FALSE, FALSE, 1 ); - textlinkNum.show(); + textlinkNum = ui::Entry(256); + hbox.pack_start(textlinkNum, FALSE, FALSE, 1); + textlinkNum.show(); - w = ui::Label( "Number of elements in chain" ); - hbox.pack_start( w, FALSE, FALSE, 1 ); - w.show(); + w = ui::Label("Number of elements in chain"); + hbox.pack_start(w, FALSE, FALSE, 1); + w.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - textlinkName = ui::Entry( 256 ); - hbox.pack_start( textlinkName, FALSE, FALSE, 0 ); - textlinkName.show(); + textlinkName = ui::Entry(256); + hbox.pack_start(textlinkName, FALSE, FALSE, 0); + textlinkName.show(); - w = ui::Label( "Basename for chain's targetnames." ); - hbox.pack_start( w, FALSE, FALSE, 1 ); - w.show(); + w = ui::Label("Basename for chain's targetnames."); + hbox.pack_start(w, FALSE, FALSE, 1); + w.show(); - w = ui::Button( "OK" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); + w = ui::Button("OK"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); - ret = eIDCANCEL; + ret = eIDCANCEL; - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - bool dialogError = TRUE; - while ( dialogError ) - { - loop = 1; - while ( loop ) - gtk_main_iteration(); + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } - dialogError = FALSE; + dialogError = FALSE; - if ( ret == eIDOK ) { - strcpy( rs->linkName, gtk_entry_get_text( textlinkName ) ); - if ( !ValidateTextInt( gtk_entry_get_text( textlinkNum ), "Elements", &rs->linkNum ) ) { - dialogError = TRUE; - } - } - } + if (ret == eIDOK) { + strcpy(rs->linkName, gtk_entry_get_text(textlinkName)); + if (!ValidateTextInt(gtk_entry_get_text(textlinkNum), "Elements", &rs->linkNum)) { + dialogError = TRUE; + } + } + } - gtk_grab_remove( window ); - window.destroy(); + gtk_grab_remove(window); + window.destroy(); - return ret; + return ret; } diff --git a/contrib/bobtoolz/dialogs/dialogs-gtk.h b/contrib/bobtoolz/dialogs/dialogs-gtk.h index a8490459..478e75be 100644 --- a/contrib/bobtoolz/dialogs/dialogs-gtk.h +++ b/contrib/bobtoolz/dialogs/dialogs-gtk.h @@ -23,88 +23,97 @@ #include "qerplugin.h" struct BuildStairsRS { - char mainTexture[256]; - char riserTexture[256]; - int direction; - int style; - int stairHeight; - bool bUseDetail; + char mainTexture[256]; + char riserTexture[256]; + int direction; + int style; + int stairHeight; + bool bUseDetail; }; struct ResetTextureRS { - int bResetTextureName; - char textureName[256]; - char newTextureName[256]; + int bResetTextureName; + char textureName[256]; + char newTextureName[256]; - int bResetScale[2]; - float fScale[2]; + int bResetScale[2]; + float fScale[2]; - int bResetShift[2]; - float fShift[2]; + int bResetShift[2]; + float fShift[2]; - int bResetRotation; - int rotation; + int bResetRotation; + int rotation; }; struct TrainThingRS { - float fRadiusX, fRadiusY; - float fStartAngle, fEndAngle; - int iNumPoints; - float fStartHeight, fEndHeight; + float fRadiusX, fRadiusY; + float fStartAngle, fEndAngle; + int iNumPoints; + float fStartHeight, fEndHeight; }; struct IntersectRS { - int nBrushOptions; - bool bUseDetail; - bool bDuplicateOnly; + int nBrushOptions; + bool bUseDetail; + bool bDuplicateOnly; }; struct PolygonRS { - bool bUseBorder; - bool bInverse; - bool bAlignTop; - int nSides; - int nBorderWidth; + bool bUseBorder; + bool bInverse; + bool bAlignTop; + int nSides; + int nBorderWidth; }; struct DoorRS { - char mainTexture[256]; - char trimTexture[256]; - bool bScaleMainH; - bool bScaleMainV; - bool bScaleTrimH; - bool bScaleTrimV; - int nOrientation; + char mainTexture[256]; + char trimTexture[256]; + bool bScaleMainH; + bool bScaleMainV; + bool bScaleTrimH; + bool bScaleTrimV; + int nOrientation; }; struct PathPlotterRS { - int nPoints; - float fMultiplier; - float fGravity; - bool bNoUpdate; - bool bShowExtra; + int nPoints; + float fMultiplier; + float fGravity; + bool bNoUpdate; + bool bShowExtra; }; struct MakeChainRS { - char linkName[256]; - int linkNum; + char linkName[256]; + int linkNum; }; struct TwinWidget { - ui::Widget one{ui::null}; - ui::ComboBox two{ui::null}; + ui::Widget one{ui::null}; + ui::ComboBox two{ui::null}; }; -EMessageBoxReturn DoMessageBox( const char* lpText, const char* lpCaption, EMessageBoxType type ); -EMessageBoxReturn DoIntersectBox( IntersectRS* rs ); -EMessageBoxReturn DoPolygonBox( PolygonRS* rs ); -EMessageBoxReturn DoResetTextureBox( ResetTextureRS* rs ); -EMessageBoxReturn DoBuildStairsBox( BuildStairsRS* rs ); -EMessageBoxReturn DoDoorsBox( DoorRS* rs ); -EMessageBoxReturn DoPathPlotterBox( PathPlotterRS* rs ); +EMessageBoxReturn DoMessageBox(const char *lpText, const char *lpCaption, EMessageBoxType type); + +EMessageBoxReturn DoIntersectBox(IntersectRS *rs); + +EMessageBoxReturn DoPolygonBox(PolygonRS *rs); + +EMessageBoxReturn DoResetTextureBox(ResetTextureRS *rs); + +EMessageBoxReturn DoBuildStairsBox(BuildStairsRS *rs); + +EMessageBoxReturn DoDoorsBox(DoorRS *rs); + +EMessageBoxReturn DoPathPlotterBox(PathPlotterRS *rs); + EMessageBoxReturn DoCTFColourChangeBox(); -EMessageBoxReturn DoTrainThingBox( TrainThingRS* rs ); -EMessageBoxReturn DoMakeChainBox( MakeChainRS* rs ); + +EMessageBoxReturn DoTrainThingBox(TrainThingRS *rs); + +EMessageBoxReturn DoMakeChainBox(MakeChainRS *rs); //GtkWidget* GetProgressWindow(char* title, GtkProgressBar* feedback); #endif diff --git a/contrib/bobtoolz/dialogs/pathplotterdialog.cpp b/contrib/bobtoolz/dialogs/pathplotterdialog.cpp index 65e4f506..5be0e628 100644 --- a/contrib/bobtoolz/dialogs/pathplotterdialog.cpp +++ b/contrib/bobtoolz/dialogs/pathplotterdialog.cpp @@ -28,49 +28,57 @@ // CPathPlotterDialog dialog -CPathPlotterDialog::CPathPlotterDialog( CWnd* pParent /*=NULL*/ ) - : CDialog( CPathPlotterDialog::IDD, pParent ){ - //{{AFX_DATA_INIT(CPathPlotterDialog) - m_fGravity = -800.0f; - m_fMultiplier = 3.0f; - m_bNoUpdate = FALSE; - m_nPoints = 25; - m_bShowExtra = FALSE; - //}}AFX_DATA_INIT +CPathPlotterDialog::CPathPlotterDialog(CWnd *pParent /*=NULL*/ ) + : CDialog(CPathPlotterDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPathPlotterDialog) + m_fGravity = -800.0f; + m_fMultiplier = 3.0f; + m_bNoUpdate = FALSE; + m_nPoints = 25; + m_bShowExtra = FALSE; + //}}AFX_DATA_INIT } -void CPathPlotterDialog::DoDataExchange( CDataExchange* pDX ){ - CDialog::DoDataExchange( pDX ); - //{{AFX_DATA_MAP(CPathPlotterDialog) - DDX_Text( pDX, IDC_GRAVITY_EDIT, m_fGravity ); - DDV_MinMaxFloat( pDX, m_fGravity, -10000.f, -1.f ); - DDX_Text( pDX, IDC_MULTIPLIER_EDIT, m_fMultiplier ); - DDV_MinMaxFloat( pDX, m_fMultiplier, 1.f, 10.f ); - DDX_Check( pDX, IDC_NOUPDATE_CHECK, m_bNoUpdate ); - DDX_Text( pDX, IDC_POINTCOUNT_EDIT, m_nPoints ); - DDV_MinMaxInt( pDX, m_nPoints, 1, 1000 ); - DDX_Check( pDX, IDC_SHOWEXTRA_CHECK, m_bShowExtra ); - //}}AFX_DATA_MAP +void CPathPlotterDialog::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPathPlotterDialog) + DDX_Text(pDX, IDC_GRAVITY_EDIT, m_fGravity); + DDV_MinMaxFloat(pDX, m_fGravity, -10000.f, -1.f); + DDX_Text(pDX, IDC_MULTIPLIER_EDIT, m_fMultiplier); + DDV_MinMaxFloat(pDX, m_fMultiplier, 1.f, 10.f); + DDX_Check(pDX, IDC_NOUPDATE_CHECK, m_bNoUpdate); + DDX_Text(pDX, IDC_POINTCOUNT_EDIT, m_nPoints); + DDV_MinMaxInt(pDX, m_nPoints, 1, 1000); + DDX_Check(pDX, IDC_SHOWEXTRA_CHECK, m_bShowExtra); + //}}AFX_DATA_MAP } -BEGIN_MESSAGE_MAP( CPathPlotterDialog, CDialog ) +BEGIN_MESSAGE_MAP( CPathPlotterDialog, CDialog +) //{{AFX_MSG_MAP(CPathPlotterDialog) -ON_BN_CLICKED( IDYES, OnYes ) -ON_BN_CLICKED( IDNO, OnNo ) +ON_BN_CLICKED( IDYES, OnYes +) +ON_BN_CLICKED( IDNO, OnNo +) + //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPathPlotterDialog message handlers -void CPathPlotterDialog::OnYes(){ - if ( UpdateData() ) { - EndModalLoop( IDYES ); - } +void CPathPlotterDialog::OnYes() +{ + if (UpdateData()) { + EndModalLoop(IDYES); + } } -void CPathPlotterDialog::OnNo(){ - EndModalLoop( IDNO ); +void CPathPlotterDialog::OnNo() +{ + EndModalLoop(IDNO); } diff --git a/contrib/bobtoolz/dialogs/pathplotterdialog.h b/contrib/bobtoolz/dialogs/pathplotterdialog.h index 03e50873..7523b025 100644 --- a/contrib/bobtoolz/dialogs/pathplotterdialog.h +++ b/contrib/bobtoolz/dialogs/pathplotterdialog.h @@ -29,20 +29,19 @@ ///////////////////////////////////////////////////////////////////////////// // CPathPlotterDialog dialog -class CPathPlotterDialog : public CDialog -{ +class CPathPlotterDialog : public CDialog { // Construction public: -CPathPlotterDialog( CWnd* pParent = NULL ); // standard constructor + CPathPlotterDialog(CWnd *pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CPathPlotterDialog) -enum { IDD = IDD_PATHPLOTTER_DIALOG }; -float m_fGravity; -float m_fMultiplier; -BOOL m_bNoUpdate; -int m_nPoints; -BOOL m_bShowExtra; + enum { IDD = IDD_PATHPLOTTER_DIALOG }; + float m_fGravity; + float m_fMultiplier; + BOOL m_bNoUpdate; + int m_nPoints; + BOOL m_bShowExtra; //}}AFX_DATA @@ -50,7 +49,7 @@ BOOL m_bShowExtra; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CPathPlotterDialog) protected: -virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -58,10 +57,12 @@ protected: // Generated message map functions //{{AFX_MSG(CPathPlotterDialog) -afx_msg void OnYes(); -afx_msg void OnNo(); + afx_msg void OnYes(); + + afx_msg void OnNo(); + //}}AFX_MSG -DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/contrib/bobtoolz/funchandlers-GTK.cpp b/contrib/bobtoolz/funchandlers-GTK.cpp index b07bf328..dfcdf6df 100644 --- a/contrib/bobtoolz/funchandlers-GTK.cpp +++ b/contrib/bobtoolz/funchandlers-GTK.cpp @@ -61,30 +61,31 @@ std::list exclusionList; // whole brush exclusion std::list exclusionList_Face; // single face exclusion -bool el1Loaded = false; -bool el2Loaded = false; -bool clrLst1Loaded = false; -bool clrLst2Loaded = false; - -DBobView* g_PathView = NULL; -DVisDrawer* g_VisView = NULL; -DTrainDrawer* g_TrainView = NULL; -DTreePlanter* g_TreePlanter = NULL; +bool el1Loaded = false; +bool el2Loaded = false; +bool clrLst1Loaded = false; +bool clrLst2Loaded = false; + +DBobView *g_PathView = NULL; +DVisDrawer *g_VisView = NULL; +DTrainDrawer *g_TrainView = NULL; +DTreePlanter *g_TreePlanter = NULL; // ------------- //========================// // Helper Functions // //========================// -void LoadLists(){ - char buffer[256]; +void LoadLists() +{ + char buffer[256]; - if ( !el1Loaded ) { - el1Loaded = LoadExclusionList( GetFilename( buffer, "bt/bt-el1.txt" ), &exclusionList ); - } - if ( !el2Loaded ) { - el2Loaded = LoadExclusionList( GetFilename( buffer, "bt/bt-el2.txt" ), &exclusionList_Face ); - } + if (!el1Loaded) { + el1Loaded = LoadExclusionList(GetFilename(buffer, "bt/bt-el1.txt"), &exclusionList); + } + if (!el2Loaded) { + el2Loaded = LoadExclusionList(GetFilename(buffer, "bt/bt-el2.txt"), &exclusionList_Face); + } } @@ -92,782 +93,775 @@ void LoadLists(){ // Main Functions // //========================// -void DoIntersect(){ - UndoableCommand undo( "bobToolz.intersect" ); - IntersectRS rs; - - if ( DoIntersectBox( &rs ) == eIDCANCEL ) { - return; - } - - if ( rs.nBrushOptions == BRUSH_OPT_SELECTED ) { - if ( GlobalSelectionSystem().countSelected() < 2 ) { - //DoMessageBox("Invalid number of brushes selected, choose at least 2", "Error", eMB_OK); - globalErrorStream() << "bobToolz Intersect: Invalid number of brushes selected, choose at least 2.\n"; - return; - } - } - - DEntity world; - switch ( rs.nBrushOptions ) - { - case BRUSH_OPT_SELECTED: - { - - world.LoadFromEntity( GlobalRadiant().getMapWorldEntity(), false ); - world.LoadSelectedBrushes(); - break; - } - case BRUSH_OPT_WHOLE_MAP: - { - world.LoadFromEntity( GlobalRadiant().getMapWorldEntity(), false ); - break; - } - } - world.RemoveNonCheckBrushes( &exclusionList, rs.bUseDetail ); - - bool* pbSelectList; - if ( rs.bDuplicateOnly ) { - pbSelectList = world.BuildDuplicateList(); - } - else{ - pbSelectList = world.BuildIntersectList(); - } - - world.SelectBrushes( pbSelectList ); - int brushCount = GlobalSelectionSystem().countSelected(); - globalOutputStream() << "bobToolz Intersect: " << brushCount << " intersecting brushes found.\n"; - delete[] pbSelectList; +void DoIntersect() +{ + UndoableCommand undo("bobToolz.intersect"); + IntersectRS rs; + + if (DoIntersectBox(&rs) == eIDCANCEL) { + return; + } + + if (rs.nBrushOptions == BRUSH_OPT_SELECTED) { + if (GlobalSelectionSystem().countSelected() < 2) { + //DoMessageBox("Invalid number of brushes selected, choose at least 2", "Error", eMB_OK); + globalErrorStream() << "bobToolz Intersect: Invalid number of brushes selected, choose at least 2.\n"; + return; + } + } + + DEntity world; + switch (rs.nBrushOptions) { + case BRUSH_OPT_SELECTED: { + + world.LoadFromEntity(GlobalRadiant().getMapWorldEntity(), false); + world.LoadSelectedBrushes(); + break; + } + case BRUSH_OPT_WHOLE_MAP: { + world.LoadFromEntity(GlobalRadiant().getMapWorldEntity(), false); + break; + } + } + world.RemoveNonCheckBrushes(&exclusionList, rs.bUseDetail); + + bool *pbSelectList; + if (rs.bDuplicateOnly) { + pbSelectList = world.BuildDuplicateList(); + } else { + pbSelectList = world.BuildIntersectList(); + } + + world.SelectBrushes(pbSelectList); + int brushCount = GlobalSelectionSystem().countSelected(); + globalOutputStream() << "bobToolz Intersect: " << brushCount << " intersecting brushes found.\n"; + delete[] pbSelectList; } -void DoPolygonsTB(){ - DoPolygons(); +void DoPolygonsTB() +{ + DoPolygons(); } -void DoPolygons(){ - UndoableCommand undo( "bobToolz.polygons" ); - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 1 ) { - //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); - globalErrorStream() << "bobToolz Polygons: Invalid number of brushes selected, choose 1 only.\n"; - return; - } - - PolygonRS rs; - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); - if ( !Node_isBrush( instance.path().top() ) ) { - //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK); - globalErrorStream() << "bobToolz Polygons: No brush selected, select ONLY one brush.\n"; - return; - } - // ask user for type, size, etc.... - if ( DoPolygonBox( &rs ) == eIDOK ) { - DShape poly; - - vec3_t vMin, vMax; - - { - - VectorSubtract( instance.worldAABB().origin, instance.worldAABB().extents, vMin ); - VectorAdd( instance.worldAABB().origin, instance.worldAABB().extents, vMax ); - - Path_deleteTop( instance.path() ); - } - - if ( rs.bInverse ) { - poly.BuildInversePrism( vMin, vMax, rs.nSides, rs.bAlignTop ); - } - else - { - if ( rs.bUseBorder ) { - poly.BuildBorderedPrism( vMin, vMax, rs.nSides, rs.nBorderWidth, rs.bAlignTop ); - } - else{ - poly.BuildRegularPrism( vMin, vMax, rs.nSides, rs.bAlignTop ); - } - - } - - poly.Commit(); - } +void DoPolygons() +{ + UndoableCommand undo("bobToolz.polygons"); + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 1) { + //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); + globalErrorStream() << "bobToolz Polygons: Invalid number of brushes selected, choose 1 only.\n"; + return; + } + + PolygonRS rs; + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); + if (!Node_isBrush(instance.path().top())) { + //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK); + globalErrorStream() << "bobToolz Polygons: No brush selected, select ONLY one brush.\n"; + return; + } + // ask user for type, size, etc.... + if (DoPolygonBox(&rs) == eIDOK) { + DShape poly; + + vec3_t vMin, vMax; + + { + + VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin); + VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax); + + Path_deleteTop(instance.path()); + } + + if (rs.bInverse) { + poly.BuildInversePrism(vMin, vMax, rs.nSides, rs.bAlignTop); + } else { + if (rs.bUseBorder) { + poly.BuildBorderedPrism(vMin, vMax, rs.nSides, rs.nBorderWidth, rs.bAlignTop); + } else { + poly.BuildRegularPrism(vMin, vMax, rs.nSides, rs.bAlignTop); + } + + } + + poly.Commit(); + } } -void DoFixBrushes(){ - UndoableCommand undo( "bobToolz.fixBrushes" ); - DMap world; - world.LoadAll(); +void DoFixBrushes() +{ + UndoableCommand undo("bobToolz.fixBrushes"); + DMap world; + world.LoadAll(); - int count = world.FixBrushes(); + int count = world.FixBrushes(); - globalOutputStream() << "bobToolz FixBrushes: " << count << " invalid/duplicate planes removed.\n"; + globalOutputStream() << "bobToolz FixBrushes: " << count << " invalid/duplicate planes removed.\n"; } -void DoResetTextures(){ - UndoableCommand undo( "bobToolz.resetTextures" ); - static ResetTextureRS rs; - - const char* texName; - if ( 1 /*g_SelectedFaceTable.m_pfnGetSelectedFaceCount() != 1*/ ) { - texName = NULL; - } - else - { - texName = GetCurrentTexture(); - strcpy( rs.textureName, GetCurrentTexture() ); - } - - EMessageBoxReturn ret; - if ( ( ret = DoResetTextureBox( &rs ) ) == eIDCANCEL ) { - return; - } - - if ( rs.bResetTextureName ) { - texName = rs.textureName; - } - - if ( ret == eIDOK ) { - DEntity world; - world.LoadSelectedBrushes(); - world.ResetTextures( texName, rs.fScale, rs.fShift, rs.rotation, rs.newTextureName, - rs.bResetTextureName, rs.bResetScale, rs.bResetShift, rs.bResetRotation, true ); - } - else - { - DMap world; - world.LoadAll( true ); - world.ResetTextures( texName, rs.fScale, rs.fShift, rs.rotation, rs.newTextureName, - rs.bResetTextureName, rs.bResetScale, rs.bResetShift, rs.bResetRotation ); - } +void DoResetTextures() +{ + UndoableCommand undo("bobToolz.resetTextures"); + static ResetTextureRS rs; + + const char *texName; + if (1 /*g_SelectedFaceTable.m_pfnGetSelectedFaceCount() != 1*/ ) { + texName = NULL; + } else { + texName = GetCurrentTexture(); + strcpy(rs.textureName, GetCurrentTexture()); + } + + EMessageBoxReturn ret; + if ((ret = DoResetTextureBox(&rs)) == eIDCANCEL) { + return; + } + + if (rs.bResetTextureName) { + texName = rs.textureName; + } + + if (ret == eIDOK) { + DEntity world; + world.LoadSelectedBrushes(); + world.ResetTextures(texName, rs.fScale, rs.fShift, rs.rotation, rs.newTextureName, + rs.bResetTextureName, rs.bResetScale, rs.bResetShift, rs.bResetRotation, true); + } else { + DMap world; + world.LoadAll(true); + world.ResetTextures(texName, rs.fScale, rs.fShift, rs.rotation, rs.newTextureName, + rs.bResetTextureName, rs.bResetScale, rs.bResetShift, rs.bResetRotation); + } } -void DoBuildStairs(){ - UndoableCommand undo( "bobToolz.buildStairs" ); - BuildStairsRS rs; - - strcpy( rs.mainTexture, GetCurrentTexture() ); - - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 1 ) { - //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); - globalErrorStream() << "bobToolz BuildStairs: Invalid number of brushes selected, choose 1 only.\n"; - return; - } - - // ask user for type, size, etc.... - if ( DoBuildStairsBox( &rs ) == eIDOK ) { - vec3_t vMin, vMax; - - { - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); - VectorSubtract( instance.worldAABB().origin, instance.worldAABB().extents, vMin ); - VectorAdd( instance.worldAABB().origin, instance.worldAABB().extents, vMax ); - } - - // calc brush size - vec3_t size; - VectorSubtract( vMax, vMin, size ); - - if ( ( (int)size[2] % rs.stairHeight ) != 0 ) { - // stairs must fit evenly into brush - //DoMessageBox("Invalid stair height\nHeight of block must be divisable by stair height", "Error", eMB_OK); - globalErrorStream() << "bobToolz BuildStairs: Invalid stair height. Height of block must be divisable by stair height.\n"; - } - else - { - { - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); - Path_deleteTop( instance.path() ); - } - - // Get Step Count - int numSteps = (int)size[2] / rs.stairHeight; - - if ( rs.style == STYLE_CORNER ) { - BuildCornerStairs( vMin, vMax, numSteps, rs.mainTexture, rs.riserTexture ); - } - else - { - - // Get Step Dimensions - float stairHeight = (float)rs.stairHeight; - float stairWidth; - if ( ( rs.direction == MOVE_EAST ) || ( rs.direction == MOVE_WEST ) ) { - stairWidth = ( size[0] ) / numSteps; - } - else{ - stairWidth = ( size[1] ) / numSteps; - } - - - // Build Base For Stair (bob's style) - if ( rs.style == STYLE_BOB ) { - Build_Wedge( rs.direction, vMin, vMax, true ); - } - - - // Set First Step Starting Position - vMax[2] = vMin[2] + stairHeight; - SetInitialStairPos( rs.direction, vMin, vMax, stairWidth ); - - - // Build The Steps - for ( int i = 0; i < numSteps; i++ ) - { - if ( rs.style == STYLE_BOB ) { - Build_StairStep_Wedge( rs.direction, vMin, vMax, rs.mainTexture, rs.riserTexture, rs.bUseDetail ); - } - else if ( rs.style == STYLE_ORIGINAL ) { - Build_StairStep( vMin, vMax, rs.mainTexture, rs.riserTexture, rs.direction ); - } - - // get step into next position - MoveBlock( rs.direction, vMin, vMax, stairWidth ); - vMax[2] += stairHeight; - if ( rs.style == STYLE_BOB ) { - vMin[2] += stairHeight; // wedge bottom must be raised - } - } - } - } - } +void DoBuildStairs() +{ + UndoableCommand undo("bobToolz.buildStairs"); + BuildStairsRS rs; + + strcpy(rs.mainTexture, GetCurrentTexture()); + + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 1) { + //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); + globalErrorStream() << "bobToolz BuildStairs: Invalid number of brushes selected, choose 1 only.\n"; + return; + } + + // ask user for type, size, etc.... + if (DoBuildStairsBox(&rs) == eIDOK) { + vec3_t vMin, vMax; + + { + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); + VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin); + VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax); + } + + // calc brush size + vec3_t size; + VectorSubtract(vMax, vMin, size); + + if (((int) size[2] % rs.stairHeight) != 0) { + // stairs must fit evenly into brush + //DoMessageBox("Invalid stair height\nHeight of block must be divisable by stair height", "Error", eMB_OK); + globalErrorStream() + << "bobToolz BuildStairs: Invalid stair height. Height of block must be divisable by stair height.\n"; + } else { + { + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); + Path_deleteTop(instance.path()); + } + + // Get Step Count + int numSteps = (int) size[2] / rs.stairHeight; + + if (rs.style == STYLE_CORNER) { + BuildCornerStairs(vMin, vMax, numSteps, rs.mainTexture, rs.riserTexture); + } else { + + // Get Step Dimensions + float stairHeight = (float) rs.stairHeight; + float stairWidth; + if ((rs.direction == MOVE_EAST) || (rs.direction == MOVE_WEST)) { + stairWidth = (size[0]) / numSteps; + } else { + stairWidth = (size[1]) / numSteps; + } + + + // Build Base For Stair (bob's style) + if (rs.style == STYLE_BOB) { + Build_Wedge(rs.direction, vMin, vMax, true); + } + + + // Set First Step Starting Position + vMax[2] = vMin[2] + stairHeight; + SetInitialStairPos(rs.direction, vMin, vMax, stairWidth); + + + // Build The Steps + for (int i = 0; i < numSteps; i++) { + if (rs.style == STYLE_BOB) { + Build_StairStep_Wedge(rs.direction, vMin, vMax, rs.mainTexture, rs.riserTexture, rs.bUseDetail); + } else if (rs.style == STYLE_ORIGINAL) { + Build_StairStep(vMin, vMax, rs.mainTexture, rs.riserTexture, rs.direction); + } + + // get step into next position + MoveBlock(rs.direction, vMin, vMax, stairWidth); + vMax[2] += stairHeight; + if (rs.style == STYLE_BOB) { + vMin[2] += stairHeight; // wedge bottom must be raised + } + } + } + } + } } -void DoBuildDoors(){ - UndoableCommand undo( "bobToolz.buildDoors" ); - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 1 ) { - //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); - globalErrorStream() << "bobToolz BuildDoors: Invalid number of brushes selected, choose 1 only.\n"; - return; - } - - DoorRS rs; - strcpy( rs.mainTexture, GetCurrentTexture() ); - - if ( DoDoorsBox( &rs ) == eIDOK ) { - vec3_t vMin, vMax; - - { - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); - VectorSubtract( instance.worldAABB().origin, instance.worldAABB().extents, vMin ); - VectorAdd( instance.worldAABB().origin, instance.worldAABB().extents, vMax ); - Path_deleteTop( instance.path() ); - } - - BuildDoorsX2( vMin, vMax, - rs.bScaleMainH, rs.bScaleMainV, - rs.bScaleTrimH, rs.bScaleTrimV, - rs.mainTexture, rs.trimTexture, - rs.nOrientation ); // shapes.cpp - } +void DoBuildDoors() +{ + UndoableCommand undo("bobToolz.buildDoors"); + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 1) { + //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); + globalErrorStream() << "bobToolz BuildDoors: Invalid number of brushes selected, choose 1 only.\n"; + return; + } + + DoorRS rs; + strcpy(rs.mainTexture, GetCurrentTexture()); + + if (DoDoorsBox(&rs) == eIDOK) { + vec3_t vMin, vMax; + + { + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); + VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin); + VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax); + Path_deleteTop(instance.path()); + } + + BuildDoorsX2(vMin, vMax, + rs.bScaleMainH, rs.bScaleMainV, + rs.bScaleTrimH, rs.bScaleTrimV, + rs.mainTexture, rs.trimTexture, + rs.nOrientation); // shapes.cpp + } } -void DoPathPlotter(){ - UndoableCommand undo( "bobToolz.pathPlotter" ); - PathPlotterRS rs; - EMessageBoxReturn ret = DoPathPlotterBox( &rs ); - if ( ret == eIDCANCEL ) { - return; - } - if ( ret == eIDNO ) { - if ( g_PathView ) { - delete g_PathView; - } - return; - } - - // ensure we have something selected - /* - if( GlobalSelectionSystem().countSelected() != 1 ) - { - //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); - globalOutputStream() << "bobToolz PathPlotter: Invalid number of entities selected, choose 1 trigger_push entity only.\n"; - return; - } - */ - Entity* entity = Node_getEntity( GlobalSelectionSystem().ultimateSelected().path().top() ); - if ( entity != 0 ) { - DBobView_setEntity( *entity, rs.fMultiplier, rs.nPoints, rs.fGravity, rs.bNoUpdate, rs.bShowExtra ); - } - else{ globalErrorStream() << "bobToolz PathPlotter: No trigger_push entitity selected, select 1 only (Use list to select it).\n"; } - return; +void DoPathPlotter() +{ + UndoableCommand undo("bobToolz.pathPlotter"); + PathPlotterRS rs; + EMessageBoxReturn ret = DoPathPlotterBox(&rs); + if (ret == eIDCANCEL) { + return; + } + if (ret == eIDNO) { + if (g_PathView) { + delete g_PathView; + } + return; + } + + // ensure we have something selected + /* + if( GlobalSelectionSystem().countSelected() != 1 ) + { + //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); + globalOutputStream() << "bobToolz PathPlotter: Invalid number of entities selected, choose 1 trigger_push entity only.\n"; + return; + } + */ + Entity *entity = Node_getEntity(GlobalSelectionSystem().ultimateSelected().path().top()); + if (entity != 0) { + DBobView_setEntity(*entity, rs.fMultiplier, rs.nPoints, rs.fGravity, rs.bNoUpdate, rs.bShowExtra); + } else { + globalErrorStream() + << "bobToolz PathPlotter: No trigger_push entitity selected, select 1 only (Use list to select it).\n"; + } + return; } -void DoPitBuilder(){ - UndoableCommand undo( "bobToolz.pitBuilder" ); - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 1 ) { - //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); - globalErrorStream() << "bobToolz PitBuilder: Invalid number of brushes selected, choose 1 only.\n"; - return; - } - - vec3_t vMin, vMax; - - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); - //seems it does this also with a patch with valid dimensions.. but probably better to enforce a brush. - if ( !Node_isBrush( instance.path().top() ) ) { - //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK); - globalErrorStream() << "bobToolz PitBuilder: No brush selected, select ONLY 1 brush.\n"; - return; - } - - VectorSubtract( instance.worldAABB().origin, instance.worldAABB().extents, vMin ); - VectorAdd( instance.worldAABB().origin, instance.worldAABB().extents, vMax ); - - DShape pit; - - if ( pit.BuildPit( vMin, vMax ) ) { - pit.Commit(); - Path_deleteTop( instance.path() ); - } - else - { - //DoMessageBox("Failed To Make Pit\nTry Making The Brush Bigger", "Error", eMB_OK); - globalErrorStream() << "bobToolz PitBuilder: Failed to make Pit, try making the brush bigger.\n"; - } +void DoPitBuilder() +{ + UndoableCommand undo("bobToolz.pitBuilder"); + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 1) { + //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK); + globalErrorStream() << "bobToolz PitBuilder: Invalid number of brushes selected, choose 1 only.\n"; + return; + } + + vec3_t vMin, vMax; + + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); + //seems it does this also with a patch with valid dimensions.. but probably better to enforce a brush. + if (!Node_isBrush(instance.path().top())) { + //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK); + globalErrorStream() << "bobToolz PitBuilder: No brush selected, select ONLY 1 brush.\n"; + return; + } + + VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin); + VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax); + + DShape pit; + + if (pit.BuildPit(vMin, vMax)) { + pit.Commit(); + Path_deleteTop(instance.path()); + } else { + //DoMessageBox("Failed To Make Pit\nTry Making The Brush Bigger", "Error", eMB_OK); + globalErrorStream() << "bobToolz PitBuilder: Failed to make Pit, try making the brush bigger.\n"; + } } -void DoMergePatches(){ - UndoableCommand undo( "bobToolz.mergePatches" ); - patch_merge_t merge_info; - DPatch mrgPatches[2]; - int i; - - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 2 ) { - globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose 2 only.\n"; - //DoMessageBox("Invalid number of patches selected, choose 2 only", "Error", eMB_OK); - return; - } - - scene::Instance* patches[2]; - patches[0] = &GlobalSelectionSystem().ultimateSelected(); - patches[1] = &GlobalSelectionSystem().penultimateSelected(); - - for ( i = 0; i < 2; i++ ) - { - if ( !Node_isPatch( patches[i]->path().top() ) ) { - //DoMessageBox("No patches selected, select ONLY patches", "Error", eMB_OK); - globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose ONLY 2 patches.\n"; - return; - } - - mrgPatches[i].LoadFromPatch( *patches[i] ); - } - - /* mrgPatches[0].Transpose(); - mrgPatches[0].RemoveFromRadiant(); - mrgPatches[0].BuildInRadiant();*/ - - merge_info = mrgPatches[0].IsMergable( &mrgPatches[1] ); - - if ( merge_info.mergable ) { - globalOutputStream() << merge_info.pos1 << " " << merge_info.pos2; - //Message removed, No tools give feedback on success. - //globalOutputStream() << "bobToolz MergePatches: Patches Mergable.\n"; - DPatch* newPatch = mrgPatches[0].MergePatches( merge_info, &mrgPatches[0], &mrgPatches[1] ); - - /* mrgPatches[0].RemoveFromRadiant(); - mrgPatches[0].BuildInRadiant(); - - mrgPatches[1].RemoveFromRadiant(); - mrgPatches[1].BuildInRadiant(); - - - delete newPatch;*/ - - if ( !newPatch ) { - } - else - { - Path_deleteTop( patches[0]->path() ); - Path_deleteTop( patches[1]->path() ); - - newPatch->BuildInRadiant(); - delete newPatch; - } - } - else - { - globalErrorStream() << "bobToolz.mergePatch: The selected patches are not mergable.\n"; - - } +void DoMergePatches() +{ + UndoableCommand undo("bobToolz.mergePatches"); + patch_merge_t merge_info; + DPatch mrgPatches[2]; + int i; + + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 2) { + globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose 2 only.\n"; + //DoMessageBox("Invalid number of patches selected, choose 2 only", "Error", eMB_OK); + return; + } + + scene::Instance *patches[2]; + patches[0] = &GlobalSelectionSystem().ultimateSelected(); + patches[1] = &GlobalSelectionSystem().penultimateSelected(); + + for (i = 0; i < 2; i++) { + if (!Node_isPatch(patches[i]->path().top())) { + //DoMessageBox("No patches selected, select ONLY patches", "Error", eMB_OK); + globalErrorStream() + << "bobToolz MergePatches: Invalid number of patches selected, choose ONLY 2 patches.\n"; + return; + } + + mrgPatches[i].LoadFromPatch(*patches[i]); + } + + /* mrgPatches[0].Transpose(); + mrgPatches[0].RemoveFromRadiant(); + mrgPatches[0].BuildInRadiant();*/ + + merge_info = mrgPatches[0].IsMergable(&mrgPatches[1]); + + if (merge_info.mergable) { + globalOutputStream() << merge_info.pos1 << " " << merge_info.pos2; + //Message removed, No tools give feedback on success. + //globalOutputStream() << "bobToolz MergePatches: Patches Mergable.\n"; + DPatch *newPatch = mrgPatches[0].MergePatches(merge_info, &mrgPatches[0], &mrgPatches[1]); + + /* mrgPatches[0].RemoveFromRadiant(); + mrgPatches[0].BuildInRadiant(); + + mrgPatches[1].RemoveFromRadiant(); + mrgPatches[1].BuildInRadiant(); + + + delete newPatch;*/ + + if (!newPatch) { + } else { + Path_deleteTop(patches[0]->path()); + Path_deleteTop(patches[1]->path()); + + newPatch->BuildInRadiant(); + delete newPatch; + } + } else { + globalErrorStream() << "bobToolz.mergePatch: The selected patches are not mergable.\n"; + + } } -void DoSplitPatch() { - UndoableCommand undo( "bobToolz.splitPatch" ); +void DoSplitPatch() +{ + UndoableCommand undo("bobToolz.splitPatch"); - DPatch patch; + DPatch patch; - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 1 ) { - //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK); - globalErrorStream() << "bobToolz SplitPatch: Invalid number of patches selected, choose only 1 patch.\n"; - return; - } + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 1) { + //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK); + globalErrorStream() << "bobToolz SplitPatch: Invalid number of patches selected, choose only 1 patch.\n"; + return; + } - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); - if ( !Node_isPatch( instance.path().top() ) ) { - //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK); - globalErrorStream() << "bobToolz SplitPatch: No patch selected, select ONLY 1 patch.\n"; - return; - } + if (!Node_isPatch(instance.path().top())) { + //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK); + globalErrorStream() << "bobToolz SplitPatch: No patch selected, select ONLY 1 patch.\n"; + return; + } - patch.LoadFromPatch( instance ); + patch.LoadFromPatch(instance); - std::list patchList = patch.Split(); - for ( std::list::iterator patches = patchList.begin(); patches != patchList.end(); patches++ ) { - ( *patches ).BuildInRadiant(); - } + std::list patchList = patch.Split(); + for (std::list::iterator patches = patchList.begin(); patches != patchList.end(); patches++) { + (*patches).BuildInRadiant(); + } - Path_deleteTop( instance.path() ); + Path_deleteTop(instance.path()); } -void DoSplitPatchCols() { - UndoableCommand undo( "bobToolz.splitPatchCols" ); +void DoSplitPatchCols() +{ + UndoableCommand undo("bobToolz.splitPatchCols"); - DPatch patch; + DPatch patch; - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 1 ) { - //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK); - globalErrorStream() << "bobToolz SplitPatchCols: Invalid number of patches selected, choose 1 only.\n"; - return; - } + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 1) { + //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK); + globalErrorStream() << "bobToolz SplitPatchCols: Invalid number of patches selected, choose 1 only.\n"; + return; + } - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); - if ( !Node_isPatch( instance.path().top() ) ) { - //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK); - globalErrorStream() << "bobToolz SplitPatchCols: No patch selected, select ONLY 1 patch.\n"; - return; - } + if (!Node_isPatch(instance.path().top())) { + //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK); + globalErrorStream() << "bobToolz SplitPatchCols: No patch selected, select ONLY 1 patch.\n"; + return; + } - patch.LoadFromPatch( instance ); + patch.LoadFromPatch(instance); - std::list patchList = patch.SplitCols(); - for ( std::list::iterator patches = patchList.begin(); patches != patchList.end(); patches++ ) { - ( *patches ).BuildInRadiant(); - } + std::list patchList = patch.SplitCols(); + for (std::list::iterator patches = patchList.begin(); patches != patchList.end(); patches++) { + (*patches).BuildInRadiant(); + } - Path_deleteTop( instance.path() ); + Path_deleteTop(instance.path()); } -void DoSplitPatchRows() { - UndoableCommand undo( "bobToolz.splitPatchRows" ); +void DoSplitPatchRows() +{ + UndoableCommand undo("bobToolz.splitPatchRows"); - DPatch patch; + DPatch patch; - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 1 ) { - //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK); - globalErrorStream() << "bobToolz SplitPatchRows: Invalid number of patches selected, choose 1 only.\n"; - return; - } + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 1) { + //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK); + globalErrorStream() << "bobToolz SplitPatchRows: Invalid number of patches selected, choose 1 only.\n"; + return; + } - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); - if ( !Node_isPatch( instance.path().top() ) ) { - //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK); - globalErrorStream() << "bobToolz SplitPatchRows: No patch selected, select ONLY 1 patch.\n"; - return; - } + if (!Node_isPatch(instance.path().top())) { + //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK); + globalErrorStream() << "bobToolz SplitPatchRows: No patch selected, select ONLY 1 patch.\n"; + return; + } - patch.LoadFromPatch( instance ); + patch.LoadFromPatch(instance); - std::list patchList = patch.SplitRows(); - for ( std::list::iterator patches = patchList.begin(); patches != patchList.end(); patches++ ) { - ( *patches ).BuildInRadiant(); - } + std::list patchList = patch.SplitRows(); + for (std::list::iterator patches = patchList.begin(); patches != patchList.end(); patches++) { + (*patches).BuildInRadiant(); + } - Path_deleteTop( instance.path() ); + Path_deleteTop(instance.path()); } -void DoVisAnalyse(){ - char filename[1024]; - - if ( GlobalSelectionSystem().countSelected() == 0 ) { - globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n"; - if ( g_VisView ) { - delete g_VisView; - return; - } - } - - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 1 ) { - //DoMessageBox("Invalid number of objects selected, choose 1 only", "Error", eMB_OK); - globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n"; - return; - } - - scene::Instance& brush = GlobalSelectionSystem().ultimateSelected(); - //ensure we have a brush selected - if ( !Node_isBrush( brush.path().top() ) ) { - //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK); - globalErrorStream() << "bobToolz VisAnalyse: No brush selected, select ONLY 1 brush.\n"; - return; - } - DBrush orgBrush; - orgBrush.LoadFromBrush( brush, false ); - - orgBrush.BuildBounds(); - vec3_t origin; - origin[0] = ( orgBrush.bbox_max[0] + orgBrush.bbox_min[0] ) / 2.f; - origin[1] = ( orgBrush.bbox_max[1] + orgBrush.bbox_min[1] ) / 2.f; - origin[2] = ( orgBrush.bbox_max[2] + orgBrush.bbox_min[2] ) / 2.f; - - - const char* rad_filename = GlobalRadiant().getMapName(); - if ( !rad_filename ) { - //DoMessageBox("An ERROR occurred while trying\n to get the map filename", "Error", eMB_OK); - globalErrorStream() << "bobToolz VisAnalyse: An ERROR occurred while trying to get the map filename.\n"; - return; - } - - strcpy( filename, rad_filename ); - - char* ext = strrchr( filename, '.' ) + 1; - strcpy( ext, "bsp" ); // rename the extension - - std::list *pointList = BuildTrace( filename, origin ); - - if ( !g_VisView ) { - g_VisView = new DVisDrawer; - } - - g_VisView->SetList( pointList ); +void DoVisAnalyse() +{ + char filename[1024]; + + if (GlobalSelectionSystem().countSelected() == 0) { + globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n"; + if (g_VisView) { + delete g_VisView; + return; + } + } + + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 1) { + //DoMessageBox("Invalid number of objects selected, choose 1 only", "Error", eMB_OK); + globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n"; + return; + } + + scene::Instance &brush = GlobalSelectionSystem().ultimateSelected(); + //ensure we have a brush selected + if (!Node_isBrush(brush.path().top())) { + //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK); + globalErrorStream() << "bobToolz VisAnalyse: No brush selected, select ONLY 1 brush.\n"; + return; + } + DBrush orgBrush; + orgBrush.LoadFromBrush(brush, false); + + orgBrush.BuildBounds(); + vec3_t origin; + origin[0] = (orgBrush.bbox_max[0] + orgBrush.bbox_min[0]) / 2.f; + origin[1] = (orgBrush.bbox_max[1] + orgBrush.bbox_min[1]) / 2.f; + origin[2] = (orgBrush.bbox_max[2] + orgBrush.bbox_min[2]) / 2.f; + + + const char *rad_filename = GlobalRadiant().getMapName(); + if (!rad_filename) { + //DoMessageBox("An ERROR occurred while trying\n to get the map filename", "Error", eMB_OK); + globalErrorStream() << "bobToolz VisAnalyse: An ERROR occurred while trying to get the map filename.\n"; + return; + } + + strcpy(filename, rad_filename); + + char *ext = strrchr(filename, '.') + 1; + strcpy(ext, "bsp"); // rename the extension + + std::list *pointList = BuildTrace(filename, origin); + + if (!g_VisView) { + g_VisView = new DVisDrawer; + } + + g_VisView->SetList(pointList); } -void DoTrainPathPlot() { - if ( g_TrainView ) { - delete g_TrainView; - g_TrainView = NULL; - } +void DoTrainPathPlot() +{ + if (g_TrainView) { + delete g_TrainView; + g_TrainView = NULL; + } - g_TrainView = new DTrainDrawer(); + g_TrainView = new DTrainDrawer(); } -void DoCaulkSelection() { - UndoableCommand undo( "bobToolz.caulkSelection" ); - DEntity world; +void DoCaulkSelection() +{ + UndoableCommand undo("bobToolz.caulkSelection"); + DEntity world; - float fScale[2] = { 0.5f, 0.5f }; - float fShift[2] = { 0.0f, 0.0f }; + float fScale[2] = {0.5f, 0.5f}; + float fShift[2] = {0.0f, 0.0f}; - int bResetScale[2] = { false, false }; - int bResetShift[2] = { false, false }; + int bResetScale[2] = {false, false}; + int bResetShift[2] = {false, false}; - world.LoadSelectedBrushes(); - world.LoadSelectedPatches(); - world.ResetTextures( NULL, fScale, fShift, 0, "textures/common/caulk", true, bResetScale, bResetShift, false, true ); + world.LoadSelectedBrushes(); + world.LoadSelectedPatches(); + world.ResetTextures(NULL, fScale, fShift, 0, "textures/common/caulk", true, bResetScale, bResetShift, false, true); } -void DoTreePlanter() { - UndoableCommand undo( "bobToolz.treePlanter" ); - if ( g_TreePlanter ) { - delete g_TreePlanter; - g_TreePlanter = NULL; - return; - } +void DoTreePlanter() +{ + UndoableCommand undo("bobToolz.treePlanter"); + if (g_TreePlanter) { + delete g_TreePlanter; + g_TreePlanter = NULL; + return; + } - g_TreePlanter = new DTreePlanter(); + g_TreePlanter = new DTreePlanter(); } -void DoDropEnts() { - UndoableCommand undo( "bobToolz.dropEntities" ); - if ( g_TreePlanter ) { - g_TreePlanter->DropEntsToGround(); - } +void DoDropEnts() +{ + UndoableCommand undo("bobToolz.dropEntities"); + if (g_TreePlanter) { + g_TreePlanter->DropEntsToGround(); + } } -void DoMakeChain() { - MakeChainRS rs; - if ( DoMakeChainBox( &rs ) == eIDOK ) { - if ( rs.linkNum > 1001 ) { - globalErrorStream() << "bobToolz MakeChain: " << rs.linkNum << " to many Elemets, limited to 1000.\n"; - return; - } - UndoableCommand undo( "bobToolz.makeChain" ); - DTreePlanter pl; - pl.MakeChain( rs.linkNum,rs.linkName ); - } +void DoMakeChain() +{ + MakeChainRS rs; + if (DoMakeChainBox(&rs) == eIDOK) { + if (rs.linkNum > 1001) { + globalErrorStream() << "bobToolz MakeChain: " << rs.linkNum << " to many Elemets, limited to 1000.\n"; + return; + } + UndoableCommand undo("bobToolz.makeChain"); + DTreePlanter pl; + pl.MakeChain(rs.linkNum, rs.linkName); + } } -typedef DPoint* pntTripple[3]; +typedef DPoint *pntTripple[3]; bool bFacesNoTop[6] = {true, true, true, true, true, false}; -void DoFlipTerrain() { - UndoableCommand undo( "bobToolz.flipTerrain" ); - vec3_t vUp = { 0.f, 0.f, 1.f }; - int i; - - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 2 ) { - //DoMessageBox("Invalid number of objects selected, choose 2 only", "Error", eMB_OK); - globalErrorStream() << "bobToolz FlipTerrain: Invalid number of objects selected, choose 2 only.\n"; - return; - } - - scene::Instance* brushes[2]; - brushes[0] = &GlobalSelectionSystem().ultimateSelected(); - brushes[1] = &GlobalSelectionSystem().penultimateSelected(); - //ensure we have only Brushes selected. - for ( i = 0; i < 2; i++ ) - { - if ( !Node_isBrush( brushes[i]->path().top() ) ) { - //DoMessageBox("No brushes selected, select ONLY brushes", "Error", eMB_OK); - globalErrorStream() << "bobToolz FlipTerrain: No brushes selected, select ONLY 2 brushes.\n"; - return; - } - } - DBrush Brushes[2]; - DPlane* Planes[2]; - pntTripple Points[2]; - for ( i = 0; i < 2; i++ ) { - Brushes[i].LoadFromBrush( *brushes[i], false ); - if ( !( Planes[i] = Brushes[i].FindPlaneWithClosestNormal( vUp ) ) || Brushes[i].FindPointsForPlane( Planes[i], Points[i], 3 ) != 3 ) { - //DoMessageBox("Error", "Error", eMB_OK); - globalErrorStream() << "bobToolz FlipTerrain: ERROR (FindPlaneWithClosestNormal/FindPointsForPlane).\n"; - return; - } - } - - vec3_t mins1, mins2, maxs1, maxs2; - Brushes[0].GetBounds( mins1, maxs1 ); - Brushes[1].GetBounds( mins2, maxs2 ); - - - - int dontmatch[2] = { -1, -1 }; - bool found = false; - for ( i = 0; i < 3; i++ ) { - for ( int j = 0; j < 3 && !found; j++ ) { - if ( VectorCompare( ( Points[0] )[i]->_pnt, ( Points[1] )[j]->_pnt ) ) { - found = true; - break; - } - } - if ( !found ) { - dontmatch[0] = i; - break; - } - found = false; - } - if ( dontmatch[0] == -1 ) { - //DoMessageBox("Error", "Error", eMB_OK); - globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[0]).\n"; - return; - } - - for ( i = 0; i < 3; i++ ) { - for ( int j = 0; j < 3 && !found; j++ ) { - if ( VectorCompare( ( Points[1] )[i]->_pnt, ( Points[0] )[j]->_pnt ) ) { - found = true; - break; - } - } - if ( !found ) { - dontmatch[1] = i; - break; - } - found = false; - } - if ( dontmatch[1] == -1 ) { - //DoMessageBox("Error", "Error", eMB_OK); - globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[1]).\n"; - return; - } - - vec3_t plnpnts1[3]; - vec3_t plnpnts2[3]; - vec3_t plnpntsshr[3]; - - VectorCopy( ( Points[0] )[dontmatch[0]]->_pnt, plnpnts1[0] ); - for ( i = 0; i < 3; i++ ) { - if ( dontmatch[0] != i ) { - VectorCopy( ( Points[0] )[i]->_pnt, plnpnts1[1] ); - break; - } - } - VectorCopy( ( Points[1] )[dontmatch[1]]->_pnt, plnpnts1[2] ); - - VectorCopy( ( Points[1] )[dontmatch[1]]->_pnt, plnpnts2[0] ); - for ( i = 0; i < 3; i++ ) { - if ( dontmatch[1] != i && !VectorCompare( ( Points[1] )[i]->_pnt, plnpnts1[1] ) ) { - VectorCopy( ( Points[1] )[i]->_pnt, plnpnts2[1] ); - break; - } - } - VectorCopy( ( Points[0] )[dontmatch[0]]->_pnt, plnpnts2[2] ); - - VectorCopy( ( Points[0] )[dontmatch[0]]->_pnt, plnpntsshr[0] ); - VectorCopy( ( Points[1] )[dontmatch[1]]->_pnt, plnpntsshr[1] ); - if ( ( Points[1] )[dontmatch[1]]->_pnt[2] < ( Points[0] )[dontmatch[0]]->_pnt[2] ) { - VectorCopy( ( Points[1] )[dontmatch[1]]->_pnt, plnpntsshr[2] ); - } - else { - VectorCopy( ( Points[0] )[dontmatch[0]]->_pnt, plnpntsshr[2] ); - } - plnpntsshr[2][2] -= 16; - - for ( i = 0; i < 3; i++ ) { - if ( mins2[i] < mins1[i] ) { - mins1[i] = mins2[i]; - } - if ( maxs2[i] > maxs1[i] ) { - maxs1[i] = maxs2[i]; - } - } - - DBrush* newBrushes[2]; - newBrushes[0] = DShape::GetBoundingCube_Ext( mins1, maxs1, "textures/common/caulk", bFacesAll, true ); - newBrushes[1] = DShape::GetBoundingCube_Ext( mins1, maxs1, "textures/common/caulk", bFacesAll, true ); - - vec3_t normal; - MakeNormal( plnpnts1[0], plnpnts1[1], plnpnts1[2], normal ); - if ( normal[2] >= 0 ) { - newBrushes[0]->AddFace( plnpnts1[0], plnpnts1[1], plnpnts1[2], "textures/common/terrain", true ); - } - else { - newBrushes[0]->AddFace( plnpnts1[2], plnpnts1[1], plnpnts1[0], "textures/common/terrain", true ); - } - - MakeNormal( plnpnts2[0], plnpnts2[1], plnpnts2[2], normal ); - if ( normal[2] >= 0 ) { - newBrushes[1]->AddFace( plnpnts2[0], plnpnts2[1], plnpnts2[2], "textures/common/terrain", true ); - } - else { - newBrushes[1]->AddFace( plnpnts2[2], plnpnts2[1], plnpnts2[0], "textures/common/terrain", true ); - } - - vec3_t vec; - MakeNormal( plnpntsshr[0], plnpntsshr[1], plnpntsshr[2], normal ); - - VectorSubtract( plnpnts1[2], plnpnts1[1], vec ); - if ( DotProduct( vec, normal ) >= 0 ) { - newBrushes[0]->AddFace( plnpntsshr[0], plnpntsshr[1], plnpntsshr[2], "textures/common/caulk", true ); - } - else { - newBrushes[0]->AddFace( plnpntsshr[2], plnpntsshr[1], plnpntsshr[0], "textures/common/caulk", true ); - } - - VectorSubtract( plnpnts2[2], plnpnts2[1], vec ); - if ( DotProduct( vec, normal ) >= 0 ) { - newBrushes[1]->AddFace( plnpntsshr[0], plnpntsshr[1], plnpntsshr[2], "textures/common/caulk", true ); - } - else { - newBrushes[1]->AddFace( plnpntsshr[2], plnpntsshr[1], plnpntsshr[0], "textures/common/caulk", true ); - } - - for ( i = 0; i < 2; i++ ) { - newBrushes[i]->RemoveRedundantPlanes(); - newBrushes[i]->BuildInRadiant( false, NULL, brushes[i]->path().parent().get_pointer() ); - Path_deleteTop( brushes[i]->path() ); - delete newBrushes[i]; - } +void DoFlipTerrain() +{ + UndoableCommand undo("bobToolz.flipTerrain"); + vec3_t vUp = {0.f, 0.f, 1.f}; + int i; + + // ensure we have something selected + if (GlobalSelectionSystem().countSelected() != 2) { + //DoMessageBox("Invalid number of objects selected, choose 2 only", "Error", eMB_OK); + globalErrorStream() << "bobToolz FlipTerrain: Invalid number of objects selected, choose 2 only.\n"; + return; + } + + scene::Instance *brushes[2]; + brushes[0] = &GlobalSelectionSystem().ultimateSelected(); + brushes[1] = &GlobalSelectionSystem().penultimateSelected(); + //ensure we have only Brushes selected. + for (i = 0; i < 2; i++) { + if (!Node_isBrush(brushes[i]->path().top())) { + //DoMessageBox("No brushes selected, select ONLY brushes", "Error", eMB_OK); + globalErrorStream() << "bobToolz FlipTerrain: No brushes selected, select ONLY 2 brushes.\n"; + return; + } + } + DBrush Brushes[2]; + DPlane *Planes[2]; + pntTripple Points[2]; + for (i = 0; i < 2; i++) { + Brushes[i].LoadFromBrush(*brushes[i], false); + if (!(Planes[i] = Brushes[i].FindPlaneWithClosestNormal(vUp)) || + Brushes[i].FindPointsForPlane(Planes[i], Points[i], 3) != 3) { + //DoMessageBox("Error", "Error", eMB_OK); + globalErrorStream() << "bobToolz FlipTerrain: ERROR (FindPlaneWithClosestNormal/FindPointsForPlane).\n"; + return; + } + } + + vec3_t mins1, mins2, maxs1, maxs2; + Brushes[0].GetBounds(mins1, maxs1); + Brushes[1].GetBounds(mins2, maxs2); + + + int dontmatch[2] = {-1, -1}; + bool found = false; + for (i = 0; i < 3; i++) { + for (int j = 0; j < 3 && !found; j++) { + if (VectorCompare((Points[0])[i]->_pnt, (Points[1])[j]->_pnt)) { + found = true; + break; + } + } + if (!found) { + dontmatch[0] = i; + break; + } + found = false; + } + if (dontmatch[0] == -1) { + //DoMessageBox("Error", "Error", eMB_OK); + globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[0]).\n"; + return; + } + + for (i = 0; i < 3; i++) { + for (int j = 0; j < 3 && !found; j++) { + if (VectorCompare((Points[1])[i]->_pnt, (Points[0])[j]->_pnt)) { + found = true; + break; + } + } + if (!found) { + dontmatch[1] = i; + break; + } + found = false; + } + if (dontmatch[1] == -1) { + //DoMessageBox("Error", "Error", eMB_OK); + globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[1]).\n"; + return; + } + + vec3_t plnpnts1[3]; + vec3_t plnpnts2[3]; + vec3_t plnpntsshr[3]; + + VectorCopy((Points[0])[dontmatch[0]]->_pnt, plnpnts1[0]); + for (i = 0; i < 3; i++) { + if (dontmatch[0] != i) { + VectorCopy((Points[0])[i]->_pnt, plnpnts1[1]); + break; + } + } + VectorCopy((Points[1])[dontmatch[1]]->_pnt, plnpnts1[2]); + + VectorCopy((Points[1])[dontmatch[1]]->_pnt, plnpnts2[0]); + for (i = 0; i < 3; i++) { + if (dontmatch[1] != i && !VectorCompare((Points[1])[i]->_pnt, plnpnts1[1])) { + VectorCopy((Points[1])[i]->_pnt, plnpnts2[1]); + break; + } + } + VectorCopy((Points[0])[dontmatch[0]]->_pnt, plnpnts2[2]); + + VectorCopy((Points[0])[dontmatch[0]]->_pnt, plnpntsshr[0]); + VectorCopy((Points[1])[dontmatch[1]]->_pnt, plnpntsshr[1]); + if ((Points[1])[dontmatch[1]]->_pnt[2] < (Points[0])[dontmatch[0]]->_pnt[2]) { + VectorCopy((Points[1])[dontmatch[1]]->_pnt, plnpntsshr[2]); + } else { + VectorCopy((Points[0])[dontmatch[0]]->_pnt, plnpntsshr[2]); + } + plnpntsshr[2][2] -= 16; + + for (i = 0; i < 3; i++) { + if (mins2[i] < mins1[i]) { + mins1[i] = mins2[i]; + } + if (maxs2[i] > maxs1[i]) { + maxs1[i] = maxs2[i]; + } + } + + DBrush *newBrushes[2]; + newBrushes[0] = DShape::GetBoundingCube_Ext(mins1, maxs1, "textures/common/caulk", bFacesAll, true); + newBrushes[1] = DShape::GetBoundingCube_Ext(mins1, maxs1, "textures/common/caulk", bFacesAll, true); + + vec3_t normal; + MakeNormal(plnpnts1[0], plnpnts1[1], plnpnts1[2], normal); + if (normal[2] >= 0) { + newBrushes[0]->AddFace(plnpnts1[0], plnpnts1[1], plnpnts1[2], "textures/common/terrain", true); + } else { + newBrushes[0]->AddFace(plnpnts1[2], plnpnts1[1], plnpnts1[0], "textures/common/terrain", true); + } + + MakeNormal(plnpnts2[0], plnpnts2[1], plnpnts2[2], normal); + if (normal[2] >= 0) { + newBrushes[1]->AddFace(plnpnts2[0], plnpnts2[1], plnpnts2[2], "textures/common/terrain", true); + } else { + newBrushes[1]->AddFace(plnpnts2[2], plnpnts2[1], plnpnts2[0], "textures/common/terrain", true); + } + + vec3_t vec; + MakeNormal(plnpntsshr[0], plnpntsshr[1], plnpntsshr[2], normal); + + VectorSubtract(plnpnts1[2], plnpnts1[1], vec); + if (DotProduct(vec, normal) >= 0) { + newBrushes[0]->AddFace(plnpntsshr[0], plnpntsshr[1], plnpntsshr[2], "textures/common/caulk", true); + } else { + newBrushes[0]->AddFace(plnpntsshr[2], plnpntsshr[1], plnpntsshr[0], "textures/common/caulk", true); + } + + VectorSubtract(plnpnts2[2], plnpnts2[1], vec); + if (DotProduct(vec, normal) >= 0) { + newBrushes[1]->AddFace(plnpntsshr[0], plnpntsshr[1], plnpntsshr[2], "textures/common/caulk", true); + } else { + newBrushes[1]->AddFace(plnpntsshr[2], plnpntsshr[1], plnpntsshr[0], "textures/common/caulk", true); + } + + for (i = 0; i < 2; i++) { + newBrushes[i]->RemoveRedundantPlanes(); + newBrushes[i]->BuildInRadiant(false, NULL, brushes[i]->path().parent().get_pointer()); + Path_deleteTop(brushes[i]->path()); + delete newBrushes[i]; + } } diff --git a/contrib/bobtoolz/funchandlers-ctf-GTK.cpp b/contrib/bobtoolz/funchandlers-ctf-GTK.cpp index 637cf5a2..302fcd43 100644 --- a/contrib/bobtoolz/funchandlers-ctf-GTK.cpp +++ b/contrib/bobtoolz/funchandlers-ctf-GTK.cpp @@ -29,8 +29,8 @@ #include "funchandlers.h" // for ctf texture changer -list clrList_Blue; -list clrList_Red; +list clrList_Blue; +list clrList_Red; BOOL clrLst1Loaded = FALSE; BOOL clrLst2Loaded = FALSE; @@ -41,17 +41,18 @@ BOOL clrLst2Loaded = FALSE; // Helper Functions // //========================// -void LoadLists(){ - char buffer[256]; - - if ( !clrLst1Loaded ) { - clrLst1Loaded = LoadExclusionList( GetFilename( buffer, "plugins/bt/ctf-blue.txt" ), &clrList_Blue ); - LoadExclusionList( GetFilename( buffer, "plugins/bt/blue.txt" ), &clrList_Blue ); - } - if ( !clrLst2Loaded ) { - clrLst2Loaded = LoadExclusionList( GetFilename( buffer, "plugins/bt/ctf-red.txt" ), &clrList_Red ); - LoadExclusionList( GetFilename( buffer, "plugins/bt/red.txt" ), &clrList_Red ); - } +void LoadLists() +{ + char buffer[256]; + + if (!clrLst1Loaded) { + clrLst1Loaded = LoadExclusionList(GetFilename(buffer, "plugins/bt/ctf-blue.txt"), &clrList_Blue); + LoadExclusionList(GetFilename(buffer, "plugins/bt/blue.txt"), &clrList_Blue); + } + if (!clrLst2Loaded) { + clrLst2Loaded = LoadExclusionList(GetFilename(buffer, "plugins/bt/ctf-red.txt"), &clrList_Red); + LoadExclusionList(GetFilename(buffer, "plugins/bt/red.txt"), &clrList_Red); + } } @@ -59,49 +60,48 @@ void LoadLists(){ // Main Functions // //========================// -void DoCTFColourChanger(){ - if ( !clrLst1Loaded || !clrLst2Loaded ) { - DoMessageBox( "CTF texture lists not found, this function will terminate.", "Error", MB_OK ); - return; - } - - int ret = DoCTFColourChangeBox(); - if ( ret == IDCANCEL ) { - return; - } +void DoCTFColourChanger() +{ + if (!clrLst1Loaded || !clrLst2Loaded) { + DoMessageBox("CTF texture lists not found, this function will terminate.", "Error", MB_OK); + return; + } - int cnt = Min( clrList_Blue.size(), clrList_Red.size() ); + int ret = DoCTFColourChangeBox(); + if (ret == IDCANCEL) { + return; + } - list::const_iterator Texture_change; - list::const_iterator Texture_new; + int cnt = Min(clrList_Blue.size(), clrList_Red.size()); - float fDummy[2]; + list::const_iterator Texture_change; + list::const_iterator Texture_new; - int eCnt = g_FuncTable.m_pfnGetEntityCount(); + float fDummy[2]; - DMap world; - world.LoadAll( TRUE ); + int eCnt = g_FuncTable.m_pfnGetEntityCount(); - if ( ret == IDYES ) { - Texture_change = clrList_Blue.begin(); - Texture_new = clrList_Red.begin(); - } - else - { - Texture_change = clrList_Red.begin(); - Texture_new = clrList_Blue.begin(); - } + DMap world; + world.LoadAll(TRUE); + + if (ret == IDYES) { + Texture_change = clrList_Blue.begin(); + Texture_new = clrList_Red.begin(); + } else { + Texture_change = clrList_Red.begin(); + Texture_new = clrList_Blue.begin(); + } - for ( int i = 0; i < cnt; i++ ) - { - world.ResetTextures( ( *Texture_change ).c_str(), fDummy, fDummy, 0, ( *Texture_new ).c_str(), TRUE ); + for (int i = 0; i < cnt; i++) { + world.ResetTextures((*Texture_change).c_str(), fDummy, fDummy, 0, (*Texture_new).c_str(), TRUE); - Texture_change++; - Texture_new++; - } + Texture_change++; + Texture_new++; + } } -void DoSwapLights(){ +void DoSwapLights() +{ /* DMap world; world.LoadAll(); @@ -118,85 +118,77 @@ void DoSwapLights(){ } }*/ - int cnt = g_FuncTable.m_pfnGetEntityCount(); - - for ( int i = 0; i < cnt; i++ ) - { - void* ent = g_FuncTable.m_pfnGetEntityHandle( i ); - - for ( epair_t* epList = *g_FuncTable.m_pfnGetEntityKeyValList( ent ); epList; epList = epList->next ) - { - if ( !stricmp( "_color", epList->key ) ) { - float r, g, b; - sscanf( epList->value, "%f %f %f", &r, &g, &b ); - sprintf( epList->value, "%f %f %f", b, g, r ); - } - } - } + int cnt = g_FuncTable.m_pfnGetEntityCount(); + + for (int i = 0; i < cnt; i++) { + void *ent = g_FuncTable.m_pfnGetEntityHandle(i); + + for (epair_t *epList = *g_FuncTable.m_pfnGetEntityKeyValList(ent); epList; epList = epList->next) { + if (!stricmp("_color", epList->key)) { + float r, g, b; + sscanf(epList->value, "%f %f %f", &r, &g, &b); + sprintf(epList->value, "%f %f %f", b, g, r); + } + } + } } -void DoChangeAngles(){ - int cnt = g_FuncTable.m_pfnGetEntityCount(); - - for ( int i = 0; i < cnt; i++ ) - { - void* ent = g_FuncTable.m_pfnGetEntityHandle( i ); - - for ( epair_t* epList = *g_FuncTable.m_pfnGetEntityKeyValList( ent ); epList; epList = epList->next ) - { - if ( !stricmp( "angle", epList->key ) ) { - float angle; - sscanf( epList->value, "%f", &angle ); - angle += 180; - while ( angle > 360 ) - angle -= 360; - - sprintf( epList->value, "%f", angle ); - } - } - } +void DoChangeAngles() +{ + int cnt = g_FuncTable.m_pfnGetEntityCount(); + + for (int i = 0; i < cnt; i++) { + void *ent = g_FuncTable.m_pfnGetEntityHandle(i); + + for (epair_t *epList = *g_FuncTable.m_pfnGetEntityKeyValList(ent); epList; epList = epList->next) { + if (!stricmp("angle", epList->key)) { + float angle; + sscanf(epList->value, "%f", &angle); + angle += 180; + while (angle > 360) { + angle -= 360; + } + + sprintf(epList->value, "%f", angle); + } + } + } } -void DoSwapSpawns(){ - int cnt = g_FuncTable.m_pfnGetEntityCount(); - - for ( int i = 0; i < cnt; i++ ) - { - void* ent = g_FuncTable.m_pfnGetEntityHandle( i ); - - for ( epair_t* epList = *g_FuncTable.m_pfnGetEntityKeyValList( ent ); epList; epList = epList->next ) - { - if ( !stricmp( "classname", epList->key ) ) { - if ( !strcmp( epList->value, "team_CTF_redplayer" ) ) { - sprintf( epList->value, "team_CTF_blueplayer" ); - } - else if ( !strcmp( epList->value, "team_CTF_blueplayer" ) ) { - sprintf( epList->value, "team_CTF_redplayer" ); - } - - if ( !strcmp( epList->value, "team_CTF_redspawn" ) ) { - sprintf( epList->value, "team_CTF_bluespawn" ); - } - else if ( !strcmp( epList->value, "team_CTF_bluespawn" ) ) { - sprintf( epList->value, "team_CTF_redspawn" ); - } - - if ( !strcmp( epList->value, "team_CTF_redflag" ) ) { - sprintf( epList->value, "team_CTF_blueflag" ); - } - else if ( !strcmp( epList->value, "team_CTF_blueflag" ) ) { - sprintf( epList->value, "team_CTF_redflag" ) - ; - } - if ( !strcmp( epList->value, "team_redobelisk" ) ) { - sprintf( epList->value, "team_blueobelisk" ); - } - else if ( !strcmp( epList->value, "team_blueobelisk" ) ) { - sprintf( epList->value, "team_redobelisk" ); - } - } - } - } +void DoSwapSpawns() +{ + int cnt = g_FuncTable.m_pfnGetEntityCount(); + + for (int i = 0; i < cnt; i++) { + void *ent = g_FuncTable.m_pfnGetEntityHandle(i); + + for (epair_t *epList = *g_FuncTable.m_pfnGetEntityKeyValList(ent); epList; epList = epList->next) { + if (!stricmp("classname", epList->key)) { + if (!strcmp(epList->value, "team_CTF_redplayer")) { + sprintf(epList->value, "team_CTF_blueplayer"); + } else if (!strcmp(epList->value, "team_CTF_blueplayer")) { + sprintf(epList->value, "team_CTF_redplayer"); + } + + if (!strcmp(epList->value, "team_CTF_redspawn")) { + sprintf(epList->value, "team_CTF_bluespawn"); + } else if (!strcmp(epList->value, "team_CTF_bluespawn")) { + sprintf(epList->value, "team_CTF_redspawn"); + } + + if (!strcmp(epList->value, "team_CTF_redflag")) { + sprintf(epList->value, "team_CTF_blueflag"); + } else if (!strcmp(epList->value, "team_CTF_blueflag")) { + sprintf(epList->value, "team_CTF_redflag"); + } + if (!strcmp(epList->value, "team_redobelisk")) { + sprintf(epList->value, "team_blueobelisk"); + } else if (!strcmp(epList->value, "team_blueobelisk")) { + sprintf(epList->value, "team_redobelisk"); + } + } + } + } } /*void test() diff --git a/contrib/bobtoolz/funchandlers.cpp b/contrib/bobtoolz/funchandlers.cpp index 2a404211..9242cc56 100644 --- a/contrib/bobtoolz/funchandlers.cpp +++ b/contrib/bobtoolz/funchandlers.cpp @@ -39,13 +39,13 @@ #include "DShape.h" // for autocaulk -std::list exclusionList; // whole brush exclusion -std::list exclusionList_Face; // single face exclusion +std::list exclusionList; // whole brush exclusion +std::list exclusionList_Face; // single face exclusion BOOL el1Loaded; BOOL el2Loaded; -DBobView* g_PathView = NULL; +DBobView *g_PathView = NULL; // ------------- /************************ @@ -64,440 +64,433 @@ CPathPlotterDialog ppDlg; --Main Functions-- ************************/ -void LoadLists(){ - char buffer[256]; +void LoadLists() +{ + char buffer[256]; - if ( !el1Loaded ) { - el1Loaded = LoadExclusionList( GetFilename( buffer, "bt\\bt-el1.txt" ), &exclusionList ); - } - if ( !el2Loaded ) { - el2Loaded = LoadExclusionList( GetFilename( buffer, "bt\\bt-el2.txt" ), &exclusionList ); - } + if (!el1Loaded) { + el1Loaded = LoadExclusionList(GetFilename(buffer, "bt\\bt-el1.txt"), &exclusionList); + } + if (!el2Loaded) { + el2Loaded = LoadExclusionList(GetFilename(buffer, "bt\\bt-el2.txt"), &exclusionList); + } } -void PolygonBuilder( vec3_t vMin, vec3_t vMax ){ - // ensure we have something selected - if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) { - MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK ); - return; - } +void PolygonBuilder(vec3_t vMin, vec3_t vMax) +{ + // ensure we have something selected + if (g_FuncTable.m_pfnSelectedBrushCount() != 1) { + MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK); + return; + } - // tell Radiant we want to access the selected brushes - g_FuncTable.m_pfnAllocateSelectedBrushHandles(); + // tell Radiant we want to access the selected brushes + g_FuncTable.m_pfnAllocateSelectedBrushHandles(); - // get handle to size definition brush - brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 ); - // cant release until we delete the brush, if we do... + // get handle to size definition brush + brush_t *brush = (brush_t *) g_FuncTable.m_pfnGetSelectedBrushHandle(0); + // cant release until we delete the brush, if we do... - // ask user for type, size, etc.... - if ( polygonDlg.DoModal() == IDOK ) { - DShape poly; + // ask user for type, size, etc.... + if (polygonDlg.DoModal() == IDOK) { + DShape poly; - g_FuncTable.m_pfnDeleteBrushHandle( brush ); + g_FuncTable.m_pfnDeleteBrushHandle(brush); - if ( polygonDlg.m_bInverse ) { - poly.BuildInversePrism( vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop ); - } - else - { - if ( polygonDlg.m_bBorder ) { - poly.BuildBorderedPrism( vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_nBorderSize, polygonDlg.m_bAlignTop ); - } - else{ - poly.BuildRegularPrism( vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop ); - } - } + if (polygonDlg.m_bInverse) { + poly.BuildInversePrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop); + } else { + if (polygonDlg.m_bBorder) { + poly.BuildBorderedPrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_nBorderSize, + polygonDlg.m_bAlignTop); + } else { + poly.BuildRegularPrism(vMin, vMax, polygonDlg.m_nSideCount, polygonDlg.m_bAlignTop); + } + } - poly.Commit(); - } + poly.Commit(); + } - g_FuncTable.m_pfnReleaseSelectedBrushHandles(); + g_FuncTable.m_pfnReleaseSelectedBrushHandles(); } -void IntersectionFinder(){ - if ( intrDlg.DoModal() == IDCANCEL ) { - return; - } - - if ( intrDlg.m_nBrushOptions == BRUSH_OPT_SELECTED ) { - // ensure we have enough brushes selected - if ( g_FuncTable.m_pfnSelectedBrushCount() < 2 ) { - MessageBox( NULL, "Invalid number of brushes selected, choose at least 2", "Error", MB_OK ); - return; - } - } - - CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog(); - intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG ); - - DEntity world; - - switch ( intrDlg.m_nBrushOptions ) - { - case BRUSH_OPT_SELECTED: - { - world.LoadSelectedBrushes( &intrInfoDlg->m_prog1 ); - break; - } - case BRUSH_OPT_WHOLE_MAP: - { - world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 ); - break; - } - } - - world.RemoveNonCheckBrushes( &exclusionList, intrDlg.m_bUseDetail ); - BOOL* pbSelectList; - if ( intrDlg.m_bDuplicateOnly ) { - pbSelectList = world.BuildDuplicateList(); - } - else{ - pbSelectList = world.BuildIntersectList(); - } - - world.SelectBrushes( pbSelectList ); - - intrInfoDlg->DestroyWindow(); - delete[] pbSelectList; +void IntersectionFinder() +{ + if (intrDlg.DoModal() == IDCANCEL) { + return; + } + + if (intrDlg.m_nBrushOptions == BRUSH_OPT_SELECTED) { + // ensure we have enough brushes selected + if (g_FuncTable.m_pfnSelectedBrushCount() < 2) { + MessageBox(NULL, "Invalid number of brushes selected, choose at least 2", "Error", MB_OK); + return; + } + } + + CIntersectInfoDialog *intrInfoDlg = new CIntersectInfoDialog(); + intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG); + + DEntity world; + + switch (intrDlg.m_nBrushOptions) { + case BRUSH_OPT_SELECTED: { + world.LoadSelectedBrushes(&intrInfoDlg->m_prog1); + break; + } + case BRUSH_OPT_WHOLE_MAP: { + world.LoadFromEntity(0, &intrInfoDlg->m_prog1); + break; + } + } + + world.RemoveNonCheckBrushes(&exclusionList, intrDlg.m_bUseDetail); + BOOL *pbSelectList; + if (intrDlg.m_bDuplicateOnly) { + pbSelectList = world.BuildDuplicateList(); + } else { + pbSelectList = world.BuildIntersectList(); + } + + world.SelectBrushes(pbSelectList); + + intrInfoDlg->DestroyWindow(); + delete[] pbSelectList; } -void StairBuilder( vec3_t vMin, vec3_t vMax ){ - // ensure we have something selected - if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) { - MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK ); - return; - } - - // tell Radiant we want to access the selected brushes - g_FuncTable.m_pfnAllocateSelectedBrushHandles(); - - // get handle to size definition brush - brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 ); - // cant release until we delete the brush, if we do... - - - // ask user for type, size, etc.... - if ( stairDlg.DoModal() == IDOK ) { - - // calc brush size - vec3_t size; - _VectorSubtract( vMax, vMin, size ); - - - if ( ( (int)size[2] % stairDlg.m_nStairHeight ) != 0 ) { - // stairs must fit evenly into brush - MessageBox( NULL, "Invalid stair height\nHeight of block must be divisable by stair height", "Error", MB_OK ); - } - else - { - - // Remove Size Brush - g_FuncTable.m_pfnDeleteBrushHandle( brush ); - - - // Get Step Count, Direction of Stairs, Stair Style - int numSteps = (int)size[2] / stairDlg.m_nStairHeight; - int direction = stairDlg.m_StairDir; - int style = stairDlg.m_StairStyle; - - if ( stairDlg.m_StairStyle == STYLE_CORNER ) { - BuildCornerStairs( vMin, vMax, numSteps, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture ); - } - else - { - // Get Step Dimensions - float stairHeight = (float)stairDlg.m_nStairHeight; - float stairWidth; - if ( ( direction == MOVE_EAST ) || ( direction == MOVE_WEST ) ) { - stairWidth = ( size[0] ) / numSteps; - } - else{ - stairWidth = ( size[1] ) / numSteps; - } - - - // Build Base For Stair (bob's style) - if ( style == STYLE_BOB ) { - Build_Wedge( direction, vMin, vMax, TRUE ); - } - - - // Set First Step Starting Position - vMax[2] = vMin[2] + stairHeight; - SetInitialStairPos( direction, vMin, vMax, stairWidth ); - - - // Build The Steps - for ( int i = 0; i < numSteps; i++ ) - { - if ( style == STYLE_BOB ) { - Build_StairStep_Wedge( direction, vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, stairDlg.m_bDetail ); - } - else if ( style == STYLE_ORIGINAL ) { - Build_StairStep( vMin, vMax, "textures/common/caulk", (LPCTSTR)stairDlg.m_riserTexture, direction ); - } - - // get step into next position - MoveBlock( direction, vMin, vMax, stairWidth ); - vMax[2] += stairHeight; - if ( style == STYLE_BOB ) { - vMin[2] += stairHeight; // wedge bottom must be raised - } - } - } - } - } - - g_FuncTable.m_pfnReleaseSelectedBrushHandles(); +void StairBuilder(vec3_t vMin, vec3_t vMax) +{ + // ensure we have something selected + if (g_FuncTable.m_pfnSelectedBrushCount() != 1) { + MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK); + return; + } + + // tell Radiant we want to access the selected brushes + g_FuncTable.m_pfnAllocateSelectedBrushHandles(); + + // get handle to size definition brush + brush_t *brush = (brush_t *) g_FuncTable.m_pfnGetSelectedBrushHandle(0); + // cant release until we delete the brush, if we do... + + + // ask user for type, size, etc.... + if (stairDlg.DoModal() == IDOK) { + + // calc brush size + vec3_t size; + _VectorSubtract(vMax, vMin, size); + + + if (((int) size[2] % stairDlg.m_nStairHeight) != 0) { + // stairs must fit evenly into brush + MessageBox(NULL, "Invalid stair height\nHeight of block must be divisable by stair height", "Error", MB_OK); + } else { + + // Remove Size Brush + g_FuncTable.m_pfnDeleteBrushHandle(brush); + + + // Get Step Count, Direction of Stairs, Stair Style + int numSteps = (int) size[2] / stairDlg.m_nStairHeight; + int direction = stairDlg.m_StairDir; + int style = stairDlg.m_StairStyle; + + if (stairDlg.m_StairStyle == STYLE_CORNER) { + BuildCornerStairs(vMin, vMax, numSteps, "textures/common/caulk", (LPCTSTR) stairDlg.m_riserTexture); + } else { + // Get Step Dimensions + float stairHeight = (float) stairDlg.m_nStairHeight; + float stairWidth; + if ((direction == MOVE_EAST) || (direction == MOVE_WEST)) { + stairWidth = (size[0]) / numSteps; + } else { + stairWidth = (size[1]) / numSteps; + } + + + // Build Base For Stair (bob's style) + if (style == STYLE_BOB) { + Build_Wedge(direction, vMin, vMax, TRUE); + } + + + // Set First Step Starting Position + vMax[2] = vMin[2] + stairHeight; + SetInitialStairPos(direction, vMin, vMax, stairWidth); + + + // Build The Steps + for (int i = 0; i < numSteps; i++) { + if (style == STYLE_BOB) { + Build_StairStep_Wedge(direction, vMin, vMax, "textures/common/caulk", + (LPCTSTR) stairDlg.m_riserTexture, stairDlg.m_bDetail); + } else if (style == STYLE_ORIGINAL) { + Build_StairStep(vMin, vMax, "textures/common/caulk", (LPCTSTR) stairDlg.m_riserTexture, + direction); + } + + // get step into next position + MoveBlock(direction, vMin, vMax, stairWidth); + vMax[2] += stairHeight; + if (style == STYLE_BOB) { + vMin[2] += stairHeight; // wedge bottom must be raised + } + } + } + } + } + + g_FuncTable.m_pfnReleaseSelectedBrushHandles(); } -void DoorBuilder( vec3_t vMin, vec3_t vMax ){ - // ensure we have something selected - if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) { - MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK ); - return; - } +void DoorBuilder(vec3_t vMin, vec3_t vMax) +{ + // ensure we have something selected + if (g_FuncTable.m_pfnSelectedBrushCount() != 1) { + MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK); + return; + } - // tell Radiant we want to access the selected brushes - g_FuncTable.m_pfnAllocateSelectedBrushHandles(); + // tell Radiant we want to access the selected brushes + g_FuncTable.m_pfnAllocateSelectedBrushHandles(); - // get handle to size definition brush - brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 ); - // cant release until we delete the brush, if we do... + // get handle to size definition brush + brush_t *brush = (brush_t *) g_FuncTable.m_pfnGetSelectedBrushHandle(0); + // cant release until we delete the brush, if we do... - strcpy( doorDlg.m_fbTextureName.GetBuffer( 256 ), g_FuncTable.m_pfnGetCurrentTexture() ); + strcpy(doorDlg.m_fbTextureName.GetBuffer(256), g_FuncTable.m_pfnGetCurrentTexture()); - if ( doorDlg.DoModal() == IDOK ) { - g_FuncTable.m_pfnDeleteBrushHandle( brush ); + if (doorDlg.DoModal() == IDOK) { + g_FuncTable.m_pfnDeleteBrushHandle(brush); - BuildDoorsX2( vMin, vMax, - doorDlg.m_bSclMainHor, doorDlg.m_bSclMainVert, - doorDlg.m_bSclTrimHor, doorDlg.m_bSclTrimVert, - (LPCTSTR)doorDlg.m_fbTextureName, - (LPCTSTR)doorDlg.m_trimTextureName, - doorDlg.m_doorDirection ); - } + BuildDoorsX2(vMin, vMax, + doorDlg.m_bSclMainHor, doorDlg.m_bSclMainVert, + doorDlg.m_bSclTrimHor, doorDlg.m_bSclTrimVert, + (LPCTSTR) doorDlg.m_fbTextureName, + (LPCTSTR) doorDlg.m_trimTextureName, + doorDlg.m_doorDirection); + } - g_FuncTable.m_pfnReleaseSelectedBrushHandles(); + g_FuncTable.m_pfnReleaseSelectedBrushHandles(); } -void FixBrushes(){ - DEntity world; +void FixBrushes() +{ + DEntity world; - CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog(); - intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG ); + CIntersectInfoDialog *intrInfoDlg = new CIntersectInfoDialog(); + intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG); - world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 ); + world.LoadFromEntity(0, &intrInfoDlg->m_prog1); - intrInfoDlg->DestroyWindow(); + intrInfoDlg->DestroyWindow(); - CBrushCheckDialog* chkDlg = new CBrushCheckDialog(); - chkDlg->Create( IDD_BRUSHCHECKER_DIALOG ); + CBrushCheckDialog *chkDlg = new CBrushCheckDialog(); + chkDlg->Create(IDD_BRUSHCHECKER_DIALOG); - int count = world.FixBrushes( TRUE, &chkDlg->m_prog1 ); + int count = world.FixBrushes(TRUE, &chkDlg->m_prog1); - chkDlg->DestroyWindow(); + chkDlg->DestroyWindow(); - Sys_Printf( "%i invalid/duplicate planes removed\n", count ); + Sys_Printf("%i invalid/duplicate planes removed\n", count); } -void AutoCaulk(){ - UndoableCommand undo( "bobToolz.autoCaulk" ); +void AutoCaulk() +{ + UndoableCommand undo("bobToolz.autoCaulk"); - if ( !el1Loaded ) { - autocaulkDlg.m_Warning1 = "WARNING: Brush exclusion list not found\n, ALL BRUSHES WILL BE USED"; - } + if (!el1Loaded) { + autocaulkDlg.m_Warning1 = "WARNING: Brush exclusion list not found\n, ALL BRUSHES WILL BE USED"; + } - if ( autocaulkDlg.DoModal() == IDCANCEL ) { - return; - } + if (autocaulkDlg.DoModal() == IDCANCEL) { + return; + } - if ( autocaulkDlg.m_nMode == MODE_AC_BUILD_MINI_PRT ) { - BuildMiniPrt( &exclusionList ); - return; - } + if (autocaulkDlg.m_nMode == MODE_AC_BUILD_MINI_PRT) { + BuildMiniPrt(&exclusionList); + return; + } - CAutoCaulkDialog* acDlg = new CAutoCaulkDialog; - acDlg->Create( IDD_AUTOCAULK_DIALOG ); + CAutoCaulkDialog *acDlg = new CAutoCaulkDialog; + acDlg->Create(IDD_AUTOCAULK_DIALOG); - char filename[1204]; + char filename[1204]; - if ( autocaulkDlg.m_nMode == MODE_AC_NORMAL ) { - char* rad_filename = g_BSPTable.m_pfnGetMapName(); - if ( !rad_filename ) { - MessageBox( NULL, "An Error Occurred While Trying To Get The Map Filename", "Error", MB_OK ); - acDlg->DestroyWindow(); - return; - } + if (autocaulkDlg.m_nMode == MODE_AC_NORMAL) { + char *rad_filename = g_BSPTable.m_pfnGetMapName(); + if (!rad_filename) { + MessageBox(NULL, "An Error Occurred While Trying To Get The Map Filename", "Error", MB_OK); + acDlg->DestroyWindow(); + return; + } - strcpy( filename, rad_filename ); + strcpy(filename, rad_filename); - char* ext = strrchr( filename, '.' ) + 1; - strcpy( ext, "prt" ); // rename the extension - } - else - { - IEpair* pEp = g_EpairTable.m_pfnIEpairForProjectKeys(); - char *pn = pEp->ValueForKey( "mapspath" ); - pEp->DecRef(); + char *ext = strrchr(filename, '.') + 1; + strcpy(ext, "prt"); // rename the extension + } else { + IEpair *pEp = g_EpairTable.m_pfnIEpairForProjectKeys(); + char *pn = pEp->ValueForKey("mapspath"); + pEp->DecRef(); - strcpy( filename, pn ); - strcat( filename, "/ac_prt.prt" ); - } + strcpy(filename, pn); + strcat(filename, "/ac_prt.prt"); + } - DEntity portals; - if ( !portals.LoadFromPrt( filename, &acDlg->m_prog1 ) ) { - MessageBox( NULL, "Failed To Load Portal File", "Error", MB_OK ); - acDlg->DestroyWindow(); - return; - } - // load portal file + DEntity portals; + if (!portals.LoadFromPrt(filename, &acDlg->m_prog1)) { + MessageBox(NULL, "Failed To Load Portal File", "Error", MB_OK); + acDlg->DestroyWindow(); + return; + } + // load portal file - CIntersectInfoDialog* intrInfoDlg = new CIntersectInfoDialog(); - intrInfoDlg->Create( IDD_INTERSECT_INFO_DIALOG ); + CIntersectInfoDialog *intrInfoDlg = new CIntersectInfoDialog(); + intrInfoDlg->Create(IDD_INTERSECT_INFO_DIALOG); - DEntity world; + DEntity world; - world.LoadFromEntity( 0, &intrInfoDlg->m_prog1 ); - intrInfoDlg->DestroyWindow(); + world.LoadFromEntity(0, &intrInfoDlg->m_prog1); + intrInfoDlg->DestroyWindow(); - if ( autocaulkDlg.m_nMode == MODE_AC_NORMAL ) { - world.RemoveNonCheckBrushes( &exclusionList, FALSE ); - } - else{ - world.RemoveNonCheckBrushes( &exclusionList, TRUE ); - } + if (autocaulkDlg.m_nMode == MODE_AC_NORMAL) { + world.RemoveNonCheckBrushes(&exclusionList, FALSE); + } else { + world.RemoveNonCheckBrushes(&exclusionList, TRUE); + } - world.ResetChecks( &exclusionList_Face ); + world.ResetChecks(&exclusionList_Face); - int caulkedCount = 0; - int killCnt = world.AutoCaulk( &portals, autocaulkDlg.m_bAllowDestruction, &caulkedCount, &acDlg->m_prog2 ); + int caulkedCount = 0; + int killCnt = world.AutoCaulk(&portals, autocaulkDlg.m_bAllowDestruction, &caulkedCount, &acDlg->m_prog2); - if ( autocaulkDlg.m_bAllowDestruction ) { - Sys_Printf( "%i unrequired brush(es) killed\n", killCnt ); - } - Sys_Printf( "%i face(s) caulked\n", caulkedCount ); + if (autocaulkDlg.m_bAllowDestruction) { + Sys_Printf("%i unrequired brush(es) killed\n", killCnt); + } + Sys_Printf("%i face(s) caulked\n", caulkedCount); - acDlg->DestroyWindow(); + acDlg->DestroyWindow(); } -void ResetTextures(){ - texRstDlg.m_TextureName = GetCurrentTexture(); - texRstDlg.m_NewTextureName = GetCurrentTexture(); - - if ( texRstDlg.DoModal() == IDCANCEL ) { - return; - } - - float fScale[2]; - float fShift[2]; - fScale[1] = texRstDlg.m_fScaleVertical; - fScale[0] = texRstDlg.m_fScaleHorizontal; - - fShift[1] = (float)texRstDlg.m_nShiftVertical; - fShift[0] = (float)texRstDlg.m_nShiftHorizontal; - - DEntity world; - world.LoadFromEntity( 0, NULL ); - - if ( texRstDlg.m_bAllTextures ) { - world.ResetTextures( NULL, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture ); - } - else{ - world.ResetTextures( texRstDlg.m_TextureName, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, texRstDlg.m_bOnlyTexture ); - } +void ResetTextures() +{ + texRstDlg.m_TextureName = GetCurrentTexture(); + texRstDlg.m_NewTextureName = GetCurrentTexture(); + + if (texRstDlg.DoModal() == IDCANCEL) { + return; + } + + float fScale[2]; + float fShift[2]; + fScale[1] = texRstDlg.m_fScaleVertical; + fScale[0] = texRstDlg.m_fScaleHorizontal; + + fShift[1] = (float) texRstDlg.m_nShiftVertical; + fShift[0] = (float) texRstDlg.m_nShiftHorizontal; + + DEntity world; + world.LoadFromEntity(0, NULL); + + if (texRstDlg.m_bAllTextures) { + world.ResetTextures(NULL, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, + texRstDlg.m_bOnlyTexture); + } else { + world.ResetTextures(texRstDlg.m_TextureName, fScale, fShift, texRstDlg.m_nRotation, texRstDlg.m_NewTextureName, + texRstDlg.m_bOnlyTexture); + } } -void PathPlotter(){ - int ret = ppDlg.DoModal(); - if ( ret == IDCANCEL ) { - return; - } - if ( ret == IDNO ) { - if ( g_PathView ) { - delete g_PathView; - } - - return; - } - - if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) { - MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK ); - return; - } - - // tell Radiant we want to access the selected brushes - g_FuncTable.m_pfnAllocateSelectedBrushHandles(); - - // get handle to size definition brush - brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 ); - // cant release until we delete the brush, if we do... - - DEntity world; - world.LoadEPairList( *g_FuncTable.m_pfnGetEntityKeyValList( brush->owner ) ); - - DEPair* trigger_ep = world.FindEPairByKey( "targetname" ); - - if ( trigger_ep ) { - if ( !strcmp( world.m_Classname, "trigger_push" ) ) { - DEPair* target_ep = world.FindEPairByKey( "target" ); - if ( target_ep ) { - entity_s* entTarget = FindEntityFromTargetname( target_ep->value ); - if ( entTarget ) { - if ( g_PathView ) { - delete g_PathView; - } - g_PathView = new DBobView; - - g_PathView->Begin( trigger_ep->value, target_ep->value, ppDlg.m_fMultiplier, ppDlg.m_nPoints, ppDlg.m_fGravity, ppDlg.m_bNoUpdate, ppDlg.m_bShowExtra ); - } - else{ - MessageBox( NULL, "trigger_push target could not be found.", "Error", MB_OK ); - } - } - else{ - MessageBox( NULL, "trigger_push has no target.", "Error", MB_OK ); - } - } - else{ - MessageBox( NULL, "You must select a 'trigger_push' entity.", "Error", MB_OK ); - } - } - else{ - MessageBox( NULL, "Entity must have a targetname", "Error", MB_OK ); - } - - g_FuncTable.m_pfnReleaseSelectedBrushHandles(); +void PathPlotter() +{ + int ret = ppDlg.DoModal(); + if (ret == IDCANCEL) { + return; + } + if (ret == IDNO) { + if (g_PathView) { + delete g_PathView; + } + + return; + } + + if (g_FuncTable.m_pfnSelectedBrushCount() != 1) { + MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK); + return; + } + + // tell Radiant we want to access the selected brushes + g_FuncTable.m_pfnAllocateSelectedBrushHandles(); + + // get handle to size definition brush + brush_t *brush = (brush_t *) g_FuncTable.m_pfnGetSelectedBrushHandle(0); + // cant release until we delete the brush, if we do... + + DEntity world; + world.LoadEPairList(*g_FuncTable.m_pfnGetEntityKeyValList(brush->owner)); + + DEPair *trigger_ep = world.FindEPairByKey("targetname"); + + if (trigger_ep) { + if (!strcmp(world.m_Classname, "trigger_push")) { + DEPair *target_ep = world.FindEPairByKey("target"); + if (target_ep) { + entity_s *entTarget = FindEntityFromTargetname(target_ep->value); + if (entTarget) { + if (g_PathView) { + delete g_PathView; + } + g_PathView = new DBobView; + + g_PathView->Begin(trigger_ep->value, target_ep->value, ppDlg.m_fMultiplier, ppDlg.m_nPoints, + ppDlg.m_fGravity, ppDlg.m_bNoUpdate, ppDlg.m_bShowExtra); + } else { + MessageBox(NULL, "trigger_push target could not be found.", "Error", MB_OK); + } + } else { + MessageBox(NULL, "trigger_push has no target.", "Error", MB_OK); + } + } else { + MessageBox(NULL, "You must select a 'trigger_push' entity.", "Error", MB_OK); + } + } else { + MessageBox(NULL, "Entity must have a targetname", "Error", MB_OK); + } + + g_FuncTable.m_pfnReleaseSelectedBrushHandles(); } -void PitBuilder( vec3_t vMin, vec3_t vMax ){ - // ensure we have something selected - if ( g_FuncTable.m_pfnSelectedBrushCount() != 1 ) { - MessageBox( NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK ); - return; - } +void PitBuilder(vec3_t vMin, vec3_t vMax) +{ + // ensure we have something selected + if (g_FuncTable.m_pfnSelectedBrushCount() != 1) { + MessageBox(NULL, "Invalid number of brushes selected, chose 1 only", "Error", MB_OK); + return; + } - // tell Radiant we want to access the selected brushes - g_FuncTable.m_pfnAllocateSelectedBrushHandles(); + // tell Radiant we want to access the selected brushes + g_FuncTable.m_pfnAllocateSelectedBrushHandles(); - // get handle to size definition brush - brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle( 0 ); - // cant release until we delete the brush, if we do... + // get handle to size definition brush + brush_t *brush = (brush_t *) g_FuncTable.m_pfnGetSelectedBrushHandle(0); + // cant release until we delete the brush, if we do... - DShape pit; + DShape pit; - if ( pit.BuildPit( vMin, vMax ) ) { - pit.Commit(); + if (pit.BuildPit(vMin, vMax)) { + pit.Commit(); - g_FuncTable.m_pfnDeleteBrushHandle( brush ); - } - else{ - MessageBox( NULL, "Failed To Make Pit\nTry Making The Brush Bigger", "Error", MB_OK ); - } + g_FuncTable.m_pfnDeleteBrushHandle(brush); + } else { + MessageBox(NULL, "Failed To Make Pit\nTry Making The Brush Bigger", "Error", MB_OK); + } - g_FuncTable.m_pfnReleaseSelectedBrushHandles(); + g_FuncTable.m_pfnReleaseSelectedBrushHandles(); } diff --git a/contrib/bobtoolz/funchandlers.h b/contrib/bobtoolz/funchandlers.h index 6062ea6e..97c8651c 100644 --- a/contrib/bobtoolz/funchandlers.h +++ b/contrib/bobtoolz/funchandlers.h @@ -18,32 +18,35 @@ */ class DBobView; + class DVisDrawer; + class DTrainDrawer; + class DTreePlanter; -extern DBobView* g_PathView; -extern DVisDrawer* g_VisView; -extern DTrainDrawer* g_TrainView; -extern DTreePlanter* g_TreePlanter; +extern DBobView *g_PathView; +extern DVisDrawer *g_VisView; +extern DTrainDrawer *g_TrainView; +extern DTreePlanter *g_TreePlanter; // intersect stuff const int BRUSH_OPT_WHOLE_MAP = 0; -const int BRUSH_OPT_SELECTED = 1; +const int BRUSH_OPT_SELECTED = 1; // defines for stairs -const int MOVE_NORTH = 0; -const int MOVE_SOUTH = 1; -const int MOVE_EAST = 2; -const int MOVE_WEST = 3; +const int MOVE_NORTH = 0; +const int MOVE_SOUTH = 1; +const int MOVE_EAST = 2; +const int MOVE_WEST = 3; -const int STYLE_ORIGINAL = 0; -const int STYLE_BOB = 1; -const int STYLE_CORNER = 2; +const int STYLE_ORIGINAL = 0; +const int STYLE_BOB = 1; +const int STYLE_CORNER = 2; // defines for doors -const int DIRECTION_NS = 0; -const int DIRECTION_EW = 1; +const int DIRECTION_NS = 0; +const int DIRECTION_EW = 1; // help void LoadLists(); @@ -51,24 +54,45 @@ void LoadLists(); // djbob void DoIntersect(); + void DoPolygonsTB(); + void DoPolygons(); + void DoFixBrushes(); + void DoResetTextures(); + void DoBuildStairs(); + void DoBuildDoors(); + void DoPathPlotter(); + void DoPitBuilder(); + void DoCTFColourChanger(); + void DoMergePatches(); + void DoSplitPatch(); + void DoSplitPatchRows(); + void DoSplitPatchCols(); + void DoVisAnalyse(); + void DoTrainThing(); + void DoTrainPathPlot(); + void DoCaulkSelection(); + void DoTreePlanter(); + void DoDropEnts(); + void DoMakeChain(); + void DoFlipTerrain(); diff --git a/contrib/bobtoolz/lists.cpp b/contrib/bobtoolz/lists.cpp index 74e31bc8..9830c376 100644 --- a/contrib/bobtoolz/lists.cpp +++ b/contrib/bobtoolz/lists.cpp @@ -26,58 +26,56 @@ #include "misc.h" -bool LoadExclusionList( char* filename, std::list* exclusionList ){ - FILE* eFile = fopen( filename, "r" ); - if ( eFile ) { - char buffer[256]; - int cnt = 0; - while ( !feof( eFile ) ) - { - memset( buffer, 0, 256 ); - fscanf( eFile, "%s\n", buffer ); - - if ( strlen( buffer ) > 0 ) { - exclusionList->push_back( buffer ); - } - else{ - cnt++; - } - } - - fclose( eFile ); - - return TRUE; - } - - globalErrorStream() << "Failed To Load Exclusion List: " << filename << "\n"; - return FALSE; +bool LoadExclusionList(char *filename, std::list *exclusionList) +{ + FILE *eFile = fopen(filename, "r"); + if (eFile) { + char buffer[256]; + int cnt = 0; + while (!feof(eFile)) { + memset(buffer, 0, 256); + fscanf(eFile, "%s\n", buffer); + + if (strlen(buffer) > 0) { + exclusionList->push_back(buffer); + } else { + cnt++; + } + } + + fclose(eFile); + + return TRUE; + } + + globalErrorStream() << "Failed To Load Exclusion List: " << filename << "\n"; + return FALSE; } -bool LoadGList( char* filename, ui::ListStore loadlist ){ - FILE* eFile = fopen( filename, "r" ); - if ( eFile ) { - char buffer[256]; - int cnt = 0; - while ( !feof( eFile ) ) - { - memset( buffer, 0, 256 ); - fscanf( eFile, "%s\n", buffer ); - - if ( strlen( buffer ) > 0 ) { - char* buffer2 = new char[strlen( buffer ) + 1]; - strcpy( buffer2, buffer ); - loadlist.append(0, buffer2); - } - else{ - cnt++; - } - } - - fclose( eFile ); - - return TRUE; - } - - globalErrorStream() << "Failed To Load GList: " << filename << "\n"; - return FALSE; +bool LoadGList(char *filename, ui::ListStore loadlist) +{ + FILE *eFile = fopen(filename, "r"); + if (eFile) { + char buffer[256]; + int cnt = 0; + while (!feof(eFile)) { + memset(buffer, 0, 256); + fscanf(eFile, "%s\n", buffer); + + if (strlen(buffer) > 0) { + char *buffer2 = new char[strlen(buffer) + 1]; + strcpy(buffer2, buffer); + loadlist.append(0, buffer2); + } else { + cnt++; + } + } + + fclose(eFile); + + return TRUE; + } + + globalErrorStream() << "Failed To Load GList: " << filename << "\n"; + return FALSE; } diff --git a/contrib/bobtoolz/lists.h b/contrib/bobtoolz/lists.h index 7a8ecc18..05ea60d8 100644 --- a/contrib/bobtoolz/lists.h +++ b/contrib/bobtoolz/lists.h @@ -20,7 +20,9 @@ #include #include #include "str.h" + typedef struct _GList GList; -bool LoadExclusionList( char* filename, std::list* exclusionList ); -bool LoadGList( char* filename, ui::ListStore loadlist ); +bool LoadExclusionList(char *filename, std::list *exclusionList); + +bool LoadGList(char *filename, ui::ListStore loadlist); diff --git a/contrib/bobtoolz/misc.cpp b/contrib/bobtoolz/misc.cpp index f73c9787..95274655 100644 --- a/contrib/bobtoolz/misc.cpp +++ b/contrib/bobtoolz/misc.cpp @@ -33,8 +33,10 @@ #include "funchandlers.h" #if GDEF_OS_POSIX + #include #include + #endif #include "iundo.h" @@ -59,120 +61,115 @@ char g_CurrentTexture[256] = ""; //============================================================= //============================================================= -void ReadCurrentTexture(){ - const char* textureName = GlobalRadiant().TextureBrowser_getSelectedShader(); - strcpy( g_CurrentTexture, textureName ); +void ReadCurrentTexture() +{ + const char *textureName = GlobalRadiant().TextureBrowser_getSelectedShader(); + strcpy(g_CurrentTexture, textureName); } -const char* GetCurrentTexture(){ - ReadCurrentTexture(); - return g_CurrentTexture; +const char *GetCurrentTexture() +{ + ReadCurrentTexture(); + return g_CurrentTexture; } -void MoveBlock( int dir, vec3_t min, vec3_t max, float dist ){ - switch ( dir ) - { - case MOVE_EAST: - { - min[0] += dist; - max[0] += dist; - break; - } - case MOVE_WEST: - { - min[0] -= dist; - max[0] -= dist; - break; - } - case MOVE_NORTH: - { - min[1] += dist; - max[1] += dist; - break; - } - case MOVE_SOUTH: - { - min[1] -= dist; - max[1] -= dist; - break; - } - } +void MoveBlock(int dir, vec3_t min, vec3_t max, float dist) +{ + switch (dir) { + case MOVE_EAST: { + min[0] += dist; + max[0] += dist; + break; + } + case MOVE_WEST: { + min[0] -= dist; + max[0] -= dist; + break; + } + case MOVE_NORTH: { + min[1] += dist; + max[1] += dist; + break; + } + case MOVE_SOUTH: { + min[1] -= dist; + max[1] -= dist; + break; + } + } } -void SetInitialStairPos( int dir, vec3_t min, vec3_t max, float width ){ - switch ( dir ) - { - case MOVE_EAST: - { - max[0] = min[0] + width; - break; - } - case MOVE_WEST: - { - min[0] = max[0] - width; - break; - } - case MOVE_NORTH: - { - max[1] = min[1] + width; - break; - } - case MOVE_SOUTH: - { - min[1] = max[1] - width; - break; - } - } +void SetInitialStairPos(int dir, vec3_t min, vec3_t max, float width) +{ + switch (dir) { + case MOVE_EAST: { + max[0] = min[0] + width; + break; + } + case MOVE_WEST: { + min[0] = max[0] - width; + break; + } + case MOVE_NORTH: { + max[1] = min[1] + width; + break; + } + case MOVE_SOUTH: { + min[1] = max[1] - width; + break; + } + } } -char* TranslateString( char *buf ){ - static char buf2[32768]; - - std::size_t l = strlen( buf ); - char* out = buf2; - for ( std::size_t i = 0 ; i < l ; i++ ) - { - if ( buf[i] == '\n' ) { - *out++ = '\r'; - *out++ = '\n'; - } - else{ - *out++ = buf[i]; - } - } - *out++ = 0; - - return buf2; +char *TranslateString(char *buf) +{ + static char buf2[32768]; + + std::size_t l = strlen(buf); + char *out = buf2; + for (std::size_t i = 0; i < l; i++) { + if (buf[i] == '\n') { + *out++ = '\r'; + *out++ = '\n'; + } else { + *out++ = buf[i]; + } + } + *out++ = 0; + + return buf2; } -char* UnixToDosPath( char* path ){ +char *UnixToDosPath(char *path) +{ #if !GDEF_OS_WINDOWS - return path; + return path; #else - for ( char* p = path; *p; p++ ) - { - if ( *p == '/' ) { - *p = '\\'; - } - } - return path; + for ( char* p = path; *p; p++ ) + { + if ( *p == '/' ) { + *p = '\\'; + } + } + return path; #endif } -const char* ExtractFilename( const char* path ){ - const char* p = strrchr( path, '/' ); - if ( !p ) { - p = strrchr( path, '\\' ); - - if ( !p ) { - return path; - } - } - return ++p; +const char *ExtractFilename(const char *path) +{ + const char *p = strrchr(path, '/'); + if (!p) { + p = strrchr(path, '\\'); + + if (!p) { + return path; + } + } + return ++p; } -extern char* PLUGIN_NAME; +extern char *PLUGIN_NAME; /*char* GetGameFilename(char* buffer, const char* filename) { strcpy(buffer, g_FuncTable.m_pfnGetGamePath()); @@ -184,29 +181,31 @@ extern char* PLUGIN_NAME; }*/ #if GDEF_OS_POSIX + // the bCreateConsole parameter is ignored on linux .. -bool Q_Exec( const char *pCmd, bool bCreateConsole ){ - switch ( fork() ) - { - case -1: - return false; +bool Q_Exec(const char *pCmd, bool bCreateConsole) +{ + switch (fork()) { + case -1: + return false; // Error ("CreateProcess failed"); - break; - case 0: + break; + case 0: #if GDEF_DEBUG - printf( "Running system...\n" ); - printf( "Command: %s\n", pCmd ); + printf("Running system...\n"); + printf("Command: %s\n", pCmd); #endif - // NOTE: we could use that to detect when a step finishes. But then it - // would not work for remote compiling stuff. + // NOTE: we could use that to detect when a step finishes. But then it + // would not work for remote compiling stuff. // execlp (pCmd, pCmd, NULL); - system( pCmd ); - printf( "system() returned" ); - _exit( 0 ); - break; - } - return true; + system(pCmd); + printf("system() returned"); + _exit(0); + break; + } + return true; } + #endif #if GDEF_OS_WINDOWS @@ -214,178 +213,190 @@ bool Q_Exec( const char *pCmd, bool bCreateConsole ){ #include bool Q_Exec( const char *pCmd, bool bCreateConsole ){ - // G_DeWan: Don't know if this is needed for linux version + // G_DeWan: Don't know if this is needed for linux version - PROCESS_INFORMATION pi; - STARTUPINFO si = {0}; // Initialize all members to zero - si.cb = sizeof( STARTUPINFO ); // Set byte count - DWORD dwCreationFlags; + PROCESS_INFORMATION pi; + STARTUPINFO si = {0}; // Initialize all members to zero + si.cb = sizeof( STARTUPINFO ); // Set byte count + DWORD dwCreationFlags; - if ( bCreateConsole ) { - dwCreationFlags = CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS; - } - else{ - dwCreationFlags = DETACHED_PROCESS | NORMAL_PRIORITY_CLASS; - } + if ( bCreateConsole ) { + dwCreationFlags = CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS; + } + else{ + dwCreationFlags = DETACHED_PROCESS | NORMAL_PRIORITY_CLASS; + } - for (; *pCmd == ' '; pCmd++ ) ; + for (; *pCmd == ' '; pCmd++ ) ; - if ( !CreateProcess( NULL, (char *)pCmd, NULL, NULL, false, dwCreationFlags, NULL, NULL, &si, &pi ) ) { - return false; - } + if ( !CreateProcess( NULL, (char *)pCmd, NULL, NULL, false, dwCreationFlags, NULL, NULL, &si, &pi ) ) { + return false; + } - return true; + return true; } #endif -void StartBSP(){ - char exename[256]; - GetFilename( exename, "q3map" ); - UnixToDosPath( exename ); // do we want this done in linux version? +void StartBSP() +{ + char exename[256]; + GetFilename(exename, "q3map"); + UnixToDosPath(exename); // do we want this done in linux version? - char mapname[256]; - const char *pn = GlobalRadiant().getMapsPath(); + char mapname[256]; + const char *pn = GlobalRadiant().getMapsPath(); - strcpy( mapname, pn ); - strcat( mapname, "/ac_prt.map" ); - UnixToDosPath( mapname ); + strcpy(mapname, pn); + strcat(mapname, "/ac_prt.map"); + UnixToDosPath(mapname); - char command[1024]; - sprintf( command, "%s -nowater -fulldetail %s", exename, mapname ); + char command[1024]; + sprintf(command, "%s -nowater -fulldetail %s", exename, mapname); - Q_Exec( command, true ); + Q_Exec(command, true); } -class EntityWriteMiniPrt -{ -mutable DEntity world; -FILE* pFile; -std::list* exclusionList; +class EntityWriteMiniPrt { + mutable DEntity world; + FILE *pFile; + std::list *exclusionList; public: -EntityWriteMiniPrt( FILE* pFile, std::list* exclusionList ) - : pFile( pFile ), exclusionList( exclusionList ){ -} -void operator()( scene::Instance& instance ) const { - const char* classname = Node_getEntity( instance.path().top() )->getKeyValue( "classname" ); - - if ( !strcmp( classname, "worldspawn" ) ) { - world.LoadFromEntity( instance.path().top(), false ); - world.RemoveNonCheckBrushes( exclusionList, true ); - world.SaveToFile( pFile ); - } - else if ( strstr( classname, "info_" ) ) { - world.ClearBrushes(); - world.ClearEPairs(); - world.LoadEPairList( Node_getEntity( instance.path().top() ) ); - world.SaveToFile( pFile ); - } -} + EntityWriteMiniPrt(FILE *pFile, std::list *exclusionList) + : pFile(pFile), exclusionList(exclusionList) + { + } + + void operator()(scene::Instance &instance) const + { + const char *classname = Node_getEntity(instance.path().top())->getKeyValue("classname"); + + if (!strcmp(classname, "worldspawn")) { + world.LoadFromEntity(instance.path().top(), false); + world.RemoveNonCheckBrushes(exclusionList, true); + world.SaveToFile(pFile); + } else if (strstr(classname, "info_")) { + world.ClearBrushes(); + world.ClearEPairs(); + world.LoadEPairList(Node_getEntity(instance.path().top())); + world.SaveToFile(pFile); + } + } }; -void BuildMiniPrt( std::list* exclusionList ){ - // yes, we could just use -fulldetail option, but, as SPOG said - // it'd be faster without all the hint, donotenter etc textures and - // doors, etc +void BuildMiniPrt(std::list *exclusionList) +{ + // yes, we could just use -fulldetail option, but, as SPOG said + // it'd be faster without all the hint, donotenter etc textures and + // doors, etc - char buffer[128]; - const char *pn = GlobalRadiant().getMapsPath(); + char buffer[128]; + const char *pn = GlobalRadiant().getMapsPath(); - strcpy( buffer, pn ); - strcat( buffer, "/ac_prt.map" ); - FILE* pFile = fopen( buffer, "w" ); + strcpy(buffer, pn); + strcat(buffer, "/ac_prt.map"); + FILE *pFile = fopen(buffer, "w"); - // ahem, thx rr2 - if ( !pFile ) { - return; - } + // ahem, thx rr2 + if (!pFile) { + return; + } - Scene_forEachEntity( EntityWriteMiniPrt( pFile, exclusionList ) ); + Scene_forEachEntity(EntityWriteMiniPrt(pFile, exclusionList)); - fclose( pFile ); + fclose(pFile); - StartBSP(); + StartBSP(); } -class EntityFindByTargetName -{ -const char* targetname; +class EntityFindByTargetName { + const char *targetname; public: -mutable const scene::Path* result; -EntityFindByTargetName( const char* targetname ) - : targetname( targetname ), result( 0 ){ -} -void operator()( scene::Instance& instance ) const { - if ( result == 0 ) { - const char* value = Node_getEntity( instance.path().top() )->getKeyValue( "targetname" ); - - if ( !strcmp( value, targetname ) ) { - result = &instance.path(); - } - } -} + mutable const scene::Path *result; + + EntityFindByTargetName(const char *targetname) + : targetname(targetname), result(0) + { + } + + void operator()(scene::Instance &instance) const + { + if (result == 0) { + const char *value = Node_getEntity(instance.path().top())->getKeyValue("targetname"); + + if (!strcmp(value, targetname)) { + result = &instance.path(); + } + } + } }; -const scene::Path* FindEntityFromTargetname( const char* targetname ){ - return Scene_forEachEntity( EntityFindByTargetName( targetname ) ).result; +const scene::Path *FindEntityFromTargetname(const char *targetname) +{ + return Scene_forEachEntity(EntityFindByTargetName(targetname)).result; } -void FillDefaultTexture( _QERFaceData* faceData, vec3_t va, vec3_t vb, vec3_t vc, const char* texture ){ - faceData->m_texdef.rotate = 0; - faceData->m_texdef.scale[0] = 0.5; - faceData->m_texdef.scale[1] = 0.5; - faceData->m_texdef.shift[0] = 0; - faceData->m_texdef.shift[1] = 0; - faceData->contents = 0; - faceData->flags = 0; - faceData->value = 0; - if ( *texture ) { - faceData->m_shader = texture; - } - else{ - faceData->m_shader = "textures/common/caulk"; - } - VectorCopy( va, faceData->m_p0 ); - VectorCopy( vb, faceData->m_p1 ); - VectorCopy( vc, faceData->m_p2 ); +void FillDefaultTexture(_QERFaceData *faceData, vec3_t va, vec3_t vb, vec3_t vc, const char *texture) +{ + faceData->m_texdef.rotate = 0; + faceData->m_texdef.scale[0] = 0.5; + faceData->m_texdef.scale[1] = 0.5; + faceData->m_texdef.shift[0] = 0; + faceData->m_texdef.shift[1] = 0; + faceData->contents = 0; + faceData->flags = 0; + faceData->value = 0; + if (*texture) { + faceData->m_shader = texture; + } else { + faceData->m_shader = "textures/common/caulk"; + } + VectorCopy(va, faceData->m_p0); + VectorCopy(vb, faceData->m_p1); + VectorCopy(vc, faceData->m_p2); } -float Determinant3x3( float a1, float a2, float a3, - float b1, float b2, float b3, - float c1, float c2, float c3 ){ - return a1 * ( b2 * c3 - b3 * c2 ) - a2 * ( b1 * c3 - b3 * c1 ) + a3 * ( b1 * c2 - b2 * c1 ); +float Determinant3x3(float a1, float a2, float a3, + float b1, float b2, float b3, + float c1, float c2, float c3) +{ + return a1 * (b2 * c3 - b3 * c2) - a2 * (b1 * c3 - b3 * c1) + a3 * (b1 * c2 - b2 * c1); } -bool GetEntityCentre( const char* entity, vec3_t centre ){ - const scene::Path* ent = FindEntityFromTargetname( entity ); - if ( !ent ) { - return false; - } +bool GetEntityCentre(const char *entity, vec3_t centre) +{ + const scene::Path *ent = FindEntityFromTargetname(entity); + if (!ent) { + return false; + } - scene::Instance& instance = *GlobalSceneGraph().find( *ent ); - VectorCopy( instance.worldAABB().origin, centre ); + scene::Instance &instance = *GlobalSceneGraph().find(*ent); + VectorCopy(instance.worldAABB().origin, centre); - return true; + return true; } -vec_t Min( vec_t a, vec_t b ){ - if ( a < b ) { - return a; - } - return b; +vec_t Min(vec_t a, vec_t b) +{ + if (a < b) { + return a; + } + return b; } -void MakeNormal( const vec_t* va, const vec_t* vb, const vec_t* vc, vec_t* out ) { - vec3_t v1, v2; - VectorSubtract( va, vb, v1 ); - VectorSubtract( vc, vb, v2 ); - CrossProduct( v1, v2, out ); +void MakeNormal(const vec_t *va, const vec_t *vb, const vec_t *vc, vec_t *out) +{ + vec3_t v1, v2; + VectorSubtract(va, vb, v1); + VectorSubtract(vc, vb, v2); + CrossProduct(v1, v2, out); } -char* GetFilename( char* buffer, const char* filename ) { - strcpy( buffer, GlobalRadiant().getAppPath() ); - strcat( buffer, "plugins/" ); - strcat( buffer, filename ); - return buffer; +char *GetFilename(char *buffer, const char *filename) +{ + strcpy(buffer, GlobalRadiant().getAppPath()); + strcat(buffer, "plugins/"); + strcat(buffer, filename); + return buffer; } diff --git a/contrib/bobtoolz/misc.h b/contrib/bobtoolz/misc.h index 43839356..2b8d800b 100644 --- a/contrib/bobtoolz/misc.h +++ b/contrib/bobtoolz/misc.h @@ -27,31 +27,35 @@ const double MAX_ROUND_ERROR = 0.05; -vec_t Min( vec_t a, vec_t b ); +vec_t Min(vec_t a, vec_t b); // reads current texture into global, returns pointer to it -const char* GetCurrentTexture(); +const char *GetCurrentTexture(); class _QERFaceData; -void FillDefaultTexture( _QERFaceData* faceData, vec3_t va, vec3_t vb, vec3_t vc, const char* texture ); -void BuildMiniPrt( std::list* exclusionList ); +void FillDefaultTexture(_QERFaceData *faceData, vec3_t va, vec3_t vb, vec3_t vc, const char *texture); -void MoveBlock( int dir, vec3_t min, vec3_t max, float dist ); -void SetInitialStairPos( int dir, vec3_t min, vec3_t max, float width ); +void BuildMiniPrt(std::list *exclusionList); -const scene::Path* FindEntityFromTargetname( const char* targetname ); +void MoveBlock(int dir, vec3_t min, vec3_t max, float dist); -char* UnixToDosPath( char* path ); +void SetInitialStairPos(int dir, vec3_t min, vec3_t max, float width); -char* GetFilename( char* buffer, const char* filename ); -char* GetGameFilename( char* buffer, const char* filename ); +const scene::Path *FindEntityFromTargetname(const char *targetname); -float Determinant3x3( float a1, float a2, float a3, - float b1, float b2, float b3, - float c1, float c2, float c3 ); +char *UnixToDosPath(char *path); -bool GetEntityCentre( const char* entity, vec3_t centre ); -void MakeNormal( const vec_t* va, const vec_t* vb, const vec_t* vc, vec_t* out ); +char *GetFilename(char *buffer, const char *filename); + +char *GetGameFilename(char *buffer, const char *filename); + +float Determinant3x3(float a1, float a2, float a3, + float b1, float b2, float b3, + float c1, float c2, float c3); + +bool GetEntityCentre(const char *entity, vec3_t centre); + +void MakeNormal(const vec_t *va, const vec_t *vb, const vec_t *vc, vec_t *out); #endif diff --git a/contrib/bobtoolz/res/plugin.rc2 b/contrib/bobtoolz/res/plugin.rc2 index 2704dbfa..1ee25535 100644 --- a/contrib/bobtoolz/res/plugin.rc2 +++ b/contrib/bobtoolz/res/plugin.rc2 @@ -3,7 +3,7 @@ // #ifdef APSTUDIO_INVOKED - #error this file is not editable by Microsoft Visual C++ +#error this file is not editable by Microsoft Visual C++ #endif //APSTUDIO_INVOKED diff --git a/contrib/bobtoolz/shapes.cpp b/contrib/bobtoolz/shapes.cpp index 2e47035d..8ef88955 100644 --- a/contrib/bobtoolz/shapes.cpp +++ b/contrib/bobtoolz/shapes.cpp @@ -78,519 +78,508 @@ extern bool bFacesAll[]; Helper Functions ************************/ -float Deg2Rad( float angle ){ - return (float)( angle * Q_PI / 180 ); +float Deg2Rad(float angle) +{ + return (float) (angle * Q_PI / 180); } -void AddFaceWithTexture( scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc, const char* texture, bool detail ){ - _QERFaceData faceData; - FillDefaultTexture( &faceData, va, vb, vc, texture ); - if ( detail ) { - faceData.contents |= FACE_DETAIL; - } - GlobalBrushCreator().Brush_addFace( brush, faceData ); +void AddFaceWithTexture(scene::Node &brush, vec3_t va, vec3_t vb, vec3_t vc, const char *texture, bool detail) +{ + _QERFaceData faceData; + FillDefaultTexture(&faceData, va, vb, vc, texture); + if (detail) { + faceData.contents |= FACE_DETAIL; + } + GlobalBrushCreator().Brush_addFace(brush, faceData); } -void AddFaceWithTextureScaled( scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc, - const char* texture, bool bVertScale, bool bHorScale, - float minX, float minY, float maxX, float maxY ){ - qtexture_t* pqtTexInfo; - - // TTimo: there used to be a call to pfnHasShader here - // this was not necessary. In Radiant everything is shader. - // If a texture doesn't have a shader script, a default shader object is used. - // The IShader object was leaking also - // collect texture info: sizes, etc - IShader* i = GlobalShaderSystem().getShaderForName( texture ); - pqtTexInfo = i->getTexture(); // shader width/height doesn't come out properly - - if ( pqtTexInfo ) { - float scale[2] = {0.5f, 0.5f}; - float shift[2] = {0, 0}; - - if ( bHorScale ) { - float width = maxX - minX; - - scale[0] = width / pqtTexInfo->width; - shift[0] = -(float)( (int)maxX % (int)width ) / scale[0]; - } - - if ( bVertScale ) { - float height = maxY - minY; - - scale[1] = height / pqtTexInfo->height; - shift[1] = (float)( (int)minY % (int)height ) / scale[1]; - } - - _QERFaceData addFace; - FillDefaultTexture( &addFace, va, vb, vc, texture ); - addFace.m_texdef.scale[0] = scale[0]; - addFace.m_texdef.scale[1] = scale[1]; - addFace.m_texdef.shift[0] = shift[0]; - addFace.m_texdef.shift[1] = shift[1]; - - GlobalBrushCreator().Brush_addFace( brush, addFace ); - } - else - { - // shouldn't even get here, as default missing texture should be returned if - // texture doesn't exist, but just in case - AddFaceWithTexture( brush, va, vb, vc, texture, false ); - globalErrorStream() << "BobToolz::Invalid Texture Name-> " << texture; - } - // the IShader is not kept referenced, DecRef it - i->DecRef(); +void AddFaceWithTextureScaled(scene::Node &brush, vec3_t va, vec3_t vb, vec3_t vc, + const char *texture, bool bVertScale, bool bHorScale, + float minX, float minY, float maxX, float maxY) +{ + qtexture_t *pqtTexInfo; + + // TTimo: there used to be a call to pfnHasShader here + // this was not necessary. In Radiant everything is shader. + // If a texture doesn't have a shader script, a default shader object is used. + // The IShader object was leaking also + // collect texture info: sizes, etc + IShader *i = GlobalShaderSystem().getShaderForName(texture); + pqtTexInfo = i->getTexture(); // shader width/height doesn't come out properly + + if (pqtTexInfo) { + float scale[2] = {0.5f, 0.5f}; + float shift[2] = {0, 0}; + + if (bHorScale) { + float width = maxX - minX; + + scale[0] = width / pqtTexInfo->width; + shift[0] = -(float) ((int) maxX % (int) width) / scale[0]; + } + + if (bVertScale) { + float height = maxY - minY; + + scale[1] = height / pqtTexInfo->height; + shift[1] = (float) ((int) minY % (int) height) / scale[1]; + } + + _QERFaceData addFace; + FillDefaultTexture(&addFace, va, vb, vc, texture); + addFace.m_texdef.scale[0] = scale[0]; + addFace.m_texdef.scale[1] = scale[1]; + addFace.m_texdef.shift[0] = shift[0]; + addFace.m_texdef.shift[1] = shift[1]; + + GlobalBrushCreator().Brush_addFace(brush, addFace); + } else { + // shouldn't even get here, as default missing texture should be returned if + // texture doesn't exist, but just in case + AddFaceWithTexture(brush, va, vb, vc, texture, false); + globalErrorStream() << "BobToolz::Invalid Texture Name-> " << texture; + } + // the IShader is not kept referenced, DecRef it + i->DecRef(); } /************************ --Main Functions-- ************************/ -void Build_Wedge( int dir, vec3_t min, vec3_t max, bool bUp ){ - NodeSmartReference newBrush( GlobalBrushCreator().createBrush() ); +void Build_Wedge(int dir, vec3_t min, vec3_t max, bool bUp) +{ + NodeSmartReference newBrush(GlobalBrushCreator().createBrush()); - vec3_t v1, v2, v3, v5, v6, v7, v8; - VectorCopy( min, v1 ); - VectorCopy( min, v2 ); - VectorCopy( min, v3 ); - VectorCopy( max, v5 ); - VectorCopy( max, v6 ); - VectorCopy( max, v7 ); - VectorCopy( max, v8 ); + vec3_t v1, v2, v3, v5, v6, v7, v8; + VectorCopy(min, v1); + VectorCopy(min, v2); + VectorCopy(min, v3); + VectorCopy(max, v5); + VectorCopy(max, v6); + VectorCopy(max, v7); + VectorCopy(max, v8); - v2[0] = max[0]; - v3[1] = max[1]; + v2[0] = max[0]; + v3[1] = max[1]; - v6[0] = min[0]; - v7[1] = min[1]; - v8[2] = min[2]; + v6[0] = min[0]; + v7[1] = min[1]; + v8[2] = min[2]; - if ( bUp ) { + if (bUp) { - if ( dir != MOVE_EAST ) { - AddFaceWithTexture( newBrush, v1, v3, v6, "textures/common/caulk", false ); - } + if (dir != MOVE_EAST) { + AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", false); + } - if ( dir != MOVE_WEST ) { - AddFaceWithTexture( newBrush, v7, v5, v8, "textures/common/caulk", false ); - } + if (dir != MOVE_WEST) { + AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", false); + } - if ( dir != MOVE_NORTH ) { - AddFaceWithTexture( newBrush, v1, v7, v2, "textures/common/caulk", false ); - } + if (dir != MOVE_NORTH) { + AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", false); + } - if ( dir != MOVE_SOUTH ) { - AddFaceWithTexture( newBrush, v3, v8, v6, "textures/common/caulk", false ); - } + if (dir != MOVE_SOUTH) { + AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", false); + } - AddFaceWithTexture( newBrush, v1, v2, v3, "textures/common/caulk", false ); + AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", false); - if ( dir == MOVE_EAST ) { - AddFaceWithTexture( newBrush, v1, v3, v5, "textures/common/caulk", false ); - } + if (dir == MOVE_EAST) { + AddFaceWithTexture(newBrush, v1, v3, v5, "textures/common/caulk", false); + } - if ( dir == MOVE_WEST ) { - AddFaceWithTexture( newBrush, v2, v6, v8, "textures/common/caulk", false ); - } + if (dir == MOVE_WEST) { + AddFaceWithTexture(newBrush, v2, v6, v8, "textures/common/caulk", false); + } - if ( dir == MOVE_NORTH ) { - AddFaceWithTexture( newBrush, v1, v6, v5, "textures/common/caulk", false ); - } + if (dir == MOVE_NORTH) { + AddFaceWithTexture(newBrush, v1, v6, v5, "textures/common/caulk", false); + } - if ( dir == MOVE_SOUTH ) { - AddFaceWithTexture( newBrush, v7, v3, v8, "textures/common/caulk", false ); - } - } - else - { - if ( dir != MOVE_WEST ) { - AddFaceWithTexture( newBrush, v7, v5, v8, "textures/common/caulk", false ); - } + if (dir == MOVE_SOUTH) { + AddFaceWithTexture(newBrush, v7, v3, v8, "textures/common/caulk", false); + } + } else { + if (dir != MOVE_WEST) { + AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", false); + } - if ( dir != MOVE_EAST ) { - AddFaceWithTexture( newBrush, v1, v3, v6, "textures/common/caulk", false ); - } + if (dir != MOVE_EAST) { + AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", false); + } - if ( dir != MOVE_NORTH ) { - AddFaceWithTexture( newBrush, v3, v8, v6, "textures/common/caulk", false ); - } + if (dir != MOVE_NORTH) { + AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", false); + } - if ( dir != MOVE_SOUTH ) { - AddFaceWithTexture( newBrush, v1, v7, v2, "textures/common/caulk", false ); - } + if (dir != MOVE_SOUTH) { + AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", false); + } - AddFaceWithTexture( newBrush, v6, v5, v7, "textures/common/caulk", false ); + AddFaceWithTexture(newBrush, v6, v5, v7, "textures/common/caulk", false); - if ( dir == MOVE_WEST ) { - AddFaceWithTexture( newBrush, v1, v5, v3, "textures/common/caulk", false ); - } + if (dir == MOVE_WEST) { + AddFaceWithTexture(newBrush, v1, v5, v3, "textures/common/caulk", false); + } - if ( dir == MOVE_EAST ) { - AddFaceWithTexture( newBrush, v2, v8, v6, "textures/common/caulk", false ); - } + if (dir == MOVE_EAST) { + AddFaceWithTexture(newBrush, v2, v8, v6, "textures/common/caulk", false); + } - if ( dir == MOVE_NORTH ) { - AddFaceWithTexture( newBrush, v1, v5, v6, "textures/common/caulk", false ); - } + if (dir == MOVE_NORTH) { + AddFaceWithTexture(newBrush, v1, v5, v6, "textures/common/caulk", false); + } - if ( dir == MOVE_SOUTH ) { - AddFaceWithTexture( newBrush, v7, v8, v3, "textures/common/caulk", false ); - } - } + if (dir == MOVE_SOUTH) { + AddFaceWithTexture(newBrush, v7, v8, v3, "textures/common/caulk", false); + } + } - Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( newBrush ); + Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(newBrush); } //----------------------------------------------------------------------------------- //----------------------------------------------------------------------------------- -void Build_StairStep_Wedge( int dir, vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, bool detail ){ - NodeSmartReference newBrush( GlobalBrushCreator().createBrush() ); - - //----- Build Outer Bounds --------- - - vec3_t v1, v2, v3, v5, v6, v7, v8; - VectorCopy( min, v1 ); - VectorCopy( min, v2 ); - VectorCopy( min, v3 ); - VectorCopy( max, v5 ); - VectorCopy( max, v6 ); - VectorCopy( max, v7 ); - VectorCopy( max, v8 ); - - v2[0] = max[0]; - v3[1] = max[1]; - - v6[0] = min[0]; - v7[1] = min[1]; - - v8[2] = min[2]; - //v8 needed this time, becoz of sloping faces (2-4-6-8) - - //---------------------------------- - - AddFaceWithTexture( newBrush, v6, v5, v7, mainTexture, detail ); - - if ( dir != MOVE_EAST ) { - if ( dir == MOVE_WEST ) { - AddFaceWithTexture( newBrush, v5, v2, v7, riserTexture, detail ); - } - else{ - AddFaceWithTexture( newBrush, v5, v2, v7, "textures/common/caulk", detail ); - } - } - - if ( dir != MOVE_WEST ) { - if ( dir == MOVE_EAST ) { - AddFaceWithTexture( newBrush, v1, v3, v6, riserTexture, detail ); - } - else{ - AddFaceWithTexture( newBrush, v1, v3, v6, "textures/common/caulk", detail ); - } - } - - if ( dir != MOVE_NORTH ) { - if ( dir == MOVE_SOUTH ) { - AddFaceWithTexture( newBrush, v3, v5, v6, riserTexture, detail ); - } - else{ - AddFaceWithTexture( newBrush, v3, v5, v6, "textures/common/caulk", detail ); - } - } - - if ( dir != MOVE_SOUTH ) { - if ( dir == MOVE_NORTH ) { - AddFaceWithTexture( newBrush, v1, v7, v2, riserTexture, detail ); - } - else{ - AddFaceWithTexture( newBrush, v1, v7, v2, "textures/common/caulk", detail ); - } - } - - - if ( dir == MOVE_EAST ) { - AddFaceWithTexture( newBrush, v1, v5, v3, "textures/common/caulk", detail ); - } - - if ( dir == MOVE_WEST ) { - AddFaceWithTexture( newBrush, v2, v8, v6, "textures/common/caulk", detail ); - } - - if ( dir == MOVE_NORTH ) { - AddFaceWithTexture( newBrush, v1, v5, v6, "textures/common/caulk", detail ); - } - - if ( dir == MOVE_SOUTH ) { - AddFaceWithTexture( newBrush, v7, v8, v3, "textures/common/caulk", detail ); - } - - Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( newBrush ); +void +Build_StairStep_Wedge(int dir, vec3_t min, vec3_t max, const char *mainTexture, const char *riserTexture, bool detail) +{ + NodeSmartReference newBrush(GlobalBrushCreator().createBrush()); + + //----- Build Outer Bounds --------- + + vec3_t v1, v2, v3, v5, v6, v7, v8; + VectorCopy(min, v1); + VectorCopy(min, v2); + VectorCopy(min, v3); + VectorCopy(max, v5); + VectorCopy(max, v6); + VectorCopy(max, v7); + VectorCopy(max, v8); + + v2[0] = max[0]; + v3[1] = max[1]; + + v6[0] = min[0]; + v7[1] = min[1]; + + v8[2] = min[2]; + //v8 needed this time, becoz of sloping faces (2-4-6-8) + + //---------------------------------- + + AddFaceWithTexture(newBrush, v6, v5, v7, mainTexture, detail); + + if (dir != MOVE_EAST) { + if (dir == MOVE_WEST) { + AddFaceWithTexture(newBrush, v5, v2, v7, riserTexture, detail); + } else { + AddFaceWithTexture(newBrush, v5, v2, v7, "textures/common/caulk", detail); + } + } + + if (dir != MOVE_WEST) { + if (dir == MOVE_EAST) { + AddFaceWithTexture(newBrush, v1, v3, v6, riserTexture, detail); + } else { + AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", detail); + } + } + + if (dir != MOVE_NORTH) { + if (dir == MOVE_SOUTH) { + AddFaceWithTexture(newBrush, v3, v5, v6, riserTexture, detail); + } else { + AddFaceWithTexture(newBrush, v3, v5, v6, "textures/common/caulk", detail); + } + } + + if (dir != MOVE_SOUTH) { + if (dir == MOVE_NORTH) { + AddFaceWithTexture(newBrush, v1, v7, v2, riserTexture, detail); + } else { + AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", detail); + } + } + + + if (dir == MOVE_EAST) { + AddFaceWithTexture(newBrush, v1, v5, v3, "textures/common/caulk", detail); + } + + if (dir == MOVE_WEST) { + AddFaceWithTexture(newBrush, v2, v8, v6, "textures/common/caulk", detail); + } + + if (dir == MOVE_NORTH) { + AddFaceWithTexture(newBrush, v1, v5, v6, "textures/common/caulk", detail); + } + + if (dir == MOVE_SOUTH) { + AddFaceWithTexture(newBrush, v7, v8, v3, "textures/common/caulk", detail); + } + + Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(newBrush); } //----------------------------------------------------------------------------------- //----------------------------------------------------------------------------------- // internal use only, to get a box without finishing construction -scene::Node& Build_Get_BoundingCube_Selective( vec3_t min, vec3_t max, char* texture, bool* useFaces ){ - NodeSmartReference newBrush( GlobalBrushCreator().createBrush() ); - - //----- Build Outer Bounds --------- - - vec3_t v1, v2, v3, v5, v6, v7; - VectorCopy( min, v1 ); - VectorCopy( min, v2 ); - VectorCopy( min, v3 ); - VectorCopy( max, v5 ); - VectorCopy( max, v6 ); - VectorCopy( max, v7 ); - - v2[0] = max[0]; - v3[1] = max[1]; - - v6[0] = min[0]; - v7[1] = min[1]; - - //---------------------------------- - - //----- Add Six Cube Faces --------- - - if ( useFaces[0] ) { - AddFaceWithTexture( newBrush, v1, v2, v3, texture, false ); - } - if ( useFaces[1] ) { - AddFaceWithTexture( newBrush, v1, v3, v6, texture, false ); - } - if ( useFaces[2] ) { - AddFaceWithTexture( newBrush, v1, v7, v2, texture, false ); - } - - if ( useFaces[3] ) { - AddFaceWithTexture( newBrush, v5, v6, v3, texture, false ); - } - if ( useFaces[4] ) { - AddFaceWithTexture( newBrush, v5, v2, v7, texture, false ); - } - if ( useFaces[5] ) { - AddFaceWithTexture( newBrush, v5, v7, v6, texture, false ); - } - - //---------------------------------- - - return newBrush; +scene::Node &Build_Get_BoundingCube_Selective(vec3_t min, vec3_t max, char *texture, bool *useFaces) +{ + NodeSmartReference newBrush(GlobalBrushCreator().createBrush()); + + //----- Build Outer Bounds --------- + + vec3_t v1, v2, v3, v5, v6, v7; + VectorCopy(min, v1); + VectorCopy(min, v2); + VectorCopy(min, v3); + VectorCopy(max, v5); + VectorCopy(max, v6); + VectorCopy(max, v7); + + v2[0] = max[0]; + v3[1] = max[1]; + + v6[0] = min[0]; + v7[1] = min[1]; + + //---------------------------------- + + //----- Add Six Cube Faces --------- + + if (useFaces[0]) { + AddFaceWithTexture(newBrush, v1, v2, v3, texture, false); + } + if (useFaces[1]) { + AddFaceWithTexture(newBrush, v1, v3, v6, texture, false); + } + if (useFaces[2]) { + AddFaceWithTexture(newBrush, v1, v7, v2, texture, false); + } + + if (useFaces[3]) { + AddFaceWithTexture(newBrush, v5, v6, v3, texture, false); + } + if (useFaces[4]) { + AddFaceWithTexture(newBrush, v5, v2, v7, texture, false); + } + if (useFaces[5]) { + AddFaceWithTexture(newBrush, v5, v7, v6, texture, false); + } + + //---------------------------------- + + return newBrush; } -scene::Node& Build_Get_BoundingCube( vec3_t min, vec3_t max, char* texture ){ - return Build_Get_BoundingCube_Selective( min, max, texture, bFacesAll ); +scene::Node &Build_Get_BoundingCube(vec3_t min, vec3_t max, char *texture) +{ + return Build_Get_BoundingCube_Selective(min, max, texture, bFacesAll); } //----------------------------------------------------------------------------------- //----------------------------------------------------------------------------------- -void Build_StairStep( vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, int direction ){ - NodeSmartReference newBrush( GlobalBrushCreator().createBrush() ); +void Build_StairStep(vec3_t min, vec3_t max, const char *mainTexture, const char *riserTexture, int direction) +{ + NodeSmartReference newBrush(GlobalBrushCreator().createBrush()); - //----- Build Outer Bounds --------- + //----- Build Outer Bounds --------- - vec3_t v1, v2, v3, v5, v6, v7; - VectorCopy( min, v1 ); - VectorCopy( min, v2 ); - VectorCopy( min, v3 ); - VectorCopy( max, v5 ); - VectorCopy( max, v6 ); - VectorCopy( max, v7 ); + vec3_t v1, v2, v3, v5, v6, v7; + VectorCopy(min, v1); + VectorCopy(min, v2); + VectorCopy(min, v3); + VectorCopy(max, v5); + VectorCopy(max, v6); + VectorCopy(max, v7); - v2[0] = max[0]; - v3[1] = max[1]; + v2[0] = max[0]; + v3[1] = max[1]; - v6[0] = min[0]; - v7[1] = min[1]; + v6[0] = min[0]; + v7[1] = min[1]; - //---------------------------------- + //---------------------------------- - AddFaceWithTexture( newBrush, v6, v5, v7, mainTexture, false ); - // top gets current texture + AddFaceWithTexture(newBrush, v6, v5, v7, mainTexture, false); + // top gets current texture - if ( direction == MOVE_EAST ) { - AddFaceWithTexture( newBrush, v1, v3, v6, riserTexture, false ); - } - else{ - AddFaceWithTexture( newBrush, v1, v3, v6, "textures/common/caulk", false ); - } - // west facing side, etc... + if (direction == MOVE_EAST) { + AddFaceWithTexture(newBrush, v1, v3, v6, riserTexture, false); + } else { + AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", false); + } + // west facing side, etc... - if ( direction == MOVE_NORTH ) { - AddFaceWithTexture( newBrush, v1, v7, v2, riserTexture, false ); - } - else{ - AddFaceWithTexture( newBrush, v1, v7, v2, "textures/common/caulk", false ); - } + if (direction == MOVE_NORTH) { + AddFaceWithTexture(newBrush, v1, v7, v2, riserTexture, false); + } else { + AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", false); + } - if ( direction == MOVE_SOUTH ) { - AddFaceWithTexture( newBrush, v3, v5, v6, riserTexture, false ); - } - else{ - AddFaceWithTexture( newBrush, v3, v5, v6, "textures/common/caulk", false ); - } + if (direction == MOVE_SOUTH) { + AddFaceWithTexture(newBrush, v3, v5, v6, riserTexture, false); + } else { + AddFaceWithTexture(newBrush, v3, v5, v6, "textures/common/caulk", false); + } - if ( direction == MOVE_WEST ) { - AddFaceWithTexture( newBrush, v7, v5, v2, riserTexture, false ); - } - else{ - AddFaceWithTexture( newBrush, v7, v5, v2, "textures/common/caulk", false ); - } + if (direction == MOVE_WEST) { + AddFaceWithTexture(newBrush, v7, v5, v2, riserTexture, false); + } else { + AddFaceWithTexture(newBrush, v7, v5, v2, "textures/common/caulk", false); + } - AddFaceWithTexture( newBrush, v1, v2, v3, "textures/common/caulk", false ); - // base is caulked + AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", false); + // base is caulked - Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( newBrush ); - // finish brush + Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(newBrush); + // finish brush } //----------------------------------------------------------------------------------- //----------------------------------------------------------------------------------- -void BuildDoorsX2( vec3_t min, vec3_t max, - bool bSclMainHor, bool bSclMainVert, - bool bSclTrimHor, bool bSclTrimVert, - const char* mainTexture, const char* trimTexture, - int direction ){ - int xy; - if ( direction == 0 ) { - xy = 0; - } - else{ - xy = 1; - } +void BuildDoorsX2(vec3_t min, vec3_t max, + bool bSclMainHor, bool bSclMainVert, + bool bSclTrimHor, bool bSclTrimVert, + const char *mainTexture, const char *trimTexture, + int direction) +{ + int xy; + if (direction == 0) { + xy = 0; + } else { + xy = 1; + } - //----- Build Outer Bounds --------- - - vec3_t v1, v2, v3, v5, v6, v7, ve_1, ve_2, ve_3; - VectorCopy( min, v1 ); - VectorCopy( min, v2 ); - VectorCopy( min, v3 ); - VectorCopy( max, v5 ); - VectorCopy( max, v6 ); - VectorCopy( max, v7 ); - - v2[0] = max[0]; - v3[1] = max[1]; - - v6[0] = min[0]; - v7[1] = min[1]; - - float width = ( max[xy] - min[xy] ) / 2; - - if ( direction == 0 ) { - VectorCopy( v1, ve_1 ); - VectorCopy( v3, ve_2 ); - VectorCopy( v6, ve_3 ); - } - else - { - VectorCopy( v7, ve_1 ); - VectorCopy( v1, ve_2 ); - VectorCopy( v2, ve_3 ); - } - - ve_1[xy] += width; - ve_2[xy] += width; - ve_3[xy] += width; - - //---------------------------------- - - NodeSmartReference newBrush1( GlobalBrushCreator().createBrush() ); - NodeSmartReference newBrush2( GlobalBrushCreator().createBrush() ); - - AddFaceWithTexture( newBrush1, v1, v2, v3, "textures/common/caulk", false ); - AddFaceWithTexture( newBrush1, v5, v7, v6, "textures/common/caulk", false ); - - AddFaceWithTexture( newBrush2, v1, v2, v3, "textures/common/caulk", false ); - AddFaceWithTexture( newBrush2, v5, v7, v6, "textures/common/caulk", false ); - - if ( direction == 0 ) { - AddFaceWithTexture( newBrush1, v1, v3, v6, "textures/common/caulk", false ); - AddFaceWithTexture( newBrush2, v5, v2, v7, "textures/common/caulk", false ); - } - else - { - AddFaceWithTexture( newBrush1, v1, v7, v2, "textures/common/caulk", false ); - AddFaceWithTexture( newBrush2, v5, v6, v3, "textures/common/caulk", false ); - } - - if ( direction == 0 ) { - AddFaceWithTextureScaled( newBrush1, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor, - min[0], min[2], max[0], max[2] ); - AddFaceWithTextureScaled( newBrush1, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor, - max[0], min[2], min[0], max[2] ); - - - AddFaceWithTextureScaled( newBrush2, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor, - min[0], min[2], max[0], max[2] ); - AddFaceWithTextureScaled( newBrush2, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor, - max[0], min[2], min[0], max[2] ); // flip max/min to reverse tex dir - - - - AddFaceWithTextureScaled( newBrush1, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor, - min[1], min[2], max[1], max[2] ); - - AddFaceWithTextureScaled( newBrush2, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor, - max[1], min[2], min[1], max[2] ); - } - else - { - AddFaceWithTextureScaled( newBrush1, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor, - min[1], min[2], max[1], max[2] ); - AddFaceWithTextureScaled( newBrush1, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor, - max[1], min[2], min[1], max[2] ); - - - AddFaceWithTextureScaled( newBrush2, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor, - min[1], min[2], max[1], max[2] ); - AddFaceWithTextureScaled( newBrush2, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor, - max[1], min[2], min[1], max[2] ); // flip max/min to reverse tex dir - - - AddFaceWithTextureScaled( newBrush1, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor, - min[0], min[2], max[0], max[2] ); + //----- Build Outer Bounds --------- - AddFaceWithTextureScaled( newBrush2, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor, - max[0], min[2], min[0], max[2] ); - } + vec3_t v1, v2, v3, v5, v6, v7, ve_1, ve_2, ve_3; + VectorCopy(min, v1); + VectorCopy(min, v2); + VectorCopy(min, v3); + VectorCopy(max, v5); + VectorCopy(max, v6); + VectorCopy(max, v7); - //---------------------------------- + v2[0] = max[0]; + v3[1] = max[1]; + v6[0] = min[0]; + v7[1] = min[1]; - EntityClass* doorClass = GlobalEntityClassManager().findOrInsert( "func_door", true ); - NodeSmartReference pEDoor1( GlobalEntityCreator().createEntity( doorClass ) ); - NodeSmartReference pEDoor2( GlobalEntityCreator().createEntity( doorClass ) ); + float width = (max[xy] - min[xy]) / 2; - if ( direction == 0 ) { - Node_getEntity( pEDoor1 )->setKeyValue( "angle", "180" ); - Node_getEntity( pEDoor2 )->setKeyValue( "angle", "360" ); - } - else - { - Node_getEntity( pEDoor1 )->setKeyValue( "angle", "270" ); - Node_getEntity( pEDoor2 )->setKeyValue( "angle", "90" ); - } + if (direction == 0) { + VectorCopy(v1, ve_1); + VectorCopy(v3, ve_2); + VectorCopy(v6, ve_3); + } else { + VectorCopy(v7, ve_1); + VectorCopy(v1, ve_2); + VectorCopy(v2, ve_3); + } - srand( (unsigned)time( NULL ) ); + ve_1[xy] += width; + ve_2[xy] += width; + ve_3[xy] += width; - char teamname[256]; - sprintf( teamname, "t%i", rand() ); - Node_getEntity( pEDoor1 )->setKeyValue( "team", teamname ); - Node_getEntity( pEDoor2 )->setKeyValue( "team", teamname ); + //---------------------------------- - Node_getTraversable( pEDoor1 )->insert( newBrush1 ); - Node_getTraversable( pEDoor2 )->insert( newBrush2 ); + NodeSmartReference newBrush1(GlobalBrushCreator().createBrush()); + NodeSmartReference newBrush2(GlobalBrushCreator().createBrush()); - Node_getTraversable( GlobalSceneGraph().root() )->insert( pEDoor1 ); - Node_getTraversable( GlobalSceneGraph().root() )->insert( pEDoor2 ); + AddFaceWithTexture(newBrush1, v1, v2, v3, "textures/common/caulk", false); + AddFaceWithTexture(newBrush1, v5, v7, v6, "textures/common/caulk", false); + + AddFaceWithTexture(newBrush2, v1, v2, v3, "textures/common/caulk", false); + AddFaceWithTexture(newBrush2, v5, v7, v6, "textures/common/caulk", false); + + if (direction == 0) { + AddFaceWithTexture(newBrush1, v1, v3, v6, "textures/common/caulk", false); + AddFaceWithTexture(newBrush2, v5, v2, v7, "textures/common/caulk", false); + } else { + AddFaceWithTexture(newBrush1, v1, v7, v2, "textures/common/caulk", false); + AddFaceWithTexture(newBrush2, v5, v6, v3, "textures/common/caulk", false); + } + + if (direction == 0) { + AddFaceWithTextureScaled(newBrush1, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor, + min[0], min[2], max[0], max[2]); + AddFaceWithTextureScaled(newBrush1, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor, + max[0], min[2], min[0], max[2]); + + + AddFaceWithTextureScaled(newBrush2, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor, + min[0], min[2], max[0], max[2]); + AddFaceWithTextureScaled(newBrush2, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor, + max[0], min[2], min[0], max[2]); // flip max/min to reverse tex dir + + + + AddFaceWithTextureScaled(newBrush1, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor, + min[1], min[2], max[1], max[2]); + + AddFaceWithTextureScaled(newBrush2, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor, + max[1], min[2], min[1], max[2]); + } else { + AddFaceWithTextureScaled(newBrush1, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor, + min[1], min[2], max[1], max[2]); + AddFaceWithTextureScaled(newBrush1, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor, + max[1], min[2], min[1], max[2]); + + + AddFaceWithTextureScaled(newBrush2, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor, + min[1], min[2], max[1], max[2]); + AddFaceWithTextureScaled(newBrush2, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor, + max[1], min[2], min[1], max[2]); // flip max/min to reverse tex dir + + + AddFaceWithTextureScaled(newBrush1, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor, + min[0], min[2], max[0], max[2]); + + AddFaceWithTextureScaled(newBrush2, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor, + max[0], min[2], min[0], max[2]); + } + + //---------------------------------- + + + EntityClass *doorClass = GlobalEntityClassManager().findOrInsert("func_door", true); + NodeSmartReference pEDoor1(GlobalEntityCreator().createEntity(doorClass)); + NodeSmartReference pEDoor2(GlobalEntityCreator().createEntity(doorClass)); + + if (direction == 0) { + Node_getEntity(pEDoor1)->setKeyValue("angle", "180"); + Node_getEntity(pEDoor2)->setKeyValue("angle", "360"); + } else { + Node_getEntity(pEDoor1)->setKeyValue("angle", "270"); + Node_getEntity(pEDoor2)->setKeyValue("angle", "90"); + } + + srand((unsigned) time(NULL)); + + char teamname[256]; + sprintf(teamname, "t%i", rand()); + Node_getEntity(pEDoor1)->setKeyValue("team", teamname); + Node_getEntity(pEDoor2)->setKeyValue("team", teamname); + + Node_getTraversable(pEDoor1)->insert(newBrush1); + Node_getTraversable(pEDoor2)->insert(newBrush2); + + Node_getTraversable(GlobalSceneGraph().root())->insert(pEDoor1); + Node_getTraversable(GlobalSceneGraph().root())->insert(pEDoor2); // ResetCurrentTexture(); } @@ -598,122 +587,125 @@ void BuildDoorsX2( vec3_t min, vec3_t max, //----------------------------------------------------------------------------------- //----------------------------------------------------------------------------------- -void MakeBevel( vec3_t vMin, vec3_t vMax ){ - NodeSmartReference patch( GlobalPatchCreator().createPatch() ); - GlobalPatchCreator().Patch_resize( patch, 3, 3 ); - GlobalPatchCreator().Patch_setShader( patch, "textures/common/caulk" ); - PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints( patch ); - vec3_t x_3, y_3, z_3; - x_3[0] = vMin[0]; x_3[1] = vMin[0]; x_3[2] = vMax[0]; - y_3[0] = vMin[1]; y_3[1] = vMax[1]; y_3[2] = vMax[1]; - z_3[0] = vMin[2]; z_3[1] = ( vMax[2] + vMin[2] ) / 2; z_3[2] = vMax[2]; - /* - x_3[0] = 0; x_3[1] = 0; x_3[2] = 64; - y_3[0] = 0; y_3[1] = 64; y_3[2] = 64; - z_3[0] = 0; z_3[1] = 32; z_3[2] = 64;*/ - for ( int i = 0; i < 3; i++ ) - { - for ( int j = 0; j < 3; j++ ) - { - PatchControl& p = matrix( i, j ); - p.m_vertex[0] = x_3[i]; - p.m_vertex[1] = y_3[i]; - p.m_vertex[2] = z_3[j]; - } - } - //does invert the matrix, else the patch face is on wrong side. - for ( int i = 0 ; i < 3 ; i++ ) - { - for ( int j = 0; j < 1; j++ ) - { - PatchControl& p = matrix( i,2 - j ); - PatchControl& q = matrix( i, j ); - std::swap( p.m_vertex, q.m_vertex ); - //std::swap(p.m_texcoord, q.m_texcoord); - } - } - GlobalPatchCreator().Patch_controlPointsChanged( patch ); - //TODO - the patch has textures weird, patchmanip.h has all function it needs.. lots of duplicate code.. - //NaturalTexture(patch); - Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( patch ); +void MakeBevel(vec3_t vMin, vec3_t vMax) +{ + NodeSmartReference patch(GlobalPatchCreator().createPatch()); + GlobalPatchCreator().Patch_resize(patch, 3, 3); + GlobalPatchCreator().Patch_setShader(patch, "textures/common/caulk"); + PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch); + vec3_t x_3, y_3, z_3; + x_3[0] = vMin[0]; + x_3[1] = vMin[0]; + x_3[2] = vMax[0]; + y_3[0] = vMin[1]; + y_3[1] = vMax[1]; + y_3[2] = vMax[1]; + z_3[0] = vMin[2]; + z_3[1] = (vMax[2] + vMin[2]) / 2; + z_3[2] = vMax[2]; + /* + x_3[0] = 0; x_3[1] = 0; x_3[2] = 64; + y_3[0] = 0; y_3[1] = 64; y_3[2] = 64; + z_3[0] = 0; z_3[1] = 32; z_3[2] = 64;*/ + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + PatchControl &p = matrix(i, j); + p.m_vertex[0] = x_3[i]; + p.m_vertex[1] = y_3[i]; + p.m_vertex[2] = z_3[j]; + } + } + //does invert the matrix, else the patch face is on wrong side. + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 1; j++) { + PatchControl &p = matrix(i, 2 - j); + PatchControl &q = matrix(i, j); + std::swap(p.m_vertex, q.m_vertex); + //std::swap(p.m_texcoord, q.m_texcoord); + } + } + GlobalPatchCreator().Patch_controlPointsChanged(patch); + //TODO - the patch has textures weird, patchmanip.h has all function it needs.. lots of duplicate code.. + //NaturalTexture(patch); + Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(patch); } -void BuildCornerStairs( vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTexture, const char* riserTex ){ - vec3_t* topPoints = new vec3_t[nSteps + 1]; - vec3_t* botPoints = new vec3_t[nSteps + 1]; +void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char *mainTexture, const char *riserTex) +{ + vec3_t *topPoints = new vec3_t[nSteps + 1]; + vec3_t *botPoints = new vec3_t[nSteps + 1]; - //bool bFacesUse[6] = {true, true, false, true, false, false}; + //bool bFacesUse[6] = {true, true, false, true, false, false}; - vec3_t centre; - VectorCopy( vMin, centre ); - centre[0] = vMax[0]; + vec3_t centre; + VectorCopy(vMin, centre); + centre[0] = vMax[0]; - int height = (int)( vMax[2] - vMin[2] ) / nSteps; + int height = (int) (vMax[2] - vMin[2]) / nSteps; - vec3_t vTop, vBot; - VectorCopy( vMax, vTop ); - VectorCopy( vMin, vBot ); - vTop[2] = vMin[2] + height; + vec3_t vTop, vBot; + VectorCopy(vMax, vTop); + VectorCopy(vMin, vBot); + vTop[2] = vMin[2] + height; - int i; - for ( i = 0; i <= nSteps; i++ ) - { - VectorCopy( centre, topPoints[i] ); - VectorCopy( centre, botPoints[i] ); + int i; + for (i = 0; i <= nSteps; i++) { + VectorCopy(centre, topPoints[i]); + VectorCopy(centre, botPoints[i]); - topPoints[i][2] = vMax[2]; - botPoints[i][2] = vMin[2]; + topPoints[i][2] = vMax[2]; + botPoints[i][2] = vMin[2]; - topPoints[i][0] -= 10 * sinf( Q_PI * i / ( 2 * nSteps ) ); - topPoints[i][1] += 10 * cosf( Q_PI * i / ( 2 * nSteps ) ); + topPoints[i][0] -= 10 * sinf(Q_PI * i / (2 * nSteps)); + topPoints[i][1] += 10 * cosf(Q_PI * i / (2 * nSteps)); - botPoints[i][0] = topPoints[i][0]; - botPoints[i][1] = topPoints[i][1]; - } + botPoints[i][0] = topPoints[i][0]; + botPoints[i][1] = topPoints[i][1]; + } - vec3_t tp[3]; - for ( int j = 0; j < 3; j++ ) - VectorCopy( topPoints[j], tp[j] ); + vec3_t tp[3]; + for (int j = 0; j < 3; j++) + VectorCopy(topPoints[j], tp[j]); - for ( i = 0; i < nSteps; i++ ) - { - NodeSmartReference brush( GlobalBrushCreator().createBrush() ); - vec3_t v1, v2, v3, v5, v6, v7; - VectorCopy( vBot, v1 ); - VectorCopy( vBot, v2 ); - VectorCopy( vBot, v3 ); - VectorCopy( vTop, v5 ); - VectorCopy( vTop, v6 ); - VectorCopy( vTop, v7 ); + for (i = 0; i < nSteps; i++) { + NodeSmartReference brush(GlobalBrushCreator().createBrush()); + vec3_t v1, v2, v3, v5, v6, v7; + VectorCopy(vBot, v1); + VectorCopy(vBot, v2); + VectorCopy(vBot, v3); + VectorCopy(vTop, v5); + VectorCopy(vTop, v6); + VectorCopy(vTop, v7); - v2[0] = vTop[0]; - v3[1] = vTop[1]; + v2[0] = vTop[0]; + v3[1] = vTop[1]; - v6[0] = vBot[0]; - v7[1] = vBot[1]; + v6[0] = vBot[0]; + v7[1] = vBot[1]; - AddFaceWithTexture( brush, v1, v2, v3, "textures/common/caulk", false ); - AddFaceWithTexture( brush, v1, v3, v6, "textures/common/caulk", false ); - AddFaceWithTexture( brush, v5, v6, v3, "textures/common/caulk", false ); + AddFaceWithTexture(brush, v1, v2, v3, "textures/common/caulk", false); + AddFaceWithTexture(brush, v1, v3, v6, "textures/common/caulk", false); + AddFaceWithTexture(brush, v5, v6, v3, "textures/common/caulk", false); - for ( int j = 0; j < 3; j++ ) - tp[j][2] = vTop[2]; + for (int j = 0; j < 3; j++) { + tp[j][2] = vTop[2]; + } - AddFaceWithTexture( brush, tp[2], tp[1], tp[0], mainTexture, false ); + AddFaceWithTexture(brush, tp[2], tp[1], tp[0], mainTexture, false); - AddFaceWithTexture( brush, centre, botPoints[i + 1], topPoints[i + 1], "textures/common/caulk", false ); - AddFaceWithTexture( brush, centre, topPoints[i], botPoints[i], riserTex, false ); + AddFaceWithTexture(brush, centre, botPoints[i + 1], topPoints[i + 1], "textures/common/caulk", false); + AddFaceWithTexture(brush, centre, topPoints[i], botPoints[i], riserTex, false); - Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( brush ); + Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(brush); - vTop[2] += height; - vBot[2] += height; - } + vTop[2] += height; + vBot[2] += height; + } - delete[] topPoints; - delete[] botPoints; + delete[] topPoints; + delete[] botPoints; - vMin[2] += height; - vMax[2] += height; - MakeBevel( vMin, vMax ); + vMin[2] += height; + vMax[2] += height; + MakeBevel(vMin, vMax); } diff --git a/contrib/bobtoolz/shapes.h b/contrib/bobtoolz/shapes.h index c35809e7..0af6262a 100644 --- a/contrib/bobtoolz/shapes.h +++ b/contrib/bobtoolz/shapes.h @@ -26,28 +26,32 @@ // defines for polygon stuff #define MAX_POLYGON_FACES 128 -namespace scene -{ -class Node; +namespace scene { + class Node; } #include "mathlib.h" // generic (detail added 12/01/01, for AC+) -void AddFaceWithTexture( scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc, const char* texture, bool detail ); +void AddFaceWithTexture(scene::Node &brush, vec3_t va, vec3_t vb, vec3_t vc, const char *texture, bool detail); // ------------- // ---caulked--- // ------------- -void Build_Wedge( int dir, vec3_t min, vec3_t max, bool bUp ); +void Build_Wedge(int dir, vec3_t min, vec3_t max, bool bUp); // -------------- // ---textured--- // -------------- -void BuildDoorsX2( vec3_t min, vec3_t max, bool bSclMainHor, bool bSclMainVert, bool bSclTrimHor, bool bSclTrimVert, const char* mainTexture, const char* trimTexture, int direction ); -void Build_StairStep( vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, int direction ); -void Build_StairStep_Wedge( int dir, vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, bool detail ); -void BuildCornerStairs( vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTexture, const char* riserTex ); +void BuildDoorsX2(vec3_t min, vec3_t max, bool bSclMainHor, bool bSclMainVert, bool bSclTrimHor, bool bSclTrimVert, + const char *mainTexture, const char *trimTexture, int direction); + +void Build_StairStep(vec3_t min, vec3_t max, const char *mainTexture, const char *riserTexture, int direction); + +void +Build_StairStep_Wedge(int dir, vec3_t min, vec3_t max, const char *mainTexture, const char *riserTexture, bool detail); + +void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char *mainTexture, const char *riserTex); // stairs stuff. //void Build_Prism_Border(vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop = FALSE); //moved to DShape diff --git a/contrib/bobtoolz/visfind.cpp b/contrib/bobtoolz/visfind.cpp index 629c1633..2e49da3e 100644 --- a/contrib/bobtoolz/visfind.cpp +++ b/contrib/bobtoolz/visfind.cpp @@ -10,65 +10,63 @@ #include typedef struct { - int portalclusters; - int leafbytes; //leafbytes = ((portalclusters+63)&~63)>>3; + int portalclusters; + int leafbytes; //leafbytes = ((portalclusters+63)&~63)>>3; } vis_header; // added because int shift = 32; i = 0xFFFFFFFF >> shift; // then i = 0xFFFFFFFF, when it should = 0 const unsigned long bitmasks[33] = + { + 0x00000000, + 0x00000001, 0x00000003, 0x00000007, 0x0000000F, + 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, + 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, + 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, + 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, + 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, + 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, + 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF + }; + +int bsp_leafnumfororigin(vec3_t origin) { - 0x00000000, - 0x00000001, 0x00000003, 0x00000007, 0x0000000F, - 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, - 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, - 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, - 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, - 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, - 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, - 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF -}; - -int bsp_leafnumfororigin( vec3_t origin ){ - dnode_t *node; - dplane_t *plane; - float d; - - // TODO: check if origin is in the map?? - - node = dnodes; - while ( true ) - { - plane = &dplanes[node->planeNum]; - d = DotProduct( origin, plane->normal ) - plane->dist; - if ( d >= 0 ) { - if ( node->children[0] < 0 ) { - return -( node->children[0] + 1 ); - } - else{ - node = &dnodes[node->children[0]]; - } - } - else - if ( node->children[1] < 0 ) { - return -( node->children[1] + 1 ); - } - else{ - node = &dnodes[node->children[1]]; - } - } - return 0; + dnode_t *node; + dplane_t *plane; + float d; + + // TODO: check if origin is in the map?? + + node = dnodes; + while (true) { + plane = &dplanes[node->planeNum]; + d = DotProduct(origin, plane->normal) - plane->dist; + if (d >= 0) { + if (node->children[0] < 0) { + return -(node->children[0] + 1); + } else { + node = &dnodes[node->children[0]]; + } + } else if (node->children[1] < 0) { + return -(node->children[1] + 1); + } else { + node = &dnodes[node->children[1]]; + } + } + return 0; } -int bsp_leafnumforcluster( int cluster ){ - dleaf_t *l; - int i; - - for ( i = 0, l = dleafs; i < numleafs; i++, l++ ) - if ( l->cluster == cluster ) { - return( i ); - } - return( 0 ); +int bsp_leafnumforcluster(int cluster) +{ + dleaf_t *l; + int i; + + for (i = 0, l = dleafs; i < numleafs; i++, l++) { + if (l->cluster == cluster) { + return (i); + } + } + return (0); } // leaf1 = origin leaf @@ -84,86 +82,94 @@ int bsp_leafnumforcluster( int cluster ){ return( *( visdata + ( cluster1 * vheader->leafbytes ) + (cluster2 / 8) ) & ( 1 << ( cluster2 % 8 ) ) ); }*/ -void bsp_setbitvectorlength( byte *v, int length_bits, int length_vector ){ - int i; +void bsp_setbitvectorlength(byte *v, int length_bits, int length_vector) +{ + int i; - i = length_bits / 8; + i = length_bits / 8; - *( v + i ) = (byte) bitmasks[length_bits % 8]; + *(v + i) = (byte) bitmasks[length_bits % 8]; - memset( ( v + i + 1 ), 0, length_vector - i - 1 ); + memset((v + i + 1), 0, length_vector - i - 1); } -void bsp_bitvectorsubtract( byte *first, byte *second, byte *out, int length ){ +void bsp_bitvectorsubtract(byte *first, byte *second, byte *out, int length) +{ - int i; + int i; - for ( i = 0; i < length; i++ ) - *( out + i ) = *( first + i ) & ~( *( second + i ) ); + for (i = 0; i < length; i++) { + *(out + i) = *(first + i) & ~(*(second + i)); + } } -int bsp_countclusters( byte *bitvector, int length ){ - int i, j, c; - - c = 0; - for ( i = 0; i < length; i++ ) - for ( j = 0; j < 8; j++ ) - if ( ( *( bitvector + i ) & ( 1 << j ) ) ) { - c++; - } - return( c ); +int bsp_countclusters(byte *bitvector, int length) +{ + int i, j, c; + + c = 0; + for (i = 0; i < length; i++) { + for (j = 0; j < 8; j++) { + if ((*(bitvector + i) & (1 << j))) { + c++; + } + } + } + return (c); } -int bsp_countclusters_mask( byte *bitvector, byte *maskvector, int length ){ - int i, j, c; - - c = 0; - for ( i = 0; i < length; i++ ) - for ( j = 0; j < 8; j++ ) - if ( ( *( bitvector + i ) & ( 1 << j ) ) && ( *( maskvector + i ) & ( 1 << j ) ) ) { - c++; - } - return( c ); +int bsp_countclusters_mask(byte *bitvector, byte *maskvector, int length) +{ + int i, j, c; + + c = 0; + for (i = 0; i < length; i++) { + for (j = 0; j < 8; j++) { + if ((*(bitvector + i) & (1 << j)) && (*(maskvector + i) & (1 << j))) { + c++; + } + } + } + return (c); } -void AddCluster( std::list *pointlist, dleaf_t *cl, bool* repeatlist, vec3_t clr ){ - DWinding* w; - - int* leafsurf = &dleafsurfaces[cl->firstLeafSurface]; - for ( int k = 0; k < cl->numLeafSurfaces; k++, leafsurf++ ) - { - if ( repeatlist[*leafsurf] ) { - continue; - } - - dsurface_t* surf = &drawSurfaces[*leafsurf]; - if ( surf->surfaceType != MST_PLANAR ) { - continue; - } - - qdrawVert_t* vert = &drawVerts[surf->firstVert]; - if ( surf->firstVert + surf->numVerts > numDrawVerts ) { - DoMessageBox( "Warning", "Warning", eMB_OK ); - } - - w = new DWinding(); - w->AllocWinding( surf->numVerts ); - - for ( int l = 0; l < surf->numVerts; l++, vert++ ) - { - ( w->p[l] )[0] = vert->xyz[0]; - ( w->p[l] )[1] = vert->xyz[1]; - ( w->p[l] )[2] = vert->xyz[2]; - - w->clr[0] = clr[0]; - w->clr[1] = clr[1]; - w->clr[2] = clr[2]; - } - pointlist->push_back( w ); - - repeatlist[*leafsurf] = true; - } +void AddCluster(std::list *pointlist, dleaf_t *cl, bool *repeatlist, vec3_t clr) +{ + DWinding *w; + + int *leafsurf = &dleafsurfaces[cl->firstLeafSurface]; + for (int k = 0; k < cl->numLeafSurfaces; k++, leafsurf++) { + if (repeatlist[*leafsurf]) { + continue; + } + + dsurface_t *surf = &drawSurfaces[*leafsurf]; + if (surf->surfaceType != MST_PLANAR) { + continue; + } + + qdrawVert_t *vert = &drawVerts[surf->firstVert]; + if (surf->firstVert + surf->numVerts > numDrawVerts) { + DoMessageBox("Warning", "Warning", eMB_OK); + } + + w = new DWinding(); + w->AllocWinding(surf->numVerts); + + for (int l = 0; l < surf->numVerts; l++, vert++) { + (w->p[l])[0] = vert->xyz[0]; + (w->p[l])[1] = vert->xyz[1]; + (w->p[l])[2] = vert->xyz[2]; + + w->clr[0] = clr[0]; + w->clr[1] = clr[1]; + w->clr[2] = clr[2]; + } + pointlist->push_back(w); + + repeatlist[*leafsurf] = true; + } } /* @@ -171,47 +177,46 @@ void AddCluster( std::list *pointlist, dleaf_t *cl, bool* repeatli CreateTrace ============= */ -std::list *CreateTrace( dleaf_t *leaf, int c, vis_header *header, byte *visdata, byte *seen ){ - byte *vis; - int i, j, clusterNum; - std::list *pointlist = new std::list; - bool* repeatlist = new bool[numDrawSurfaces]; - dleaf_t *cl; +std::list *CreateTrace(dleaf_t *leaf, int c, vis_header *header, byte *visdata, byte *seen) +{ + byte *vis; + int i, j, clusterNum; + std::list *pointlist = new std::list; + bool *repeatlist = new bool[numDrawSurfaces]; + dleaf_t *cl; - vec3_t clrRnd[5] = { - {0.f, 0.f, 1.f}, - {0.f, 1.f, 1.f}, - {1.f, 0.f, 0.f}, - {1.f, 0.f, 1.f}, - {1.f, 1.f, 0.f}, - }; + vec3_t clrRnd[5] = { + {0.f, 0.f, 1.f}, + {0.f, 1.f, 1.f}, + {1.f, 0.f, 0.f}, + {1.f, 0.f, 1.f}, + {1.f, 1.f, 0.f}, + }; - vec3_t clrGreen = {0.f, 1.f, 0.f}; + vec3_t clrGreen = {0.f, 1.f, 0.f}; - memset( repeatlist, 0, sizeof( bool ) * numDrawSurfaces ); + memset(repeatlist, 0, sizeof(bool) * numDrawSurfaces); - vis = visdata + ( c * header->leafbytes ); + vis = visdata + (c * header->leafbytes); - clusterNum = 0; + clusterNum = 0; - AddCluster( pointlist, &( dleafs[bsp_leafnumforcluster( c )] ), repeatlist, clrGreen ); + AddCluster(pointlist, &(dleafs[bsp_leafnumforcluster(c)]), repeatlist, clrGreen); - for ( i = 0; i < header->leafbytes; i++ ) - { - for ( j = 0; j < 8; j++ ) - { - cl = &( dleafs[bsp_leafnumforcluster( clusterNum )] ); + for (i = 0; i < header->leafbytes; i++) { + for (j = 0; j < 8; j++) { + cl = &(dleafs[bsp_leafnumforcluster(clusterNum)]); - if ( ( *( vis + i ) & ( 1 << j ) ) && ( *( seen + i ) & ( 1 << j ) ) && ( leaf->area == cl->area ) ) { - AddCluster( pointlist, cl, repeatlist, clrRnd[rand() % 5] ); - } - clusterNum++; - } - } + if ((*(vis + i) & (1 << j)) && (*(seen + i) & (1 << j)) && (leaf->area == cl->area)) { + AddCluster(pointlist, cl, repeatlist, clrRnd[rand() % 5]); + } + clusterNum++; + } + } - delete repeatlist; + delete repeatlist; - return pointlist; + return pointlist; } /* @@ -221,33 +226,35 @@ std::list *CreateTrace( dleaf_t *leaf, int c, vis_header *header, byt setup for CreateTrace ============= */ -std::list *TraceCluster( int leafnum ){ - byte seen[( MAX_MAP_LEAFS / 8 ) + 1]; - vis_header *vheader; - byte *visdata; - dleaf_t *leaf; +std::list *TraceCluster(int leafnum) +{ + byte seen[(MAX_MAP_LEAFS / 8) + 1]; + vis_header *vheader; + byte *visdata; + dleaf_t *leaf; - vheader = (vis_header *) visBytes; - visdata = visBytes + sizeof( vis_header ); + vheader = (vis_header *) visBytes; + visdata = visBytes + sizeof(vis_header); - memset( seen, 0xFF, sizeof( seen ) ); - bsp_setbitvectorlength( seen, vheader->portalclusters, sizeof( seen ) ); + memset(seen, 0xFF, sizeof(seen)); + bsp_setbitvectorlength(seen, vheader->portalclusters, sizeof(seen)); - leaf = &( dleafs[leafnum] ); + leaf = &(dleafs[leafnum]); - return CreateTrace( leaf, leaf->cluster, vheader, visdata, seen ); + return CreateTrace(leaf, leaf->cluster, vheader, visdata, seen); } -std::list* BuildTrace( char* filename, vec3_t v_origin ){ - if ( !LoadBSPFile( filename ) ) { - return NULL; - } +std::list *BuildTrace(char *filename, vec3_t v_origin) +{ + if (!LoadBSPFile(filename)) { + return NULL; + } - int leafnum = bsp_leafnumfororigin( v_origin ); + int leafnum = bsp_leafnumfororigin(v_origin); - std::list *pointlist = TraceCluster( leafnum ); + std::list *pointlist = TraceCluster(leafnum); - FreeBSPData(); + FreeBSPData(); - return pointlist; + return pointlist; } diff --git a/contrib/bobtoolz/visfind.h b/contrib/bobtoolz/visfind.h index 54b3660d..7f2361ad 100644 --- a/contrib/bobtoolz/visfind.h +++ b/contrib/bobtoolz/visfind.h @@ -4,4 +4,4 @@ class DWinding; -std::list *BuildTrace( char* filename, vec3_t v_origin ); +std::list *BuildTrace(char *filename, vec3_t v_origin); diff --git a/contrib/brushexport/callbacks.cpp b/contrib/brushexport/callbacks.cpp index 1e7dbb2a..87b920ab 100644 --- a/contrib/brushexport/callbacks.cpp +++ b/contrib/brushexport/callbacks.cpp @@ -13,135 +13,136 @@ void DestroyWindow(); namespace callbacks { -void OnDestroy( ui::Widget w, gpointer data ){ - DestroyWindow(); -} - -void OnExportClicked( ui::Button button, gpointer user_data ){ - auto window = ui::Window::from(lookup_widget( button , "w_plugplug2" )); - ASSERT_TRUE( window ); - const char* cpath = GlobalRadiant().m_pfnFileDialog( window, false, "Save as Obj", 0, 0, false, false, true ); - if ( !cpath ) { - return; - } - - std::string path( cpath ); - - // get ignore list from ui - std::set ignore; - - auto view = ui::TreeView::from(lookup_widget(button, "t_materialist")); - ui::ListStore list = ui::ListStore::from(gtk_tree_view_get_model( view )); - - GtkTreeIter iter; - gboolean valid = gtk_tree_model_get_iter_first(list, &iter ); - while ( valid ) - { - gchar* data; - gtk_tree_model_get(list, &iter, 0, &data, -1 ); - globalOutputStream() << data << "\n"; - ignore.insert( std::string( data ) ); - g_free( data ); - valid = gtk_tree_model_iter_next(list, &iter ); - } - - for ( std::set::iterator it( ignore.begin() ); it != ignore.end(); ++it ) - globalOutputStream() << it->c_str() << "\n"; - - // collapse mode - collapsemode mode = COLLAPSE_NONE; - - auto radio = lookup_widget( button , "r_collapse" ); - ASSERT_TRUE( radio ); - - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radio ) ) ) { - mode = COLLAPSE_ALL; - } - else - { - radio = lookup_widget( button , "r_collapsebymaterial" ); - ASSERT_TRUE( radio ); - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radio ) ) ) { - mode = COLLAPSE_BY_MATERIAL; - } - else - { - radio = lookup_widget( button , "r_nocollapse" ); - ASSERT_TRUE( radio ); - ASSERT_TRUE( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radio ) ) ); - mode = COLLAPSE_NONE; - } - } - - // export materials? - auto toggle = lookup_widget( button , "t_exportmaterials" ); - ASSERT_TRUE( toggle ); - - bool exportmat = FALSE; - - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( toggle ) ) ) { - exportmat = TRUE; - } - - // limit material names? - toggle = lookup_widget( button , "t_limitmatnames" ); - ASSERT_TRUE( toggle ); - - bool limitMatNames = FALSE; - - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( toggle ) ) && exportmat ) { - limitMatNames = TRUE; - } - - // create objects instead of groups? - toggle = lookup_widget( button , "t_objects" ); - ASSERT_TRUE( toggle ); - - bool objects = FALSE; - - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( toggle ) ) && exportmat ) { - objects = TRUE; - } - - // export - ExportSelection( ignore, mode, exportmat, path, limitMatNames, objects ); -} - -void OnAddMaterial( ui::Button button, gpointer user_data ){ - auto edit = ui::Entry::from( lookup_widget( button , "ed_materialname" ) ); - ASSERT_TRUE( edit ); - - const gchar* name = gtk_entry_get_text( edit ); - if ( g_utf8_strlen( name, -1 ) > 0 ) { - ui::ListStore list = ui::ListStore::from( gtk_tree_view_get_model(ui::TreeView::from(lookup_widget(button, "t_materialist") )) ); - list.append(0, name); - gtk_entry_set_text( edit, "" ); - } -} - -void OnRemoveMaterial( ui::Button button, gpointer user_data ){ - ui::TreeView view = ui::TreeView::from(lookup_widget(button, "t_materialist")); - ui::ListStore list = ui::ListStore::from( gtk_tree_view_get_model( view ) ); - auto sel = ui::TreeSelection::from(gtk_tree_view_get_selection( view )); - - GtkTreeIter iter; - if ( gtk_tree_selection_get_selected( sel, 0, &iter ) ) { - gtk_list_store_remove( list, &iter ); - } -} - -void OnExportMatClicked( ui::Button button, gpointer user_data ){ - ui::Widget toggleLimit = lookup_widget( button , "t_limitmatnames" ); - ui::Widget toggleObject = lookup_widget( button , "t_objects" ); - - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ) ) ) { - gtk_widget_set_sensitive( toggleLimit , TRUE ); - gtk_widget_set_sensitive( toggleObject , TRUE ); - } - else { - gtk_widget_set_sensitive( toggleLimit , FALSE ); - gtk_widget_set_sensitive( toggleObject , FALSE ); - } -} + void OnDestroy(ui::Widget w, gpointer data) + { + DestroyWindow(); + } + + void OnExportClicked(ui::Button button, gpointer user_data) + { + auto window = ui::Window::from(lookup_widget(button, "w_plugplug2")); + ASSERT_TRUE(window); + const char *cpath = GlobalRadiant().m_pfnFileDialog(window, false, "Save as Obj", 0, 0, false, false, true); + if (!cpath) { + return; + } + + std::string path(cpath); + + // get ignore list from ui + std::set ignore; + + auto view = ui::TreeView::from(lookup_widget(button, "t_materialist")); + ui::ListStore list = ui::ListStore::from(gtk_tree_view_get_model(view)); + + GtkTreeIter iter; + gboolean valid = gtk_tree_model_get_iter_first(list, &iter); + while (valid) { + gchar *data; + gtk_tree_model_get(list, &iter, 0, &data, -1); + globalOutputStream() << data << "\n"; + ignore.insert(std::string(data)); + g_free(data); + valid = gtk_tree_model_iter_next(list, &iter); + } + + for (std::set::iterator it(ignore.begin()); it != ignore.end(); ++it) { + globalOutputStream() << it->c_str() << "\n"; + } + + // collapse mode + collapsemode mode = COLLAPSE_NONE; + + auto radio = lookup_widget(button, "r_collapse"); + ASSERT_TRUE(radio); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio))) { + mode = COLLAPSE_ALL; + } else { + radio = lookup_widget(button, "r_collapsebymaterial"); + ASSERT_TRUE(radio); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio))) { + mode = COLLAPSE_BY_MATERIAL; + } else { + radio = lookup_widget(button, "r_nocollapse"); + ASSERT_TRUE(radio); + ASSERT_TRUE(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio))); + mode = COLLAPSE_NONE; + } + } + + // export materials? + auto toggle = lookup_widget(button, "t_exportmaterials"); + ASSERT_TRUE(toggle); + + bool exportmat = FALSE; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) { + exportmat = TRUE; + } + + // limit material names? + toggle = lookup_widget(button, "t_limitmatnames"); + ASSERT_TRUE(toggle); + + bool limitMatNames = FALSE; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)) && exportmat) { + limitMatNames = TRUE; + } + + // create objects instead of groups? + toggle = lookup_widget(button, "t_objects"); + ASSERT_TRUE(toggle); + + bool objects = FALSE; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)) && exportmat) { + objects = TRUE; + } + + // export + ExportSelection(ignore, mode, exportmat, path, limitMatNames, objects); + } + + void OnAddMaterial(ui::Button button, gpointer user_data) + { + auto edit = ui::Entry::from(lookup_widget(button, "ed_materialname")); + ASSERT_TRUE(edit); + + const gchar *name = gtk_entry_get_text(edit); + if (g_utf8_strlen(name, -1) > 0) { + ui::ListStore list = ui::ListStore::from( + gtk_tree_view_get_model(ui::TreeView::from(lookup_widget(button, "t_materialist")))); + list.append(0, name); + gtk_entry_set_text(edit, ""); + } + } + + void OnRemoveMaterial(ui::Button button, gpointer user_data) + { + ui::TreeView view = ui::TreeView::from(lookup_widget(button, "t_materialist")); + ui::ListStore list = ui::ListStore::from(gtk_tree_view_get_model(view)); + auto sel = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); + + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(sel, 0, &iter)) { + gtk_list_store_remove(list, &iter); + } + } + + void OnExportMatClicked(ui::Button button, gpointer user_data) + { + ui::Widget toggleLimit = lookup_widget(button, "t_limitmatnames"); + ui::Widget toggleObject = lookup_widget(button, "t_objects"); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) { + gtk_widget_set_sensitive(toggleLimit, TRUE); + gtk_widget_set_sensitive(toggleObject, TRUE); + } else { + gtk_widget_set_sensitive(toggleLimit, FALSE); + gtk_widget_set_sensitive(toggleObject, FALSE); + } + } } // callbacks diff --git a/contrib/brushexport/callbacks.h b/contrib/brushexport/callbacks.h index ca4b9a14..6279696d 100644 --- a/contrib/brushexport/callbacks.h +++ b/contrib/brushexport/callbacks.h @@ -3,10 +3,14 @@ namespace callbacks { -void OnDestroy( ui::Widget, gpointer ); -void OnExportClicked( ui::Button, gpointer ); -void OnAddMaterial( ui::Button, gpointer ); -void OnRemoveMaterial( ui::Button, gpointer ); -void OnExportMatClicked( ui::Button button, gpointer ); + void OnDestroy(ui::Widget, gpointer); + + void OnExportClicked(ui::Button, gpointer); + + void OnAddMaterial(ui::Button, gpointer); + + void OnRemoveMaterial(ui::Button, gpointer); + + void OnExportMatClicked(ui::Button button, gpointer); } // callbacks diff --git a/contrib/brushexport/export.cpp b/contrib/brushexport/export.cpp index cbc4abf6..22354559 100644 --- a/contrib/brushexport/export.cpp +++ b/contrib/brushexport/export.cpp @@ -20,342 +20,346 @@ const int MAX_MATERIAL_NAME = 20; the class collects all the data which then gets exported through the WriteToFile method. */ -class ExportData -{ +class ExportData { public: -ExportData( const std::set& ignorelist, collapsemode mode, bool limNames, bool objs ); -virtual ~ExportData( void ); + ExportData(const std::set &ignorelist, collapsemode mode, bool limNames, bool objs); + + virtual ~ExportData(void); + + virtual void BeginBrush(Brush &b); -virtual void BeginBrush( Brush& b ); -virtual void AddBrushFace( Face& f ); -virtual void EndBrush( void ); + virtual void AddBrushFace(Face &f); -virtual bool WriteToFile( const std::string& path, collapsemode mode ) const = 0; + virtual void EndBrush(void); + + virtual bool WriteToFile(const std::string &path, collapsemode mode) const = 0; protected: // a group of faces -class group -{ -public: -std::string name; -std::list faces; -}; + class group { + public: + std::string name; + std::list faces; + }; -std::list groups; + std::list groups; private: // "textures/common/caulk" -> "caulk" -void GetShaderNameFromShaderPath( const char* path, std::string& name ); + void GetShaderNameFromShaderPath(const char *path, std::string &name); -group* current; -collapsemode mode; -const std::set& ignorelist; + group *current; + collapsemode mode; + const std::set &ignorelist; }; -ExportData::ExportData( const std::set& _ignorelist, collapsemode _mode, bool _limNames, bool _objs ) - : mode( _mode ), - ignorelist( _ignorelist ){ - current = 0; - - // in this mode, we need just one group - if ( mode == COLLAPSE_ALL ) { - groups.push_back( group() ); - current = &groups.back(); - current->name = "all"; - } +ExportData::ExportData(const std::set &_ignorelist, collapsemode _mode, bool _limNames, bool _objs) + : mode(_mode), + ignorelist(_ignorelist) +{ + current = 0; + + // in this mode, we need just one group + if (mode == COLLAPSE_ALL) { + groups.push_back(group()); + current = &groups.back(); + current->name = "all"; + } } -ExportData::~ExportData( void ){ +ExportData::~ExportData(void) +{ } -void ExportData::BeginBrush( Brush& b ){ - // create a new group for each brush - if ( mode == COLLAPSE_NONE ) { - groups.push_back( group() ); - current = &groups.back(); - - StringOutputStream str( 256 ); - str << "Brush" << (const unsigned int)groups.size(); - current->name = str.c_str(); - } +void ExportData::BeginBrush(Brush &b) +{ + // create a new group for each brush + if (mode == COLLAPSE_NONE) { + groups.push_back(group()); + current = &groups.back(); + + StringOutputStream str(256); + str << "Brush" << (const unsigned int) groups.size(); + current->name = str.c_str(); + } } -void ExportData::EndBrush( void ){ - // all faces of this brush were on the ignorelist, discard the emptygroup - if ( mode == COLLAPSE_NONE ) { - ASSERT_NOTNULL( current ); - if ( current->faces.empty() ) { - groups.pop_back(); - current = 0; - } - } +void ExportData::EndBrush(void) +{ + // all faces of this brush were on the ignorelist, discard the emptygroup + if (mode == COLLAPSE_NONE) { + ASSERT_NOTNULL(current); + if (current->faces.empty()) { + groups.pop_back(); + current = 0; + } + } } -void ExportData::AddBrushFace( Face& f ){ - std::string shadername; - GetShaderNameFromShaderPath( f.GetShader(), shadername ); - - // ignore faces from ignore list - if ( ignorelist.find( shadername ) != ignorelist.end() ) { - return; - } - - if ( mode == COLLAPSE_BY_MATERIAL ) { - // find a group for this material - current = 0; - const std::list::iterator end( groups.end() ); - for ( std::list::iterator it( groups.begin() ); it != end; ++it ) - { - if ( it->name == shadername ) { - current = &( *it ); - } - } - - // no group found, create one - if ( !current ) { - groups.push_back( group() ); - current = &groups.back(); - current->name = shadername; - } - } - - ASSERT_NOTNULL( current ); - - // add face to current group - current->faces.push_back( &f ); +void ExportData::AddBrushFace(Face &f) +{ + std::string shadername; + GetShaderNameFromShaderPath(f.GetShader(), shadername); + + // ignore faces from ignore list + if (ignorelist.find(shadername) != ignorelist.end()) { + return; + } + + if (mode == COLLAPSE_BY_MATERIAL) { + // find a group for this material + current = 0; + const std::list::iterator end(groups.end()); + for (std::list::iterator it(groups.begin()); it != end; ++it) { + if (it->name == shadername) { + current = &(*it); + } + } + + // no group found, create one + if (!current) { + groups.push_back(group()); + current = &groups.back(); + current->name = shadername; + } + } + + ASSERT_NOTNULL(current); + + // add face to current group + current->faces.push_back(&f); #if GDEF_DEBUG - globalOutputStream() << "Added Face to group " << current->name.c_str() << "\n"; + globalOutputStream() << "Added Face to group " << current->name.c_str() << "\n"; #endif } -void ExportData::GetShaderNameFromShaderPath( const char* path, std::string& name ){ - std::string tmp( path ); +void ExportData::GetShaderNameFromShaderPath(const char *path, std::string &name) +{ + std::string tmp(path); - size_t last_slash = tmp.find_last_of( "/" ); + size_t last_slash = tmp.find_last_of("/"); - if ( last_slash != std::string::npos && last_slash == ( tmp.length() - 1 ) ) { - name = path; - } - else{ - name = tmp.substr( last_slash + 1, tmp.length() - last_slash ); - } + if (last_slash != std::string::npos && last_slash == (tmp.length() - 1)) { + name = path; + } else { + name = tmp.substr(last_slash + 1, tmp.length() - last_slash); + } #if GDEF_DEBUG - globalOutputStream() << "Last: " << (const unsigned int) last_slash << " " << "length: " << (const unsigned int)tmp.length() << "Name: " << name.c_str() << "\n"; + globalOutputStream() << "Last: " << (const unsigned int) last_slash << " " << "length: " + << (const unsigned int) tmp.length() << "Name: " << name.c_str() << "\n"; #endif } /* Exporter writing facedata as wavefront object */ -class ExportDataAsWavefront : public ExportData -{ +class ExportDataAsWavefront : public ExportData { private: -bool expmat; -bool limNames; -bool objs; + bool expmat; + bool limNames; + bool objs; public: -ExportDataAsWavefront( const std::set& _ignorelist, collapsemode _mode, bool _expmat, bool _limNames, bool _objs ) - : ExportData( _ignorelist, _mode, _limNames, _objs ){ - expmat = _expmat; - limNames = _limNames; - objs = _objs; -} - -bool WriteToFile( const std::string& path, collapsemode mode ) const; + ExportDataAsWavefront(const std::set &_ignorelist, collapsemode _mode, bool _expmat, bool _limNames, + bool _objs) + : ExportData(_ignorelist, _mode, _limNames, _objs) + { + expmat = _expmat; + limNames = _limNames; + objs = _objs; + } + + bool WriteToFile(const std::string &path, collapsemode mode) const; }; -bool ExportDataAsWavefront::WriteToFile( const std::string& path, collapsemode mode ) const { - std::string objFile = path; - - if ( path.compare( path.length() - 4, 4, ".obj" ) != 0 ) { - objFile += ".obj"; - } - - std::string mtlFile = objFile.substr( 0, objFile.length() - 4 ) + ".mtl"; - - std::set materials; - - TextFileOutputStream out( objFile.c_str() ); - - if ( out.failed() ) { - globalErrorStream() << "Unable to open file\n"; - return false; - } - - out << "# Wavefront Objectfile exported with radiants brushexport plugin 3.0 by Thomas 'namespace' Nitschke, spam@codecreator.net\n\n"; - - if ( expmat ) { - size_t last = mtlFile.find_last_of( "//" ); - std::string mtllib = mtlFile.substr( last + 1, mtlFile.size() - last ).c_str(); - out << "mtllib " << mtllib.c_str() << "\n"; - } - - unsigned int vertex_count = 0; - - const std::list::const_iterator gend( groups.end() ); - for ( std::list::const_iterator git( groups.begin() ); git != gend; ++git ) - { - typedef std::multimap bm; - bm brushMaterials; - typedef std::pair String_Pair; - - const std::list::const_iterator end( git->faces.end() ); - - // submesh starts here - if ( objs ) { - out << "\no "; - } - else { - out << "\ng "; - } - out << git->name.c_str() << "\n"; - - // material - if ( expmat && mode == COLLAPSE_ALL ) { - out << "usemtl material" << "\n\n"; - materials.insert( "material" ); - } - - for ( std::list::const_iterator it( git->faces.begin() ); it != end; ++it ) - { - const Winding& w( ( *it )->getWinding() ); - - // vertices - for ( size_t i = 0; i < w.numpoints; ++i ) - out << "v " << FloatFormat( w[i].vertex.x(), 1, 6 ) << " " << FloatFormat( w[i].vertex.z(), 1, 6 ) << " " << FloatFormat( w[i].vertex.y(), 1, 6 ) << "\n"; - } - out << "\n"; - - for ( std::list::const_iterator it( git->faces.begin() ); it != end; ++it ) - { - const Winding& w( ( *it )->getWinding() ); - - // texcoords - for ( size_t i = 0; i < w.numpoints; ++i ) - out << "vt " << FloatFormat( w[i].texcoord.x(), 1, 6 ) << " " << FloatFormat( w[i].texcoord.y(), 1, 6 ) << "\n"; - } - - for ( std::list::const_iterator it( git->faces.begin() ); it != end; ++it ) - { - const Winding& w( ( *it )->getWinding() ); - - // faces - StringOutputStream faceLine( 256 ); - faceLine << "\nf"; - for ( size_t i = 0; i < w.numpoints; ++i, ++vertex_count ) - { - faceLine << " " << vertex_count + 1 << "/" << vertex_count + 1; - } - - if ( mode != COLLAPSE_ALL ) { - materials.insert( ( *it )->getShader().getShader() ); - brushMaterials.insert( String_Pair( ( *it )->getShader().getShader(), faceLine.c_str() ) ); - } - else { - out << faceLine.c_str(); - } - } - - if ( mode != COLLAPSE_ALL ) { - std::string lastMat; - std::string mat; - std::string faces; - - for ( bm::iterator iter = brushMaterials.begin(); iter != brushMaterials.end(); iter++ ) - { - mat = ( *iter ).first.c_str(); - faces = ( *iter ).second.c_str(); - - if ( mat != lastMat ) { - if ( limNames && mat.size() > MAX_MATERIAL_NAME ) { - out << "\nusemtl " << mat.substr( mat.size() - MAX_MATERIAL_NAME, mat.size() ).c_str(); - } - else { - out << "\nusemtl " << mat.c_str(); - } - } - - out << faces.c_str(); - lastMat = mat; - } - } - - out << "\n"; - } - - if ( expmat ) { - TextFileOutputStream outMtl( mtlFile.c_str() ); - if ( outMtl.failed() ) { - globalErrorStream() << "Unable to open material file\n"; - return false; - } - - outMtl << "# Wavefront material file exported with NetRadiants brushexport plugin.\n"; - outMtl << "# Material Count: " << (const Unsigned)materials.size() << "\n\n"; - for ( std::set::const_iterator it( materials.begin() ); it != materials.end(); ++it ) - { - if ( limNames && it->size() > MAX_MATERIAL_NAME ) { - outMtl << "newmtl " << it->substr( it->size() - MAX_MATERIAL_NAME, it->size() ).c_str() << "\n"; - } - else { - outMtl << "newmtl " << it->c_str() << "\n"; - } - } - } - - return true; +bool ExportDataAsWavefront::WriteToFile(const std::string &path, collapsemode mode) const +{ + std::string objFile = path; + + if (path.compare(path.length() - 4, 4, ".obj") != 0) { + objFile += ".obj"; + } + + std::string mtlFile = objFile.substr(0, objFile.length() - 4) + ".mtl"; + + std::set materials; + + TextFileOutputStream out(objFile.c_str()); + + if (out.failed()) { + globalErrorStream() << "Unable to open file\n"; + return false; + } + + out + << "# Wavefront Objectfile exported with radiants brushexport plugin 3.0 by Thomas 'namespace' Nitschke, spam@codecreator.net\n\n"; + + if (expmat) { + size_t last = mtlFile.find_last_of("//"); + std::string mtllib = mtlFile.substr(last + 1, mtlFile.size() - last).c_str(); + out << "mtllib " << mtllib.c_str() << "\n"; + } + + unsigned int vertex_count = 0; + + const std::list::const_iterator gend(groups.end()); + for (std::list::const_iterator git(groups.begin()); git != gend; ++git) { + typedef std::multimap bm; + bm brushMaterials; + typedef std::pair String_Pair; + + const std::list::const_iterator end(git->faces.end()); + + // submesh starts here + if (objs) { + out << "\no "; + } else { + out << "\ng "; + } + out << git->name.c_str() << "\n"; + + // material + if (expmat && mode == COLLAPSE_ALL) { + out << "usemtl material" << "\n\n"; + materials.insert("material"); + } + + for (std::list::const_iterator it(git->faces.begin()); it != end; ++it) { + const Winding &w((*it)->getWinding()); + + // vertices + for (size_t i = 0; i < w.numpoints; ++i) { + out << "v " << FloatFormat(w[i].vertex.x(), 1, 6) << " " << FloatFormat(w[i].vertex.z(), 1, 6) << " " + << FloatFormat(w[i].vertex.y(), 1, 6) << "\n"; + } + } + out << "\n"; + + for (std::list::const_iterator it(git->faces.begin()); it != end; ++it) { + const Winding &w((*it)->getWinding()); + + // texcoords + for (size_t i = 0; i < w.numpoints; ++i) { + out << "vt " << FloatFormat(w[i].texcoord.x(), 1, 6) << " " << FloatFormat(w[i].texcoord.y(), 1, 6) + << "\n"; + } + } + + for (std::list::const_iterator it(git->faces.begin()); it != end; ++it) { + const Winding &w((*it)->getWinding()); + + // faces + StringOutputStream faceLine(256); + faceLine << "\nf"; + for (size_t i = 0; i < w.numpoints; ++i, ++vertex_count) { + faceLine << " " << vertex_count + 1 << "/" << vertex_count + 1; + } + + if (mode != COLLAPSE_ALL) { + materials.insert((*it)->getShader().getShader()); + brushMaterials.insert(String_Pair((*it)->getShader().getShader(), faceLine.c_str())); + } else { + out << faceLine.c_str(); + } + } + + if (mode != COLLAPSE_ALL) { + std::string lastMat; + std::string mat; + std::string faces; + + for (bm::iterator iter = brushMaterials.begin(); iter != brushMaterials.end(); iter++) { + mat = (*iter).first.c_str(); + faces = (*iter).second.c_str(); + + if (mat != lastMat) { + if (limNames && mat.size() > MAX_MATERIAL_NAME) { + out << "\nusemtl " << mat.substr(mat.size() - MAX_MATERIAL_NAME, mat.size()).c_str(); + } else { + out << "\nusemtl " << mat.c_str(); + } + } + + out << faces.c_str(); + lastMat = mat; + } + } + + out << "\n"; + } + + if (expmat) { + TextFileOutputStream outMtl(mtlFile.c_str()); + if (outMtl.failed()) { + globalErrorStream() << "Unable to open material file\n"; + return false; + } + + outMtl << "# Wavefront material file exported with NetRadiants brushexport plugin.\n"; + outMtl << "# Material Count: " << (const Unsigned) materials.size() << "\n\n"; + for (std::set::const_iterator it(materials.begin()); it != materials.end(); ++it) { + if (limNames && it->size() > MAX_MATERIAL_NAME) { + outMtl << "newmtl " << it->substr(it->size() - MAX_MATERIAL_NAME, it->size()).c_str() << "\n"; + } else { + outMtl << "newmtl " << it->c_str() << "\n"; + } + } + } + + return true; } -class ForEachFace : public BrushVisitor -{ +class ForEachFace : public BrushVisitor { public: -ForEachFace( ExportData& _exporter ) - : exporter( _exporter ) -{} + ForEachFace(ExportData &_exporter) + : exporter(_exporter) + {} -void visit( Face& face ) const { - exporter.AddBrushFace( face ); -} + void visit(Face &face) const + { + exporter.AddBrushFace(face); + } private: -ExportData& exporter; + ExportData &exporter; }; -class ForEachSelected : public SelectionSystem::Visitor -{ +class ForEachSelected : public SelectionSystem::Visitor { public: -ForEachSelected( ExportData& _exporter ) - : exporter( _exporter ) -{} - -void visit( scene::Instance& instance ) const { - BrushInstance* bptr = InstanceTypeCast::cast( instance ); - if ( bptr ) { - Brush& brush( bptr->getBrush() ); - - exporter.BeginBrush( brush ); - ForEachFace face_vis( exporter ); - brush.forEachFace( face_vis ); - exporter.EndBrush(); - } -} + ForEachSelected(ExportData &_exporter) + : exporter(_exporter) + {} + + void visit(scene::Instance &instance) const + { + BrushInstance *bptr = InstanceTypeCast::cast(instance); + if (bptr) { + Brush &brush(bptr->getBrush()); + + exporter.BeginBrush(brush); + ForEachFace face_vis(exporter); + brush.forEachFace(face_vis); + exporter.EndBrush(); + } + } private: -ExportData& exporter; + ExportData &exporter; }; -bool ExportSelection( const std::set& ignorelist, collapsemode m, bool exmat, const std::string& path, bool limNames, bool objs ){ - ExportDataAsWavefront exporter( ignorelist, m, exmat, limNames, objs ); +bool ExportSelection(const std::set &ignorelist, collapsemode m, bool exmat, const std::string &path, + bool limNames, bool objs) +{ + ExportDataAsWavefront exporter(ignorelist, m, exmat, limNames, objs); - ForEachSelected vis( exporter ); - GlobalSelectionSystem().foreachSelected( vis ); + ForEachSelected vis(exporter); + GlobalSelectionSystem().foreachSelected(vis); - return exporter.WriteToFile( path, m ); + return exporter.WriteToFile(path, m); } diff --git a/contrib/brushexport/export.h b/contrib/brushexport/export.h index 40fa7c44..e0623dcc 100644 --- a/contrib/brushexport/export.h +++ b/contrib/brushexport/export.h @@ -1,15 +1,16 @@ #ifndef EXPORT_H #define EXPORT_H + #include #include -enum collapsemode -{ - COLLAPSE_ALL, - COLLAPSE_BY_MATERIAL, - COLLAPSE_NONE +enum collapsemode { + COLLAPSE_ALL, + COLLAPSE_BY_MATERIAL, + COLLAPSE_NONE }; -bool ExportSelection( const std::set& ignorelist, collapsemode m, bool exmat, const std::string& path, bool limitMatNames, bool objects ); +bool ExportSelection(const std::set &ignorelist, collapsemode m, bool exmat, const std::string &path, + bool limitMatNames, bool objects); #endif diff --git a/contrib/brushexport/interface.cpp b/contrib/brushexport/interface.cpp index d464a02a..dd97e636 100644 --- a/contrib/brushexport/interface.cpp +++ b/contrib/brushexport/interface.cpp @@ -5,209 +5,215 @@ #include "callbacks.h" #include "support.h" -#define GLADE_HOOKUP_OBJECT( component,widget,name ) \ - g_object_set_data_full( G_OBJECT( component ), name, \ - g_object_ref( (void *) widget ), (GDestroyNotify) g_object_unref ) +#define GLADE_HOOKUP_OBJECT(component, widget, name) \ + g_object_set_data_full( G_OBJECT( component ), name, \ + g_object_ref( (void *) widget ), (GDestroyNotify) g_object_unref ) -#define GLADE_HOOKUP_OBJECT_NO_REF( component,widget,name ) \ - g_object_set_data( G_OBJECT( component ), name, (void *) widget ) +#define GLADE_HOOKUP_OBJECT_NO_REF(component, widget, name) \ + g_object_set_data( G_OBJECT( component ), name, (void *) widget ) // created by glade -ui::Widget create_w_plugplug2( void ){ - GSList *r_collapse_group = NULL; - - auto w_plugplug2 = ui::Window( ui::window_type::TOP ); - gtk_widget_set_name( w_plugplug2, "w_plugplug2" ); - gtk_window_set_title( w_plugplug2, "BrushExport-Plugin 3.0 by namespace" ); - gtk_window_set_position( w_plugplug2, GTK_WIN_POS_CENTER ); - gtk_window_set_destroy_with_parent( w_plugplug2, TRUE ); - - auto vbox1 = ui::VBox( FALSE, 0 ); - gtk_widget_set_name( vbox1, "vbox1" ); - vbox1.show(); - w_plugplug2.add(vbox1); - gtk_container_set_border_width( GTK_CONTAINER( vbox1 ), 5 ); - - auto hbox2 = ui::HBox( TRUE, 5 ); - gtk_widget_set_name( hbox2, "hbox2" ); - hbox2.show(); - vbox1.pack_start( hbox2, FALSE, FALSE, 0 ); - gtk_container_set_border_width( GTK_CONTAINER( hbox2 ), 5 ); - - auto vbox4 = ui::VBox( TRUE, 0 ); - gtk_widget_set_name( vbox4, "vbox4" ); - vbox4.show(); - hbox2.pack_start( vbox4, TRUE, FALSE, 0 ); - - auto r_collapse = ui::Widget::from(gtk_radio_button_new_with_mnemonic( NULL, "Collapse mesh" )); - gtk_widget_set_name( r_collapse, "r_collapse" ); - gtk_widget_set_tooltip_text(r_collapse, "Collapse all brushes into a single group"); - r_collapse.show(); - vbox4.pack_start( r_collapse, FALSE, FALSE, 0 ); - gtk_radio_button_set_group( GTK_RADIO_BUTTON( r_collapse ), r_collapse_group ); - r_collapse_group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( r_collapse ) ); - - auto r_collapsebymaterial = ui::Widget::from(gtk_radio_button_new_with_mnemonic( NULL, "Collapse by material" )); - gtk_widget_set_name( r_collapsebymaterial, "r_collapsebymaterial" ); - gtk_widget_set_tooltip_text(r_collapsebymaterial, "Collapse into groups by material"); - r_collapsebymaterial.show(); - vbox4.pack_start( r_collapsebymaterial, FALSE, FALSE, 0 ); - gtk_radio_button_set_group( GTK_RADIO_BUTTON( r_collapsebymaterial ), r_collapse_group ); - r_collapse_group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( r_collapsebymaterial ) ); - - auto r_nocollapse = ui::Widget::from(gtk_radio_button_new_with_mnemonic( NULL, "Don't collapse" )); - gtk_widget_set_name( r_nocollapse, "r_nocollapse" ); - gtk_widget_set_tooltip_text(r_nocollapse, "Every brush is stored in its own group"); - r_nocollapse.show(); - vbox4.pack_start( r_nocollapse, FALSE, FALSE, 0 ); - gtk_radio_button_set_group( GTK_RADIO_BUTTON( r_nocollapse ), r_collapse_group ); - r_collapse_group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( r_nocollapse ) ); - - auto vbox3 = ui::VBox( FALSE, 0 ); - gtk_widget_set_name( vbox3, "vbox3" ); - vbox3.show(); - hbox2.pack_start( vbox3, FALSE, FALSE, 0 ); - - auto b_export = ui::Button::from(gtk_button_new_from_stock( "gtk-save" )); - gtk_widget_set_name( b_export, "b_export" ); - b_export.show(); - vbox3.pack_start( b_export, TRUE, FALSE, 0 ); - gtk_container_set_border_width( GTK_CONTAINER( b_export ), 5 ); - - auto b_close = ui::Button::from(gtk_button_new_from_stock( "gtk-cancel" )); - gtk_widget_set_name( b_close, "b_close" ); - b_close.show(); - vbox3.pack_start( b_close, TRUE, FALSE, 0 ); - gtk_container_set_border_width( GTK_CONTAINER( b_close ), 5 ); - - auto vbox2 = ui::VBox( FALSE, 5 ); - gtk_widget_set_name( vbox2, "vbox2" ); - vbox2.show(); - vbox1.pack_start( vbox2, TRUE, TRUE, 0 ); - gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 2 ); - - auto label1 = ui::Label( "Ignored materials:" ); - gtk_widget_set_name( label1, "label1" ); - label1.show(); - vbox2.pack_start( label1, FALSE, FALSE, 0 ); - - auto scrolledwindow1 = ui::ScrolledWindow(ui::New); - gtk_widget_set_name( scrolledwindow1, "scrolledwindow1" ); - scrolledwindow1.show(); - vbox2.pack_start( scrolledwindow1, TRUE, TRUE, 0 ); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolledwindow1 ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); - gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scrolledwindow1 ), GTK_SHADOW_IN ); - - auto t_materialist = ui::TreeView(ui::New); - gtk_widget_set_name( t_materialist, "t_materialist" ); - t_materialist.show(); - scrolledwindow1.add(t_materialist); - gtk_tree_view_set_headers_visible(t_materialist, FALSE ); - gtk_tree_view_set_enable_search(t_materialist, FALSE ); - - auto ed_materialname = ui::Entry(ui::New); - gtk_widget_set_name( ed_materialname, "ed_materialname" ); - ed_materialname.show(); - vbox2.pack_start( ed_materialname, FALSE, FALSE, 0 ); - - auto hbox1 = ui::HBox( TRUE, 0 ); - gtk_widget_set_name( hbox1, "hbox1" ); - hbox1.show(); - vbox2.pack_start( hbox1, FALSE, FALSE, 0 ); - - auto b_addmaterial = ui::Button::from(gtk_button_new_from_stock( "gtk-add" )); - gtk_widget_set_name( b_addmaterial, "b_addmaterial" ); - b_addmaterial.show(); - hbox1.pack_start( b_addmaterial, FALSE, FALSE, 0 ); - - auto b_removematerial = ui::Button::from(gtk_button_new_from_stock( "gtk-remove" )); - gtk_widget_set_name( b_removematerial, "b_removematerial" ); - b_removematerial.show(); - hbox1.pack_start( b_removematerial, FALSE, FALSE, 0 ); - - auto t_limitmatnames = ui::Widget::from(gtk_check_button_new_with_mnemonic( "Use short material names (max. 20 chars)" )); - gtk_widget_set_name( t_limitmatnames, "t_limitmatnames" ); - t_limitmatnames.show(); - vbox2.pack_end( t_limitmatnames, FALSE, FALSE, 0 ); - - auto t_objects = ui::Widget::from(gtk_check_button_new_with_mnemonic( "Create (o)bjects instead of (g)roups" )); - gtk_widget_set_name( t_objects, "t_objects" ); - t_objects.show(); - vbox2.pack_end(t_objects, FALSE, FALSE, 0); - - auto t_exportmaterials = ui::CheckButton::from(gtk_check_button_new_with_mnemonic( "Create material information (.mtl file)" )); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( t_exportmaterials ), true ); - gtk_widget_set_name( t_exportmaterials, "t_exportmaterials" ); - t_exportmaterials.show(); - vbox2.pack_end(t_exportmaterials, FALSE, FALSE, 10); - - using namespace callbacks; - w_plugplug2.connect( "destroy", G_CALLBACK( OnDestroy ), NULL ); - g_signal_connect_swapped( G_OBJECT( b_close ), "clicked", G_CALLBACK( OnDestroy ), NULL ); - - b_export.connect( "clicked", G_CALLBACK( OnExportClicked ), NULL ); - b_addmaterial.connect( "clicked", G_CALLBACK( OnAddMaterial ), NULL ); - b_removematerial.connect( "clicked", G_CALLBACK( OnRemoveMaterial ), NULL ); - t_exportmaterials.connect( "clicked", G_CALLBACK( OnExportMatClicked ), NULL ); - - /* Store pointers to all widgets, for use by lookup_widget(). */ - GLADE_HOOKUP_OBJECT_NO_REF( w_plugplug2, w_plugplug2, "w_plugplug2" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, vbox1, "vbox1" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, hbox2, "hbox2" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, vbox4, "vbox4" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, r_collapse, "r_collapse" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, r_collapsebymaterial, "r_collapsebymaterial" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, r_nocollapse, "r_nocollapse" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, vbox3, "vbox3" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, b_export, "b_export" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, b_close, "b_close" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, vbox2, "vbox2" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, label1, "label1" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, scrolledwindow1, "scrolledwindow1" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, t_materialist, "t_materialist" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, ed_materialname, "ed_materialname" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, hbox1, "hbox1" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, b_addmaterial, "b_addmaterial" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, b_removematerial, "b_removematerial" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, t_exportmaterials, "t_exportmaterials" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, t_limitmatnames, "t_limitmatnames" ); - GLADE_HOOKUP_OBJECT( w_plugplug2, t_objects, "t_objects" ); - - return w_plugplug2; +ui::Widget create_w_plugplug2(void) +{ + GSList *r_collapse_group = NULL; + + auto w_plugplug2 = ui::Window(ui::window_type::TOP); + gtk_widget_set_name(w_plugplug2, "w_plugplug2"); + gtk_window_set_title(w_plugplug2, "BrushExport-Plugin 3.0 by namespace"); + gtk_window_set_position(w_plugplug2, GTK_WIN_POS_CENTER); + gtk_window_set_destroy_with_parent(w_plugplug2, TRUE); + + auto vbox1 = ui::VBox(FALSE, 0); + gtk_widget_set_name(vbox1, "vbox1"); + vbox1.show(); + w_plugplug2.add(vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + + auto hbox2 = ui::HBox(TRUE, 5); + gtk_widget_set_name(hbox2, "hbox2"); + hbox2.show(); + vbox1.pack_start(hbox2, FALSE, FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(hbox2), 5); + + auto vbox4 = ui::VBox(TRUE, 0); + gtk_widget_set_name(vbox4, "vbox4"); + vbox4.show(); + hbox2.pack_start(vbox4, TRUE, FALSE, 0); + + auto r_collapse = ui::Widget::from(gtk_radio_button_new_with_mnemonic(NULL, "Collapse mesh")); + gtk_widget_set_name(r_collapse, "r_collapse"); + gtk_widget_set_tooltip_text(r_collapse, "Collapse all brushes into a single group"); + r_collapse.show(); + vbox4.pack_start(r_collapse, FALSE, FALSE, 0); + gtk_radio_button_set_group(GTK_RADIO_BUTTON(r_collapse), r_collapse_group); + r_collapse_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(r_collapse)); + + auto r_collapsebymaterial = ui::Widget::from(gtk_radio_button_new_with_mnemonic(NULL, "Collapse by material")); + gtk_widget_set_name(r_collapsebymaterial, "r_collapsebymaterial"); + gtk_widget_set_tooltip_text(r_collapsebymaterial, "Collapse into groups by material"); + r_collapsebymaterial.show(); + vbox4.pack_start(r_collapsebymaterial, FALSE, FALSE, 0); + gtk_radio_button_set_group(GTK_RADIO_BUTTON(r_collapsebymaterial), r_collapse_group); + r_collapse_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(r_collapsebymaterial)); + + auto r_nocollapse = ui::Widget::from(gtk_radio_button_new_with_mnemonic(NULL, "Don't collapse")); + gtk_widget_set_name(r_nocollapse, "r_nocollapse"); + gtk_widget_set_tooltip_text(r_nocollapse, "Every brush is stored in its own group"); + r_nocollapse.show(); + vbox4.pack_start(r_nocollapse, FALSE, FALSE, 0); + gtk_radio_button_set_group(GTK_RADIO_BUTTON(r_nocollapse), r_collapse_group); + r_collapse_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(r_nocollapse)); + + auto vbox3 = ui::VBox(FALSE, 0); + gtk_widget_set_name(vbox3, "vbox3"); + vbox3.show(); + hbox2.pack_start(vbox3, FALSE, FALSE, 0); + + auto b_export = ui::Button::from(gtk_button_new_from_stock("gtk-save")); + gtk_widget_set_name(b_export, "b_export"); + b_export.show(); + vbox3.pack_start(b_export, TRUE, FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(b_export), 5); + + auto b_close = ui::Button::from(gtk_button_new_from_stock("gtk-cancel")); + gtk_widget_set_name(b_close, "b_close"); + b_close.show(); + vbox3.pack_start(b_close, TRUE, FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(b_close), 5); + + auto vbox2 = ui::VBox(FALSE, 5); + gtk_widget_set_name(vbox2, "vbox2"); + vbox2.show(); + vbox1.pack_start(vbox2, TRUE, TRUE, 0); + gtk_container_set_border_width(GTK_CONTAINER(vbox2), 2); + + auto label1 = ui::Label("Ignored materials:"); + gtk_widget_set_name(label1, "label1"); + label1.show(); + vbox2.pack_start(label1, FALSE, FALSE, 0); + + auto scrolledwindow1 = ui::ScrolledWindow(ui::New); + gtk_widget_set_name(scrolledwindow1, "scrolledwindow1"); + scrolledwindow1.show(); + vbox2.pack_start(scrolledwindow1, TRUE, TRUE, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwindow1), GTK_SHADOW_IN); + + auto t_materialist = ui::TreeView(ui::New); + gtk_widget_set_name(t_materialist, "t_materialist"); + t_materialist.show(); + scrolledwindow1.add(t_materialist); + gtk_tree_view_set_headers_visible(t_materialist, FALSE); + gtk_tree_view_set_enable_search(t_materialist, FALSE); + + auto ed_materialname = ui::Entry(ui::New); + gtk_widget_set_name(ed_materialname, "ed_materialname"); + ed_materialname.show(); + vbox2.pack_start(ed_materialname, FALSE, FALSE, 0); + + auto hbox1 = ui::HBox(TRUE, 0); + gtk_widget_set_name(hbox1, "hbox1"); + hbox1.show(); + vbox2.pack_start(hbox1, FALSE, FALSE, 0); + + auto b_addmaterial = ui::Button::from(gtk_button_new_from_stock("gtk-add")); + gtk_widget_set_name(b_addmaterial, "b_addmaterial"); + b_addmaterial.show(); + hbox1.pack_start(b_addmaterial, FALSE, FALSE, 0); + + auto b_removematerial = ui::Button::from(gtk_button_new_from_stock("gtk-remove")); + gtk_widget_set_name(b_removematerial, "b_removematerial"); + b_removematerial.show(); + hbox1.pack_start(b_removematerial, FALSE, FALSE, 0); + + auto t_limitmatnames = ui::Widget::from( + gtk_check_button_new_with_mnemonic("Use short material names (max. 20 chars)")); + gtk_widget_set_name(t_limitmatnames, "t_limitmatnames"); + t_limitmatnames.show(); + vbox2.pack_end(t_limitmatnames, FALSE, FALSE, 0); + + auto t_objects = ui::Widget::from(gtk_check_button_new_with_mnemonic("Create (o)bjects instead of (g)roups")); + gtk_widget_set_name(t_objects, "t_objects"); + t_objects.show(); + vbox2.pack_end(t_objects, FALSE, FALSE, 0); + + auto t_exportmaterials = ui::CheckButton::from( + gtk_check_button_new_with_mnemonic("Create material information (.mtl file)")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_exportmaterials), true); + gtk_widget_set_name(t_exportmaterials, "t_exportmaterials"); + t_exportmaterials.show(); + vbox2.pack_end(t_exportmaterials, FALSE, FALSE, 10); + + using namespace callbacks; + w_plugplug2.connect("destroy", G_CALLBACK(OnDestroy), NULL); + g_signal_connect_swapped(G_OBJECT(b_close), "clicked", G_CALLBACK(OnDestroy), NULL); + + b_export.connect("clicked", G_CALLBACK(OnExportClicked), NULL); + b_addmaterial.connect("clicked", G_CALLBACK(OnAddMaterial), NULL); + b_removematerial.connect("clicked", G_CALLBACK(OnRemoveMaterial), NULL); + t_exportmaterials.connect("clicked", G_CALLBACK(OnExportMatClicked), NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF(w_plugplug2, w_plugplug2, "w_plugplug2"); + GLADE_HOOKUP_OBJECT(w_plugplug2, vbox1, "vbox1"); + GLADE_HOOKUP_OBJECT(w_plugplug2, hbox2, "hbox2"); + GLADE_HOOKUP_OBJECT(w_plugplug2, vbox4, "vbox4"); + GLADE_HOOKUP_OBJECT(w_plugplug2, r_collapse, "r_collapse"); + GLADE_HOOKUP_OBJECT(w_plugplug2, r_collapsebymaterial, "r_collapsebymaterial"); + GLADE_HOOKUP_OBJECT(w_plugplug2, r_nocollapse, "r_nocollapse"); + GLADE_HOOKUP_OBJECT(w_plugplug2, vbox3, "vbox3"); + GLADE_HOOKUP_OBJECT(w_plugplug2, b_export, "b_export"); + GLADE_HOOKUP_OBJECT(w_plugplug2, b_close, "b_close"); + GLADE_HOOKUP_OBJECT(w_plugplug2, vbox2, "vbox2"); + GLADE_HOOKUP_OBJECT(w_plugplug2, label1, "label1"); + GLADE_HOOKUP_OBJECT(w_plugplug2, scrolledwindow1, "scrolledwindow1"); + GLADE_HOOKUP_OBJECT(w_plugplug2, t_materialist, "t_materialist"); + GLADE_HOOKUP_OBJECT(w_plugplug2, ed_materialname, "ed_materialname"); + GLADE_HOOKUP_OBJECT(w_plugplug2, hbox1, "hbox1"); + GLADE_HOOKUP_OBJECT(w_plugplug2, b_addmaterial, "b_addmaterial"); + GLADE_HOOKUP_OBJECT(w_plugplug2, b_removematerial, "b_removematerial"); + GLADE_HOOKUP_OBJECT(w_plugplug2, t_exportmaterials, "t_exportmaterials"); + GLADE_HOOKUP_OBJECT(w_plugplug2, t_limitmatnames, "t_limitmatnames"); + GLADE_HOOKUP_OBJECT(w_plugplug2, t_objects, "t_objects"); + + return w_plugplug2; } // global main window, is 0 when not created ui::Widget g_brushexp_window{ui::null}; // spawn plugin window (and make sure it got destroyed first or never created) -void CreateWindow( void ){ - ASSERT_TRUE( !g_brushexp_window ); +void CreateWindow(void) +{ + ASSERT_TRUE(!g_brushexp_window); - ui::Widget wnd = create_w_plugplug2(); + ui::Widget wnd = create_w_plugplug2(); - // column & renderer + // column & renderer auto col = ui::TreeViewColumn::from(gtk_tree_view_column_new()); - gtk_tree_view_column_set_title( col, "materials" ); - auto view = ui::TreeView::from(lookup_widget(wnd, "t_materialist")); - gtk_tree_view_append_column(view, col ); - auto renderer = ui::CellRendererText(ui::New); - gtk_tree_view_insert_column_with_attributes(view, -1, "", renderer, "text", 0, NULL ); - - // list store - auto ignorelist = ui::ListStore::from(gtk_list_store_new( 1, G_TYPE_STRING )); - gtk_tree_view_set_model(view, ignorelist ); + gtk_tree_view_column_set_title(col, "materials"); + auto view = ui::TreeView::from(lookup_widget(wnd, "t_materialist")); + gtk_tree_view_append_column(view, col); + auto renderer = ui::CellRendererText(ui::New); + gtk_tree_view_insert_column_with_attributes(view, -1, "", renderer, "text", 0, NULL); + + // list store + auto ignorelist = ui::ListStore::from(gtk_list_store_new(1, G_TYPE_STRING)); + gtk_tree_view_set_model(view, ignorelist); ignorelist.unref(); - gtk_widget_show_all( wnd ); - g_brushexp_window = wnd; + gtk_widget_show_all(wnd); + g_brushexp_window = wnd; } -void DestroyWindow(){ - ASSERT_TRUE( g_brushexp_window ); - ui::Widget(g_brushexp_window).destroy(); - g_brushexp_window = ui::Widget(ui::null); +void DestroyWindow() +{ + ASSERT_TRUE(g_brushexp_window); + ui::Widget(g_brushexp_window).destroy(); + g_brushexp_window = ui::Widget(ui::null); } -bool IsWindowOpen(){ - return g_brushexp_window; +bool IsWindowOpen() +{ + return g_brushexp_window; } diff --git a/contrib/brushexport/plugin.cpp b/contrib/brushexport/plugin.cpp index 2a221c71..f5e43635 100644 --- a/contrib/brushexport/plugin.cpp +++ b/contrib/brushexport/plugin.cpp @@ -43,82 +43,93 @@ #include "typesystem.h" -void CreateWindow( void ); -void DestroyWindow( void ); -bool IsWindowOpen( void ); - -namespace BrushExport -{ -ui::Window g_mainwnd{ui::null}; - -const char* init( void* hApp, void* pMainWidget ){ - g_mainwnd = ui::Window::from(pMainWidget); - ASSERT_TRUE( g_mainwnd ); - return ""; -} -const char* getName(){ - return "Brush export Plugin"; -} -const char* getCommandList(){ - return "Export selected as Wavefront Object;About"; -} -const char* getCommandTitleList(){ - return ""; -} - -void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){ - if ( string_equal( command, "About" ) ) { - GlobalRadiant().m_pfnMessageBox( g_mainwnd, "Brushexport plugin v 2.0 by namespace (www.codecreator.net)\n" - "Enjoy!\n\nSend feedback to spam@codecreator.net", "About me...", - eMB_OK, - eMB_ICONDEFAULT ); - } - else if ( string_equal( command, "Export selected as Wavefront Object" ) ) { - if ( IsWindowOpen() ) { - DestroyWindow(); - } - CreateWindow(); - } -} +void CreateWindow(void); + +void DestroyWindow(void); + +bool IsWindowOpen(void); + +namespace BrushExport { + ui::Window g_mainwnd{ui::null}; + + const char *init(void *hApp, void *pMainWidget) + { + g_mainwnd = ui::Window::from(pMainWidget); + ASSERT_TRUE(g_mainwnd); + return ""; + } + + const char *getName() + { + return "Brush export Plugin"; + } + + const char *getCommandList() + { + return "Export selected as Wavefront Object;About"; + } + + const char *getCommandTitleList() + { + return ""; + } + + void dispatch(const char *command, float *vMin, float *vMax, bool bSingleBrush) + { + if (string_equal(command, "About")) { + GlobalRadiant().m_pfnMessageBox(g_mainwnd, "Brushexport plugin v 2.0 by namespace (www.codecreator.net)\n" + "Enjoy!\n\nSend feedback to spam@codecreator.net", "About me...", + eMB_OK, + eMB_ICONDEFAULT); + } else if (string_equal(command, "Export selected as Wavefront Object")) { + if (IsWindowOpen()) { + DestroyWindow(); + } + CreateWindow(); + } + } } class BrushExportDependencies : - public GlobalRadiantModuleRef, - public GlobalFiletypesModuleRef, - public GlobalBrushModuleRef, - public GlobalFileSystemModuleRef, - public GlobalSceneGraphModuleRef, - public GlobalSelectionModuleRef -{ + public GlobalRadiantModuleRef, + public GlobalFiletypesModuleRef, + public GlobalBrushModuleRef, + public GlobalFileSystemModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalSelectionModuleRef { public: -BrushExportDependencies( void ) - : GlobalBrushModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "brushtypes" ) ) -{} + BrushExportDependencies(void) + : GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")) + {} }; -class BrushExportModule : public TypeSystemRef -{ -_QERPluginTable m_plugin; +class BrushExportModule : public TypeSystemRef { + _QERPluginTable m_plugin; public: -typedef _QERPluginTable Type; -STRING_CONSTANT( Name, "brushexport2" ); - -BrushExportModule(){ - m_plugin.m_pfnQERPlug_Init = &BrushExport::init; - m_plugin.m_pfnQERPlug_GetName = &BrushExport::getName; - m_plugin.m_pfnQERPlug_GetCommandList = &BrushExport::getCommandList; - m_plugin.m_pfnQERPlug_GetCommandTitleList = &BrushExport::getCommandTitleList; - m_plugin.m_pfnQERPlug_Dispatch = &BrushExport::dispatch; -} -_QERPluginTable* getTable(){ - return &m_plugin; -} + typedef _QERPluginTable Type; + + STRING_CONSTANT(Name, "brushexport2"); + + BrushExportModule() + { + m_plugin.m_pfnQERPlug_Init = &BrushExport::init; + m_plugin.m_pfnQERPlug_GetName = &BrushExport::getName; + m_plugin.m_pfnQERPlug_GetCommandList = &BrushExport::getCommandList; + m_plugin.m_pfnQERPlug_GetCommandTitleList = &BrushExport::getCommandTitleList; + m_plugin.m_pfnQERPlug_Dispatch = &BrushExport::dispatch; + } + + _QERPluginTable *getTable() + { + return &m_plugin; + } }; typedef SingletonModule SingletonBrushExportModule; SingletonBrushExportModule g_BrushExportModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); - g_BrushExportModule.selfRegister(); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); + g_BrushExportModule.selfRegister(); } diff --git a/contrib/brushexport/support.cpp b/contrib/brushexport/support.cpp index b2586177..d227b5ba 100644 --- a/contrib/brushexport/support.cpp +++ b/contrib/brushexport/support.cpp @@ -4,30 +4,29 @@ #include "support.h" ui::Widget -lookup_widget(ui::Widget widget, - const gchar *widget_name ){ +lookup_widget(ui::Widget widget, + const gchar *widget_name) +{ ui::Widget parent{ui::null}; - for (;; ) - { - if ( GTK_IS_MENU( widget ) ) { - parent = ui::Widget::from(gtk_menu_get_attach_widget( GTK_MENU( widget ) )); - } - else{ - parent = ui::Widget::from(gtk_widget_get_parent(widget)); - } - if ( !parent ) { - parent = ui::Widget::from(g_object_get_data( G_OBJECT( widget ), "GladeParentKey" )); - } - if ( parent == NULL ) { - break; - } - widget = parent; - } + for (;;) { + if (GTK_IS_MENU(widget)) { + parent = ui::Widget::from(gtk_menu_get_attach_widget(GTK_MENU(widget))); + } else { + parent = ui::Widget::from(gtk_widget_get_parent(widget)); + } + if (!parent) { + parent = ui::Widget::from(g_object_get_data(G_OBJECT(widget), "GladeParentKey")); + } + if (parent == NULL) { + break; + } + widget = parent; + } - auto found_widget = ui::Widget::from(g_object_get_data( G_OBJECT( widget ), widget_name )); - if ( !found_widget ) { - g_warning( "Widget not found: %s", widget_name ); - } - return found_widget; + auto found_widget = ui::Widget::from(g_object_get_data(G_OBJECT(widget), widget_name)); + if (!found_widget) { + g_warning("Widget not found: %s", widget_name); + } + return found_widget; } diff --git a/contrib/brushexport/support.h b/contrib/brushexport/support.h index 20116a13..374ba75e 100644 --- a/contrib/brushexport/support.h +++ b/contrib/brushexport/support.h @@ -18,5 +18,5 @@ * or alternatively any widget in the component, and the name of the widget * you want returned. */ -ui::Widget lookup_widget(ui::Widget widget, - const gchar *widget_name ); +ui::Widget lookup_widget(ui::Widget widget, + const gchar *widget_name); diff --git a/contrib/camera/camera.cpp b/contrib/camera/camera.cpp index 635b3679..f78fc741 100644 --- a/contrib/camera/camera.cpp +++ b/contrib/camera/camera.cpp @@ -27,10 +27,10 @@ #include "camera.h" // Render view -CRenderer *Renderer = NULL; +CRenderer *Renderer = NULL; // Interaction -CListener *Listener = NULL; +CListener *Listener = NULL; // plugin name static const char *PLUGIN_NAME = "Camera"; @@ -41,82 +41,79 @@ static const char *PLUGIN_COMMANDS = "About...,-,Load Camera...,-,Preview Camera // globals ui::Window g_pRadiantWnd{ui::null}; ui::Window g_pCameraInspectorWnd{ui::null}; -CCamera *firstCam = NULL; // double linked list -CCamera *firstFreeCam = NULL; // single linked list -CCamera *currentCam = NULL; // single item +CCamera *firstCam = NULL; // double linked list +CCamera *firstFreeCam = NULL; // single linked list +CCamera *currentCam = NULL; // single item bool g_bEditOn = false; int g_iEditMode = 0; // 0: editting points 1: adding points int g_iActiveTarget = -1; int g_iPreviewRunning = 0; // 0: no preview 1: start preview 2: preview in progress static const char *PLUGIN_ABOUT = "Camera v1.0 for NetRadiant\n" - "by Arnout van Meer (rr2do2@splashdamage.com)\n\n" - "This product contains software technology\n" - "from id Software, Inc. ('id Technology').\n" - "id Technology (c) 2001, 2002 id Software, Inc."; + "by Arnout van Meer (rr2do2@splashdamage.com)\n\n" + "This product contains software technology\n" + "from id Software, Inc. ('id Technology').\n" + "id Technology (c) 2001, 2002 id Software, Inc."; #include "iplugin.h" -const char* QERPlug_Init( void* hApp, void* pMainWidget ){ - g_pRadiantWnd = (GtkWidget*)pMainWidget; - - // initialize cams - for ( int i = 0; i < MAX_CAMERAS; i++ ) { - if ( i == 0 ) { - firstFreeCam = new CCamera( i ); - firstCam = firstFreeCam; - } - else { - firstCam->SetNext( new CCamera( i ) ); - firstCam = firstCam->GetNext(); - } - } - firstCam = NULL; - - if ( !Renderer ) { - Renderer = new CRenderer; - } - - if ( g_pCameraInspectorWnd == NULL ) { - g_pCameraInspectorWnd = CreateCameraInspectorDialog(); - } - - GetFileTypeRegistry()->addType( "camera", "", filetype_t( "Camera file", "*.camera" ) ); - - return "Camera for NetRadiant"; +const char *QERPlug_Init(void *hApp, void *pMainWidget) +{ + g_pRadiantWnd = (GtkWidget *) pMainWidget; + + // initialize cams + for (int i = 0; i < MAX_CAMERAS; i++) { + if (i == 0) { + firstFreeCam = new CCamera(i); + firstCam = firstFreeCam; + } else { + firstCam->SetNext(new CCamera(i)); + firstCam = firstCam->GetNext(); + } + } + firstCam = NULL; + + if (!Renderer) { + Renderer = new CRenderer; + } + + if (g_pCameraInspectorWnd == NULL) { + g_pCameraInspectorWnd = CreateCameraInspectorDialog(); + } + + GetFileTypeRegistry()->addType("camera", "", filetype_t("Camera file", "*.camera")); + + return "Camera for NetRadiant"; } -const char* QERPlug_GetName(){ - return PLUGIN_NAME; +const char *QERPlug_GetName() +{ + return PLUGIN_NAME; } -const char* QERPlug_GetCommandList(){ - return PLUGIN_COMMANDS; +const char *QERPlug_GetCommandList() +{ + return PLUGIN_COMMANDS; } -void QERPlug_Dispatch( const char* p, float* vMin, float* vMax, bool bSingleBrush ){ - if ( !strcmp( p, "New Fixed Camera" ) ) { - DoNewFixedCamera(); - } - else if ( !strcmp( p, "New Interpolated Camera" ) ) { - DoNewInterpolatedCamera(); - } - else if ( !strcmp( p, "New Spline Camera" ) ) { - DoNewSplineCamera(); - } - else if ( !strcmp( p, "Camera Inspector..." ) ) { - DoCameraInspector(); - } - else if ( !strcmp( p, "Preview Camera" ) ) { - DoPreviewCamera(); - } - else if ( !strcmp( p, "Load Camera..." ) ) { - DoLoadCamera(); - } - else if ( !strcmp( p, "About..." ) ) { - g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, PLUGIN_ABOUT, "About", eMB_OK ); - } +void QERPlug_Dispatch(const char *p, float *vMin, float *vMax, bool bSingleBrush) +{ + if (!strcmp(p, "New Fixed Camera")) { + DoNewFixedCamera(); + } else if (!strcmp(p, "New Interpolated Camera")) { + DoNewInterpolatedCamera(); + } else if (!strcmp(p, "New Spline Camera")) { + DoNewSplineCamera(); + } else if (!strcmp(p, "Camera Inspector...")) { + DoCameraInspector(); + } else if (!strcmp(p, "Preview Camera")) { + DoPreviewCamera(); + } else if (!strcmp(p, "Load Camera...")) { + DoLoadCamera(); + } else if (!strcmp(p, "About...")) { + g_FuncTable.m_pfnMessageBox((GtkWidget *) g_pRadiantWnd, PLUGIN_ABOUT, "About", eMB_OK); + } } @@ -124,34 +121,44 @@ void QERPlug_Dispatch( const char* p, float* vMin, float* vMax, bool bSingleBrus #include "itoolbar.h" -unsigned int ToolbarButtonCount(){ - return 1; +unsigned int ToolbarButtonCount() +{ + return 1; } -class CameraInspectorButton : public IToolbarButton -{ +class CameraInspectorButton : public IToolbarButton { public: -virtual const char* getImage() const { - return "camera_insp.jpg"; -} -virtual const char* getText() const { - return "Inspector"; -} -virtual const char* getTooltip() const { - return "Camera Inspector"; -} -virtual void activate() const { - DoCameraInspector(); -} -virtual EType getType() const { - return eButton; -} + virtual const char *getImage() const + { + return "camera_insp.jpg"; + } + + virtual const char *getText() const + { + return "Inspector"; + } + + virtual const char *getTooltip() const + { + return "Camera Inspector"; + } + + virtual void activate() const + { + DoCameraInspector(); + } + + virtual EType getType() const + { + return eButton; + } }; CameraInspectorButton g_camerainspectorbutton; -const IToolbarButton* GetToolbarButton( unsigned int index ){ - return &g_camerainspectorbutton; +const IToolbarButton *GetToolbarButton(unsigned int index) +{ + return &g_camerainspectorbutton; } @@ -165,121 +172,131 @@ _QERCameraTable g_CameraTable; #include "synapse.h" -class CameraSynapseClient : public CSynapseClient -{ +class CameraSynapseClient : public CSynapseClient { public: // CSynapseClient API -bool RequestAPI( APIDescriptor_t *pAPI ); -const char* GetInfo(); + bool RequestAPI(APIDescriptor_t *pAPI); -CameraSynapseClient() { } -virtual ~CameraSynapseClient() { } -}; + const char *GetInfo(); -CSynapseServer* g_pSynapseServer = NULL; -CameraSynapseClient g_SynapseClient; + CameraSynapseClient() + {} -extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ){ - if ( strcmp( version, SYNAPSE_VERSION ) ) { - Syn_Printf( "ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version ); - return NULL; - } - g_pSynapseServer = pServer; - g_pSynapseServer->IncRef(); - Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() ); + virtual ~CameraSynapseClient() + {} +}; - g_SynapseClient.AddAPI( TOOLBAR_MAJOR, "camera", sizeof( _QERPlugToolbarTable ) ); - g_SynapseClient.AddAPI( PLUGIN_MAJOR, "camera", sizeof( _QERPluginTable ) ); +CSynapseServer *g_pSynapseServer = NULL; +CameraSynapseClient g_SynapseClient; - g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( _QERFuncTable_1 ), SYN_REQUIRE, &g_FuncTable ); - g_SynapseClient.AddAPI( UI_MAJOR, NULL, sizeof( _QERUITable ), SYN_REQUIRE, &g_UITable ); - g_SynapseClient.AddAPI( QGL_MAJOR, NULL, sizeof( _QERQglTable ), SYN_REQUIRE, &g_QglTable ); - g_SynapseClient.AddAPI( CAMERA_MAJOR, NULL, sizeof( _QERCameraTable ), SYN_REQUIRE, &g_CameraTable ); +extern "C" CSynapseClient *SYNAPSE_DLL_EXPORT - return &g_SynapseClient; +Synapse_EnumerateInterfaces(const char *version, CSynapseServer *pServer) +{ + if (strcmp(version, SYNAPSE_VERSION)) { + Syn_Printf("ERROR: synapse API version mismatch: should be '" + SYNAPSE_VERSION + "', got '%s'\n", version ); + return NULL; + } + g_pSynapseServer = pServer; + g_pSynapseServer->IncRef(); + Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf()); + + g_SynapseClient.AddAPI(TOOLBAR_MAJOR, "camera", sizeof(_QERPlugToolbarTable)); + g_SynapseClient.AddAPI(PLUGIN_MAJOR, "camera", sizeof(_QERPluginTable)); + + g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(_QERFuncTable_1), SYN_REQUIRE, &g_FuncTable); + g_SynapseClient.AddAPI(UI_MAJOR, NULL, sizeof(_QERUITable), SYN_REQUIRE, &g_UITable); + g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(_QERQglTable), SYN_REQUIRE, &g_QglTable); + g_SynapseClient.AddAPI(CAMERA_MAJOR, NULL, sizeof(_QERCameraTable), SYN_REQUIRE, &g_CameraTable); + + return &g_SynapseClient; } -bool CameraSynapseClient::RequestAPI( APIDescriptor_t *pAPI ){ - if ( !strcmp( pAPI->major_name, TOOLBAR_MAJOR ) ) { - _QERPlugToolbarTable* pTable = static_cast<_QERPlugToolbarTable*>( pAPI->mpTable ); - - pTable->m_pfnToolbarButtonCount = &ToolbarButtonCount; - pTable->m_pfnGetToolbarButton = &GetToolbarButton; - return true; - } - else if ( !strcmp( pAPI->major_name, PLUGIN_MAJOR ) ) { - _QERPluginTable* pTable = static_cast<_QERPluginTable*>( pAPI->mpTable ); - - pTable->m_pfnQERPlug_Init = QERPlug_Init; - pTable->m_pfnQERPlug_GetName = QERPlug_GetName; - pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; - pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; - return true; - } - - Syn_Printf( "ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo() ); - return false; +bool CameraSynapseClient::RequestAPI(APIDescriptor_t *pAPI) +{ + if (!strcmp(pAPI->major_name, TOOLBAR_MAJOR)) { + _QERPlugToolbarTable *pTable = static_cast<_QERPlugToolbarTable *>( pAPI->mpTable ); + + pTable->m_pfnToolbarButtonCount = &ToolbarButtonCount; + pTable->m_pfnGetToolbarButton = &GetToolbarButton; + return true; + } else if (!strcmp(pAPI->major_name, PLUGIN_MAJOR)) { + _QERPluginTable *pTable = static_cast<_QERPluginTable *>( pAPI->mpTable ); + + pTable->m_pfnQERPlug_Init = QERPlug_Init; + pTable->m_pfnQERPlug_GetName = QERPlug_GetName; + pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; + pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; + return true; + } + + Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo()); + return false; } #include "version.h" -const char* CameraSynapseClient::GetInfo(){ - return "Camera plugin v1.0 - Arnout van Meer - built " __DATE__ " " RADIANT_VERSION; +const char *CameraSynapseClient::GetInfo() +{ + return "Camera plugin v1.0 - Arnout van Meer - built " __DATE__ " " + RADIANT_VERSION; } - // // CCamera // -CCamera *AllocCam() { - if ( !firstFreeCam ) { - return( NULL ); - } - - CCamera *cam = firstFreeCam; - firstFreeCam = firstFreeCam->GetNext(); - cam->Init(); - if ( firstCam ) { - cam->SetNext( firstCam ); - firstCam->SetPrev( cam ); - } - firstCam = cam; - - return( cam ); +CCamera *AllocCam() +{ + if (!firstFreeCam) { + return (NULL); + } + + CCamera *cam = firstFreeCam; + firstFreeCam = firstFreeCam->GetNext(); + cam->Init(); + if (firstCam) { + cam->SetNext(firstCam); + firstCam->SetPrev(cam); + } + firstCam = cam; + + return (cam); } -void FreeCam( CCamera *cam ) { - if ( cam->GetPrev() ) { - if ( cam->GetNext() ) { - cam->GetPrev()->SetNext( cam->GetNext() ); - cam->GetNext()->SetPrev( cam->GetPrev() ); - } - else { - cam->GetPrev()->SetNext( NULL ); - } - } - else if ( cam->GetNext() ) { - cam->GetNext()->SetPrev( NULL ); - firstCam = cam->GetNext(); - } - else { - firstCam = NULL; - } - - cam->GetCam()->clear(); - cam->Init(); - - if ( firstFreeCam ) { - cam->SetNext( firstFreeCam ); - } - firstFreeCam = cam; +void FreeCam(CCamera *cam) +{ + if (cam->GetPrev()) { + if (cam->GetNext()) { + cam->GetPrev()->SetNext(cam->GetNext()); + cam->GetNext()->SetPrev(cam->GetPrev()); + } else { + cam->GetPrev()->SetNext(NULL); + } + } else if (cam->GetNext()) { + cam->GetNext()->SetPrev(NULL); + firstCam = cam->GetNext(); + } else { + firstCam = NULL; + } + + cam->GetCam()->clear(); + cam->Init(); + + if (firstFreeCam) { + cam->SetNext(firstFreeCam); + } + firstFreeCam = cam; } -void SetCurrentCam( CCamera *cam ) { - currentCam = cam; +void SetCurrentCam(CCamera *cam) +{ + currentCam = cam; } -CCamera *GetCurrentCam() { - return( currentCam ); +CCamera *GetCurrentCam() +{ + return (currentCam); } diff --git a/contrib/camera/camera.h b/contrib/camera/camera.h index ba008a2c..9ded6386 100644 --- a/contrib/camera/camera.h +++ b/contrib/camera/camera.h @@ -35,11 +35,14 @@ typedef unsigned char byte; #include #define USE_QERTABLE_DEFINE + #include "iscenegraph.h" #include "qerplugin.h" #define USE_QGLTABLE_DEFINE + #include "igl.h" + extern _QERQglTable __QGLTABLENAME; #include "iui.h" @@ -63,12 +66,12 @@ extern _QERQglTable g_QglTable; extern _QERUITable g_UITable; extern _QERCameraTable g_CameraTable; -extern CRenderer *Renderer; -extern CListener *Listener; +extern CRenderer *Renderer; +extern CListener *Listener; // splinelib #define CAMERA_PLUGIN -#define DotProduct( a,b ) ( ( a )[0] * ( b )[0] + ( a )[1] * ( b )[1] + ( a )[2] * ( b )[2] ) +#define DotProduct(a, b) ( ( a )[0] * ( b )[0] + ( a )[1] * ( b )[1] + ( a )[2] * ( b )[2] ) #include "splines/splines.h" @@ -76,7 +79,7 @@ extern CListener *Listener; #define MAX_CAMERAS 64 extern idCameraDef camera[MAX_CAMERAS]; -extern "C" qboolean loadCamera( int camNum, const char *name ); +extern "C" qboolean loadCamera(int camNum, const char *name); #ifndef PATH_MAX #define PATH_MAX 260 @@ -88,71 +91,91 @@ extern "C" qboolean loadCamera( int camNum, const char *name ); class CCamera { public: -CCamera( int i ) { - cam = &camera[i]; - camnum = i; - Init(); -} -~CCamera(); - -void Init() { - next = prev = NULL; - fileName[0] = '\0'; - hasbeensaved = 0; -} - -idCameraDef *GetCam() { - return( cam ); -} -int GetCamNum() { - return( camnum ); -} - -char *GetFileName() { - return( fileName ); -} -void SetFileName( const char *name, bool save ) { - strcpy( fileName, name ); - if ( save ) { - hasbeensaved = 1; - } -} - -CCamera *GetNext() { - return( next ); -} - -CCamera *GetPrev() { - return( prev ); -} - -void SetNext( CCamera *camera ) { - next = camera; -} -void SetPrev( CCamera *camera ) { - prev = camera; -} - -int HasBeenSaved() { - return( hasbeensaved ); -} -void HasBeenModified() { - if ( hasbeensaved ) { - hasbeensaved = 2; - } -} + CCamera(int i) + { + cam = &camera[i]; + camnum = i; + Init(); + } + + ~CCamera(); + + void Init() + { + next = prev = NULL; + fileName[0] = '\0'; + hasbeensaved = 0; + } + + idCameraDef *GetCam() + { + return (cam); + } + + int GetCamNum() + { + return (camnum); + } + + char *GetFileName() + { + return (fileName); + } + + void SetFileName(const char *name, bool save) + { + strcpy(fileName, name); + if (save) { + hasbeensaved = 1; + } + } + + CCamera *GetNext() + { + return (next); + } + + CCamera *GetPrev() + { + return (prev); + } + + void SetNext(CCamera *camera) + { + next = camera; + } + + void SetPrev(CCamera *camera) + { + prev = camera; + } + + int HasBeenSaved() + { + return (hasbeensaved); + } + + void HasBeenModified() + { + if (hasbeensaved) { + hasbeensaved = 2; + } + } protected: -idCameraDef *cam; -int camnum; -CCamera *next, *prev; -char fileName[PATH_MAX]; -int hasbeensaved; // 0:never saved 1:saved 2:saved, but modified + idCameraDef *cam; + int camnum; + CCamera *next, *prev; + char fileName[PATH_MAX]; + int hasbeensaved; // 0:never saved 1:saved 2:saved, but modified }; CCamera *AllocCam(); -void FreeCam( CCamera *cam ); -void SetCurrentCam( CCamera *cam ); + +void FreeCam(CCamera *cam); + +void SetCurrentCam(CCamera *cam); + CCamera *GetCurrentCam(); // globals diff --git a/contrib/camera/dialogs.cpp b/contrib/camera/dialogs.cpp index 5bcd984d..13746e09 100644 --- a/contrib/camera/dialogs.cpp +++ b/contrib/camera/dialogs.cpp @@ -38,16 +38,18 @@ static GtkWidget *g_pTrackCamera = NULL; static GtkWidget *g_pCamName = NULL; static char *g_cNull = '\0'; -static gint ci_editmode_edit( GtkWidget *widget, gpointer data ){ - g_iEditMode = 0; +static gint ci_editmode_edit(GtkWidget *widget, gpointer data) +{ + g_iEditMode = 0; - return TRUE; + return TRUE; } -static gint ci_editmode_add( GtkWidget *widget, gpointer data ){ - g_iEditMode = 1; +static gint ci_editmode_add(GtkWidget *widget, gpointer data) +{ + g_iEditMode = 1; - return TRUE; + return TRUE; } /*static gint ci_delete_selected( GtkWidget *widget, gpointer data ) @@ -60,1295 +62,1309 @@ static gint ci_editmode_add( GtkWidget *widget, gpointer data ){ return TRUE; }*/ -static gint ci_new( GtkWidget *widget, gpointer data ){ - GtkWidget *w, *hbox; //, *name; - GtkWidget *fixed, *interpolated, *spline; - EMessageBoxReturn ret; - int loop = 1; - GSList *targetTypeRadio = NULL; +static gint ci_new(GtkWidget *widget, gpointer data) +{ + GtkWidget *w, *hbox; //, *name; + GtkWidget *fixed, *interpolated, *spline; + EMessageBoxReturn ret; + int loop = 1; + GSList *targetTypeRadio = NULL; // char buf[128]; - // create the window - auto window = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( window, "New Camera" ); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); - gtk_window_set_transient_for( window, g_pCameraInspectorWnd ); + // create the window + auto window = ui::Window(ui::window_type::TOP); + gtk_window_set_title(window, "New Camera"); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_window_set_transient_for(window, g_pCameraInspectorWnd); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - gtk_widget_realize( window ); + gtk_widget_realize(window); - // fill the window - auto vbox = ui::VBox( FALSE, 5 ); - window.add(vbox); - vbox.show(); + // fill the window + auto vbox = ui::VBox(FALSE, 5); + window.add(vbox); + vbox.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto frame = ui::Frame( "Type" ); - hbox.pack_start( frame, TRUE, TRUE, 0 ); - frame.show(); + auto frame = ui::Frame("Type"); + hbox.pack_start(frame, TRUE, TRUE, 0); + frame.show(); - auto vbox2 = ui::VBox( FALSE, 5 ); - frame.add(vbox2); - gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 5 ); - vbox2.show(); + auto vbox2 = ui::VBox(FALSE, 5); + frame.add(vbox2); + gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); + vbox2.show(); - // -------------------------- // + // -------------------------- // - fixed = gtk_radio_button_new_with_label( targetTypeRadio, "Fixed" ); - vbox2.pack_start( fixed, FALSE, FALSE, 3 ); - fixed.show(); - targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( fixed ) ); + fixed = gtk_radio_button_new_with_label(targetTypeRadio, "Fixed"); + vbox2.pack_start(fixed, FALSE, FALSE, 3); + fixed.show(); + targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(fixed)); - interpolated = gtk_radio_button_new_with_label( targetTypeRadio, "Interpolated" ); - vbox2.pack_start( interpolated, FALSE, FALSE, 3 ); - interpolated.show(); - targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( interpolated ) ); + interpolated = gtk_radio_button_new_with_label(targetTypeRadio, "Interpolated"); + vbox2.pack_start(interpolated, FALSE, FALSE, 3); + interpolated.show(); + targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(interpolated)); - spline = gtk_radio_button_new_with_label( targetTypeRadio, "Spline" ); - vbox2.pack_start( spline, FALSE, FALSE, 3 ); - spline.show(); - targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( spline ) ); + spline = gtk_radio_button_new_with_label(targetTypeRadio, "Spline"); + vbox2.pack_start(spline, FALSE, FALSE, 3); + spline.show(); + targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(spline)); - // -------------------------- // + // -------------------------- // - w = gtk_hseparator_new(); - vbox.pack_start( w, FALSE, FALSE, 2 ); - w.show(); + w = gtk_hseparator_new(); + vbox.pack_start(w, FALSE, FALSE, 2); + w.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - w.show(); + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + w.show(); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; - // -------------------------- // + // -------------------------- // - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - bool dialogError = TRUE; - while ( dialogError ) { - loop = 1; - while ( loop ) - gtk_main_iteration(); + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } - dialogError = FALSE; + dialogError = FALSE; - if ( ret == eIDOK ) { - if ( gtk_toggle_button_get_active( (GtkToggleButton*)fixed ) ) { - DoNewFixedCamera(); - } - else if ( gtk_toggle_button_get_active( (GtkToggleButton*)interpolated ) ) { - DoNewInterpolatedCamera(); - } - else if ( gtk_toggle_button_get_active( (GtkToggleButton*)spline ) ) { - DoNewSplineCamera(); - } - } - } - - gtk_grab_remove( window ); - window.destroy(); + if (ret == eIDOK) { + if (gtk_toggle_button_get_active((GtkToggleButton *) fixed)) { + DoNewFixedCamera(); + } else if (gtk_toggle_button_get_active((GtkToggleButton *) interpolated)) { + DoNewInterpolatedCamera(); + } else if (gtk_toggle_button_get_active((GtkToggleButton *) spline)) { + DoNewSplineCamera(); + } + } + } + + gtk_grab_remove(window); + window.destroy(); - return TRUE; + return TRUE; } -static gint ci_load( GtkWidget *widget, gpointer data ){ - DoLoadCamera(); +static gint ci_load(GtkWidget *widget, gpointer data) +{ + DoLoadCamera(); - return TRUE; + return TRUE; } -static gint ci_save( GtkWidget *widget, gpointer data ){ - DoSaveCamera(); +static gint ci_save(GtkWidget *widget, gpointer data) +{ + DoSaveCamera(); - return TRUE; + return TRUE; } -static gint ci_unload( GtkWidget *widget, gpointer data ){ - DoUnloadCamera(); +static gint ci_unload(GtkWidget *widget, gpointer data) +{ + DoUnloadCamera(); - return TRUE; + return TRUE; } -static gint ci_apply( GtkWidget *widget, gpointer data ){ - if ( GetCurrentCam() ) { - const char *str; - char buf[128]; - bool build = false; +static gint ci_apply(GtkWidget *widget, gpointer data) +{ + if (GetCurrentCam()) { + const char *str; + char buf[128]; + bool build = false; - str = gtk_entry_get_text( GTK_ENTRY( g_pCamName ) ); + str = gtk_entry_get_text(GTK_ENTRY(g_pCamName)); - if ( str ) { - GetCurrentCam()->GetCam()->setName( str ); - build = true; - } + if (str) { + GetCurrentCam()->GetCam()->setName(str); + build = true; + } - str = gtk_entry_get_text( GTK_ENTRY( g_pSecondsEntry ) ); + str = gtk_entry_get_text(GTK_ENTRY(g_pSecondsEntry)); - if ( str ) { - GetCurrentCam()->GetCam()->setBaseTime( atof( str ) ); - build = true; - } + if (str) { + GetCurrentCam()->GetCam()->setBaseTime(atof(str)); + build = true; + } - if ( build ) { - GetCurrentCam()->GetCam()->buildCamera(); - } + if (build) { + GetCurrentCam()->GetCam()->buildCamera(); + } - sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getBaseTime() ); - gtk_entry_set_text( GTK_ENTRY( g_pSecondsEntry ), buf ); + sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getBaseTime()); + gtk_entry_set_text(GTK_ENTRY(g_pSecondsEntry), buf); - sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime() ); - gtk_label_set_text( g_pCurrentTime, "0.00" ); - gtk_label_set_text( g_pTotalTime, buf ); + sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime()); + gtk_label_set_text(g_pCurrentTime, "0.00"); + gtk_label_set_text(g_pTotalTime, buf); - gtk_adjustment_set_value( g_pTimeLine, 0.f ); - g_pTimeLine->upper = GetCurrentCam()->GetCam()->getTotalTime() * 1000; + gtk_adjustment_set_value(g_pTimeLine, 0.f); + g_pTimeLine->upper = GetCurrentCam()->GetCam()->getTotalTime() * 1000; - GetCurrentCam()->HasBeenModified(); - } + GetCurrentCam()->HasBeenModified(); + } - return TRUE; + return TRUE; } -static gint ci_preview( GtkWidget *widget, gpointer data ){ - if ( GetCurrentCam() ) { - g_iPreviewRunning = 1; - g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA ); - } +static gint ci_preview(GtkWidget *widget, gpointer data) +{ + if (GetCurrentCam()) { + g_iPreviewRunning = 1; + g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA); + } - return TRUE; + return TRUE; } -static gint ci_expose( GtkWidget *widget, gpointer data ){ - // start edit mode - DoStartEdit( GetCurrentCam() ); +static gint ci_expose(GtkWidget *widget, gpointer data) +{ + // start edit mode + DoStartEdit(GetCurrentCam()); - return FALSE; + return FALSE; } -static gint ci_close( GtkWidget *widget, gpointer data ){ - gtk_widget_hide( g_pCameraInspectorWnd ); +static gint ci_close(GtkWidget *widget, gpointer data) +{ + gtk_widget_hide(g_pCameraInspectorWnd); - // exit edit mode - DoStopEdit(); + // exit edit mode + DoStopEdit(); - return TRUE; + return TRUE; } static GtkWidget *g_pPathListCombo = NULL; static GtkLabel *g_pPathType = NULL; -static void RefreshPathListCombo( void ){ - if ( !g_pPathListCombo ) { - return; - } - - GList *combo_list = (GList*)NULL; - - if ( GetCurrentCam() ) { - combo_list = g_list_append( combo_list, (void *)GetCurrentCam()->GetCam()->getPositionObj()->getName() ); - for ( int i = 0; i < GetCurrentCam()->GetCam()->numTargets(); i++ ) { - combo_list = g_list_append( combo_list, (void *)GetCurrentCam()->GetCam()->getActiveTarget( i )->getName() ); - } - } - else { - // add one empty string make gtk be quiet - combo_list = g_list_append( combo_list, (gpointer)g_cNull ); - } - - gtk_combo_set_popdown_strings( GTK_COMBO( g_pPathListCombo ), combo_list ); - g_list_free( combo_list ); +static void RefreshPathListCombo(void) +{ + if (!g_pPathListCombo) { + return; + } + + GList *combo_list = (GList *) NULL; + + if (GetCurrentCam()) { + combo_list = g_list_append(combo_list, (void *) GetCurrentCam()->GetCam()->getPositionObj()->getName()); + for (int i = 0; i < GetCurrentCam()->GetCam()->numTargets(); i++) { + combo_list = g_list_append(combo_list, (void *) GetCurrentCam()->GetCam()->getActiveTarget(i)->getName()); + } + } else { + // add one empty string make gtk be quiet + combo_list = g_list_append(combo_list, (gpointer) g_cNull); + } + + gtk_combo_set_popdown_strings(GTK_COMBO(g_pPathListCombo), combo_list); + g_list_free(combo_list); } -static gint ci_pathlist_changed( GtkWidget *widget, gpointer data ){ - const char *str = gtk_entry_get_text( GTK_ENTRY( widget ) ); - - if ( !str || !GetCurrentCam() ) { - return TRUE; - } - - int i; - for ( i = 0; i < GetCurrentCam()->GetCam()->numTargets(); i++ ) { - if ( !strcmp( str, GetCurrentCam()->GetCam()->getActiveTarget( i )->getName() ) ) { - break; - } - } - - if ( i >= 0 && i < GetCurrentCam()->GetCam()->numTargets() ) { - GetCurrentCam()->GetCam()->setActiveTarget( i ); - - g_iActiveTarget = i; - if ( g_pPathType ) { - gtk_label_set_text( g_pPathType, GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget )->typeStr() ); - } - } - else { - g_iActiveTarget = -1; - if ( g_pPathType ) { - gtk_label_set_text( g_pPathType, GetCurrentCam()->GetCam()->getPositionObj()->typeStr() ); - } - } - - // start edit mode - if ( g_pCameraInspectorWnd && gtk_widget_get_visible( g_pCameraInspectorWnd ) ) { - DoStartEdit( GetCurrentCam() ); - } - - return TRUE; +static gint ci_pathlist_changed(GtkWidget *widget, gpointer data) +{ + const char *str = gtk_entry_get_text(GTK_ENTRY(widget)); + + if (!str || !GetCurrentCam()) { + return TRUE; + } + + int i; + for (i = 0; i < GetCurrentCam()->GetCam()->numTargets(); i++) { + if (!strcmp(str, GetCurrentCam()->GetCam()->getActiveTarget(i)->getName())) { + break; + } + } + + if (i >= 0 && i < GetCurrentCam()->GetCam()->numTargets()) { + GetCurrentCam()->GetCam()->setActiveTarget(i); + + g_iActiveTarget = i; + if (g_pPathType) { + gtk_label_set_text(g_pPathType, GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget)->typeStr()); + } + } else { + g_iActiveTarget = -1; + if (g_pPathType) { + gtk_label_set_text(g_pPathType, GetCurrentCam()->GetCam()->getPositionObj()->typeStr()); + } + } + + // start edit mode + if (g_pCameraInspectorWnd && gtk_widget_get_visible(g_pCameraInspectorWnd)) { + DoStartEdit(GetCurrentCam()); + } + + return TRUE; } -static void RefreshEventList( void ){ - int i; - char buf[128]; - - // Clear events list - gtk_clist_freeze( GTK_CLIST( g_pEventsList ) ); - gtk_clist_clear( GTK_CLIST( g_pEventsList ) ); - - if ( GetCurrentCam() ) { - // Fill events list - for ( i = 0; i < GetCurrentCam()->GetCam()->numEvents(); i++ ) { - char rowbuf[3][128], *row[3]; - // FIXME: sort by time? - sprintf( rowbuf[0], "%li", GetCurrentCam()->GetCam()->getEvent( i )->getTime() ); row[0] = rowbuf[0]; - strncpy( rowbuf[1], GetCurrentCam()->GetCam()->getEvent( i )->typeStr(), sizeof( rowbuf[0] ) ); row[1] = rowbuf[1]; - strncpy( rowbuf[2], GetCurrentCam()->GetCam()->getEvent( i )->getParam(), sizeof( rowbuf[1] ) ); row[2] = rowbuf[2]; - gtk_clist_append( GTK_CLIST( g_pEventsList ), row ); - } - - // Total duration might have changed - sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime() ); - gtk_label_set_text( g_pCurrentTime, "0.00" ); - gtk_label_set_text( g_pTotalTime, buf ); - - gtk_adjustment_set_value( g_pTimeLine, 0.f ); - g_pTimeLine->upper = ( GetCurrentCam()->GetCam()->getTotalTime() * 1000 ); - } - - gtk_clist_thaw( GTK_CLIST( g_pEventsList ) ); +static void RefreshEventList(void) +{ + int i; + char buf[128]; + + // Clear events list + gtk_clist_freeze(GTK_CLIST(g_pEventsList)); + gtk_clist_clear(GTK_CLIST(g_pEventsList)); + + if (GetCurrentCam()) { + // Fill events list + for (i = 0; i < GetCurrentCam()->GetCam()->numEvents(); i++) { + char rowbuf[3][128], *row[3]; + // FIXME: sort by time? + sprintf(rowbuf[0], "%li", GetCurrentCam()->GetCam()->getEvent(i)->getTime()); + row[0] = rowbuf[0]; + strncpy(rowbuf[1], GetCurrentCam()->GetCam()->getEvent(i)->typeStr(), sizeof(rowbuf[0])); + row[1] = rowbuf[1]; + strncpy(rowbuf[2], GetCurrentCam()->GetCam()->getEvent(i)->getParam(), sizeof(rowbuf[1])); + row[2] = rowbuf[2]; + gtk_clist_append(GTK_CLIST(g_pEventsList), row); + } + + // Total duration might have changed + sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime()); + gtk_label_set_text(g_pCurrentTime, "0.00"); + gtk_label_set_text(g_pTotalTime, buf); + + gtk_adjustment_set_value(g_pTimeLine, 0.f); + g_pTimeLine->upper = (GetCurrentCam()->GetCam()->getTotalTime() * 1000); + } + + gtk_clist_thaw(GTK_CLIST(g_pEventsList)); } -static gint ci_rename( GtkWidget *widget, gpointer data ){ - GtkWidget *w, *hbox, *name; - EMessageBoxReturn ret; - int loop = 1; +static gint ci_rename(GtkWidget *widget, gpointer data) +{ + GtkWidget *w, *hbox, *name; + EMessageBoxReturn ret; + int loop = 1; - if ( !GetCurrentCam() ) { - return TRUE; - } - - // create the window - auto window = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( window, "Rename Path" ); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); - gtk_window_set_transient_for( window, g_pCameraInspectorWnd ); + if (!GetCurrentCam()) { + return TRUE; + } - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + // create the window + auto window = ui::Window(ui::window_type::TOP); + gtk_window_set_title(window, "Rename Path"); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_window_set_transient_for(window, g_pCameraInspectorWnd); - gtk_widget_realize( window ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - // fill the window - auto vbox = ui::VBox( FALSE, 5 ); - window.add(vbox); - vbox.show(); + gtk_widget_realize(window); - // -------------------------- // + // fill the window + auto vbox = ui::VBox(FALSE, 5); + window.add(vbox); + vbox.show(); - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + // -------------------------- // - w = ui::Label( "Name:" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - name = ui::Entry(); - hbox.pack_start( name, FALSE, FALSE, 0 ); - name.show(); + w = ui::Label("Name:"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - if ( g_iActiveTarget < 0 ) { - gtk_entry_set_text( GTK_ENTRY( name ), GetCurrentCam()->GetCam()->getPositionObj()->getName() ); - } - else{ - gtk_entry_set_text( GTK_ENTRY( name ), GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget )->getName() ); - } + name = ui::Entry(); + hbox.pack_start(name, FALSE, FALSE, 0); + name.show(); - // -------------------------- // + if (g_iActiveTarget < 0) { + gtk_entry_set_text(GTK_ENTRY(name), GetCurrentCam()->GetCam()->getPositionObj()->getName()); + } else { + gtk_entry_set_text(GTK_ENTRY(name), GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget)->getName()); + } - w = gtk_hseparator_new(); - vbox.pack_start( w, FALSE, FALSE, 2 ); - w.show(); + // -------------------------- // - // -------------------------- // + w = gtk_hseparator_new(); + vbox.pack_start(w, FALSE, FALSE, 2); + w.show(); - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + // -------------------------- // - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - w.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + w.show(); - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); - // -------------------------- // + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + // -------------------------- // - bool dialogError = TRUE; - while ( dialogError ) { - loop = 1; - while ( loop ) - gtk_main_iteration(); + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - dialogError = FALSE; + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } - if ( ret == eIDOK ) { - const char *str = gtk_entry_get_text( GTK_ENTRY( name ) ); + dialogError = FALSE; - if ( str && str[0] ) { - // Update the path - if ( g_iActiveTarget < 0 ) { - GetCurrentCam()->GetCam()->getPositionObj()->setName( str ); - } - else{ - GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget )->setName( str ); - } + if (ret == eIDOK) { + const char *str = gtk_entry_get_text(GTK_ENTRY(name)); - GetCurrentCam()->GetCam()->buildCamera(); - - // Rebuild the listbox - RefreshPathListCombo(); - } - else { - dialogError = TRUE; - } - } - } - - gtk_grab_remove( window ); - window.destroy(); + if (str && str[0]) { + // Update the path + if (g_iActiveTarget < 0) { + GetCurrentCam()->GetCam()->getPositionObj()->setName(str); + } else { + GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget)->setName(str); + } - return TRUE; + GetCurrentCam()->GetCam()->buildCamera(); + + // Rebuild the listbox + RefreshPathListCombo(); + } else { + dialogError = TRUE; + } + } + } + + gtk_grab_remove(window); + window.destroy(); + + return TRUE; } -static gint ci_add_target( GtkWidget *widget, gpointer data ){ - GtkWidget *w, *hbox, *name; - GtkWidget *fixed, *interpolated, *spline; - EMessageBoxReturn ret; - int loop = 1; - GSList *targetTypeRadio = NULL; - char buf[128]; +static gint ci_add_target(GtkWidget *widget, gpointer data) +{ + GtkWidget *w, *hbox, *name; + GtkWidget *fixed, *interpolated, *spline; + EMessageBoxReturn ret; + int loop = 1; + GSList *targetTypeRadio = NULL; + char buf[128]; + + if (!GetCurrentCam()) { + return TRUE; + } - if ( !GetCurrentCam() ) { - return TRUE; - } + // create the window + auto window = ui::Window(ui::window_type::TOP); + gtk_window_set_title(window, "Add Target"); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_window_set_transient_for(window, g_pCameraInspectorWnd); - // create the window - auto window = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( window, "Add Target" ); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); - gtk_window_set_transient_for( window, g_pCameraInspectorWnd ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + gtk_widget_realize(window); - gtk_widget_realize( window ); + // fill the window + auto vbox = ui::VBox(FALSE, 5); + window.add(vbox); + vbox.show(); - // fill the window - auto vbox = ui::VBox( FALSE, 5 ); - window.add(vbox); - vbox.show(); + // -------------------------- // - // -------------------------- // + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + w = ui::Label("Name:"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - w = ui::Label( "Name:" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + name = ui::Entry(); + hbox.pack_start(name, TRUE, TRUE, 0); + name.show(); - name = ui::Entry(); - hbox.pack_start( name, TRUE, TRUE, 0 ); - name.show(); + sprintf(buf, "target%i", GetCurrentCam()->GetCam()->numTargets() + 1); + gtk_entry_set_text(GTK_ENTRY(name), buf); - sprintf( buf, "target%i", GetCurrentCam()->GetCam()->numTargets() + 1 ); - gtk_entry_set_text( GTK_ENTRY( name ), buf ); + // -------------------------- // - // -------------------------- // + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + auto frame = ui::Frame("Type"); + hbox.pack_start(frame, TRUE, TRUE, 0); + frame.show(); - auto frame = ui::Frame( "Type" ); - hbox.pack_start( frame, TRUE, TRUE, 0 ); - frame.show(); + auto vbox2 = ui::VBox(FALSE, 5); + frame.add(vbox2); + gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); + vbox2.show(); - auto vbox2 = ui::VBox( FALSE, 5 ); - frame.add(vbox2); - gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 5 ); - vbox2.show(); + // -------------------------- // - // -------------------------- // + fixed = gtk_radio_button_new_with_label(targetTypeRadio, "Fixed"); + vbox2.pack_start(fixed, FALSE, FALSE, 3); + fixed.show(); + targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(fixed)); - fixed = gtk_radio_button_new_with_label( targetTypeRadio, "Fixed" ); - vbox2.pack_start( fixed, FALSE, FALSE, 3 ); - fixed.show(); - targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( fixed ) ); + interpolated = gtk_radio_button_new_with_label(targetTypeRadio, "Interpolated"); + vbox2.pack_start(interpolated, FALSE, FALSE, 3); + interpolated.show(); + targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(interpolated)); - interpolated = gtk_radio_button_new_with_label( targetTypeRadio, "Interpolated" ); - vbox2.pack_start( interpolated, FALSE, FALSE, 3 ); - interpolated.show(); - targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( interpolated ) ); + spline = gtk_radio_button_new_with_label(targetTypeRadio, "Spline"); + vbox2.pack_start(spline, FALSE, FALSE, 3); + spline.show(); + targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(spline)); - spline = gtk_radio_button_new_with_label( targetTypeRadio, "Spline" ); - vbox2.pack_start( spline, FALSE, FALSE, 3 ); - spline.show(); - targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( spline ) ); + // -------------------------- // - // -------------------------- // + w = gtk_hseparator_new(); + vbox.pack_start(w, FALSE, FALSE, 2); + w.show(); - w = gtk_hseparator_new(); - vbox.pack_start( w, FALSE, FALSE, 2 ); - w.show(); + // -------------------------- // - // -------------------------- // + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + w.show(); - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - w.show(); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; + // -------------------------- // - // -------------------------- // + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } - bool dialogError = TRUE; - while ( dialogError ) { - loop = 1; - while ( loop ) - gtk_main_iteration(); + dialogError = FALSE; - dialogError = FALSE; + if (ret == eIDOK) { + const char *str = gtk_entry_get_text(GTK_ENTRY(name)); - if ( ret == eIDOK ) { - const char *str = gtk_entry_get_text( GTK_ENTRY( name ) ); + if (str && str[0]) { + int type; + GList *li; - if ( str && str[0] ) { - int type; - GList *li; + if (gtk_toggle_button_get_active((GtkToggleButton *) fixed)) { + type = 0; + } else if (gtk_toggle_button_get_active((GtkToggleButton *) interpolated)) { + type = 1; + } else if (gtk_toggle_button_get_active((GtkToggleButton *) spline)) { + type = 2; + } - if ( gtk_toggle_button_get_active( (GtkToggleButton*)fixed ) ) { - type = 0; - } - else if ( gtk_toggle_button_get_active( (GtkToggleButton*)interpolated ) ) { - type = 1; - } - else if ( gtk_toggle_button_get_active( (GtkToggleButton*)spline ) ) { - type = 2; - } + // Add the target + GetCurrentCam()->GetCam()->addTarget(str, static_cast( type )); - // Add the target - GetCurrentCam()->GetCam()->addTarget( str, static_cast( type ) ); + // Rebuild the listbox + RefreshPathListCombo(); - // Rebuild the listbox - RefreshPathListCombo(); + // Select the last item in the listbox + li = g_list_last(GTK_LIST(GTK_COMBO(g_pPathListCombo)->list)->children); + gtk_list_select_child(GTK_LIST(GTK_COMBO(g_pPathListCombo)->list), li->data); - // Select the last item in the listbox - li = g_list_last( GTK_LIST( GTK_COMBO( g_pPathListCombo )->list )->children ); - gtk_list_select_child( GTK_LIST( GTK_COMBO( g_pPathListCombo )->list ), li->data ); + // If this was the first one, refresh the event list + if (GetCurrentCam()->GetCam()->numTargets() == 1) { + RefreshEventList(); + } - // If this was the first one, refresh the event list - if ( GetCurrentCam()->GetCam()->numTargets() == 1 ) { - RefreshEventList(); - } + // Go to editmode Add + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_pEditModeAddRadioButton), TRUE); - // Go to editmode Add - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_pEditModeAddRadioButton ), TRUE ); - - } - else { - dialogError = TRUE; - } - } - } + } else { + dialogError = TRUE; + } + } + } - gtk_grab_remove( window ); - window.destroy(); + gtk_grab_remove(window); + window.destroy(); - return TRUE; + return TRUE; } static GtkWidget *g_pCamListCombo = NULL; static GtkLabel *g_pCamType = NULL; -void RefreshCamListCombo( void ){ - if ( !g_pCamListCombo ) { - return; - } - - GList *combo_list = (GList*)NULL; - CCamera *combo_cam = firstCam; - if ( combo_cam ) { - while ( combo_cam ) { - //combo_list = g_list_append( combo_list, (void *)combo_cam->GetCam()->getName() ); - //if( combo_cam->HasBeenSaved() ) { - combo_list = g_list_append( combo_list, (void *)combo_cam->GetFileName() ); - /*} else { - char buf[128]; - sprintf( buf, "Unsaved Camera %i", combo_cam->GetCamNum() ); - combo_list = g_list_append( combo_list, (void *)buf ); - - //combo_list = g_list_append( combo_list, (void *)combo_cam->GetCam()->getName() ); // FIXME: this requires camera.dll to create unique names for new cams - }*/ - combo_cam = combo_cam->GetNext(); - } - } - else { - // add one empty string make gtk be quiet - combo_list = g_list_append( combo_list, (gpointer)g_cNull ); - } - gtk_combo_set_popdown_strings( GTK_COMBO( g_pCamListCombo ), combo_list ); - g_list_free( combo_list ); - - // select our current entry in the list - if ( GetCurrentCam() ) { - // stop editing on the current cam - //GetCurrentCam()->GetCam()->stopEdit(); // FIXME: this crashed on creating new cameras, why is it here? - - GList *li = GTK_LIST( GTK_COMBO( g_pCamListCombo )->list )->children; - combo_cam = firstCam; - while ( li && combo_cam ) { - if ( combo_cam == GetCurrentCam() ) { - gtk_list_select_child( GTK_LIST( GTK_COMBO( g_pCamListCombo )->list ), li->data ); - break; - } - li = li->next; - combo_cam = combo_cam->GetNext(); - } - } - - RefreshPathListCombo(); +void RefreshCamListCombo(void) +{ + if (!g_pCamListCombo) { + return; + } + + GList *combo_list = (GList *) NULL; + CCamera *combo_cam = firstCam; + if (combo_cam) { + while (combo_cam) { + //combo_list = g_list_append( combo_list, (void *)combo_cam->GetCam()->getName() ); + //if( combo_cam->HasBeenSaved() ) { + combo_list = g_list_append(combo_list, (void *) combo_cam->GetFileName()); + /*} else { + char buf[128]; + sprintf( buf, "Unsaved Camera %i", combo_cam->GetCamNum() ); + combo_list = g_list_append( combo_list, (void *)buf ); + + //combo_list = g_list_append( combo_list, (void *)combo_cam->GetCam()->getName() ); // FIXME: this requires camera.dll to create unique names for new cams + }*/ + combo_cam = combo_cam->GetNext(); + } + } else { + // add one empty string make gtk be quiet + combo_list = g_list_append(combo_list, (gpointer) g_cNull); + } + gtk_combo_set_popdown_strings(GTK_COMBO(g_pCamListCombo), combo_list); + g_list_free(combo_list); + + // select our current entry in the list + if (GetCurrentCam()) { + // stop editing on the current cam + //GetCurrentCam()->GetCam()->stopEdit(); // FIXME: this crashed on creating new cameras, why is it here? + + GList *li = GTK_LIST(GTK_COMBO(g_pCamListCombo)->list)->children; + combo_cam = firstCam; + while (li && combo_cam) { + if (combo_cam == GetCurrentCam()) { + gtk_list_select_child(GTK_LIST(GTK_COMBO(g_pCamListCombo)->list), li->data); + break; + } + li = li->next; + combo_cam = combo_cam->GetNext(); + } + } + + RefreshPathListCombo(); } -static gint ci_camlist_changed( GtkWidget *widget, gpointer data ){ - const char *str = gtk_entry_get_text( GTK_ENTRY( widget ) ); - - CCamera *combo_cam = firstCam; - while ( str && combo_cam ) { - //if( !strcmp( str, combo_cam->GetCam()->getName() ) ) - //if( combo_cam->HasBeenSaved() ) { - if ( !strcmp( str, combo_cam->GetFileName() ) ) { - break; - } - /*} else { - char buf[128]; - sprintf( buf, "Unsaved Camera %i", combo_cam->GetCamNum() ); - if( !strcmp( str, buf ) ) - //if( !strcmp( str, combo_cam->GetCam()->getName() ) ) - break; - }*/ - - combo_cam = combo_cam->GetNext(); - } - - SetCurrentCam( combo_cam ); - - if ( g_pCamType ) { - if ( GetCurrentCam() ) { - // Fill in our widgets fields for this camera - char buf[128]; - - // Set Name - gtk_entry_set_text( GTK_ENTRY( g_pCamName ), GetCurrentCam()->GetCam()->getName() ); - - // Set type - gtk_label_set_text( g_pCamType, GetCurrentCam()->GetCam()->getPositionObj()->typeStr() ); - - // Set duration - sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getBaseTime() ); - gtk_entry_set_text( GTK_ENTRY( g_pSecondsEntry ), buf ); - - sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime() ); - gtk_label_set_text( g_pCurrentTime, "0.00" ); - gtk_label_set_text( g_pTotalTime, buf ); - - gtk_adjustment_set_value( g_pTimeLine, 0.f ); - g_pTimeLine->upper = GetCurrentCam()->GetCam()->getTotalTime() * 1000; - } - else { - // Set Name - gtk_entry_set_text( GTK_ENTRY( g_pCamName ), "" ); - - // Set type - gtk_label_set_text( g_pCamType, "" ); - - // Set duration - gtk_entry_set_text( GTK_ENTRY( g_pSecondsEntry ), "30.00" ); - - gtk_label_set_text( g_pCurrentTime, "0.00" ); - gtk_label_set_text( g_pTotalTime, "30.00" ); - - gtk_adjustment_set_value( g_pTimeLine, 0.f ); - g_pTimeLine->upper = 30000; - } - - // Refresh event list - RefreshEventList(); - } - - RefreshPathListCombo(); - - // start edit mode - g_iActiveTarget = -1; - if ( g_pCameraInspectorWnd && gtk_widget_get_visible( g_pCameraInspectorWnd ) ) { - DoStartEdit( GetCurrentCam() ); - } - - return TRUE; +static gint ci_camlist_changed(GtkWidget *widget, gpointer data) +{ + const char *str = gtk_entry_get_text(GTK_ENTRY(widget)); + + CCamera *combo_cam = firstCam; + while (str && combo_cam) { + //if( !strcmp( str, combo_cam->GetCam()->getName() ) ) + //if( combo_cam->HasBeenSaved() ) { + if (!strcmp(str, combo_cam->GetFileName())) { + break; + } + /*} else { + char buf[128]; + sprintf( buf, "Unsaved Camera %i", combo_cam->GetCamNum() ); + if( !strcmp( str, buf ) ) + //if( !strcmp( str, combo_cam->GetCam()->getName() ) ) + break; + }*/ + + combo_cam = combo_cam->GetNext(); + } + + SetCurrentCam(combo_cam); + + if (g_pCamType) { + if (GetCurrentCam()) { + // Fill in our widgets fields for this camera + char buf[128]; + + // Set Name + gtk_entry_set_text(GTK_ENTRY(g_pCamName), GetCurrentCam()->GetCam()->getName()); + + // Set type + gtk_label_set_text(g_pCamType, GetCurrentCam()->GetCam()->getPositionObj()->typeStr()); + + // Set duration + sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getBaseTime()); + gtk_entry_set_text(GTK_ENTRY(g_pSecondsEntry), buf); + + sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime()); + gtk_label_set_text(g_pCurrentTime, "0.00"); + gtk_label_set_text(g_pTotalTime, buf); + + gtk_adjustment_set_value(g_pTimeLine, 0.f); + g_pTimeLine->upper = GetCurrentCam()->GetCam()->getTotalTime() * 1000; + } else { + // Set Name + gtk_entry_set_text(GTK_ENTRY(g_pCamName), ""); + + // Set type + gtk_label_set_text(g_pCamType, ""); + + // Set duration + gtk_entry_set_text(GTK_ENTRY(g_pSecondsEntry), "30.00"); + + gtk_label_set_text(g_pCurrentTime, "0.00"); + gtk_label_set_text(g_pTotalTime, "30.00"); + + gtk_adjustment_set_value(g_pTimeLine, 0.f); + g_pTimeLine->upper = 30000; + } + + // Refresh event list + RefreshEventList(); + } + + RefreshPathListCombo(); + + // start edit mode + g_iActiveTarget = -1; + if (g_pCameraInspectorWnd && gtk_widget_get_visible(g_pCameraInspectorWnd)) { + DoStartEdit(GetCurrentCam()); + } + + return TRUE; } enum camEventType { - EVENT_NA = 0x00, - EVENT_WAIT, // - EVENT_TARGETWAIT, // - EVENT_SPEED, // - EVENT_TARGET, // char(name) - EVENT_SNAPTARGET, // - EVENT_FOV, // int(time), int(targetfov) - EVENT_CMD, // - EVENT_TRIGGER, // - EVENT_STOP, // - EVENT_CAMERA, // - EVENT_FADEOUT, // int(time) - EVENT_FADEIN, // int(time) - EVENT_FEATHER, // - EVENT_COUNT + EVENT_NA = 0x00, + EVENT_WAIT, // + EVENT_TARGETWAIT, // + EVENT_SPEED, // + EVENT_TARGET, // char(name) + EVENT_SNAPTARGET, // + EVENT_FOV, // int(time), int(targetfov) + EVENT_CMD, // + EVENT_TRIGGER, // + EVENT_STOP, // + EVENT_CAMERA, // + EVENT_FADEOUT, // int(time) + EVENT_FADEIN, // int(time) + EVENT_FEATHER, // + EVENT_COUNT }; // { requires parameters, enabled } const bool camEventFlags[][2] = { - { false, false }, - { false, true }, - { false, false }, - { false, false }, - { true, true }, - { false, false }, - { true, true }, - { false, false }, - { false, false }, - { false, true }, - { true, true }, - { true, true }, - { true, true }, - { false, true }, + {false, false}, + {false, true}, + {false, false}, + {false, false}, + {true, true}, + {false, false}, + {true, true}, + {false, false}, + {false, false}, + {false, true}, + {true, true}, + {true, true}, + {true, true}, + {false, true}, }; const char *camEventStr[] = { - "n/a", - "Wait", - "Target wait", - "Speed", - "Change Target ", - "Snap Target", - "FOV ", - "Run Script", - "Trigger", - "Stop", - "Change to Camera (or ", - "Fade Out ", - "Fade In ", - "Feather" + "n/a", + "Wait", + "Target wait", + "Speed", + "Change Target ", + "Snap Target", + "FOV ", + "Run Script", + "Trigger", + "Stop", + "Change to Camera (or ", + "Fade Out ", + "Fade In ", + "Feather" }; -static gint ci_add( GtkWidget *widget, gpointer data ){ - GtkWidget *w, *hbox, *parameters; - GtkWidget *eventWidget[EVENT_COUNT]; - EMessageBoxReturn ret; - int i, loop = 1; - GSList *eventTypeRadio = NULL; +static gint ci_add(GtkWidget *widget, gpointer data) +{ + GtkWidget *w, *hbox, *parameters; + GtkWidget *eventWidget[EVENT_COUNT]; + EMessageBoxReturn ret; + int i, loop = 1; + GSList *eventTypeRadio = NULL; // char buf[128]; - if ( !GetCurrentCam() ) { - return TRUE; - } + if (!GetCurrentCam()) { + return TRUE; + } - // create the window - auto window = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( window, "Add Event" ); - window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); - gtk_window_set_transient_for( window, g_pCameraInspectorWnd ); + // create the window + auto window = ui::Window(ui::window_type::TOP); + gtk_window_set_title(window, "Add Event"); + window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_window_set_transient_for(window, g_pCameraInspectorWnd); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); - gtk_widget_realize( window ); + gtk_widget_realize(window); - // fill the window - auto vbox = ui::VBox( FALSE, 5 ); - window.add(vbox); - vbox.show(); + // fill the window + auto vbox = ui::VBox(FALSE, 5); + window.add(vbox); + vbox.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - auto frame = ui::Frame( "Type" ); - hbox.pack_start( frame, TRUE, TRUE, 0 ); - frame.show(); + auto frame = ui::Frame("Type"); + hbox.pack_start(frame, TRUE, TRUE, 0); + frame.show(); - auto vbox2 = ui::VBox( FALSE, 5 ); - frame.add(vbox2); - gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 5 ); - vbox2.show(); + auto vbox2 = ui::VBox(FALSE, 5); + frame.add(vbox2); + gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); + vbox2.show(); - // -------------------------- // + // -------------------------- // - for ( i = 1; i < EVENT_COUNT; i++ ) { - eventWidget[i] = gtk_radio_button_new_with_label( eventTypeRadio, camEventStr[i] ); - vbox2.pack_start( eventWidget[i], FALSE, FALSE, 3 ); - eventWidget[i].show(); - eventTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( eventWidget[i] ) ); - if ( camEventFlags[i][1] == false ) { - gtk_widget_set_sensitive( eventWidget[i], FALSE ); - } - } + for (i = 1; i < EVENT_COUNT; i++) { + eventWidget[i] = gtk_radio_button_new_with_label(eventTypeRadio, camEventStr[i]); + vbox2.pack_start(eventWidget[i], FALSE, FALSE, 3); + eventWidget[i].show(); + eventTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(eventWidget[i])); + if (camEventFlags[i][1] == false) { + gtk_widget_set_sensitive(eventWidget[i], FALSE); + } + } - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Label( "Parameters:" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("Parameters:"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - parameters = ui::Entry(); - hbox.pack_start( parameters, TRUE, TRUE, 0 ); - parameters.show(); + parameters = ui::Entry(); + hbox.pack_start(parameters, TRUE, TRUE, 0); + parameters.show(); - // -------------------------- // + // -------------------------- // - w = gtk_hseparator_new(); - vbox.pack_start( w, FALSE, FALSE, 2 ); - w.show(); + w = gtk_hseparator_new(); + vbox.pack_start(w, FALSE, FALSE, 2); + w.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) ); - w.show(); + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK)); + w.show(); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) ); - w.show(); - ret = eIDCANCEL; + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL)); + w.show(); + ret = eIDCANCEL; - // -------------------------- // + // -------------------------- // - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - window.show(); - gtk_grab_add( window ); + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + window.show(); + gtk_grab_add(window); - bool dialogError = TRUE; - while ( dialogError ) { - loop = 1; - while ( loop ) - gtk_main_iteration(); + bool dialogError = TRUE; + while (dialogError) { + loop = 1; + while (loop) { + gtk_main_iteration(); + } - dialogError = FALSE; + dialogError = FALSE; - if ( ret == eIDOK ) { - const char *str = gtk_entry_get_text( GTK_ENTRY( parameters ) ); + if (ret == eIDOK) { + const char *str = gtk_entry_get_text(GTK_ENTRY(parameters)); - if ( !camEventFlags[i][0] || ( str && str[0] ) ) { - int type = 0; + if (!camEventFlags[i][0] || (str && str[0])) { + int type = 0; // GList *li; - for ( type = 1; type < EVENT_COUNT; type++ ) { - if ( gtk_toggle_button_get_active( (GtkToggleButton*)eventWidget[type] ) ) { - break; - } - } + for (type = 1; type < EVENT_COUNT; type++) { + if (gtk_toggle_button_get_active((GtkToggleButton *) eventWidget[type])) { + break; + } + } - // Add the event - GetCurrentCam()->GetCam()->addEvent( static_cast( type ), str, (long)( g_pTimeLine->value ) ); + // Add the event + GetCurrentCam()->GetCam()->addEvent(static_cast( type ), str, + (long) (g_pTimeLine->value)); - // Refresh event list - RefreshEventList(); - } - else { - dialogError = TRUE; - } - } - } + // Refresh event list + RefreshEventList(); + } else { + dialogError = TRUE; + } + } + } - gtk_grab_remove( window ); - window.destroy(); + gtk_grab_remove(window); + window.destroy(); - return TRUE; + return TRUE; } -static gint ci_del( GtkWidget *widget, gpointer data ){ - // TODO: add support to splines lib - if ( GetCurrentCam() && GTK_CLIST( g_pEventsList )->focus_row >= 0 ) { - GetCurrentCam()->GetCam()->removeEvent( GTK_CLIST( g_pEventsList )->focus_row ); - // Refresh event list - RefreshEventList(); - } +static gint ci_del(GtkWidget *widget, gpointer data) +{ + // TODO: add support to splines lib + if (GetCurrentCam() && GTK_CLIST(g_pEventsList)->focus_row >= 0) { + GetCurrentCam()->GetCam()->removeEvent(GTK_CLIST(g_pEventsList)->focus_row); + // Refresh event list + RefreshEventList(); + } - return TRUE; + return TRUE; } -static gint ci_timeline_changed( GtkAdjustment *adjustment ){ - char buf[128]; +static gint ci_timeline_changed(GtkAdjustment *adjustment) +{ + char buf[128]; - sprintf( buf, "%.2f", adjustment->value / 1000.f ); - gtk_label_set_text( g_pCurrentTime, buf ); + sprintf(buf, "%.2f", adjustment->value / 1000.f); + gtk_label_set_text(g_pCurrentTime, buf); - // FIXME: this will never work completely perfect. Startcamera calls buildcamera, which sets all events to 'nottriggered'. - // So if you have a wait at the end of the path, this will go to nontriggered immediately when you go over it and the camera - // will have no idea where on the track it should be. - if ( GetCurrentCam() && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_pTrackCamera ) ) ) { - float fov; - vec3_t origin = { 0.0f, 0.0f, 0.0f }, dir = { 0.0f, 0.0f, 0.0f}, angles; + // FIXME: this will never work completely perfect. Startcamera calls buildcamera, which sets all events to 'nottriggered'. + // So if you have a wait at the end of the path, this will go to nontriggered immediately when you go over it and the camera + // will have no idea where on the track it should be. + if (GetCurrentCam() && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_pTrackCamera))) { + float fov; + vec3_t origin = {0.0f, 0.0f, 0.0f}, dir = {0.0f, 0.0f, 0.0f}, angles; - GetCurrentCam()->GetCam()->startCamera( 0 ); + GetCurrentCam()->GetCam()->startCamera(0); - GetCurrentCam()->GetCam()->getCameraInfo( (long)( adjustment->value ), &origin[0], &dir[0], &fov ); - VectorSet( angles, asin( dir[2] ) * 180 / 3.14159, atan2( dir[1], dir[0] ) * 180 / 3.14159, 0 ); - g_CameraTable.m_pfnSetCamera( origin, angles ); - } + GetCurrentCam()->GetCam()->getCameraInfo((long) (adjustment->value), &origin[0], &dir[0], &fov); + VectorSet(angles, asin(dir[2]) * 180 / 3.14159, atan2(dir[1], dir[0]) * 180 / 3.14159, 0); + g_CameraTable.m_pfnSetCamera(origin, angles); + } - return TRUE; + return TRUE; } -GtkWidget *CreateCameraInspectorDialog( void ){ - GtkWidget *w, *hbox; +GtkWidget *CreateCameraInspectorDialog(void) +{ + GtkWidget *w, *hbox; - // create the window - auto window = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( window, "Camera Inspector" ); - window.connect( "delete_event", G_CALLBACK( ci_close ), NULL ); - window.connect( "expose_event", G_CALLBACK( ci_expose ), NULL ); - // window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); - gtk_window_set_transient_for( window, g_pRadiantWnd ); + // create the window + auto window = ui::Window(ui::window_type::TOP); + gtk_window_set_title(window, "Camera Inspector"); + window.connect("delete_event", G_CALLBACK(ci_close), NULL); + window.connect("expose_event", G_CALLBACK(ci_expose), NULL); + // window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + gtk_window_set_transient_for(window, g_pRadiantWnd); - // don't use show, as you don't want to have it displayed on startup ;-) - gtk_widget_realize( window ); + // don't use show, as you don't want to have it displayed on startup ;-) + gtk_widget_realize(window); - // fill the window + // fill the window - // the table - // -------------------------- // + // the table + // -------------------------- // - auto table = ui::Table( 3, 2, FALSE ); - table.show(); - window.add(table); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); + auto table = ui::Table(3, 2, FALSE); + table.show(); + window.add(table); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - // the properties column - // -------------------------- // + // the properties column + // -------------------------- // - vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - table.attach(vbox, {0, 1, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + vbox = ui::VBox(FALSE, 5); + vbox.show(); + table.attach(vbox, {0, 1, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Label( "File:" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("File:"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - g_pCamListCombo = gtk_combo_new(); - hbox.pack_start( g_pCamListCombo, TRUE, TRUE, 0 ); - g_pCamListCombo.show(); + g_pCamListCombo = gtk_combo_new(); + hbox.pack_start(g_pCamListCombo, TRUE, TRUE, 0); + g_pCamListCombo.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Label( "Name:" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("Name:"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - g_pCamName = ui::Entry(); - hbox.pack_start( g_pCamName, FALSE, FALSE, 0 ); - g_pCamName.show(); + g_pCamName = ui::Entry(); + hbox.pack_start(g_pCamName, FALSE, FALSE, 0); + g_pCamName.show(); - w = ui::Label( "Type: " ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("Type: "); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - w = ui::Label( "" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); - g_pCamType = GTK_LABEL( w ); + w = ui::Label(""); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); + g_pCamType = GTK_LABEL(w); - RefreshCamListCombo(); + RefreshCamListCombo(); - gtk_editable_set_editable( GTK_EDITABLE( GTK_COMBO( g_pCamListCombo )->entry ), FALSE ); - ( GTK_COMBO( g_pCamListCombo )->entry ).connect( "changed", G_CALLBACK( ci_camlist_changed ), NULL ); + gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(g_pCamListCombo)->entry), FALSE); + (GTK_COMBO(g_pCamListCombo)->entry).connect("changed", G_CALLBACK(ci_camlist_changed), NULL); - // -------------------------- // + // -------------------------- // - auto frame = ui::Frame( "Path and Target editing" ); - frame.show(); - table.attach(frame, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + auto frame = ui::Frame("Path and Target editing"); + frame.show(); + table.attach(frame, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - auto vbox = ui::VBox( FALSE, 5 ); - frame.add(vbox); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - vbox.show(); + auto vbox = ui::VBox(FALSE, 5); + frame.add(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + vbox.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Label( "Edit:" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("Edit:"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - g_pPathListCombo = gtk_combo_new(); - hbox.pack_start( g_pPathListCombo, TRUE, TRUE, 0 ); - g_pPathListCombo.show(); + g_pPathListCombo = gtk_combo_new(); + hbox.pack_start(g_pPathListCombo, TRUE, TRUE, 0); + g_pPathListCombo.show(); - RefreshPathListCombo(); + RefreshPathListCombo(); - gtk_editable_set_editable( GTK_EDITABLE( GTK_COMBO( g_pPathListCombo )->entry ), FALSE ); - ( GTK_COMBO( g_pPathListCombo )->entry ).connect( "changed", G_CALLBACK( ci_pathlist_changed ), NULL ); + gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(g_pPathListCombo)->entry), FALSE); + (GTK_COMBO(g_pPathListCombo)->entry).connect("changed", G_CALLBACK(ci_pathlist_changed), NULL); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - g_pEditModeEditRadioButton = gtk_radio_button_new_with_label( g_pEditTypeRadio, "Edit Points" ); - hbox.pack_start( g_pEditModeEditRadioButton, FALSE, FALSE, 3 ); - g_pEditModeEditRadioButton.show(); - g_pEditTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( g_pEditModeEditRadioButton ) ); + g_pEditModeEditRadioButton = gtk_radio_button_new_with_label(g_pEditTypeRadio, "Edit Points"); + hbox.pack_start(g_pEditModeEditRadioButton, FALSE, FALSE, 3); + g_pEditModeEditRadioButton.show(); + g_pEditTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(g_pEditModeEditRadioButton)); - g_pEditModeEditRadioButton.connect( "clicked", G_CALLBACK( ci_editmode_edit ), NULL ); + g_pEditModeEditRadioButton.connect("clicked", G_CALLBACK(ci_editmode_edit), NULL); - g_pEditModeAddRadioButton = gtk_radio_button_new_with_label( g_pEditTypeRadio, "Add Points" ); - hbox.pack_start( g_pEditModeAddRadioButton, FALSE, FALSE, 3 ); - g_pEditModeAddRadioButton.show(); - g_pEditTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( g_pEditModeAddRadioButton ) ); + g_pEditModeAddRadioButton = gtk_radio_button_new_with_label(g_pEditTypeRadio, "Add Points"); + hbox.pack_start(g_pEditModeAddRadioButton, FALSE, FALSE, 3); + g_pEditModeAddRadioButton.show(); + g_pEditTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(g_pEditModeAddRadioButton)); - g_pEditModeAddRadioButton.connect( "clicked", G_CALLBACK( ci_editmode_add ), NULL ); + g_pEditModeAddRadioButton.connect("clicked", G_CALLBACK(ci_editmode_add), NULL); - // see if we should use a different default - if ( g_iEditMode == 1 ) { - // Go to editmode Add - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_pEditModeAddRadioButton ), TRUE ); - } + // see if we should use a different default + if (g_iEditMode == 1) { + // Go to editmode Add + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_pEditModeAddRadioButton), TRUE); + } - w = ui::Label( "Type: " ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("Type: "); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - w = ui::Label( "" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); - g_pPathType = GTK_LABEL( w ); + w = ui::Label(""); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); + g_pPathType = GTK_LABEL(w); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Button( "Rename..." ); - hbox.pack_start( w, FALSE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_rename ), NULL ); - w.show(); + w = ui::Button("Rename..."); + hbox.pack_start(w, FALSE, TRUE, 0); + w.connect("clicked", G_CALLBACK(ci_rename), NULL); + w.show(); - w = ui::Button( "Add Target..." ); - hbox.pack_start( w, FALSE, TRUE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_add_target ), NULL ); - w.show(); + w = ui::Button("Add Target..."); + hbox.pack_start(w, FALSE, TRUE, 0); + w.connect("clicked", G_CALLBACK(ci_add_target), NULL); + w.show(); - // not available in splines library - /*w = gtk_button_new_with_label( "Delete Selected" ); - hbox.pack_start( w, FALSE, TRUE, 0); - w.connect( "clicked", G_CALLBACK( ci_delete_selected ), NULL ); - w.show(); + // not available in splines library + /*w = gtk_button_new_with_label( "Delete Selected" ); + hbox.pack_start( w, FALSE, TRUE, 0); + w.connect( "clicked", G_CALLBACK( ci_delete_selected ), NULL ); + w.show(); - w = gtk_button_new_with_label( "Select All" ); - hbox.pack_start( w, FALSE, TRUE, 0); - w.connect( "clicked", G_CALLBACK( ci_select_all ), NULL ); - w.show();*/ + w = gtk_button_new_with_label( "Select All" ); + hbox.pack_start( w, FALSE, TRUE, 0); + w.connect( "clicked", G_CALLBACK( ci_select_all ), NULL ); + w.show();*/ - // -------------------------- // + // -------------------------- // - frame = ui::Frame( "Time" ); - frame.show(); - table.attach(frame, {0, 1, 2, 3}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + frame = ui::Frame("Time"); + frame.show(); + table.attach(frame, {0, 1, 2, 3}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - vbox = ui::VBox( FALSE, 5 ); - frame.add(vbox); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - vbox.show(); + vbox = ui::VBox(FALSE, 5); + frame.add(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + vbox.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Label( "Length (seconds):" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("Length (seconds):"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - g_pSecondsEntry = ui::Entry(); - hbox.pack_start( g_pSecondsEntry, FALSE, FALSE, 0 ); - g_pSecondsEntry.show(); + g_pSecondsEntry = ui::Entry(); + hbox.pack_start(g_pSecondsEntry, FALSE, FALSE, 0); + g_pSecondsEntry.show(); - // -------------------------- // + // -------------------------- // - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); - w = ui::Label( "Current Time: " ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); + w = ui::Label("Current Time: "); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); - w = ui::Label( "0.00" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); - g_pCurrentTime = GTK_LABEL( w ); - - w = ui::Label( " of " ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); - - w = ui::Label( "0.00" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); - g_pTotalTime = GTK_LABEL( w ); + w = ui::Label("0.00"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); + g_pCurrentTime = GTK_LABEL(w); + + w = ui::Label(" of "); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); + + w = ui::Label("0.00"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); + g_pTotalTime = GTK_LABEL(w); - // -------------------------- // - - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); - - g_pTimeLine = ui::Adjustment( 0, 0, 30000, 100, 250, 0 ); - g_pTimeLine.connect( "value_changed", G_CALLBACK( ci_timeline_changed ), NULL ); - w = ui::HScale( g_pTimeLine ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.show(); - gtk_scale_set_draw_value( GTK_SCALE( w ), FALSE ); - - // -------------------------- // - - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); - - g_pTrackCamera = ui::CheckButton( "Track Camera" ); - hbox.pack_start( g_pTrackCamera, FALSE, FALSE, 0 ); - g_pTrackCamera.show(); - - // -------------------------- // - - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); - - w = ui::Label( "Events:" ); - hbox.pack_start( w, FALSE, FALSE, 0 ); - w.show(); - - // -------------------------- // - - hbox = ui::HBox( FALSE, 5 ); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - hbox.show(); - - auto scr = w = ui::ScrolledWindow(); - w.dimensions( 0, 150 ); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( w ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.show(); - - g_pEventsList = gtk_clist_new( 3 ); - scr.add(g_pEventsList); - //g_pEventsList.connect( "select_row", G_CALLBACK (proplist_select_row), NULL); - gtk_clist_set_selection_mode( GTK_CLIST( g_pEventsList ), GTK_SELECTION_BROWSE ); - gtk_clist_column_titles_hide( GTK_CLIST( g_pEventsList ) ); - gtk_clist_set_column_auto_resize( GTK_CLIST( g_pEventsList ), 0, TRUE ); - gtk_clist_set_column_auto_resize( GTK_CLIST( g_pEventsList ), 1, TRUE ); - gtk_clist_set_column_auto_resize( GTK_CLIST( g_pEventsList ), 2, TRUE ); - g_pEventsList.show(); - - vbox = ui::VBox( FALSE, 5 ); - hbox.pack_start( vbox, FALSE, FALSE, 0 ); - vbox.show(); - - w = ui::Button( "Add..." ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_add ), NULL ); - w.show(); - - w = ui::Button( "Del" ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_del ), NULL ); - w.show(); - - // -------------------------- // - - /*/ - | - | - | - * / - - // the buttons column - // -------------------------- // - - vbox = gtk_vbox_new( FALSE, 5 ); - vbox.show(); - table.attach(vbox, {1, 2, 0, 1}, {GTK_FILL, GTK_FILL}); - - w = gtk_button_new_with_label( "New..." ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_new ), NULL ); - w.show(); - - w = gtk_button_new_with_label( "Load..." ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_load ), NULL ); - w.show(); - - // -------------------------- // - - vbox = gtk_vbox_new( FALSE, 5 ); - vbox.show(); - table.attach( vbox, {1, 2, 1, 2}, {GTK_FILL, GTK_FILL}); - - w = gtk_button_new_with_label( "Save..." ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_save ), NULL ); - w.show(); - - w = gtk_button_new_with_label( "Unload" ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_unload ), NULL ); - w.show(); - - hbox = gtk_hbox_new( FALSE, 5 ); - vbox.pack_start( hbox, TRUE, TRUE, 0 ); - hbox.show(); - - w = gtk_button_new_with_label( "Apply" ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_apply ), NULL ); - w.show(); - - w = gtk_button_new_with_label( "Preview" ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_preview ), NULL ); - w.show(); - - // -------------------------- // - - vbox = gtk_vbox_new( FALSE, 5 ); - vbox.show(); - table.attach(vbox, {1, 2, 2, 3}, {GTK_FILL, GTK_FILL}); - - hbox = gtk_hbox_new( FALSE, 5 ); - vbox.pack_start( hbox, TRUE, TRUE, 0 ); - hbox.show(); - - w = gtk_button_new_with_label( "Close" ); - vbox.pack_start( w, FALSE, FALSE, 0 ); - w.connect( "clicked", G_CALLBACK( ci_close ), NULL ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - // -------------------------- // - - return window; + // -------------------------- // + + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); + + g_pTimeLine = ui::Adjustment(0, 0, 30000, 100, 250, 0); + g_pTimeLine.connect("value_changed", G_CALLBACK(ci_timeline_changed), NULL); + w = ui::HScale(g_pTimeLine); + hbox.pack_start(w, TRUE, TRUE, 0); + w.show(); + gtk_scale_set_draw_value(GTK_SCALE(w), FALSE); + + // -------------------------- // + + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); + + g_pTrackCamera = ui::CheckButton("Track Camera"); + hbox.pack_start(g_pTrackCamera, FALSE, FALSE, 0); + g_pTrackCamera.show(); + + // -------------------------- // + + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); + + w = ui::Label("Events:"); + hbox.pack_start(w, FALSE, FALSE, 0); + w.show(); + + // -------------------------- // + + hbox = ui::HBox(FALSE, 5); + vbox.pack_start(hbox, FALSE, FALSE, 0); + hbox.show(); + + auto scr = w = ui::ScrolledWindow(); + w.dimensions(0, 150); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + hbox.pack_start(w, TRUE, TRUE, 0); + w.show(); + + g_pEventsList = gtk_clist_new(3); + scr.add(g_pEventsList); + //g_pEventsList.connect( "select_row", G_CALLBACK (proplist_select_row), NULL); + gtk_clist_set_selection_mode(GTK_CLIST(g_pEventsList), GTK_SELECTION_BROWSE); + gtk_clist_column_titles_hide(GTK_CLIST(g_pEventsList)); + gtk_clist_set_column_auto_resize(GTK_CLIST(g_pEventsList), 0, TRUE); + gtk_clist_set_column_auto_resize(GTK_CLIST(g_pEventsList), 1, TRUE); + gtk_clist_set_column_auto_resize(GTK_CLIST(g_pEventsList), 2, TRUE); + g_pEventsList.show(); + + vbox = ui::VBox(FALSE, 5); + hbox.pack_start(vbox, FALSE, FALSE, 0); + vbox.show(); + + w = ui::Button("Add..."); + vbox.pack_start(w, FALSE, FALSE, 0); + w.connect("clicked", G_CALLBACK(ci_add), NULL); + w.show(); + + w = ui::Button("Del"); + vbox.pack_start(w, FALSE, FALSE, 0); + w.connect("clicked", G_CALLBACK(ci_del), NULL); + w.show(); + + // -------------------------- // + + /*/ + | + | + | + * / + + // the buttons column + // -------------------------- // + + vbox = gtk_vbox_new( FALSE, 5 ); + vbox.show(); + table.attach(vbox, {1, 2, 0, 1}, {GTK_FILL, GTK_FILL}); + + w = gtk_button_new_with_label( "New..." ); + vbox.pack_start( w, FALSE, FALSE, 0 ); + w.connect( "clicked", G_CALLBACK( ci_new ), NULL ); + w.show(); + + w = gtk_button_new_with_label( "Load..." ); + vbox.pack_start( w, FALSE, FALSE, 0 ); + w.connect( "clicked", G_CALLBACK( ci_load ), NULL ); + w.show(); + + // -------------------------- // + + vbox = gtk_vbox_new( FALSE, 5 ); + vbox.show(); + table.attach( vbox, {1, 2, 1, 2}, {GTK_FILL, GTK_FILL}); + + w = gtk_button_new_with_label( "Save..." ); + vbox.pack_start( w, FALSE, FALSE, 0 ); + w.connect( "clicked", G_CALLBACK( ci_save ), NULL ); + w.show(); + + w = gtk_button_new_with_label( "Unload" ); + vbox.pack_start( w, FALSE, FALSE, 0 ); + w.connect( "clicked", G_CALLBACK( ci_unload ), NULL ); + w.show(); + + hbox = gtk_hbox_new( FALSE, 5 ); + vbox.pack_start( hbox, TRUE, TRUE, 0 ); + hbox.show(); + + w = gtk_button_new_with_label( "Apply" ); + vbox.pack_start( w, FALSE, FALSE, 0 ); + w.connect( "clicked", G_CALLBACK( ci_apply ), NULL ); + w.show(); + + w = gtk_button_new_with_label( "Preview" ); + vbox.pack_start( w, FALSE, FALSE, 0 ); + w.connect( "clicked", G_CALLBACK( ci_preview ), NULL ); + w.show(); + + // -------------------------- // + + vbox = gtk_vbox_new( FALSE, 5 ); + vbox.show(); + table.attach(vbox, {1, 2, 2, 3}, {GTK_FILL, GTK_FILL}); + + hbox = gtk_hbox_new( FALSE, 5 ); + vbox.pack_start( hbox, TRUE, TRUE, 0 ); + hbox.show(); + + w = gtk_button_new_with_label( "Close" ); + vbox.pack_start( w, FALSE, FALSE, 0 ); + w.connect( "clicked", G_CALLBACK( ci_close ), NULL ); + gtk_widget_set_can_default( w, true ); + gtk_widget_grab_default( w ); + w.show(); + + // -------------------------- // + + return window; } diff --git a/contrib/camera/dialogs.h b/contrib/camera/dialogs.h index 9b8f9036..38ea9cd5 100644 --- a/contrib/camera/dialogs.h +++ b/contrib/camera/dialogs.h @@ -25,13 +25,15 @@ */ struct TwinWidget { - GtkWidget* one; - GtkWidget* two; + GtkWidget *one; + GtkWidget *two; }; -void dialog_button_callback( GtkWidget *widget, gpointer data ); -gint dialog_delete_callback( GtkWidget *widget, GdkEvent* event, gpointer data ); +void dialog_button_callback(GtkWidget *widget, gpointer data); + +gint dialog_delete_callback(GtkWidget *widget, GdkEvent *event, gpointer data); //void dialog_button_callback_settex (GtkWidget *widget, gpointer data); -void RefreshCamListCombo( void ); -GtkWidget *CreateCameraInspectorDialog( void ); +void RefreshCamListCombo(void); + +GtkWidget *CreateCameraInspectorDialog(void); diff --git a/contrib/camera/dialogs_common.cpp b/contrib/camera/dialogs_common.cpp index 805071ca..d44547a9 100644 --- a/contrib/camera/dialogs_common.cpp +++ b/contrib/camera/dialogs_common.cpp @@ -26,23 +26,25 @@ #include "camera.h" -void dialog_button_callback( ui::Widget widget, gpointer data ){ - int *loop, *ret; +void dialog_button_callback(ui::Widget widget, gpointer data) +{ + int *loop, *ret; - auto parent = widget.window(); - loop = (int*)g_object_get_data( G_OBJECT( parent ), "loop" ); - ret = (int*)g_object_get_data( G_OBJECT( parent ), "ret" ); + auto parent = widget.window(); + loop = (int *) g_object_get_data(G_OBJECT(parent), "loop"); + ret = (int *) g_object_get_data(G_OBJECT(parent), "ret"); - *loop = 0; - *ret = gpointer_to_int( data ); + *loop = 0; + *ret = gpointer_to_int(data); } -gint dialog_delete_callback( GtkWidget *widget, GdkEvent* event, gpointer data ){ - int *loop; +gint dialog_delete_callback(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + int *loop; - gtk_widget_hide( widget ); - loop = (int*)g_object_get_data( G_OBJECT( widget ), "loop" ); - *loop = 0; + gtk_widget_hide(widget); + loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); + *loop = 0; - return TRUE; + return TRUE; } diff --git a/contrib/camera/funchandlers.cpp b/contrib/camera/funchandlers.cpp index 5d72242b..a0b9d756 100644 --- a/contrib/camera/funchandlers.cpp +++ b/contrib/camera/funchandlers.cpp @@ -29,252 +29,263 @@ extern GtkWidget *g_pEditModeAddRadioButton; -char* Q_realpath( const char *path, char *resolved_path, size_t size ){ +char *Q_realpath(const char *path, char *resolved_path, size_t size) +{ #if GDEF_OS_POSIX - return realpath( path, resolved_path ); + return realpath( path, resolved_path ); #elif GDEF_OS_WINDOWS - return _fullpath( resolved_path, path, size ); + return _fullpath( resolved_path, path, size ); #else #error "unsupported platform" #endif } -static void DoNewCamera( idCameraPosition::positionType type ){ - CCamera *cam = AllocCam(); +static void DoNewCamera(idCameraPosition::positionType type) +{ + CCamera *cam = AllocCam(); - if ( cam ) { - char buf[128]; - sprintf( buf, "camera%i", cam->GetCamNum() ); + if (cam) { + char buf[128]; + sprintf(buf, "camera%i", cam->GetCamNum()); - cam->GetCam()->startNewCamera( type ); - cam->GetCam()->setName( buf ); - cam->GetCam()->buildCamera(); + cam->GetCam()->startNewCamera(type); + cam->GetCam()->setName(buf); + cam->GetCam()->buildCamera(); - sprintf( buf, "Unsaved Camera %i", cam->GetCamNum() ); - cam->SetFileName( buf, false ); + sprintf(buf, "Unsaved Camera %i", cam->GetCamNum()); + cam->SetFileName(buf, false); - SetCurrentCam( cam ); - RefreshCamListCombo(); + SetCurrentCam(cam); + RefreshCamListCombo(); - // Go to editmode Add - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_pEditModeAddRadioButton ), TRUE ); + // Go to editmode Add + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_pEditModeAddRadioButton), TRUE); - // Show the camera inspector - DoCameraInspector(); + // Show the camera inspector + DoCameraInspector(); - // Start edit mode (if not initiated by DoCameraInspector) - if ( !g_bEditOn ) { - DoStartEdit( GetCurrentCam() ); - } - } - else { - g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, "No free cameras available.", "Create Camera Error", eMB_OK ); - } + // Start edit mode (if not initiated by DoCameraInspector) + if (!g_bEditOn) { + DoStartEdit(GetCurrentCam()); + } + } else { + g_FuncTable.m_pfnMessageBox((GtkWidget *) g_pRadiantWnd, "No free cameras available.", "Create Camera Error", + eMB_OK); + } } -void DoNewFixedCamera(){ - DoNewCamera( idCameraPosition::FIXED ); +void DoNewFixedCamera() +{ + DoNewCamera(idCameraPosition::FIXED); } -void DoNewInterpolatedCamera(){ - DoNewCamera( idCameraPosition::INTERPOLATED ); +void DoNewInterpolatedCamera() +{ + DoNewCamera(idCameraPosition::INTERPOLATED); } -void DoNewSplineCamera(){ - DoNewCamera( idCameraPosition::SPLINE ); +void DoNewSplineCamera() +{ + DoNewCamera(idCameraPosition::SPLINE); } -void DoCameraInspector(){ - g_pCameraInspectorWnd.show(); +void DoCameraInspector() +{ + g_pCameraInspectorWnd.show(); } -void DoPreviewCamera(){ - if ( GetCurrentCam() ) { - g_iPreviewRunning = 1; - g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA ); - } +void DoPreviewCamera() +{ + if (GetCurrentCam()) { + g_iPreviewRunning = 1; + g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA); + } } -void DoLoadCamera(){ - char basepath[PATH_MAX]; - - if ( firstCam && firstCam->HasBeenSaved() ) { - ExtractFilePath( firstCam->GetFileName(), basepath ); - } - else{ - strcpy( basepath, g_FuncTable.m_pfnGetGamePath() ); - } - - const gchar *filename = g_FuncTable.m_pfnFileDialog( (GtkWidget *)g_pRadiantWnd, TRUE, "Open Camera File", basepath, "camera" ); - - if ( filename ) { - CCamera *cam = AllocCam(); - char fullpathtofile[PATH_MAX]; - - if ( cam ) { - Q_realpath( filename, fullpathtofile, PATH_MAX ); - - // see if this camera file was already loaded - CCamera *checkCam = firstCam->GetNext(); // not the first one as we just allocated it - while ( checkCam ) { - if ( !strcmp( fullpathtofile, checkCam->GetFileName() ) ) { - char error[PATH_MAX + 64]; - FreeCam( cam ); - sprintf( error, "Camera file \'%s\' is already loaded", fullpathtofile ); - g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, error, "Load error", eMB_OK ); - //g_free( filename ); - return; - } - checkCam = checkCam->GetNext(); - } - - if ( loadCamera( cam->GetCamNum(), fullpathtofile ) ) { - cam->GetCam()->buildCamera(); - cam->SetFileName( filename, true ); - SetCurrentCam( cam ); - RefreshCamListCombo(); - g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA ); - } - else { - char error[PATH_MAX + 64]; - FreeCam( cam ); - sprintf( error, "An error occured during the loading of \'%s\'", fullpathtofile ); - g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, error, "Load error", eMB_OK ); - } - - //g_free( filename ); - } - else { - g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, "No free camera slots available", "Load error", eMB_OK ); - } - } +void DoLoadCamera() +{ + char basepath[PATH_MAX]; + + if (firstCam && firstCam->HasBeenSaved()) { + ExtractFilePath(firstCam->GetFileName(), basepath); + } else { + strcpy(basepath, g_FuncTable.m_pfnGetGamePath()); + } + + const gchar *filename = g_FuncTable.m_pfnFileDialog((GtkWidget *) g_pRadiantWnd, TRUE, "Open Camera File", basepath, + "camera"); + + if (filename) { + CCamera *cam = AllocCam(); + char fullpathtofile[PATH_MAX]; + + if (cam) { + Q_realpath(filename, fullpathtofile, PATH_MAX); + + // see if this camera file was already loaded + CCamera *checkCam = firstCam->GetNext(); // not the first one as we just allocated it + while (checkCam) { + if (!strcmp(fullpathtofile, checkCam->GetFileName())) { + char error[PATH_MAX + 64]; + FreeCam(cam); + sprintf(error, "Camera file \'%s\' is already loaded", fullpathtofile); + g_FuncTable.m_pfnMessageBox((GtkWidget *) g_pRadiantWnd, error, "Load error", eMB_OK); + //g_free( filename ); + return; + } + checkCam = checkCam->GetNext(); + } + + if (loadCamera(cam->GetCamNum(), fullpathtofile)) { + cam->GetCam()->buildCamera(); + cam->SetFileName(filename, true); + SetCurrentCam(cam); + RefreshCamListCombo(); + g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA); + } else { + char error[PATH_MAX + 64]; + FreeCam(cam); + sprintf(error, "An error occured during the loading of \'%s\'", fullpathtofile); + g_FuncTable.m_pfnMessageBox((GtkWidget *) g_pRadiantWnd, error, "Load error", eMB_OK); + } + + //g_free( filename ); + } else { + g_FuncTable.m_pfnMessageBox((GtkWidget *) g_pRadiantWnd, "No free camera slots available", "Load error", + eMB_OK); + } + } } -void DoSaveCamera() { - char basepath[PATH_MAX]; - - if ( !GetCurrentCam() ) { - return; - } - - if ( GetCurrentCam()->GetFileName()[0] ) { - ExtractFilePath( GetCurrentCam()->GetFileName(), basepath ); - } - else{ - strcpy( basepath, g_FuncTable.m_pfnGetGamePath() ); - } - - const gchar *filename = g_FuncTable.m_pfnFileDialog( g_pRadiantWnd, FALSE, "Save Camera File", basepath, "camera" ); - - if ( filename ) { - char fullpathtofile[PATH_MAX + 8]; - - Q_realpath( filename, fullpathtofile, PATH_MAX ); - - // File dialog from windows (and maybe the gtk one from radiant) doesn't handle default extensions properly. - // Add extension and check again if file exists - if ( strcmp( fullpathtofile + ( strlen( fullpathtofile ) - 7 ), ".camera" ) ) { - strcat( fullpathtofile, ".camera" ); - - if ( FileExists( fullpathtofile ) ) { - if ( g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, "File already exists.\nOverwrite?", "Save Camera File", eMB_YESNO ) == eIDNO ) { - return; - } - } - } - - // see if this camera file was already loaded - CCamera *checkCam = firstCam; - while ( checkCam ) { - if ( checkCam == GetCurrentCam() ) { - checkCam = checkCam->GetNext(); - if ( !checkCam ) { // we only have one camera file opened so no need to check further - break; - } - } - else if ( !strcmp( fullpathtofile, checkCam->GetFileName() ) ) { - char error[PATH_MAX + 64]; - sprintf( error, "Camera file \'%s\' is currently loaded by NetRadiant.\nPlease select a different filename.", fullpathtofile ); - g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, error, "Save error", eMB_OK ); - return; - } - checkCam = checkCam->GetNext(); - } - - // FIXME: check for existing directory - - GetCurrentCam()->GetCam()->save( fullpathtofile ); - GetCurrentCam()->SetFileName( fullpathtofile, true ); - RefreshCamListCombo(); - } +void DoSaveCamera() +{ + char basepath[PATH_MAX]; + + if (!GetCurrentCam()) { + return; + } + + if (GetCurrentCam()->GetFileName()[0]) { + ExtractFilePath(GetCurrentCam()->GetFileName(), basepath); + } else { + strcpy(basepath, g_FuncTable.m_pfnGetGamePath()); + } + + const gchar *filename = g_FuncTable.m_pfnFileDialog(g_pRadiantWnd, FALSE, "Save Camera File", basepath, "camera"); + + if (filename) { + char fullpathtofile[PATH_MAX + 8]; + + Q_realpath(filename, fullpathtofile, PATH_MAX); + + // File dialog from windows (and maybe the gtk one from radiant) doesn't handle default extensions properly. + // Add extension and check again if file exists + if (strcmp(fullpathtofile + (strlen(fullpathtofile) - 7), ".camera")) { + strcat(fullpathtofile, ".camera"); + + if (FileExists(fullpathtofile)) { + if (g_FuncTable.m_pfnMessageBox((GtkWidget *) g_pRadiantWnd, "File already exists.\nOverwrite?", + "Save Camera File", eMB_YESNO) == eIDNO) { + return; + } + } + } + + // see if this camera file was already loaded + CCamera *checkCam = firstCam; + while (checkCam) { + if (checkCam == GetCurrentCam()) { + checkCam = checkCam->GetNext(); + if (!checkCam) { // we only have one camera file opened so no need to check further + break; + } + } else if (!strcmp(fullpathtofile, checkCam->GetFileName())) { + char error[PATH_MAX + 64]; + sprintf(error, + "Camera file \'%s\' is currently loaded by NetRadiant.\nPlease select a different filename.", + fullpathtofile); + g_FuncTable.m_pfnMessageBox((GtkWidget *) g_pRadiantWnd, error, "Save error", eMB_OK); + return; + } + checkCam = checkCam->GetNext(); + } + + // FIXME: check for existing directory + + GetCurrentCam()->GetCam()->save(fullpathtofile); + GetCurrentCam()->SetFileName(fullpathtofile, true); + RefreshCamListCombo(); + } } -void DoUnloadCamera() { - if ( !GetCurrentCam() ) { - return; - } - - if ( !GetCurrentCam()->HasBeenSaved() ) { - char buf[PATH_MAX + 64]; - sprintf( buf, "Do you want to save the changes for camera '%s'?", GetCurrentCam()->GetCam()->getName() ); - if ( g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, buf, "Warning", eMB_YESNO ) == eIDYES ) { - DoSaveCamera(); - } - } - else if ( GetCurrentCam()->HasBeenSaved() == 2 ) { - char buf[PATH_MAX + 64]; - sprintf( buf, "Do you want to save the changes made to camera file '%s'?", GetCurrentCam()->GetFileName() ); - if ( g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, buf, "Warning", eMB_YESNO ) == eIDYES ) { - DoSaveCamera(); - } - } - - if ( g_pCurrentEditCam ) { - DoStopEdit(); - g_pCurrentEditCam = NULL; - } - - FreeCam( GetCurrentCam() ); - SetCurrentCam( NULL ); - RefreshCamListCombo(); +void DoUnloadCamera() +{ + if (!GetCurrentCam()) { + return; + } + + if (!GetCurrentCam()->HasBeenSaved()) { + char buf[PATH_MAX + 64]; + sprintf(buf, "Do you want to save the changes for camera '%s'?", GetCurrentCam()->GetCam()->getName()); + if (g_FuncTable.m_pfnMessageBox((GtkWidget *) g_pRadiantWnd, buf, "Warning", eMB_YESNO) == eIDYES) { + DoSaveCamera(); + } + } else if (GetCurrentCam()->HasBeenSaved() == 2) { + char buf[PATH_MAX + 64]; + sprintf(buf, "Do you want to save the changes made to camera file '%s'?", GetCurrentCam()->GetFileName()); + if (g_FuncTable.m_pfnMessageBox((GtkWidget *) g_pRadiantWnd, buf, "Warning", eMB_YESNO) == eIDYES) { + DoSaveCamera(); + } + } + + if (g_pCurrentEditCam) { + DoStopEdit(); + g_pCurrentEditCam = NULL; + } + + FreeCam(GetCurrentCam()); + SetCurrentCam(NULL); + RefreshCamListCombo(); } CCamera *g_pCurrentEditCam = NULL; -void DoStartEdit( CCamera *cam ) { - if ( g_pCurrentEditCam ) { - DoStopEdit(); - g_pCurrentEditCam = NULL; - } +void DoStartEdit(CCamera *cam) +{ + if (g_pCurrentEditCam) { + DoStopEdit(); + g_pCurrentEditCam = NULL; + } - if ( cam ) { - g_bEditOn = true; + if (cam) { + g_bEditOn = true; - if ( !Listener ) { - Listener = new CListener; - } + if (!Listener) { + Listener = new CListener; + } - cam->GetCam()->startEdit( g_iActiveTarget < 0 ? true : false ); + cam->GetCam()->startEdit(g_iActiveTarget < 0 ? true : false); - g_pCurrentEditCam = cam; + g_pCurrentEditCam = cam; - g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA ); - } + g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA); + } } -void DoStopEdit( void ) { - g_bEditOn = false; +void DoStopEdit(void) +{ + g_bEditOn = false; - if ( Listener ) { - delete Listener; - Listener = NULL; - } + if (Listener) { + delete Listener; + Listener = NULL; + } - if ( g_pCurrentEditCam ) { - // stop editing on the current cam - g_pCurrentEditCam->GetCam()->stopEdit(); - g_pCurrentEditCam = NULL; + if (g_pCurrentEditCam) { + // stop editing on the current cam + g_pCurrentEditCam->GetCam()->stopEdit(); + g_pCurrentEditCam = NULL; - g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA ); - } + g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA); + } } diff --git a/contrib/camera/funchandlers.h b/contrib/camera/funchandlers.h index a268315b..4a61a222 100644 --- a/contrib/camera/funchandlers.h +++ b/contrib/camera/funchandlers.h @@ -25,12 +25,21 @@ */ void DoNewFixedCamera(); + void DoNewInterpolatedCamera(); + void DoNewSplineCamera(); + void DoCameraInspector(); + void DoPreviewCamera(); + void DoLoadCamera(); + void DoSaveCamera(); + void DoUnloadCamera(); -void DoStartEdit( CCamera *cam ); -void DoStopEdit( void ); + +void DoStartEdit(CCamera *cam); + +void DoStopEdit(void); diff --git a/contrib/camera/listener.cpp b/contrib/camera/listener.cpp index b9f5fcf9..4a422970 100644 --- a/contrib/camera/listener.cpp +++ b/contrib/camera/listener.cpp @@ -26,206 +26,223 @@ #include "camera.h" -CListener::CListener(){ - refCount = 1; +CListener::CListener() +{ + refCount = 1; - m_bHooked = FALSE; + m_bHooked = FALSE; - m_bLeftMBPressed = m_bRightMBPressed = m_bMiddleMBPressed = false; + m_bLeftMBPressed = m_bRightMBPressed = m_bMiddleMBPressed = false; - oldValid = false; + oldValid = false; - Register(); + Register(); } -CListener::~CListener(){ - UnRegister(); +CListener::~CListener() +{ + UnRegister(); } -void CListener::Register(){ - g_UITable.m_pfnHookWindow( this ); - g_pXYWndWrapper = g_UITable.m_pfnGetXYWndWrapper(); - m_bHooked = TRUE; +void CListener::Register() +{ + g_UITable.m_pfnHookWindow(this); + g_pXYWndWrapper = g_UITable.m_pfnGetXYWndWrapper(); + m_bHooked = TRUE; } -void CListener::UnRegister(){ - if ( m_bHooked ) { - g_UITable.m_pfnUnHookWindow( this ); - g_pXYWndWrapper = NULL; - m_bHooked = FALSE; - } +void CListener::UnRegister() +{ + if (m_bHooked) { + g_UITable.m_pfnUnHookWindow(this); + g_pXYWndWrapper = NULL; + m_bHooked = FALSE; + } } -bool CListener::OnMouseMove( unsigned int nFlags, double x, double y ){ - SetViewType( g_pXYWndWrapper->GetViewType() ); - - if ( m_bLeftMBPressed && oldValid && g_iEditMode == 0 ) { - vec3_t click, delta; - - g_pXYWndWrapper->SnapToGrid( (int)x, (int)y, click ); - - switch ( m_vt ) { - case XY: - VectorSet( delta, click[0] - old_x, click[1] - old_y, 0 ); - old_x = click[0]; old_y = click[1]; - break; - case XZ: - VectorSet( delta, click[0] - old_x, 0, click[2] - old_y ); - old_x = click[0]; old_y = click[2]; - break; - case YZ: - VectorSet( delta, 0, click[1] - old_x, click[2] - old_y ); - old_x = click[1]; old_y = click[2]; - break; - } - - if ( g_iActiveTarget < 0 ) { - GetCurrentCam()->GetCam()->getPositionObj()->updateSelection( delta[0], delta[1], delta[2] ); - } - else{ - GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget )->updateSelection( delta[0], delta[1], delta[2] ); - } - - GetCurrentCam()->HasBeenModified(); - - g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA ); - - return true; - } - - return false; +bool CListener::OnMouseMove(unsigned int nFlags, double x, double y) +{ + SetViewType(g_pXYWndWrapper->GetViewType()); + + if (m_bLeftMBPressed && oldValid && g_iEditMode == 0) { + vec3_t click, delta; + + g_pXYWndWrapper->SnapToGrid((int) x, (int) y, click); + + switch (m_vt) { + case XY: + VectorSet(delta, click[0] - old_x, click[1] - old_y, 0); + old_x = click[0]; + old_y = click[1]; + break; + case XZ: + VectorSet(delta, click[0] - old_x, 0, click[2] - old_y); + old_x = click[0]; + old_y = click[2]; + break; + case YZ: + VectorSet(delta, 0, click[1] - old_x, click[2] - old_y); + old_x = click[1]; + old_y = click[2]; + break; + } + + if (g_iActiveTarget < 0) { + GetCurrentCam()->GetCam()->getPositionObj()->updateSelection(delta[0], delta[1], delta[2]); + } else { + GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget)->updateSelection(delta[0], delta[1], delta[2]); + } + + GetCurrentCam()->HasBeenModified(); + + g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA); + + return true; + } + + return false; } -bool CListener::OnLButtonDown( unsigned int nFlags, double x, double y ){ - SetViewType( g_pXYWndWrapper->GetViewType() ); - - m_bLeftMBPressed = true; - oldValid = true; - - vec3_t org, delta; - - g_pXYWndWrapper->SnapToGrid( (int)x, (int)y, org ); - - switch ( m_vt ) { - case XY: - old_x = org[0]; old_y = org[1]; org[2] = 64 * 1024; - VectorSet( delta, 0, 0, -1 ); - break; - case XZ: - old_x = org[0]; old_y = org[2]; org[1] = 64 * 1024; - VectorSet( delta, 0, -1, 0 ); - break; - case YZ: - old_x = org[1]; old_y = org[2]; org[0] = 64 * 1024; - VectorSet( delta, -1, 0, 0 ); - break; - } - - if ( g_iEditMode == 0 ) { - if ( g_iActiveTarget < 0 ) { - GetCurrentCam()->GetCam()->getPositionObj()->selectPointByRay( org[0], org[1], org[2], delta[0], delta[1], delta[2], true ); - } - else{ - GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget )->selectPointByRay( org[0], org[1], org[2], delta[0], delta[1], delta[2], true ); - } - } - else if ( g_iEditMode == 1 ) { - idVec3 *lastcoord; - idCameraPosition *camera; - - if ( g_iActiveTarget < 0 ) { - camera = GetCurrentCam()->GetCam()->getPositionObj(); - } - else { - camera = GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget ); - } - - if ( camera->numPoints() ) { - lastcoord = camera->getPoint( camera->numPoints() - 1 ); - switch ( m_vt ) { - case XY: - camera->addPoint( org[0], org[1], lastcoord->z ); - break; - case XZ: - camera->addPoint( org[0], lastcoord->y, org[2] ); - break; - case YZ: - camera->addPoint( lastcoord->x, org[1], org[2] ); - break; - } - } - else { - switch ( m_vt ) { - case XY: - camera->addPoint( org[0], org[1], 0 ); - break; - case XZ: - camera->addPoint( org[0], 0, org[2] ); - break; - case YZ: - camera->addPoint( 0, org[1], org[2] ); - break; - } - } - - GetCurrentCam()->HasBeenModified(); - } - - g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA ); - - return true; - - //return false; +bool CListener::OnLButtonDown(unsigned int nFlags, double x, double y) +{ + SetViewType(g_pXYWndWrapper->GetViewType()); + + m_bLeftMBPressed = true; + oldValid = true; + + vec3_t org, delta; + + g_pXYWndWrapper->SnapToGrid((int) x, (int) y, org); + + switch (m_vt) { + case XY: + old_x = org[0]; + old_y = org[1]; + org[2] = 64 * 1024; + VectorSet(delta, 0, 0, -1); + break; + case XZ: + old_x = org[0]; + old_y = org[2]; + org[1] = 64 * 1024; + VectorSet(delta, 0, -1, 0); + break; + case YZ: + old_x = org[1]; + old_y = org[2]; + org[0] = 64 * 1024; + VectorSet(delta, -1, 0, 0); + break; + } + + if (g_iEditMode == 0) { + if (g_iActiveTarget < 0) { + GetCurrentCam()->GetCam()->getPositionObj()->selectPointByRay(org[0], org[1], org[2], delta[0], delta[1], + delta[2], true); + } else { + GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget)->selectPointByRay(org[0], org[1], org[2], + delta[0], delta[1], delta[2], + true); + } + } else if (g_iEditMode == 1) { + idVec3 *lastcoord; + idCameraPosition *camera; + + if (g_iActiveTarget < 0) { + camera = GetCurrentCam()->GetCam()->getPositionObj(); + } else { + camera = GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget); + } + + if (camera->numPoints()) { + lastcoord = camera->getPoint(camera->numPoints() - 1); + switch (m_vt) { + case XY: + camera->addPoint(org[0], org[1], lastcoord->z); + break; + case XZ: + camera->addPoint(org[0], lastcoord->y, org[2]); + break; + case YZ: + camera->addPoint(lastcoord->x, org[1], org[2]); + break; + } + } else { + switch (m_vt) { + case XY: + camera->addPoint(org[0], org[1], 0); + break; + case XZ: + camera->addPoint(org[0], 0, org[2]); + break; + case YZ: + camera->addPoint(0, org[1], org[2]); + break; + } + } + + GetCurrentCam()->HasBeenModified(); + } + + g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA); + + return true; + + //return false; } -bool CListener::OnLButtonUp( unsigned int nFlags, double x, double y ){ - SetViewType( g_pXYWndWrapper->GetViewType() ); +bool CListener::OnLButtonUp(unsigned int nFlags, double x, double y) +{ + SetViewType(g_pXYWndWrapper->GetViewType()); - m_bLeftMBPressed = false; - oldValid = false; + m_bLeftMBPressed = false; + oldValid = false; - if ( g_iEditMode == 0 ) { - if ( g_iActiveTarget < 0 ) { - GetCurrentCam()->GetCam()->getPositionObj()->deselectAll(); - } - else{ - GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget )->deselectAll(); - } + if (g_iEditMode == 0) { + if (g_iActiveTarget < 0) { + GetCurrentCam()->GetCam()->getPositionObj()->deselectAll(); + } else { + GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget)->deselectAll(); + } - g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA ); - } + g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA); + } - return false; + return false; } -bool CListener::OnRButtonDown( unsigned int nFlags, double x, double y ){ - SetViewType( g_pXYWndWrapper->GetViewType() ); +bool CListener::OnRButtonDown(unsigned int nFlags, double x, double y) +{ + SetViewType(g_pXYWndWrapper->GetViewType()); - m_bRightMBPressed = true; + m_bRightMBPressed = true; - return false; + return false; } -bool CListener::OnRButtonUp( unsigned int nFlags, double x, double y ){ - SetViewType( g_pXYWndWrapper->GetViewType() ); +bool CListener::OnRButtonUp(unsigned int nFlags, double x, double y) +{ + SetViewType(g_pXYWndWrapper->GetViewType()); - m_bRightMBPressed = false; + m_bRightMBPressed = false; - return false; + return false; } -bool CListener::OnMButtonDown( unsigned int nFlags, double x, double y ){ - SetViewType( g_pXYWndWrapper->GetViewType() ); +bool CListener::OnMButtonDown(unsigned int nFlags, double x, double y) +{ + SetViewType(g_pXYWndWrapper->GetViewType()); - m_bMiddleMBPressed = true; + m_bMiddleMBPressed = true; - return false; + return false; } -bool CListener::OnMButtonUp( unsigned int nFlags, double x, double y ){ - SetViewType( g_pXYWndWrapper->GetViewType() ); +bool CListener::OnMButtonUp(unsigned int nFlags, double x, double y) +{ + SetViewType(g_pXYWndWrapper->GetViewType()); - m_bMiddleMBPressed = false; + m_bMiddleMBPressed = false; - return false; + return false; } diff --git a/contrib/camera/listener.h b/contrib/camera/listener.h index 13acd543..2bf9baf8 100644 --- a/contrib/camera/listener.h +++ b/contrib/camera/listener.h @@ -24,50 +24,69 @@ Copyright (C) 2002 Splash Damage Ltd. */ -class CListener : public IWindowListener -{ +class CListener : public IWindowListener { public: -bool OnMouseMove( guint32 nFlags, gdouble x, gdouble y ); -bool OnLButtonDown( guint32 nFlags, gdouble x, gdouble y ); -bool OnMButtonDown( guint32 nFlags, gdouble x, gdouble y ); -bool OnRButtonDown( guint32 nFlags, gdouble x, gdouble y ); -bool OnLButtonUp( guint32 nFlags, gdouble x, gdouble y ); -bool OnMButtonUp( guint32 nFlags, gdouble x, gdouble y ); -bool OnRButtonUp( guint32 nFlags, gdouble x, gdouble y ); -bool OnKeyPressed( char *s ) { return false; } -bool Paint() { return true; } -void Close() { } - -void UnRegister(); -void Register(); -CListener(); -virtual ~CListener(); - -void IncRef() { refCount++; } -void DecRef() { - refCount--; if ( refCount <= 0 ) { - delete this; - } -} - -void SetViewType( VIEWTYPE vt ) { - if ( m_vt != vt ) { - oldValid = false; - } - m_vt = vt; -} + bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y); + + bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y); + + bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y); + + bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y); + + bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y); + + bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y); + + bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y); + + bool OnKeyPressed(char *s) + { return false; } + + bool Paint() + { return true; } + + void Close() + {} + + void UnRegister(); + + void Register(); + + CListener(); + + virtual ~CListener(); + + void IncRef() + { refCount++; } + + void DecRef() + { + refCount--; + if (refCount <= 0) { + delete this; + } + } + + void SetViewType(VIEWTYPE vt) + { + if (m_vt != vt) { + oldValid = false; + } + m_vt = vt; + } private: -IXYWndWrapper *g_pXYWndWrapper; + IXYWndWrapper *g_pXYWndWrapper; -bool m_bHooked; -int refCount; -VIEWTYPE m_vt; + bool m_bHooked; + int refCount; + VIEWTYPE m_vt; // mouse button status -bool m_bLeftMBPressed, m_bRightMBPressed, m_bMiddleMBPressed; + bool m_bLeftMBPressed, m_bRightMBPressed, m_bMiddleMBPressed; // old mouse coordinates -bool oldValid; -gdouble old_x, old_y; + bool oldValid; + gdouble old_x, old_y; }; diff --git a/contrib/camera/misc.cpp b/contrib/camera/misc.cpp index 88207af7..1170ceca 100644 --- a/contrib/camera/misc.cpp +++ b/contrib/camera/misc.cpp @@ -27,60 +27,66 @@ #include "camera.h" #include "globaldefs.h" -void Sys_ERROR( char* text, ... ){ - va_list argptr; - char buf[32768]; +void Sys_ERROR(char *text, ...) +{ + va_list argptr; + char buf[32768]; - va_start( argptr,text ); - vsprintf( buf, text,argptr ); - va_end( argptr ); + va_start(argptr, text); + vsprintf(buf, text, argptr); + va_end(argptr); - Sys_Printf( "Camera::ERROR->%s", buf ); + Sys_Printf("Camera::ERROR->%s", buf); } -char* UnixToDosPath( char* path ){ +char *UnixToDosPath(char *path) +{ #if !GDEF_OS_WINDOWS - return path; + return path; #else - for ( char* p = path; *p; p++ ) - { - if ( *p == '/' ) { - *p = '\\'; - } - } - return path; + for ( char* p = path; *p; p++ ) + { + if ( *p == '/' ) { + *p = '\\'; + } + } + return path; #endif } -void ExtractFilePath( const char *path, char *dest ){ - const char *src; +void ExtractFilePath(const char *path, char *dest) +{ + const char *src; - src = path + strlen( path ) - 1; + src = path + strlen(path) - 1; // // back up until a \ or the start // - while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' ) - src--; + while (src != path && *(src - 1) != '/' && *(src - 1) != '\\') { + src--; + } - memcpy( dest, path, src - path ); - dest[src - path] = 0; + memcpy(dest, path, src - path); + dest[src - path] = 0; } -const char* ExtractFilename( const char* path ){ - char* p = strrchr( path, '/' ); - if ( !p ) { - p = strrchr( path, '\\' ); - - if ( !p ) { - return path; - } - } - return ++p; +const char *ExtractFilename(const char *path) +{ + char *p = strrchr(path, '/'); + if (!p) { + p = strrchr(path, '\\'); + + if (!p) { + return path; + } + } + return ++p; } -int Q_stricmp( const char *s1, const char *s2 ) { - return string_equal_nocase( s1, s2 ); +int Q_stricmp(const char *s1, const char *s2) +{ + return string_equal_nocase(s1, s2); } /* @@ -88,69 +94,78 @@ int Q_stricmp( const char *s1, const char *s2 ) { FileExists ============== */ -bool FileExists( const char *filename ){ - FILE *f; - - f = fopen( filename, "r" ); - if ( !f ) { - return false; - } - fclose( f ); - return true; +bool FileExists(const char *filename) +{ + FILE *f; + + f = fopen(filename, "r"); + if (!f) { + return false; + } + fclose(f); + return true; } // // command buffer // empty wrappers, don't really use them here // -void Cbuf_AddText( const char *text ) {}; -void Cbuf_Execute( void ) {}; +void Cbuf_AddText(const char *text) +{}; + +void Cbuf_Execute(void) +{}; // // Common // -void CDECL Com_Error( int level, const char *error, ... ){ - va_list argptr; - char buf[32768]; +void CDECL Com_Error(int level, const char *error, ...) +{ + va_list argptr; + char buf[32768]; - va_start( argptr,error ); - vsprintf( buf, error,argptr ); - va_end( argptr ); + va_start(argptr, error); + vsprintf(buf, error, argptr); + va_end(argptr); - Sys_Printf( "Camera::ERROR->%s", buf ); + Sys_Printf("Camera::ERROR->%s", buf); } -void CDECL Com_Printf( const char* msg, ... ){ - va_list argptr; - char buf[32768]; +void CDECL Com_Printf(const char *msg, ...) +{ + va_list argptr; + char buf[32768]; - va_start( argptr,msg ); - vsprintf( buf, msg,argptr ); - va_end( argptr ); + va_start(argptr, msg); + vsprintf(buf, msg, argptr); + va_end(argptr); - Sys_Printf( "Camera::%s", buf ); + Sys_Printf("Camera::%s", buf); } -void CDECL Com_DPrintf( const char* msg, ... ){ +void CDECL Com_DPrintf(const char *msg, ...) +{ #if GDEF_DEBUG - va_list argptr; - char buf[32768]; + va_list argptr; + char buf[32768]; - va_start( argptr,msg ); - vsprintf( buf, msg,argptr ); - va_end( argptr ); + va_start( argptr,msg ); + vsprintf( buf, msg,argptr ); + va_end( argptr ); - Sys_Printf( "Camera::%s", buf ); + Sys_Printf( "Camera::%s", buf ); #endif } -void *Com_Allocate( int bytes ) { - return( malloc( bytes ) ); +void *Com_Allocate(int bytes) +{ + return (malloc(bytes)); } -void Com_Dealloc( void *ptr ) { - free( ptr ); +void Com_Dealloc(void *ptr) +{ + free(ptr); } // @@ -158,81 +173,87 @@ void Com_Dealloc( void *ptr ) { // #if GDEF_COMPILER_MSVC - #pragma warning(disable : 4311) - #pragma warning(disable : 4312) +#pragma warning(disable : 4311) +#pragma warning(disable : 4312) #endif -int FS_Read( void *buffer, int len, fileHandle_t f ) { - return fread( buffer, len, 1, (FILE *)f ); +int FS_Read(void *buffer, int len, fileHandle_t f) +{ + return fread(buffer, len, 1, (FILE *) f); } -int FS_Write( const void *buffer, int len, fileHandle_t h ) { - return fwrite( buffer, len, 1, (FILE *)h ); +int FS_Write(const void *buffer, int len, fileHandle_t h) +{ + return fwrite(buffer, len, 1, (FILE *) h); } -int FS_ReadFile( const char *qpath, void **buffer ) { - fileHandle_t h; - byte* buf; - int len; +int FS_ReadFile(const char *qpath, void **buffer) +{ + fileHandle_t h; + byte *buf; + int len; - buf = NULL; + buf = NULL; - len = FS_FOpenFileRead( qpath, &h, qfalse ); + len = FS_FOpenFileRead(qpath, &h, qfalse); - if ( h == 0 ) { - if ( buffer ) { - *buffer = NULL; - } + if (h == 0) { + if (buffer) { + *buffer = NULL; + } - return -1; - } + return -1; + } - buf = (byte *)Com_Allocate( len + 1 ); + buf = (byte *) Com_Allocate(len + 1); - *buffer = buf; + *buffer = buf; - FS_Read( buf, len, h ); + FS_Read(buf, len, h); - buf[len] = 0; - FS_FCloseFile( h ); + buf[len] = 0; + FS_FCloseFile(h); - return len; + return len; } -void FS_FreeFile( void *buffer ) { - Com_Dealloc( buffer ); +void FS_FreeFile(void *buffer) +{ + Com_Dealloc(buffer); } -int FS_FOpenFileRead( const char *filename, fileHandle_t *file, bool uniqueFILE ) { - FILE *fh; - long len; - - fh = fopen( filename, "rb" ); - *file = *(fileHandle_t *)&fh; - - if ( file ) { - fseek( fh, 0, SEEK_END ); - len = ftell( fh ); - rewind( fh ); - return len; - } - else{ - return -1; - } +int FS_FOpenFileRead(const char *filename, fileHandle_t *file, bool uniqueFILE) +{ + FILE *fh; + long len; + + fh = fopen(filename, "rb"); + *file = *(fileHandle_t *) &fh; + + if (file) { + fseek(fh, 0, SEEK_END); + len = ftell(fh); + rewind(fh); + return len; + } else { + return -1; + } } -fileHandle_t FS_FOpenFileWrite( const char *filename ) { - FILE *fh; - fileHandle_t f; +fileHandle_t FS_FOpenFileWrite(const char *filename) +{ + FILE *fh; + fileHandle_t f; - memset( &f, 0, sizeof( f ) ); + memset(&f, 0, sizeof(f)); - fh = fopen( filename, "wb" ); + fh = fopen(filename, "wb"); - f = (fileHandle_t)fh; - return f; + f = (fileHandle_t) fh; + return f; } -void FS_FCloseFile( fileHandle_t f ) { - fclose( (FILE *)f ); +void FS_FCloseFile(fileHandle_t f) +{ + fclose((FILE *) f); } diff --git a/contrib/camera/misc.h b/contrib/camera/misc.h index 9b3f71b7..f2a35ff1 100644 --- a/contrib/camera/misc.h +++ b/contrib/camera/misc.h @@ -26,53 +26,58 @@ #include "globaldefs.h" -void Sys_ERROR( char* text, ... ); -char* UnixToDosPath( char* path ); -void ExtractFilePath( const char *path, char *dest ); -const char* ExtractFilename( const char* path ); -bool FileExists( const char *filename ); -int Q_stricmp( const char *s1, const char *s2 ); +void Sys_ERROR(char *text, ...); + +char *UnixToDosPath(char *path); + +void ExtractFilePath(const char *path, char *dest); + +const char *ExtractFilename(const char *path); + +bool FileExists(const char *filename); + +int Q_stricmp(const char *s1, const char *s2); typedef int fileHandle_t; extern "C" { // command buffer -void Cbuf_AddText( const char *text ); -void Cbuf_Execute( void ); +void Cbuf_AddText(const char *text); +void Cbuf_Execute(void); // common #ifndef CDECL #if GDEF_OS_WINDOWS - #define CDECL __cdecl +#define CDECL __cdecl #else - #define CDECL +#define CDECL #endif #endif -void CDECL Com_Error( int level, const char *error, ... ); -void CDECL Com_Printf( const char *msg, ... ); -void CDECL Com_DPrintf( const char *msg, ... ); -void *Com_Allocate( int bytes ); -void Com_Dealloc( void *ptr ); +void CDECL Com_Error(int level, const char *error, ...); +void CDECL Com_Printf(const char *msg, ...); +void CDECL Com_DPrintf(const char *msg, ...); +void *Com_Allocate(int bytes); +void Com_Dealloc(void *ptr); // filesystem -int FS_Read( void *buffer, int len, fileHandle_t f ); -int FS_Write( const void *buffer, int len, fileHandle_t h ); -int FS_ReadFile( const char *qpath, void **buffer ); -void FS_FreeFile( void *buffer ); -int FS_FOpenFileRead( const char *filename, fileHandle_t *file, bool uniqueFILE ); -fileHandle_t FS_FOpenFileWrite( const char *filename ); -void FS_FCloseFile( fileHandle_t f ); +int FS_Read(void *buffer, int len, fileHandle_t f); +int FS_Write(const void *buffer, int len, fileHandle_t h); +int FS_ReadFile(const char *qpath, void **buffer); +void FS_FreeFile(void *buffer); +int FS_FOpenFileRead(const char *filename, fileHandle_t *file, bool uniqueFILE); +fileHandle_t FS_FOpenFileWrite(const char *filename); +void FS_FCloseFile(fileHandle_t f); } // vectors -#define DotProduct4( x,y ) ( ( x )[0] * ( y )[0] + ( x )[1] * ( y )[1] + ( x )[2] * ( y )[2] + ( x )[3] * ( y )[3] ) -#define VectorSubtract4( a,b,c ) ( ( c )[0] = ( a )[0] - ( b )[0],( c )[1] = ( a )[1] - ( b )[1],( c )[2] = ( a )[2] - ( b )[2],( c )[3] = ( a )[3] - ( b )[3] ) -#define VectorAdd4( a,b,c ) ( ( c )[0] = ( a )[0] + ( b )[0],( c )[1] = ( a )[1] + ( b )[1],( c )[2] = ( a )[2] + ( b )[2],( c )[3] = ( a )[3] + ( b )[3] ) -#define VectorCopy4( a,b ) ( ( b )[0] = ( a )[0],( b )[1] = ( a )[1],( b )[2] = ( a )[2],( b )[3] = ( a )[3] ) -#define VectorScale4( v, s, o ) ( ( o )[0] = ( v )[0] * ( s ),( o )[1] = ( v )[1] * ( s ),( o )[2] = ( v )[2] * ( s ),( o )[3] = ( v )[3] * ( s ) ) -#define VectorMA4( v, s, b, o ) ( ( o )[0] = ( v )[0] + ( b )[0] * ( s ),( o )[1] = ( v )[1] + ( b )[1] * ( s ),( o )[2] = ( v )[2] + ( b )[2] * ( s ),( o )[3] = ( v )[3] + ( b )[3] * ( s ) ) +#define DotProduct4(x, y) ( ( x )[0] * ( y )[0] + ( x )[1] * ( y )[1] + ( x )[2] * ( y )[2] + ( x )[3] * ( y )[3] ) +#define VectorSubtract4(a, b, c) ( ( c )[0] = ( a )[0] - ( b )[0],( c )[1] = ( a )[1] - ( b )[1],( c )[2] = ( a )[2] - ( b )[2],( c )[3] = ( a )[3] - ( b )[3] ) +#define VectorAdd4(a, b, c) ( ( c )[0] = ( a )[0] + ( b )[0],( c )[1] = ( a )[1] + ( b )[1],( c )[2] = ( a )[2] + ( b )[2],( c )[3] = ( a )[3] + ( b )[3] ) +#define VectorCopy4(a, b) ( ( b )[0] = ( a )[0],( b )[1] = ( a )[1],( b )[2] = ( a )[2],( b )[3] = ( a )[3] ) +#define VectorScale4(v, s, o) ( ( o )[0] = ( v )[0] * ( s ),( o )[1] = ( v )[1] * ( s ),( o )[2] = ( v )[2] * ( s ),( o )[3] = ( v )[3] * ( s ) ) +#define VectorMA4(v, s, b, o) ( ( o )[0] = ( v )[0] + ( b )[0] * ( s ),( o )[1] = ( v )[1] + ( b )[1] * ( s ),( o )[2] = ( v )[2] + ( b )[2] * ( s ),( o )[3] = ( v )[3] + ( b )[3] * ( s ) ) -#define Vector4Copy( a,b ) ( ( b )[0] = ( a )[0],( b )[1] = ( a )[1],( b )[2] = ( a )[2],( b )[3] = ( a )[3] ) +#define Vector4Copy(a, b) ( ( b )[0] = ( a )[0],( b )[1] = ( a )[1],( b )[2] = ( a )[2],( b )[3] = ( a )[3] ) -#define SnapVector( v ) {v[0] = (int)v[0]; v[1] = (int)v[1]; v[2] = (int)v[2]; } +#define SnapVector(v) {v[0] = (int)v[0]; v[1] = (int)v[1]; v[2] = (int)v[2]; } diff --git a/contrib/camera/renderer.cpp b/contrib/camera/renderer.cpp index ac270836..f372ca67 100644 --- a/contrib/camera/renderer.cpp +++ b/contrib/camera/renderer.cpp @@ -26,160 +26,165 @@ #include "camera.h" -CRenderer::CRenderer() { +CRenderer::CRenderer() +{ - refCount = 1; + refCount = 1; - m_bHooked = FALSE; + m_bHooked = FALSE; - Register(); - Initialize(); + Register(); + Initialize(); } -CRenderer::~CRenderer() { - if ( m_bHooked ) { - UnRegister(); - } +CRenderer::~CRenderer() +{ + if (m_bHooked) { + UnRegister(); + } } -void CRenderer::Register() { - g_QglTable.m_pfnHookGL2DWindow( this ); - g_QglTable.m_pfnHookGL3DWindow( this ); - m_bHooked = TRUE; +void CRenderer::Register() +{ + g_QglTable.m_pfnHookGL2DWindow(this); + g_QglTable.m_pfnHookGL3DWindow(this); + m_bHooked = TRUE; } -void CRenderer::UnRegister() { - if ( g_QglTable.m_nSize ) { - g_QglTable.m_pfnUnHookGL2DWindow( this ); - g_QglTable.m_pfnUnHookGL3DWindow( this ); - } - m_bHooked = FALSE; +void CRenderer::UnRegister() +{ + if (g_QglTable.m_nSize) { + g_QglTable.m_pfnUnHookGL2DWindow(this); + g_QglTable.m_pfnUnHookGL3DWindow(this); + } + m_bHooked = FALSE; } -void CRenderer::Initialize() { +void CRenderer::Initialize() +{ } -void CRenderer::Draw2D( VIEWTYPE vt ) { - - g_QglTable.m_pfn_qglPushAttrib( GL_ALL_ATTRIB_BITS ); - g_QglTable.m_pfn_qglPushMatrix(); - - switch ( vt ) - { - case XY: - break; - case XZ: - g_QglTable.m_pfn_qglRotatef( 270.0f, 1.0f, 0.0f, 0.0f ); - break; - case YZ: - g_QglTable.m_pfn_qglRotatef( 270.0f, 1.0f, 0.0f, 0.0f ); - g_QglTable.m_pfn_qglRotatef( 270.0f, 0.0f, 0.0f, 1.0f ); - break; - } - - CCamera *cam = firstCam; - while ( cam ) { - cam->GetCam()->draw( ( ( Listener && cam == g_pCurrentEditCam ) ? true : false ) ); - cam = cam->GetNext(); - } - - g_QglTable.m_pfn_qglPopMatrix(); - g_QglTable.m_pfn_qglPopAttrib(); +void CRenderer::Draw2D(VIEWTYPE vt) +{ + + g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS); + g_QglTable.m_pfn_qglPushMatrix(); + + switch (vt) { + case XY: + break; + case XZ: + g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f); + break; + case YZ: + g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f); + g_QglTable.m_pfn_qglRotatef(270.0f, 0.0f, 0.0f, 1.0f); + break; + } + + CCamera *cam = firstCam; + while (cam) { + cam->GetCam()->draw(((Listener && cam == g_pCurrentEditCam) ? true : false)); + cam = cam->GetNext(); + } + + g_QglTable.m_pfn_qglPopMatrix(); + g_QglTable.m_pfn_qglPopAttrib(); } -void CRenderer::Draw3D() { - // FIXME: really need a mainloop callback from the editor core - static long start; - static float cycle; - static long msecs; - static long current; - - if ( g_iPreviewRunning ) { - if ( g_iPreviewRunning == 1 ) { - start = Q_QGetTickCount(); - GetCurrentCam()->GetCam()->startCamera( start ); - cycle = GetCurrentCam()->GetCam()->getTotalTime(); - msecs = (long)( cycle * 1000 ); - current = start; - g_iPreviewRunning = 2; - } - - if ( current < start + msecs ) { - float fov; - vec3_t origin = {0.0f, 0.0f, 0.0f}, dir = {0.0f, 0.0f, 0.0f}, angles; - - GetCurrentCam()->GetCam()->getCameraInfo( current, &origin[0], &dir[0], &fov ); - VectorSet( angles, asin( dir[2] ) * 180 / 3.14159, atan2( dir[1], dir[0] ) * 180 / 3.14159, 0 ); - g_CameraTable.m_pfnSetCamera( origin, angles ); - current = Q_QGetTickCount(); - } - else { - g_iPreviewRunning = 0; - GetCurrentCam()->GetCam()->setRunning( false ); - g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA ); - } - } - - g_QglTable.m_pfn_qglPushAttrib( GL_ALL_ATTRIB_BITS ); - - CCamera *cam = firstCam; - while ( cam ) { - cam->GetCam()->draw( ( ( Listener && cam == g_pCurrentEditCam ) ? true : false ) ); - cam = cam->GetNext(); - } - - if ( g_iPreviewRunning ) { - int x, y, width, height, i; - float degInRad; - - g_CameraTable.m_pfnGetCamWindowExtents( &x, &y, &width, &height ); - - // setup orthographic projection mode - g_QglTable.m_pfn_qglMatrixMode( GL_PROJECTION ); - g_QglTable.m_pfn_qglLoadIdentity(); - g_QglTable.m_pfn_qglDisable( GL_DEPTH_TEST ); - g_QglTable.m_pfn_qglOrtho( 0, (float)width, 0, (float)height, -100, 100 ); - g_QglTable.m_pfn_qglMatrixMode( GL_MODELVIEW ); - - g_QglTable.m_pfn_qglLoadIdentity(); - g_QglTable.m_pfn_qglColor3f( 1.f, 1.f, 1.f ); - g_QglTable.m_pfn_qglBegin( GL_LINE_LOOP ); - g_QglTable.m_pfn_qglVertex2f( 10, 10 ); - g_QglTable.m_pfn_qglVertex2f( 40, 10 ); - g_QglTable.m_pfn_qglVertex2f( 40, 25 ); - g_QglTable.m_pfn_qglVertex2f( 10, 25 ); - g_QglTable.m_pfn_qglEnd(); - - g_QglTable.m_pfn_qglBegin( GL_LINE_LOOP ); - for ( i = 0; i < 360; i += 60 ) { - degInRad = i * ( 3.14159265358979323846 / 180.f ); - g_QglTable.m_pfn_qglVertex2f( 18 + cos( degInRad ) * 5, 18 + sin( degInRad ) * 5 ); - } - g_QglTable.m_pfn_qglEnd(); - - degInRad = ( 360 - ( ( current - start ) % 360 ) ) * ( 3.14159265358979323846 / 180.f ); - g_QglTable.m_pfn_qglBegin( GL_LINES ); - g_QglTable.m_pfn_qglVertex2f( 18, 18 ); - g_QglTable.m_pfn_qglVertex2f( 18 + cos( degInRad ) * 5, 18 + sin( degInRad ) * 5 ); - g_QglTable.m_pfn_qglVertex2f( 32, 18 ); - g_QglTable.m_pfn_qglVertex2f( 32 + cos( degInRad ) * 5, 18 + sin( degInRad ) * 5 ); - g_QglTable.m_pfn_qglEnd(); - - g_QglTable.m_pfn_qglBegin( GL_LINE_LOOP ); - for ( i = 0; i < 360; i += 60 ) { - degInRad = i * ( 3.14159265358979323846 / 180.f ); - g_QglTable.m_pfn_qglVertex2f( 32 + cos( degInRad ) * 5, 18 + sin( degInRad ) * 5 ); - } - g_QglTable.m_pfn_qglEnd(); - - g_QglTable.m_pfn_qglBegin( GL_LINES ); - g_QglTable.m_pfn_qglVertex2f( 40, 22 ); - g_QglTable.m_pfn_qglVertex2f( 52, 31 ); - g_QglTable.m_pfn_qglVertex2f( 40, 13 ); - g_QglTable.m_pfn_qglVertex2f( 52, 4 ); - g_QglTable.m_pfn_qglEnd(); - } - - g_QglTable.m_pfn_qglPopAttrib(); +void CRenderer::Draw3D() +{ + // FIXME: really need a mainloop callback from the editor core + static long start; + static float cycle; + static long msecs; + static long current; + + if (g_iPreviewRunning) { + if (g_iPreviewRunning == 1) { + start = Q_QGetTickCount(); + GetCurrentCam()->GetCam()->startCamera(start); + cycle = GetCurrentCam()->GetCam()->getTotalTime(); + msecs = (long) (cycle * 1000); + current = start; + g_iPreviewRunning = 2; + } + + if (current < start + msecs) { + float fov; + vec3_t origin = {0.0f, 0.0f, 0.0f}, dir = {0.0f, 0.0f, 0.0f}, angles; + + GetCurrentCam()->GetCam()->getCameraInfo(current, &origin[0], &dir[0], &fov); + VectorSet(angles, asin(dir[2]) * 180 / 3.14159, atan2(dir[1], dir[0]) * 180 / 3.14159, 0); + g_CameraTable.m_pfnSetCamera(origin, angles); + current = Q_QGetTickCount(); + } else { + g_iPreviewRunning = 0; + GetCurrentCam()->GetCam()->setRunning(false); + g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA); + } + } + + g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS); + + CCamera *cam = firstCam; + while (cam) { + cam->GetCam()->draw(((Listener && cam == g_pCurrentEditCam) ? true : false)); + cam = cam->GetNext(); + } + + if (g_iPreviewRunning) { + int x, y, width, height, i; + float degInRad; + + g_CameraTable.m_pfnGetCamWindowExtents(&x, &y, &width, &height); + + // setup orthographic projection mode + g_QglTable.m_pfn_qglMatrixMode(GL_PROJECTION); + g_QglTable.m_pfn_qglLoadIdentity(); + g_QglTable.m_pfn_qglDisable(GL_DEPTH_TEST); + g_QglTable.m_pfn_qglOrtho(0, (float) width, 0, (float) height, -100, 100); + g_QglTable.m_pfn_qglMatrixMode(GL_MODELVIEW); + + g_QglTable.m_pfn_qglLoadIdentity(); + g_QglTable.m_pfn_qglColor3f(1.f, 1.f, 1.f); + g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP); + g_QglTable.m_pfn_qglVertex2f(10, 10); + g_QglTable.m_pfn_qglVertex2f(40, 10); + g_QglTable.m_pfn_qglVertex2f(40, 25); + g_QglTable.m_pfn_qglVertex2f(10, 25); + g_QglTable.m_pfn_qglEnd(); + + g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP); + for (i = 0; i < 360; i += 60) { + degInRad = i * (3.14159265358979323846 / 180.f); + g_QglTable.m_pfn_qglVertex2f(18 + cos(degInRad) * 5, 18 + sin(degInRad) * 5); + } + g_QglTable.m_pfn_qglEnd(); + + degInRad = (360 - ((current - start) % 360)) * (3.14159265358979323846 / 180.f); + g_QglTable.m_pfn_qglBegin(GL_LINES); + g_QglTable.m_pfn_qglVertex2f(18, 18); + g_QglTable.m_pfn_qglVertex2f(18 + cos(degInRad) * 5, 18 + sin(degInRad) * 5); + g_QglTable.m_pfn_qglVertex2f(32, 18); + g_QglTable.m_pfn_qglVertex2f(32 + cos(degInRad) * 5, 18 + sin(degInRad) * 5); + g_QglTable.m_pfn_qglEnd(); + + g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP); + for (i = 0; i < 360; i += 60) { + degInRad = i * (3.14159265358979323846 / 180.f); + g_QglTable.m_pfn_qglVertex2f(32 + cos(degInRad) * 5, 18 + sin(degInRad) * 5); + } + g_QglTable.m_pfn_qglEnd(); + + g_QglTable.m_pfn_qglBegin(GL_LINES); + g_QglTable.m_pfn_qglVertex2f(40, 22); + g_QglTable.m_pfn_qglVertex2f(52, 31); + g_QglTable.m_pfn_qglVertex2f(40, 13); + g_QglTable.m_pfn_qglVertex2f(52, 4); + g_QglTable.m_pfn_qglEnd(); + } + + g_QglTable.m_pfn_qglPopAttrib(); } diff --git a/contrib/camera/renderer.h b/contrib/camera/renderer.h index b84680ba..059ad604 100644 --- a/contrib/camera/renderer.h +++ b/contrib/camera/renderer.h @@ -26,25 +26,34 @@ class CRenderer : public IGL2DWindow, public IGL3DWindow { public: -CRenderer(); -virtual ~CRenderer(); + CRenderer(); + + virtual ~CRenderer(); protected: -int refCount; + int refCount; public: -void Register(); -void UnRegister(); -void Initialize(); -void Draw2D( VIEWTYPE vt ); -void Draw3D(); - -void IncRef() { refCount++; } -void DecRef() { - refCount--; if ( refCount <= 0 ) { - delete this; - } -} - -bool m_bHooked; + void Register(); + + void UnRegister(); + + void Initialize(); + + void Draw2D(VIEWTYPE vt); + + void Draw3D(); + + void IncRef() + { refCount++; } + + void DecRef() + { + refCount--; + if (refCount <= 0) { + delete this; + } + } + + bool m_bHooked; }; diff --git a/contrib/gtkgensurf/bitmap.cpp b/contrib/gtkgensurf/bitmap.cpp index 68eea5c2..51566345 100644 --- a/contrib/gtkgensurf/bitmap.cpp +++ b/contrib/gtkgensurf/bitmap.cpp @@ -22,427 +22,423 @@ #include #include "gensurf.h" -void GenerateBitmapMapping(){ - double value; - double C0, C1; - double x, y; - int i, j; - int O00,O01,O10,O11; - int r0, r1, c0, c1; - int color; - unsigned char *colors; - - if ( !gbmp.colors ) { - return; - } - - colors = gbmp.colors; - - for ( j = 0; j <= NV; j++ ) - { - y = (double)( j * ( gbmp.height - 1 ) ) / (double)NV; - r0 = (int)floor( y ); - r1 = (int)ceil( y ); - for ( i = 0; i <= NH; i++ ) - { - x = (double)( i * ( gbmp.width - 1 ) ) / (double)NH; - c0 = (int)floor( x ); - c1 = (int)ceil( x ); - O00 = r0 * gbmp.width + c0; - O01 = r0 * gbmp.width + c1; - O10 = r1 * gbmp.width + c0; - O11 = r1 * gbmp.width + c1; - C0 = (double)colors[O00] + (double)( colors[O01] - colors[O00] ) * ( x - (double)c0 ); - C1 = (double)colors[O10] + (double)( colors[O11] - colors[O10] ) * ( x - (double)c0 ); - color = (int)( C0 + ( C1 - C0 ) * ( y - r0 ) ); - - value = CalculateSnapValue( gbmp.black_value + color * ( ( gbmp.white_value - gbmp.black_value ) / 255. ) ); - - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - xyz[i][j].p[1] = value; - break; - case PLANE_YZ0: - case PLANE_YZ1: - xyz[i][j].p[0] = value; - break; - default: - xyz[i][j].p[2] = value; - } - } - } +void GenerateBitmapMapping() +{ + double value; + double C0, C1; + double x, y; + int i, j; + int O00, O01, O10, O11; + int r0, r1, c0, c1; + int color; + unsigned char *colors; + + if (!gbmp.colors) { + return; + } + + colors = gbmp.colors; + + for (j = 0; j <= NV; j++) { + y = (double) (j * (gbmp.height - 1)) / (double) NV; + r0 = (int) floor(y); + r1 = (int) ceil(y); + for (i = 0; i <= NH; i++) { + x = (double) (i * (gbmp.width - 1)) / (double) NH; + c0 = (int) floor(x); + c1 = (int) ceil(x); + O00 = r0 * gbmp.width + c0; + O01 = r0 * gbmp.width + c1; + O10 = r1 * gbmp.width + c0; + O11 = r1 * gbmp.width + c1; + C0 = (double) colors[O00] + (double) (colors[O01] - colors[O00]) * (x - (double) c0); + C1 = (double) colors[O10] + (double) (colors[O11] - colors[O10]) * (x - (double) c0); + color = (int) (C0 + (C1 - C0) * (y - r0)); + + value = CalculateSnapValue(gbmp.black_value + color * ((gbmp.white_value - gbmp.black_value) / 255.)); + + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + xyz[i][j].p[1] = value; + break; + case PLANE_YZ0: + case PLANE_YZ1: + xyz[i][j].p[0] = value; + break; + default: + xyz[i][j].p[2] = value; + } + } + } } -static unsigned char* OpenBitmapFile(){ -#define INVALID_FORMAT do { \ - fprintf( stderr,"%s:%d: Error file '%s' is malformed.\n",__FILE__,__LINE__,gbmp.name ); \ - fclose( fp ); \ - return NULL; \ +static unsigned char *OpenBitmapFile() +{ +#define INVALID_FORMAT do { \ + fprintf( stderr,"%s:%d: Error file '%s' is malformed.\n",__FILE__,__LINE__,gbmp.name ); \ + fclose( fp ); \ + return NULL; \ } while ( 0 ); - int32_t bmWidth; - int32_t bmHeight; - uint16_t bmPlanes; - uint16_t bmBitsPixel; - uint8_t m1,m2; - uint32_t sizeimage; - int16_t res1,res2; - int32_t filesize, pixoff; - int32_t bmisize, compression; - int32_t xscale, yscale; - int32_t colors, impcol; - uint32_t m_bytesRead = 0; - unsigned char *image; - FILE *fp; - - fp = fopen( gbmp.name, "rb" ); - if ( fp == NULL ) { - fprintf( stderr,"Error: Invalid filename '%s'\n",gbmp.name ); - return NULL; - } - - long rc; - rc = fread( &m1, 1, 1, fp ); - m_bytesRead++; - if ( rc == -1 ) { - INVALID_FORMAT; - } - - rc = fread( &m2, 1, 1, fp ); - m_bytesRead++; - if ( ( m1 != 'B' ) || ( m2 != 'M' ) ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( filesize ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint16_t*)&( res1 ),2,1,fp ); m_bytesRead += 2; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint16_t*)&( res2 ),2,1,fp ); m_bytesRead += 2; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( pixoff ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( bmisize ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t *)&( bmWidth ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( bmHeight ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint16_t*)&( bmPlanes ),2,1,fp ); m_bytesRead += 2; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint16_t*)&( bmBitsPixel ),2,1,fp ); m_bytesRead += 2; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( compression ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( sizeimage ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( xscale ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( yscale ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( colors ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( (uint32_t*)&( impcol ),4,1,fp ); m_bytesRead += 4; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - if ( bmBitsPixel != 8 ) { - g_FuncTable.m_pfnMessageBox( g_pWnd, "This is not an 8-bit image. GenSurf can't use it.", - "Bitmap", eMB_OK, eMB_ICONWARNING ); - fclose( fp ); - return NULL; - } - - if ( colors == 0 ) { - colors = 1 << bmBitsPixel; - } - - if ( bmBitsPixel != 24 ) { - int i; - for ( i = 0; i < colors; i++ ) - { - unsigned char r,g, b, dummy; - - rc = fread( &b, 1, 1, fp ); - m_bytesRead++; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( &g, 1, 1, fp ); - m_bytesRead++; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( &r, 1, 1, fp ); - m_bytesRead++; - if ( rc != 1 ) { - INVALID_FORMAT; - } - - rc = fread( &dummy, 1, 1, fp ); - m_bytesRead++; - if ( rc != 1 ) { - INVALID_FORMAT; - } - } - } - - if ( (long)m_bytesRead > pixoff ) { - INVALID_FORMAT; - } - - while ( (long)m_bytesRead < pixoff ) - { - char dummy; - fread( &dummy,1,1,fp ); - m_bytesRead++; - } - - int w = bmWidth; - int h = bmHeight; - - // set the output params - image = (unsigned char*)malloc( w * h ); - - if ( image != NULL ) { - unsigned char* outbuf = image; - long row = 0; - long rowOffset = 0; - - if ( compression == 0 ) { // BI_RGB - for ( row = 0; row < bmHeight; row++ ) - { - // which row are we working on? - rowOffset = (long unsigned)row * w; - - { - // pixels are packed as 1 , 4 or 8 bit vals. need to unpack them - int bit_count = 0; - unsigned long mask = ( 1 << bmBitsPixel ) - 1; - unsigned char inbyte = 0; - - for ( int col = 0; col < w; col++ ) - { - int pix = 0; - - // if we need another byte - if ( bit_count <= 0 ) { - bit_count = 8; - if ( fread( &inbyte,1,1,fp ) != 1 ) { - free( image ); - INVALID_FORMAT; - } - m_bytesRead++; - } - - // keep track of where we are in the bytes - bit_count -= bmBitsPixel; - pix = ( inbyte >> bit_count ) & mask; - - // lookup the color from the colormap - stuff it in our buffer - // swap red and blue - *( outbuf + rowOffset + col ) = pix; - } - - // read DWORD padding - while ( ( m_bytesRead - pixoff ) & 3 ) - { - char dummy; - if ( fread( &dummy,1,1,fp ) != 1 ) { - free( image ); - INVALID_FORMAT; - } - m_bytesRead++; - } - } - } - } - else // compression != 0 - { - int i, x = 0; - unsigned char c, c1 = 0, *pp; - row = 0; - pp = outbuf; - - if ( bmBitsPixel == 8 ) { - while ( row < bmHeight ) - { - c = getc( fp ); - - if ( c ) { - // encoded mode - c1 = getc( fp ); - for ( i = 0; i < c; x++, i++ ) - { - *pp = c1; pp++; - } - } - else - { - // c==0x00, escape codes - c = getc( fp ); - - if ( c == 0x00 ) { // end of line - row++; - x = 0; - pp = outbuf + row * bmWidth; - } - else if ( c == 0x01 ) { - break; // end of pic - } - else if ( c == 0x02 ) { // delta - c = getc( fp ); - x += c; - c = getc( fp ); - row += c; - pp = outbuf + x + row * bmWidth; - } - else // absolute mode - { - for ( i = 0; i < c; x++, i++ ) - { - c1 = getc( fp ); - *pp = c1; pp++; - } - - if ( c & 1 ) { - getc( fp ); // odd length run: read an extra pad byte - } - } - } - } - } - else if ( bmBitsPixel == 4 ) { - while ( row < bmHeight ) - { - c = getc( fp ); - - if ( c ) { - // encoded mode - c1 = getc( fp ); - for ( i = 0; i < c; x++, i++ ) - { - *pp = ( i & 1 ) ? ( c1 & 0x0f ) : ( ( c1 >> 4 ) & 0x0f ); pp++; - } - } - else - { - // c==0x00, escape codes - c = getc( fp ); - - if ( c == 0x00 ) { // end of line - row++; - x = 0; - pp = outbuf + bmHeight * bmWidth; - } - else if ( c == 0x01 ) { - break; // end of pic - } - else if ( c == 0x02 ) { // delta - c = getc( fp ); - x += c; - c = getc( fp ); - row += c; - pp = outbuf + x + row * bmWidth; - } - else // absolute mode - { - for ( i = 0; i < c; x++, i++ ) - { - if ( ( i & 1 ) == 0 ) { - c1 = getc( fp ); - } - *pp = ( i & 1 ) ? ( c1 & 0x0f ) : ( ( c1 >> 4 ) & 0x0f ); pp++; - } - - if ( ( ( c & 3 ) == 1 ) || ( ( c & 3 ) == 2 ) ) { - getc( fp ); // odd length run: read an extra pad byte - } - } - } - } - } - } - } - fclose( fp ); - - gbmp.width = w; - gbmp.height = h; - if ( gbmp.colors ) { - free( gbmp.colors ); - } - gbmp.colors = image; - return image; + int32_t bmWidth; + int32_t bmHeight; + uint16_t bmPlanes; + uint16_t bmBitsPixel; + uint8_t m1, m2; + uint32_t sizeimage; + int16_t res1, res2; + int32_t filesize, pixoff; + int32_t bmisize, compression; + int32_t xscale, yscale; + int32_t colors, impcol; + uint32_t m_bytesRead = 0; + unsigned char *image; + FILE *fp; + + fp = fopen(gbmp.name, "rb"); + if (fp == NULL) { + fprintf(stderr, "Error: Invalid filename '%s'\n", gbmp.name); + return NULL; + } + + long rc; + rc = fread(&m1, 1, 1, fp); + m_bytesRead++; + if (rc == -1) { + INVALID_FORMAT; + } + + rc = fread(&m2, 1, 1, fp); + m_bytesRead++; + if ((m1 != 'B') || (m2 != 'M')) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (filesize), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint16_t * ) & (res1), 2, 1, fp); + m_bytesRead += 2; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint16_t * ) & (res2), 2, 1, fp); + m_bytesRead += 2; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (pixoff), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (bmisize), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (bmWidth), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (bmHeight), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint16_t * ) & (bmPlanes), 2, 1, fp); + m_bytesRead += 2; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint16_t * ) & (bmBitsPixel), 2, 1, fp); + m_bytesRead += 2; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (compression), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (sizeimage), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (xscale), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (yscale), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (colors), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread((uint32_t * ) & (impcol), 4, 1, fp); + m_bytesRead += 4; + if (rc != 1) { + INVALID_FORMAT; + } + + if (bmBitsPixel != 8) { + g_FuncTable.m_pfnMessageBox(g_pWnd, "This is not an 8-bit image. GenSurf can't use it.", + "Bitmap", eMB_OK, eMB_ICONWARNING); + fclose(fp); + return NULL; + } + + if (colors == 0) { + colors = 1 << bmBitsPixel; + } + + if (bmBitsPixel != 24) { + int i; + for (i = 0; i < colors; i++) { + unsigned char r, g, b, dummy; + + rc = fread(&b, 1, 1, fp); + m_bytesRead++; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread(&g, 1, 1, fp); + m_bytesRead++; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread(&r, 1, 1, fp); + m_bytesRead++; + if (rc != 1) { + INVALID_FORMAT; + } + + rc = fread(&dummy, 1, 1, fp); + m_bytesRead++; + if (rc != 1) { + INVALID_FORMAT; + } + } + } + + if ((long) m_bytesRead > pixoff) { + INVALID_FORMAT; + } + + while ((long) m_bytesRead < pixoff) { + char dummy; + fread(&dummy, 1, 1, fp); + m_bytesRead++; + } + + int w = bmWidth; + int h = bmHeight; + + // set the output params + image = (unsigned char *) malloc(w * h); + + if (image != NULL) { + unsigned char *outbuf = image; + long row = 0; + long rowOffset = 0; + + if (compression == 0) { // BI_RGB + for (row = 0; row < bmHeight; row++) { + // which row are we working on? + rowOffset = (long unsigned) row * w; + + { + // pixels are packed as 1 , 4 or 8 bit vals. need to unpack them + int bit_count = 0; + unsigned long mask = (1 << bmBitsPixel) - 1; + unsigned char inbyte = 0; + + for (int col = 0; col < w; col++) { + int pix = 0; + + // if we need another byte + if (bit_count <= 0) { + bit_count = 8; + if (fread(&inbyte, 1, 1, fp) != 1) { + free(image); + INVALID_FORMAT; + } + m_bytesRead++; + } + + // keep track of where we are in the bytes + bit_count -= bmBitsPixel; + pix = (inbyte >> bit_count) & mask; + + // lookup the color from the colormap - stuff it in our buffer + // swap red and blue + *(outbuf + rowOffset + col) = pix; + } + + // read DWORD padding + while ((m_bytesRead - pixoff) & 3) { + char dummy; + if (fread(&dummy, 1, 1, fp) != 1) { + free(image); + INVALID_FORMAT; + } + m_bytesRead++; + } + } + } + } else // compression != 0 + { + int i, x = 0; + unsigned char c, c1 = 0, *pp; + row = 0; + pp = outbuf; + + if (bmBitsPixel == 8) { + while (row < bmHeight) { + c = getc(fp); + + if (c) { + // encoded mode + c1 = getc(fp); + for (i = 0; i < c; x++, i++) { + *pp = c1; + pp++; + } + } else { + // c==0x00, escape codes + c = getc(fp); + + if (c == 0x00) { // end of line + row++; + x = 0; + pp = outbuf + row * bmWidth; + } else if (c == 0x01) { + break; // end of pic + } else if (c == 0x02) { // delta + c = getc(fp); + x += c; + c = getc(fp); + row += c; + pp = outbuf + x + row * bmWidth; + } else // absolute mode + { + for (i = 0; i < c; x++, i++) { + c1 = getc(fp); + *pp = c1; + pp++; + } + + if (c & 1) { + getc(fp); // odd length run: read an extra pad byte + } + } + } + } + } else if (bmBitsPixel == 4) { + while (row < bmHeight) { + c = getc(fp); + + if (c) { + // encoded mode + c1 = getc(fp); + for (i = 0; i < c; x++, i++) { + *pp = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); + pp++; + } + } else { + // c==0x00, escape codes + c = getc(fp); + + if (c == 0x00) { // end of line + row++; + x = 0; + pp = outbuf + bmHeight * bmWidth; + } else if (c == 0x01) { + break; // end of pic + } else if (c == 0x02) { // delta + c = getc(fp); + x += c; + c = getc(fp); + row += c; + pp = outbuf + x + row * bmWidth; + } else // absolute mode + { + for (i = 0; i < c; x++, i++) { + if ((i & 1) == 0) { + c1 = getc(fp); + } + *pp = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); + pp++; + } + + if (((c & 3) == 1) || ((c & 3) == 2)) { + getc(fp); // odd length run: read an extra pad byte + } + } + } + } + } + } + } + fclose(fp); + + gbmp.width = w; + gbmp.height = h; + if (gbmp.colors) { + free(gbmp.colors); + } + gbmp.colors = image; + return image; } -bool OpenBitmap(){ +bool OpenBitmap() +{ - OpenBitmapFile(); + OpenBitmapFile(); - if ( !gbmp.colors ) { - char Text[256]; + if (!gbmp.colors) { + char Text[256]; - sprintf( Text, "Error opening %s", gbmp.name ); - g_FuncTable.m_pfnMessageBox( g_pWnd, Text, "Bitmap", eMB_OK, eMB_ICONWARNING ); - strcpy( gbmp.name, "" ); - } + sprintf(Text, "Error opening %s", gbmp.name); + g_FuncTable.m_pfnMessageBox(g_pWnd, Text, "Bitmap", eMB_OK, eMB_ICONWARNING); + strcpy(gbmp.name, ""); + } - if ( g_pWnd ) { - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_file" ) ), gbmp.name ); - gtk_widget_set_sensitive( g_object_get_data( G_OBJECT( g_pWnd , "bmp_reload" ) ), - strlen( gbmp.name ) ? TRUE : FALSE ); + if (g_pWnd) { + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "bmp_file")), gbmp.name); + gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(g_pWnd, "bmp_reload")), + strlen(gbmp.name) ? TRUE : FALSE); - UpdatePreview( true ); - } + UpdatePreview(true); + } - return ( gbmp.colors != NULL ); + return (gbmp.colors != NULL); } diff --git a/contrib/gtkgensurf/dec.cpp b/contrib/gtkgensurf/dec.cpp index 158a4302..e080f266 100644 --- a/contrib/gtkgensurf/dec.cpp +++ b/contrib/gtkgensurf/dec.cpp @@ -30,311 +30,299 @@ #include "gensurf.h" #include "triangle.h" -typedef struct -{ - float error; - int node; +typedef struct { + float error; + int node; } TRITABLE; double dh, dv; int NVP1; -#define Absolute( a ) ( ( a ) >= 0.0 ? ( a ) : -( a ) ) - -void MakeDecimatedMap( int *NumNodes, int *NumTris, NODE **pNode, TRI **pTri ){ - int compare( TRITABLE *, TRITABLE * ); - int Bisect( NODE *, int, int, int ); - void CalcAngles( NODE *, int *, float * ); - void EdgeOnSide( int *, int *, int * ); - int tricall( int, NODE *, int *, TRI * *, TRI * *, const char * ); - int CheckBorders( int *,int,NODE *,int *,TRI * * ); - - float biggesterror; - int i, j, N; - int j0, j1, j2; - int NumNodesToSave; - int NumNodesUsed; - NODE *Node; - TRI *Tri; - TRITABLE *TriTable; - - if ( Decimate <= 0 ) { - return; - } - /* - ghCursorCurrent = LoadCursor(NULL,IDC_WAIT); - SetCursor(ghCursorCurrent); - */ - dh = ( Hur - Hll ) / NH; - dv = ( Vur - Vll ) / NV; - NVP1 = NV + 1; - - NumNodes[0] = ( NH + 1 ) * ( NVP1 ); - *pNode = (NODE *) malloc( NumNodes[0] * sizeof( NODE ) ); - Node = *pNode; - memset( Node,0,NumNodes[0] * sizeof( NODE ) ); - - // Copy [NH][NV] vertex array to our working node array - for ( i = 0,N = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++, N++ ) - { - Node[N].p[0] = (float)xyz[i][j].p[0]; - Node[N].p[1] = (float)xyz[i][j].p[1]; - Node[N].p[2] = (float)xyz[i][j].p[2]; - Node[N].fixed = xyz[i][j].fixed; - } - } - // Start things off with the corner values - Node[ 0].used = 1; - Node[NV].used = 1; - Node[NH * NVP1].used = 1; - Node[NH * NVP1 + NV].used = 1; - NumNodesUsed = 4; - tricall( NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY" ); - Tri = *pTri; - - // Which coordinates are we triangulating on? - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - j0 = 1; - j1 = 0; - j2 = 2; - break; - case PLANE_YZ0: - case PLANE_YZ1: - j0 = 0; - j1 = 1; - j2 = 2; - break; - default: - j0 = 2; - j1 = 0; - j2 = 1; - } - - // TriTable stores the largest error in a triangle and the node where that - // error occurs - TriTable = (TRITABLE *) malloc( NH * NV * 2 * sizeof( TRITABLE ) ); - NumNodesToSave = min( NumNodes[0], (int)( 0.01 * ( 100 - Decimate ) * ( NumNodes[0] - NumNodesUsed ) + NumNodesUsed ) ); - - while ( NumNodesUsed < NumNodesToSave ) - { - for ( i = 0; i < NumTris[0]; i++ ) - Tri[i].flag = 0; - - // For every node that's not currently used, find what triangle it - // lies on, and the error at this node - for ( i = 0, biggesterror = 0; i < NumNodes[0]; i++ ) - { - if ( Node[i].used ) { - continue; - } - for ( j = 0, Node[i].tri = -1; ( j < NumTris[0] ) && ( Node[i].tri == -1 ); j++ ) - { - if ( side( Node[i].p[j1], Node[i].p[j2], - Node[Tri[j].v[0]].p[j1],Node[Tri[j].v[0]].p[j2], - Node[Tri[j].v[1]].p[j1],Node[Tri[j].v[1]].p[j2] ) < 0. ) { - continue; - } - if ( side( Node[i].p[j1], Node[i].p[j2], - Node[Tri[j].v[1]].p[j1],Node[Tri[j].v[1]].p[j2], - Node[Tri[j].v[2]].p[j1],Node[Tri[j].v[2]].p[j2] ) < 0. ) { - continue; - } - if ( side( Node[i].p[j1], Node[i].p[j2], - Node[Tri[j].v[2]].p[j1],Node[Tri[j].v[2]].p[j2], - Node[Tri[j].v[0]].p[j1],Node[Tri[j].v[0]].p[j2] ) < 0. ) { - continue; - } - Node[i].tri = j; - } - if ( Node[i].tri < 0 ) { - /* - ghCursorCurrent = ghCursorDefault; - SetCursor(ghCursorCurrent); - */ - g_FuncTable.m_pfnMessageBox( g_pRadiantWnd, - "Error: Couldn't find the triangle bounding a point.", - "Decimation Error", eMB_OK, eMB_ICONWARNING ); - return; - } - if ( !Tri[Node[i].tri].flag ) { - PlaneFromPoints( Node[Tri[Node[i].tri].v[0]].p, - Node[Tri[Node[i].tri].v[1]].p, - Node[Tri[Node[i].tri].v[2]].p, - &Tri[Node[i].tri].plane ); - Tri[Node[i].tri].flag = 1; - } - Node[i].error = - Node[i].p[j0] - ( Tri[Node[i].tri].plane.dist - - Tri[Node[i].tri].plane.normal[j1] * Node[i].p[j1] - - Tri[Node[i].tri].plane.normal[j2] * Node[i].p[j2] ) / - Tri[Node[i].tri].plane.normal[j0]; - biggesterror = max( biggesterror,Absolute( Node[i].error ) ); - } - if ( biggesterror == 0 ) { - NumNodesToSave = NumNodesUsed; - } - else - { - // For all current triangles, build a list of worst-case nodes - memset( TriTable,0,NH * NV * 2 * sizeof( TRITABLE ) ); - for ( i = 0; i < NumNodes[0]; i++ ) - { - if ( Node[i].used ) { - continue; - } - if ( Absolute( Node[i].error ) > TriTable[Node[i].tri].error ) { - TriTable[Node[i].tri].error = (float)( Absolute( Node[i].error ) ); - TriTable[Node[i].tri].node = i; - } - } - qsort( (void *)TriTable, (size_t)( NumTris[0] ), sizeof( TRITABLE ), ( int ( * )( const void *, const void * ) )compare ); - for ( i = 0; i < NumTris[0] && NumNodesUsed < NumNodesToSave && TriTable[i].error > 0.5 * biggesterror; i++ ) - { - if ( Node[TriTable[i].node].used ) { - continue; // shouldn't happen - } - NumNodesUsed++; - Node[TriTable[i].node].used++; - } - free( Tri ); - tricall( NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY" ); - Tri = *pTri; - // Sliver-check along borders. Since borders are often linear, the errors - // along borders will often be zero, so no new points will be added. This - // tends to produce long, thin brushes. For all border triangles, check - // that minimum angle isn't less than SLIVER_ANGLE. If it is, add another - // vertex. - while ( CheckBorders( &NumNodesUsed,NumNodes[0],Node,NumTris,pTri ) > 0 ) - { - } - Tri = *pTri; - } - } - free( TriTable ); - // One last time (because we're pessimistic), check border triangles +#define Absolute(a) ( ( a ) >= 0.0 ? ( a ) : -( a ) ) + +void MakeDecimatedMap(int *NumNodes, int *NumTris, NODE **pNode, TRI **pTri) +{ + int compare(TRITABLE *, TRITABLE *); + int Bisect(NODE *, int, int, int); + void CalcAngles(NODE *, int *, float *); + void EdgeOnSide(int *, int *, int *); + int tricall(int, NODE *, int *, TRI **, TRI **, const char *); + int CheckBorders(int *, int, NODE *, int *, TRI **); + + float biggesterror; + int i, j, N; + int j0, j1, j2; + int NumNodesToSave; + int NumNodesUsed; + NODE *Node; + TRI *Tri; + TRITABLE *TriTable; + + if (Decimate <= 0) { + return; + } + /* + ghCursorCurrent = LoadCursor(NULL,IDC_WAIT); + SetCursor(ghCursorCurrent); + */ + dh = (Hur - Hll) / NH; + dv = (Vur - Vll) / NV; + NVP1 = NV + 1; + + NumNodes[0] = (NH + 1) * (NVP1); + *pNode = (NODE *) malloc(NumNodes[0] * sizeof(NODE)); + Node = *pNode; + memset(Node, 0, NumNodes[0] * sizeof(NODE)); + + // Copy [NH][NV] vertex array to our working node array + for (i = 0, N = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++, N++) { + Node[N].p[0] = (float) xyz[i][j].p[0]; + Node[N].p[1] = (float) xyz[i][j].p[1]; + Node[N].p[2] = (float) xyz[i][j].p[2]; + Node[N].fixed = xyz[i][j].fixed; + } + } + // Start things off with the corner values + Node[0].used = 1; + Node[NV].used = 1; + Node[NH * NVP1].used = 1; + Node[NH * NVP1 + NV].used = 1; + NumNodesUsed = 4; + tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY"); + Tri = *pTri; + + // Which coordinates are we triangulating on? + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + j0 = 1; + j1 = 0; + j2 = 2; + break; + case PLANE_YZ0: + case PLANE_YZ1: + j0 = 0; + j1 = 1; + j2 = 2; + break; + default: + j0 = 2; + j1 = 0; + j2 = 1; + } + + // TriTable stores the largest error in a triangle and the node where that + // error occurs + TriTable = (TRITABLE *) malloc(NH * NV * 2 * sizeof(TRITABLE)); + NumNodesToSave = min(NumNodes[0], (int) (0.01 * (100 - Decimate) * (NumNodes[0] - NumNodesUsed) + NumNodesUsed)); + + while (NumNodesUsed < NumNodesToSave) { + for (i = 0; i < NumTris[0]; i++) { + Tri[i].flag = 0; + } + + // For every node that's not currently used, find what triangle it + // lies on, and the error at this node + for (i = 0, biggesterror = 0; i < NumNodes[0]; i++) { + if (Node[i].used) { + continue; + } + for (j = 0, Node[i].tri = -1; (j < NumTris[0]) && (Node[i].tri == -1); j++) { + if (side(Node[i].p[j1], Node[i].p[j2], + Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2], + Node[Tri[j].v[1]].p[j1], Node[Tri[j].v[1]].p[j2]) < 0.) { + continue; + } + if (side(Node[i].p[j1], Node[i].p[j2], + Node[Tri[j].v[1]].p[j1], Node[Tri[j].v[1]].p[j2], + Node[Tri[j].v[2]].p[j1], Node[Tri[j].v[2]].p[j2]) < 0.) { + continue; + } + if (side(Node[i].p[j1], Node[i].p[j2], + Node[Tri[j].v[2]].p[j1], Node[Tri[j].v[2]].p[j2], + Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2]) < 0.) { + continue; + } + Node[i].tri = j; + } + if (Node[i].tri < 0) { + /* + ghCursorCurrent = ghCursorDefault; + SetCursor(ghCursorCurrent); + */ + g_FuncTable.m_pfnMessageBox(g_pRadiantWnd, + "Error: Couldn't find the triangle bounding a point.", + "Decimation Error", eMB_OK, eMB_ICONWARNING); + return; + } + if (!Tri[Node[i].tri].flag) { + PlaneFromPoints(Node[Tri[Node[i].tri].v[0]].p, + Node[Tri[Node[i].tri].v[1]].p, + Node[Tri[Node[i].tri].v[2]].p, + &Tri[Node[i].tri].plane); + Tri[Node[i].tri].flag = 1; + } + Node[i].error = + Node[i].p[j0] - (Tri[Node[i].tri].plane.dist - + Tri[Node[i].tri].plane.normal[j1] * Node[i].p[j1] - + Tri[Node[i].tri].plane.normal[j2] * Node[i].p[j2]) / + Tri[Node[i].tri].plane.normal[j0]; + biggesterror = max(biggesterror, Absolute(Node[i].error)); + } + if (biggesterror == 0) { + NumNodesToSave = NumNodesUsed; + } else { + // For all current triangles, build a list of worst-case nodes + memset(TriTable, 0, NH * NV * 2 * sizeof(TRITABLE)); + for (i = 0; i < NumNodes[0]; i++) { + if (Node[i].used) { + continue; + } + if (Absolute(Node[i].error) > TriTable[Node[i].tri].error) { + TriTable[Node[i].tri].error = (float) (Absolute(Node[i].error)); + TriTable[Node[i].tri].node = i; + } + } + qsort((void *) TriTable, (size_t)(NumTris[0]), sizeof(TRITABLE), + (int (*)(const void *, const void *)) compare); + for (i = 0; + i < NumTris[0] && NumNodesUsed < NumNodesToSave && TriTable[i].error > 0.5 * biggesterror; i++) { + if (Node[TriTable[i].node].used) { + continue; // shouldn't happen + } + NumNodesUsed++; + Node[TriTable[i].node].used++; + } + free(Tri); + tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY"); + Tri = *pTri; + // Sliver-check along borders. Since borders are often linear, the errors + // along borders will often be zero, so no new points will be added. This + // tends to produce long, thin brushes. For all border triangles, check + // that minimum angle isn't less than SLIVER_ANGLE. If it is, add another + // vertex. + while (CheckBorders(&NumNodesUsed, NumNodes[0], Node, NumTris, pTri) > 0) { + } + Tri = *pTri; + } + } + free(TriTable); + // One last time (because we're pessimistic), check border triangles // CheckBorders(&NumNodesUsed,NumNodes[0],Node,NumTris,pTri); // Tri = *pTri; - // Check that all fixed points are exact. If not, add them to the mix. - // First check to see if we have any fixed points that aren't already used. - for ( i = 0, N = 0; i < NumNodes[0] && !N; i++ ) - { - if ( Node[i].used ) { - continue; - } - if ( Node[i].fixed ) { - N++; - } - } - if ( N ) { - // Zero out the flag member of all triangles, indicating that - // the plane equation has not been found. - for ( i = 0; i < NumTris[0]; i++ ) - Tri[i].flag = 0; - - for ( i = 0; i < NumNodes[0]; i++ ) - { - if ( Node[i].used ) { - continue; - } - if ( !Node[i].fixed ) { - continue; - } - Node[i].tri = -1; - for ( j = 0; j < NumTris[0] && Node[i].tri == -1; j++ ) - { - if ( side( Node[i].p[j1], Node[i].p[j2], - Node[Tri[j].v[0]].p[j1],Node[Tri[j].v[0]].p[j2], - Node[Tri[j].v[1]].p[j1],Node[Tri[j].v[1]].p[j2] ) < 0. ) { - continue; - } - if ( side( Node[i].p[j1], Node[i].p[j2], - Node[Tri[j].v[1]].p[j1],Node[Tri[j].v[1]].p[j2], - Node[Tri[j].v[2]].p[j1],Node[Tri[j].v[2]].p[j2] ) < 0. ) { - continue; - } - if ( side( Node[i].p[j1], Node[i].p[j2], - Node[Tri[j].v[2]].p[j1],Node[Tri[j].v[2]].p[j2], - Node[Tri[j].v[0]].p[j1],Node[Tri[j].v[0]].p[j2] ) < 0. ) { - continue; - } - Node[i].tri = j; - } - if ( Node[i].tri < 0 ) { - /* - ghCursorCurrent = ghCursorDefault; - SetCursor(ghCursorCurrent); - */ - g_FuncTable.m_pfnMessageBox( g_pRadiantWnd, - "Error: Couldn't find the triangle bounding a point.", - "Decimation Error", eMB_OK, eMB_ICONWARNING ); - return; - } - if ( !Tri[Node[i].tri].flag ) { - PlaneFromPoints( Node[Tri[Node[i].tri].v[0]].p, - Node[Tri[Node[i].tri].v[1]].p, - Node[Tri[Node[i].tri].v[2]].p, - &Tri[Node[i].tri].plane ); - Tri[Node[i].tri].flag = 1; - } - Node[i].error = - Node[i].p[j0] - ( Tri[Node[i].tri].plane.dist - - Tri[Node[i].tri].plane.normal[j1] * Node[i].p[j1] - - Tri[Node[i].tri].plane.normal[j2] * Node[i].p[j2] ) / - Tri[Node[i].tri].plane.normal[j0]; - if ( Absolute( Node[i].error ) > 0.5 ) { - NumNodesUsed++; - Node[i].used++; - free( Tri ); - tricall( NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY" ); - Tri = *pTri; - } - } - } - - // Swap node orders for surfaces facing down, north or west so that - // they are counterclockwise when facing the surface - - if ( ( Plane == PLANE_XY1 ) || ( Plane == PLANE_XZ0 ) || ( Plane == PLANE_YZ1 ) ) { - for ( i = 0; i < NumTris[0]; i++ ) - { - j = Tri[i].v[1]; - Tri[i].v[1] = Tri[i].v[2]; - Tri[i].v[2] = j; - } - } - - // Store bounding box coords - for ( i = 0; i < NumTris[0]; i++ ) - { - Tri[i].min[0] = Node[Tri[i].v[0]].p[0]; - Tri[i].min[0] = min( Tri[i].min[0],Node[Tri[i].v[1]].p[0] ); - Tri[i].min[0] = min( Tri[i].min[0],Node[Tri[i].v[2]].p[0] ); - Tri[i].min[1] = Node[Tri[i].v[0]].p[1]; - Tri[i].min[1] = min( Tri[i].min[1],Node[Tri[i].v[1]].p[1] ); - Tri[i].min[1] = min( Tri[i].min[1],Node[Tri[i].v[2]].p[1] ); - Tri[i].min[2] = Node[Tri[i].v[0]].p[2]; - Tri[i].min[2] = min( Tri[i].min[2],Node[Tri[i].v[1]].p[2] ); - Tri[i].min[2] = min( Tri[i].min[2],Node[Tri[i].v[2]].p[2] ); - Tri[i].max[0] = Node[Tri[i].v[0]].p[0]; - Tri[i].max[0] = max( Tri[i].max[0],Node[Tri[i].v[1]].p[0] ); - Tri[i].max[0] = max( Tri[i].max[0],Node[Tri[i].v[2]].p[0] ); - Tri[i].max[1] = Node[Tri[i].v[0]].p[1]; - Tri[i].max[1] = max( Tri[i].max[1],Node[Tri[i].v[1]].p[1] ); - Tri[i].max[1] = max( Tri[i].max[1],Node[Tri[i].v[2]].p[1] ); - Tri[i].max[2] = Node[Tri[i].v[0]].p[2]; - Tri[i].max[2] = max( Tri[i].max[2],Node[Tri[i].v[1]].p[2] ); - Tri[i].max[2] = max( Tri[i].max[2],Node[Tri[i].v[2]].p[2] ); - } - /* - ghCursorCurrent = ghCursorDefault; - SetCursor(ghCursorCurrent); - */ + // Check that all fixed points are exact. If not, add them to the mix. + // First check to see if we have any fixed points that aren't already used. + for (i = 0, N = 0; i < NumNodes[0] && !N; i++) { + if (Node[i].used) { + continue; + } + if (Node[i].fixed) { + N++; + } + } + if (N) { + // Zero out the flag member of all triangles, indicating that + // the plane equation has not been found. + for (i = 0; i < NumTris[0]; i++) { + Tri[i].flag = 0; + } + + for (i = 0; i < NumNodes[0]; i++) { + if (Node[i].used) { + continue; + } + if (!Node[i].fixed) { + continue; + } + Node[i].tri = -1; + for (j = 0; j < NumTris[0] && Node[i].tri == -1; j++) { + if (side(Node[i].p[j1], Node[i].p[j2], + Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2], + Node[Tri[j].v[1]].p[j1], Node[Tri[j].v[1]].p[j2]) < 0.) { + continue; + } + if (side(Node[i].p[j1], Node[i].p[j2], + Node[Tri[j].v[1]].p[j1], Node[Tri[j].v[1]].p[j2], + Node[Tri[j].v[2]].p[j1], Node[Tri[j].v[2]].p[j2]) < 0.) { + continue; + } + if (side(Node[i].p[j1], Node[i].p[j2], + Node[Tri[j].v[2]].p[j1], Node[Tri[j].v[2]].p[j2], + Node[Tri[j].v[0]].p[j1], Node[Tri[j].v[0]].p[j2]) < 0.) { + continue; + } + Node[i].tri = j; + } + if (Node[i].tri < 0) { + /* + ghCursorCurrent = ghCursorDefault; + SetCursor(ghCursorCurrent); + */ + g_FuncTable.m_pfnMessageBox(g_pRadiantWnd, + "Error: Couldn't find the triangle bounding a point.", + "Decimation Error", eMB_OK, eMB_ICONWARNING); + return; + } + if (!Tri[Node[i].tri].flag) { + PlaneFromPoints(Node[Tri[Node[i].tri].v[0]].p, + Node[Tri[Node[i].tri].v[1]].p, + Node[Tri[Node[i].tri].v[2]].p, + &Tri[Node[i].tri].plane); + Tri[Node[i].tri].flag = 1; + } + Node[i].error = + Node[i].p[j0] - (Tri[Node[i].tri].plane.dist - + Tri[Node[i].tri].plane.normal[j1] * Node[i].p[j1] - + Tri[Node[i].tri].plane.normal[j2] * Node[i].p[j2]) / + Tri[Node[i].tri].plane.normal[j0]; + if (Absolute(Node[i].error) > 0.5) { + NumNodesUsed++; + Node[i].used++; + free(Tri); + tricall(NumNodes[0], Node, NumTris, NULL, pTri, "cnzBNPY"); + Tri = *pTri; + } + } + } + + // Swap node orders for surfaces facing down, north or west so that + // they are counterclockwise when facing the surface + + if ((Plane == PLANE_XY1) || (Plane == PLANE_XZ0) || (Plane == PLANE_YZ1)) { + for (i = 0; i < NumTris[0]; i++) { + j = Tri[i].v[1]; + Tri[i].v[1] = Tri[i].v[2]; + Tri[i].v[2] = j; + } + } + + // Store bounding box coords + for (i = 0; i < NumTris[0]; i++) { + Tri[i].min[0] = Node[Tri[i].v[0]].p[0]; + Tri[i].min[0] = min(Tri[i].min[0], Node[Tri[i].v[1]].p[0]); + Tri[i].min[0] = min(Tri[i].min[0], Node[Tri[i].v[2]].p[0]); + Tri[i].min[1] = Node[Tri[i].v[0]].p[1]; + Tri[i].min[1] = min(Tri[i].min[1], Node[Tri[i].v[1]].p[1]); + Tri[i].min[1] = min(Tri[i].min[1], Node[Tri[i].v[2]].p[1]); + Tri[i].min[2] = Node[Tri[i].v[0]].p[2]; + Tri[i].min[2] = min(Tri[i].min[2], Node[Tri[i].v[1]].p[2]); + Tri[i].min[2] = min(Tri[i].min[2], Node[Tri[i].v[2]].p[2]); + Tri[i].max[0] = Node[Tri[i].v[0]].p[0]; + Tri[i].max[0] = max(Tri[i].max[0], Node[Tri[i].v[1]].p[0]); + Tri[i].max[0] = max(Tri[i].max[0], Node[Tri[i].v[2]].p[0]); + Tri[i].max[1] = Node[Tri[i].v[0]].p[1]; + Tri[i].max[1] = max(Tri[i].max[1], Node[Tri[i].v[1]].p[1]); + Tri[i].max[1] = max(Tri[i].max[1], Node[Tri[i].v[2]].p[1]); + Tri[i].max[2] = Node[Tri[i].v[0]].p[2]; + Tri[i].max[2] = max(Tri[i].max[2], Node[Tri[i].v[1]].p[2]); + Tri[i].max[2] = max(Tri[i].max[2], Node[Tri[i].v[2]].p[2]); + } + /* + ghCursorCurrent = ghCursorDefault; + SetCursor(ghCursorCurrent); + */ } /* end MakeDecimatedMap */ @@ -343,1086 +331,1086 @@ void MakeDecimatedMap( int *NumNodes, int *NumTris, NODE **pNode, TRI **pTri ){ /* tricall Takes an array of nodes, spits out an array of triangles */ /* */ /*****************************************************************************/ -int tricall( int NumNodes, NODE *Node, int *NumTris, TRI **inTri, TRI **Tri, const char *Options ){ - struct triangulateio in, out; - int i, N; - int NumUsedNodes; - int *NodeTable; - TRI *ptri; - - /* Define input points. */ - - for ( i = 0,NumUsedNodes = 0; i < NumNodes; i++ ) - if ( Node[i].used ) { - NumUsedNodes++; - } - - memset( &in, 0,sizeof( in ) ); - memset( &out,0,sizeof( out ) ); - - NodeTable = (int *) malloc( NumUsedNodes * sizeof( int ) ); - - in.numberofpoints = NumUsedNodes; - in.numberofpointattributes = 0; - in.pointlist = (REAL *) malloc( in.numberofpoints * 2 * sizeof( REAL ) ); - for ( i = 0,N = 0; i < NumNodes; i++ ) - { - if ( Node[i].used ) { - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - in.pointlist[N * 2 ] = Node[i].p[0]; - in.pointlist[N * 2 + 1] = Node[i].p[2]; - break; - case PLANE_YZ0: - case PLANE_YZ1: - in.pointlist[N * 2 ] = Node[i].p[1]; - in.pointlist[N * 2 + 1] = Node[i].p[2]; - break; - default: - in.pointlist[N * 2 ] = Node[i].p[0]; - in.pointlist[N * 2 + 1] = Node[i].p[1]; - } - NodeTable[N] = i; - N++; - } - } - in.pointattributelist = (REAL *) NULL; - in.pointmarkerlist = (int *) NULL; - - if ( strstr( Options,"r" ) ) { - int *TriTable; - TriTable = (int *) malloc( NumNodes * sizeof( int ) ); - for ( i = 0,N = 0; i < NumNodes; i++ ) - { - if ( Node[i].used ) { - TriTable[i] = N; - N++; - } - } - in.numberoftriangles = NumTris[0]; - in.numberofcorners = 3; - in.numberoftriangleattributes = 0; - in.trianglelist = (int *) malloc( in.numberofcorners * in.numberoftriangles * sizeof( int ) ); - in.triangleattributelist = (REAL *) NULL; - in.trianglearealist = (REAL *) NULL; - ptri = *inTri; - for ( i = 0; i < in.numberoftriangles; i++ ) - { - in.trianglelist[i * in.numberofcorners ] = TriTable[ptri[i].v[0]]; - in.trianglelist[i * in.numberofcorners + 1] = TriTable[ptri[i].v[1]]; - in.trianglelist[i * in.numberofcorners + 2] = TriTable[ptri[i].v[2]]; - } - free( TriTable ); - } - else - { - in.numberoftriangles = 0; - in.numberofcorners = 3; - in.numberoftriangleattributes = 0; - in.trianglelist = (int *) NULL; - in.triangleattributelist = (REAL *) NULL; - in.trianglearealist = (REAL *) NULL; - } - - in.numberofsegments = 0; - in.segmentlist = (int *) NULL; - in.segmentmarkerlist = (int *) NULL; - - in.numberofholes = 0; - in.holelist = (REAL *) NULL; - - in.numberofregions = 0; - in.regionlist = (REAL *) NULL; - - in.numberofedges = 0; - in.edgelist = (int *) NULL; - in.edgemarkerlist = (int *) NULL; - in.normlist = (REAL *) NULL; - - /* Make necessary initializations */ - out.pointlist = (REAL *) NULL; /* Not needed if -N switch used. */ - out.pointattributelist = (REAL *) NULL; /* Not needed if -N switch used or +int tricall(int NumNodes, NODE *Node, int *NumTris, TRI **inTri, TRI **Tri, const char *Options) +{ + struct triangulateio in, out; + int i, N; + int NumUsedNodes; + int *NodeTable; + TRI *ptri; + + /* Define input points. */ + + for (i = 0, NumUsedNodes = 0; i < NumNodes; i++) { + if (Node[i].used) { + NumUsedNodes++; + } + } + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + + NodeTable = (int *) malloc(NumUsedNodes * sizeof(int)); + + in.numberofpoints = NumUsedNodes; + in.numberofpointattributes = 0; + in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL)); + for (i = 0, N = 0; i < NumNodes; i++) { + if (Node[i].used) { + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + in.pointlist[N * 2] = Node[i].p[0]; + in.pointlist[N * 2 + 1] = Node[i].p[2]; + break; + case PLANE_YZ0: + case PLANE_YZ1: + in.pointlist[N * 2] = Node[i].p[1]; + in.pointlist[N * 2 + 1] = Node[i].p[2]; + break; + default: + in.pointlist[N * 2] = Node[i].p[0]; + in.pointlist[N * 2 + 1] = Node[i].p[1]; + } + NodeTable[N] = i; + N++; + } + } + in.pointattributelist = (REAL *) NULL; + in.pointmarkerlist = (int *) NULL; + + if (strstr(Options, "r")) { + int *TriTable; + TriTable = (int *) malloc(NumNodes * sizeof(int)); + for (i = 0, N = 0; i < NumNodes; i++) { + if (Node[i].used) { + TriTable[i] = N; + N++; + } + } + in.numberoftriangles = NumTris[0]; + in.numberofcorners = 3; + in.numberoftriangleattributes = 0; + in.trianglelist = (int *) malloc(in.numberofcorners * in.numberoftriangles * sizeof(int)); + in.triangleattributelist = (REAL *) NULL; + in.trianglearealist = (REAL *) NULL; + ptri = *inTri; + for (i = 0; i < in.numberoftriangles; i++) { + in.trianglelist[i * in.numberofcorners] = TriTable[ptri[i].v[0]]; + in.trianglelist[i * in.numberofcorners + 1] = TriTable[ptri[i].v[1]]; + in.trianglelist[i * in.numberofcorners + 2] = TriTable[ptri[i].v[2]]; + } + free(TriTable); + } else { + in.numberoftriangles = 0; + in.numberofcorners = 3; + in.numberoftriangleattributes = 0; + in.trianglelist = (int *) NULL; + in.triangleattributelist = (REAL *) NULL; + in.trianglearealist = (REAL *) NULL; + } + + in.numberofsegments = 0; + in.segmentlist = (int *) NULL; + in.segmentmarkerlist = (int *) NULL; + + in.numberofholes = 0; + in.holelist = (REAL *) NULL; + + in.numberofregions = 0; + in.regionlist = (REAL *) NULL; + + in.numberofedges = 0; + in.edgelist = (int *) NULL; + in.edgemarkerlist = (int *) NULL; + in.normlist = (REAL *) NULL; + + /* Make necessary initializations */ + out.pointlist = (REAL *) NULL; /* Not needed if -N switch used. */ + out.pointattributelist = (REAL *) NULL; /* Not needed if -N switch used or number of point attributes is zero: */ - out.pointmarkerlist = (int *) NULL; /* Not needed if -N or -B switch used. */ - out.trianglelist = (int *) NULL; /* Not needed if -E switch used. */ - out.triangleattributelist = (REAL *) NULL; /* Not needed if -E switch used or + out.pointmarkerlist = (int *) NULL; /* Not needed if -N or -B switch used. */ + out.trianglelist = (int *) NULL; /* Not needed if -E switch used. */ + out.triangleattributelist = (REAL *) NULL; /* Not needed if -E switch used or number of triangle attributes is zero: */ - out.trianglearealist = (REAL *) NULL; - out.neighborlist = (int *) NULL; /* Needed only if -n switch used. */ - out.segmentlist = (int *) NULL; /* Needed only if segments are output + out.trianglearealist = (REAL *) NULL; + out.neighborlist = (int *) NULL; /* Needed only if -n switch used. */ + out.segmentlist = (int *) NULL; /* Needed only if segments are output (-p or -c) and -P not used: */ - out.segmentmarkerlist = (int *) NULL; /* Needed only if segments are output + out.segmentmarkerlist = (int *) NULL; /* Needed only if segments are output (-p or -c) and -P and -B not used: */ - out.edgelist = (int *) NULL; /* Needed only if -e switch used. */ - out.edgemarkerlist = (int *) NULL; /* Needed if -e used and -B not used. */ - - triangulate( Options, &in, &out, NULL ); - - NumTris[0] = out.numberoftriangles; - *Tri = (TRI *) malloc( NumTris[0] * sizeof( TRI ) ); - ptri = *Tri; - - for ( i = 0; i < NumTris[0]; i++ ) - { - ptri[i].v[0] = NodeTable[out.trianglelist[i * out.numberofcorners ]]; - ptri[i].v[1] = NodeTable[out.trianglelist[i * out.numberofcorners + 1]]; - ptri[i].v[2] = NodeTable[out.trianglelist[i * out.numberofcorners + 2]]; - ptri[i].n[0] = out.neighborlist[i * 3 ]; - ptri[i].n[1] = out.neighborlist[i * 3 + 1]; - ptri[i].n[2] = out.neighborlist[i * 3 + 2]; - } - - /* Free all allocated arrays, including those allocated by Triangle. */ - if ( in.pointlist ) { - free( in.pointlist ); - } - if ( in.pointattributelist ) { - free( in.pointattributelist ); - } - if ( in.pointmarkerlist ) { - free( in.pointmarkerlist ); - } - if ( in.trianglelist ) { - free( in.trianglelist ); - } - if ( in.triangleattributelist ) { - free( in.triangleattributelist ); - } - if ( in.trianglearealist ) { - free( in.trianglearealist ); - } - if ( in.neighborlist ) { - free( in.neighborlist ); - } - if ( in.segmentlist ) { - free( in.segmentlist ); - } - if ( in.segmentmarkerlist ) { - free( in.segmentmarkerlist ); - } - if ( in.holelist ) { - free( in.holelist ); - } - if ( in.regionlist ) { - free( in.regionlist ); - } - if ( in.edgelist ) { - free( in.edgelist ); - } - if ( in.edgemarkerlist ) { - free( in.edgemarkerlist ); - } - if ( in.normlist ) { - free( in.normlist ); - } - if ( out.pointlist ) { - free( out.pointlist ); - } - if ( out.pointattributelist ) { - free( out.pointattributelist ); - } - if ( out.pointmarkerlist ) { - free( out.pointmarkerlist ); - } - if ( out.trianglelist ) { - free( out.trianglelist ); - } - if ( out.triangleattributelist ) { - free( out.triangleattributelist ); - } - if ( out.trianglearealist ) { - free( out.trianglearealist ); - } - if ( out.neighborlist ) { - free( out.neighborlist ); - } - if ( out.segmentlist ) { - free( out.segmentlist ); - } - if ( out.segmentmarkerlist ) { - free( out.segmentmarkerlist ); - } - if ( out.holelist ) { - free( out.holelist ); - } - if ( out.regionlist ) { - free( out.regionlist ); - } - if ( out.edgelist ) { - free( out.edgelist ); - } - if ( out.edgemarkerlist ) { - free( out.edgemarkerlist ); - } - if ( out.normlist ) { - free( out.normlist ); - } - - free( NodeTable ); - return 0; + out.edgelist = (int *) NULL; /* Needed only if -e switch used. */ + out.edgemarkerlist = (int *) NULL; /* Needed if -e used and -B not used. */ + + triangulate(Options, &in, &out, NULL); + + NumTris[0] = out.numberoftriangles; + *Tri = (TRI *) malloc(NumTris[0] * sizeof(TRI)); + ptri = *Tri; + + for (i = 0; i < NumTris[0]; i++) { + ptri[i].v[0] = NodeTable[out.trianglelist[i * out.numberofcorners]]; + ptri[i].v[1] = NodeTable[out.trianglelist[i * out.numberofcorners + 1]]; + ptri[i].v[2] = NodeTable[out.trianglelist[i * out.numberofcorners + 2]]; + ptri[i].n[0] = out.neighborlist[i * 3]; + ptri[i].n[1] = out.neighborlist[i * 3 + 1]; + ptri[i].n[2] = out.neighborlist[i * 3 + 2]; + } + + /* Free all allocated arrays, including those allocated by Triangle. */ + if (in.pointlist) { + free(in.pointlist); + } + if (in.pointattributelist) { + free(in.pointattributelist); + } + if (in.pointmarkerlist) { + free(in.pointmarkerlist); + } + if (in.trianglelist) { + free(in.trianglelist); + } + if (in.triangleattributelist) { + free(in.triangleattributelist); + } + if (in.trianglearealist) { + free(in.trianglearealist); + } + if (in.neighborlist) { + free(in.neighborlist); + } + if (in.segmentlist) { + free(in.segmentlist); + } + if (in.segmentmarkerlist) { + free(in.segmentmarkerlist); + } + if (in.holelist) { + free(in.holelist); + } + if (in.regionlist) { + free(in.regionlist); + } + if (in.edgelist) { + free(in.edgelist); + } + if (in.edgemarkerlist) { + free(in.edgemarkerlist); + } + if (in.normlist) { + free(in.normlist); + } + if (out.pointlist) { + free(out.pointlist); + } + if (out.pointattributelist) { + free(out.pointattributelist); + } + if (out.pointmarkerlist) { + free(out.pointmarkerlist); + } + if (out.trianglelist) { + free(out.trianglelist); + } + if (out.triangleattributelist) { + free(out.triangleattributelist); + } + if (out.trianglearealist) { + free(out.trianglearealist); + } + if (out.neighborlist) { + free(out.neighborlist); + } + if (out.segmentlist) { + free(out.segmentlist); + } + if (out.segmentmarkerlist) { + free(out.segmentmarkerlist); + } + if (out.holelist) { + free(out.holelist); + } + if (out.regionlist) { + free(out.regionlist); + } + if (out.edgelist) { + free(out.edgelist); + } + if (out.edgemarkerlist) { + free(out.edgemarkerlist); + } + if (out.normlist) { + free(out.normlist); + } + + free(NodeTable); + return 0; } -void EdgeOnSide( int *v, int *edge, int *border ){ - int R; - int k0, k1, N; - float Ndv; - - border[0] = -1; - - if ( ( v[0] <= NV ) && ( v[1] <= NV ) ) { - edge[0] = 0; - border[0] = 0; - } - if ( ( v[1] <= NV ) && ( v[2] <= NV ) ) { - edge[0] = 1; - border[0] = 0; - } - if ( ( v[2] <= NV ) && ( v[0] <= NV ) ) { - edge[0] = 2; - border[0] = 0; - } - - R = NH * NVP1; - - if ( ( v[0] >= R ) && ( v[1] >= R ) ) { - edge[0] = 0; - border[0] = 1; - } - if ( ( v[1] >= R ) && ( v[2] >= R ) ) { - edge[0] = 1; - border[0] = 1; - } - if ( ( v[2] >= R ) && ( v[0] >= R ) ) { - edge[0] = 2; - border[0] = 1; - } - - if ( border[0] >= 0 ) { - k0 = edge[0]; - k1 = ( k0 + 1 ) % 3; - N = Absolute( v[k0] - v[k1] ); - Ndv = (float)( N * dv ); - } - if ( ( ( v[0] % NVP1 ) == 0 ) && ( ( v[1] % NVP1 ) == 0 ) ) { - if ( border[0] >= 0 ) { - if ( Ndv > ( Absolute( v[0] - v[1] ) * dh ) ) { - return; - } - } - edge[0] = 0; - border[0] = 2; - return; - } - if ( ( ( v[1] % NVP1 ) == 0 ) && ( ( v[2] % NVP1 ) == 0 ) ) { - if ( border[0] >= 0 ) { - if ( Ndv > ( Absolute( v[1] - v[2] ) * dh ) ) { - return; - } - } - edge[0] = 1; - border[0] = 2; - return; - } - if ( ( ( v[2] % NVP1 ) == 0 ) && ( ( v[0] % NVP1 ) == 0 ) ) { - if ( border[0] >= 0 ) { - if ( Ndv > ( Absolute( v[2] - v[0] ) * dh ) ) { - return; - } - } - edge[0] = 2; - border[0] = 2; - return; - } - - if ( ( ( v[0] % NVP1 ) == NV ) && ( ( v[1] % NVP1 ) == NV ) ) { - if ( border[0] >= 0 ) { - if ( Ndv > ( Absolute( v[0] - v[1] ) * dh ) ) { - return; - } - } - edge[0] = 0; - border[0] = 3; - return; - } - if ( ( ( v[1] % NVP1 ) == NV ) && ( ( v[2] % NVP1 ) == NV ) ) { - if ( border[0] >= 0 ) { - if ( Ndv > ( Absolute( v[1] - v[2] ) * dh ) ) { - return; - } - } - edge[0] = 1; - border[0] = 3; - return; - } - if ( ( ( v[2] % NVP1 ) == NV ) && ( ( v[0] % NVP1 ) == NV ) ) { - if ( border[0] >= 0 ) { - if ( Ndv > ( Absolute( v[2] - v[0] ) * dh ) ) { - return; - } - } - edge[0] = 2; - border[0] = 3; - return; - } - return; +void EdgeOnSide(int *v, int *edge, int *border) +{ + int R; + int k0, k1, N; + float Ndv; + + border[0] = -1; + + if ((v[0] <= NV) && (v[1] <= NV)) { + edge[0] = 0; + border[0] = 0; + } + if ((v[1] <= NV) && (v[2] <= NV)) { + edge[0] = 1; + border[0] = 0; + } + if ((v[2] <= NV) && (v[0] <= NV)) { + edge[0] = 2; + border[0] = 0; + } + + R = NH * NVP1; + + if ((v[0] >= R) && (v[1] >= R)) { + edge[0] = 0; + border[0] = 1; + } + if ((v[1] >= R) && (v[2] >= R)) { + edge[0] = 1; + border[0] = 1; + } + if ((v[2] >= R) && (v[0] >= R)) { + edge[0] = 2; + border[0] = 1; + } + + if (border[0] >= 0) { + k0 = edge[0]; + k1 = (k0 + 1) % 3; + N = Absolute(v[k0] - v[k1]); + Ndv = (float) (N * dv); + } + if (((v[0] % NVP1) == 0) && ((v[1] % NVP1) == 0)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[0] - v[1]) * dh)) { + return; + } + } + edge[0] = 0; + border[0] = 2; + return; + } + if (((v[1] % NVP1) == 0) && ((v[2] % NVP1) == 0)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[1] - v[2]) * dh)) { + return; + } + } + edge[0] = 1; + border[0] = 2; + return; + } + if (((v[2] % NVP1) == 0) && ((v[0] % NVP1) == 0)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[2] - v[0]) * dh)) { + return; + } + } + edge[0] = 2; + border[0] = 2; + return; + } + + if (((v[0] % NVP1) == NV) && ((v[1] % NVP1) == NV)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[0] - v[1]) * dh)) { + return; + } + } + edge[0] = 0; + border[0] = 3; + return; + } + if (((v[1] % NVP1) == NV) && ((v[2] % NVP1) == NV)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[1] - v[2]) * dh)) { + return; + } + } + edge[0] = 1; + border[0] = 3; + return; + } + if (((v[2] % NVP1) == NV) && ((v[0] % NVP1) == NV)) { + if (border[0] >= 0) { + if (Ndv > (Absolute(v[2] - v[0]) * dh)) { + return; + } + } + edge[0] = 2; + border[0] = 3; + return; + } + return; } -void CalcAngles( NODE *node, int *v, float *angle ){ - int i, j, k; - vec l; - vec x0, x1, x2, y0, y1, y2; - vec2 vv[3]; - vec dot; - - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - i = 0; - j = 2; - break; - case PLANE_YZ0: - case PLANE_YZ1: - i = 1; - j = 2; - break; - default: - i = 0; - j = 1; - } - x0 = node[v[0]].p[i]; - x1 = node[v[1]].p[i]; - x2 = node[v[2]].p[i]; - y0 = node[v[0]].p[j]; - y1 = node[v[1]].p[j]; - y2 = node[v[2]].p[j]; - - vv[0][0] = x1 - x0; - vv[0][1] = y1 - y0; - vv[1][0] = x2 - x1; - vv[1][1] = y2 - y1; - vv[2][0] = x0 - x2; - vv[2][1] = y0 - y2; - - for ( k = 0; k < 3; k++ ) - { - l = (vec)( sqrt( vv[k][0] * vv[k][0] + vv[k][1] * vv[k][1] ) ); - if ( l > 0. ) { - vv[k][0] /= l; - vv[k][1] /= l; - } - } - - dot = -( vv[0][0] * vv[2][0] + vv[0][1] * vv[2][1] ); - angle[0] = (float)( acos( dot ) ); - dot = -( vv[1][0] * vv[0][0] + vv[1][1] * vv[0][1] ); - angle[1] = (float)( acos( dot ) ); - dot = -( vv[2][0] * vv[1][0] + vv[2][1] * vv[1][1] ); - angle[2] = (float)( acos( dot ) ); +void CalcAngles(NODE *node, int *v, float *angle) +{ + int i, j, k; + vec l; + vec x0, x1, x2, y0, y1, y2; + vec2 vv[3]; + vec dot; + + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + i = 0; + j = 2; + break; + case PLANE_YZ0: + case PLANE_YZ1: + i = 1; + j = 2; + break; + default: + i = 0; + j = 1; + } + x0 = node[v[0]].p[i]; + x1 = node[v[1]].p[i]; + x2 = node[v[2]].p[i]; + y0 = node[v[0]].p[j]; + y1 = node[v[1]].p[j]; + y2 = node[v[2]].p[j]; + + vv[0][0] = x1 - x0; + vv[0][1] = y1 - y0; + vv[1][0] = x2 - x1; + vv[1][1] = y2 - y1; + vv[2][0] = x0 - x2; + vv[2][1] = y0 - y2; + + for (k = 0; k < 3; k++) { + l = (vec) (sqrt(vv[k][0] * vv[k][0] + vv[k][1] * vv[k][1])); + if (l > 0.) { + vv[k][0] /= l; + vv[k][1] /= l; + } + } + + dot = -(vv[0][0] * vv[2][0] + vv[0][1] * vv[2][1]); + angle[0] = (float) (acos(dot)); + dot = -(vv[1][0] * vv[0][0] + vv[1][1] * vv[0][1]); + angle[1] = (float) (acos(dot)); + dot = -(vv[2][0] * vv[1][0] + vv[2][1] * vv[1][1]); + angle[2] = (float) (acos(dot)); } + //================================================================= -int Bisect( NODE *node, int border, int j0, int j1 ){ - int k; - - switch ( border ) - { - case 0: - k = ( j0 + j1 ) / 2; - break; - case 1: - k = ( j0 + j1 ) / 2; - break; - case 2: - k = (int)( ( j0 + j1 ) / ( 2 * NVP1 ) ) * NVP1; - break; - case 3: - k = (int)( ( j0 + j1 + 2 ) / ( 2 * NVP1 ) ) * NVP1 - 1; - break; - } - return( ( ( k != j0 ) && ( k != j1 ) ) ? k : 0 ); +int Bisect(NODE *node, int border, int j0, int j1) +{ + int k; + + switch (border) { + case 0: + k = (j0 + j1) / 2; + break; + case 1: + k = (j0 + j1) / 2; + break; + case 2: + k = (int) ((j0 + j1) / (2 * NVP1)) * NVP1; + break; + case 3: + k = (int) ((j0 + j1 + 2) / (2 * NVP1)) * NVP1 - 1; + break; + } + return (((k != j0) && (k != j1)) ? k : 0); } + //================================================================= -int compare( TRITABLE *t1, TRITABLE *t2 ){ - if ( t1->error > t2->error ) { - return -1; - } - if ( t1->error < t2->error ) { - return 1; - } - return 0; +int compare(TRITABLE *t1, TRITABLE *t2) +{ + if (t1->error > t2->error) { + return -1; + } + if (t1->error < t2->error) { + return 1; + } + return 0; } -void MakeBrushes( int NumTris, NODE *Node, TRI *Tri,bool surf, - int offset,char *texture0, char *texture1, char *texture2 ){ - extern double backface; - BRUSH brush; - int contents; - int i, j; - float Steep; - vec3_t PlaneNormal,SurfNormal; - bool CheckAngle; - vec3_t t[2]; - - // if texture2 is identical to texture0, there's no need to - // check surface angle - if ( !g_strcasecmp( texture0,texture2 ) || !strlen( texture2 ) ) { - CheckAngle = FALSE; - } - else - { - CheckAngle = TRUE; - Steep = (float)cos( (double)SlantAngle / 57.2957795 ); - switch ( Plane ) - { - case PLANE_XY0: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break; - case PLANE_XY1: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = -1.; break; - case PLANE_XZ0: PlaneNormal[0] = 0.; PlaneNormal[1] = 1.; PlaneNormal[2] = 1.; break; - case PLANE_XZ1: PlaneNormal[0] = 0.; PlaneNormal[1] = -1.; PlaneNormal[2] = 1.; break; - case PLANE_YZ0: PlaneNormal[0] = 1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break; - case PLANE_YZ1: PlaneNormal[0] = -1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break; - } - } - - contents = 0; - if ( surf ) { - if ( UseDetail ) { - contents += CONTENTS_DETAIL; - } - if ( UseLadder ) { - contents += CONTENTS_LADDER; - } - } - - OpenFuncGroup(); - for ( i = 0; i < NumTris; i++ ) - { - brush.Number = i; - brush.NumFaces = 5; - // front - brush.face[0].v[0][0] = Node[Tri[i].v[0]].p[0]; - brush.face[0].v[0][1] = Node[Tri[i].v[0]].p[1]; - brush.face[0].v[0][2] = Node[Tri[i].v[0]].p[2]; - - brush.face[0].v[1][0] = Node[Tri[i].v[2]].p[0]; - brush.face[0].v[1][1] = Node[Tri[i].v[2]].p[1]; - brush.face[0].v[1][2] = Node[Tri[i].v[2]].p[2]; - - brush.face[0].v[2][0] = Node[Tri[i].v[1]].p[0]; - brush.face[0].v[2][1] = Node[Tri[i].v[1]].p[1]; - brush.face[0].v[2][2] = Node[Tri[i].v[1]].p[2]; - - if ( offset != 0 ) { - switch ( Plane ) - { - case PLANE_XY0: - brush.face[0].v[0][2] += offset; - brush.face[0].v[1][2] += offset; - brush.face[0].v[1][2] += offset; - break; - case PLANE_XY1: - brush.face[0].v[0][2] -= offset; - brush.face[0].v[1][2] -= offset; - brush.face[0].v[1][2] -= offset; - break; - case PLANE_XZ0: - brush.face[0].v[0][1] += offset; - brush.face[0].v[1][1] += offset; - brush.face[0].v[1][1] += offset; - break; - case PLANE_XZ1: - brush.face[0].v[0][1] -= offset; - brush.face[0].v[1][1] -= offset; - brush.face[0].v[1][1] -= offset; - break; - case PLANE_YZ0: - brush.face[0].v[0][0] += offset; - brush.face[0].v[1][0] += offset; - brush.face[0].v[1][0] += offset; - break; - case PLANE_YZ1: - brush.face[0].v[0][0] -= offset; - brush.face[0].v[1][0] -= offset; - brush.face[0].v[1][0] -= offset; - break; - } - } - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - // back - brush.face[1].v[0][0] = Node[Tri[i].v[0]].p[0]; - brush.face[1].v[0][1] = (float)backface; - brush.face[1].v[0][2] = Node[Tri[i].v[0]].p[2]; - - brush.face[1].v[1][0] = Node[Tri[i].v[1]].p[0]; - brush.face[1].v[1][1] = (float)backface; - brush.face[1].v[1][2] = Node[Tri[i].v[1]].p[2]; - - brush.face[1].v[2][0] = Node[Tri[i].v[2]].p[0]; - brush.face[1].v[2][1] = (float)backface; - brush.face[1].v[2][2] = Node[Tri[i].v[2]].p[2]; - - // 0-1 side - brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0]; - brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1]; - brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2]; - - brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0]; - brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1]; - brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2]; - - brush.face[2].v[2][0] = Node[Tri[i].v[1]].p[0]; - brush.face[2].v[2][1] = (float)backface; - brush.face[2].v[2][2] = Node[Tri[i].v[1]].p[2]; - - // 1-2 side - brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0]; - brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1]; - brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2]; - - brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0]; - brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1]; - brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2]; - - brush.face[3].v[2][0] = Node[Tri[i].v[2]].p[0]; - brush.face[3].v[2][1] = (float)backface; - brush.face[3].v[2][2] = Node[Tri[i].v[2]].p[2]; - - // 2-0 side - brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0]; - brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1]; - brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2]; - - brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0]; - brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1]; - brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2]; - - brush.face[4].v[2][0] = Node[Tri[i].v[0]].p[0]; - brush.face[4].v[2][1] = (float)backface; - brush.face[4].v[2][2] = Node[Tri[i].v[0]].p[2]; - break; - case PLANE_YZ0: - case PLANE_YZ1: - // back - brush.face[1].v[0][0] = (float)backface; - brush.face[1].v[0][1] = Node[Tri[i].v[0]].p[1]; - brush.face[1].v[0][2] = Node[Tri[i].v[0]].p[2]; - - brush.face[1].v[1][0] = (float)backface; - brush.face[1].v[1][1] = Node[Tri[i].v[1]].p[1]; - brush.face[1].v[1][2] = Node[Tri[i].v[1]].p[2]; - - brush.face[1].v[2][0] = (float)backface; - brush.face[1].v[2][1] = Node[Tri[i].v[2]].p[1]; - brush.face[1].v[2][2] = Node[Tri[i].v[2]].p[2]; - - // 0-1 side - brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0]; - brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1]; - brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2]; - - brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0]; - brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1]; - brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2]; - - brush.face[2].v[2][0] = (float)backface; - brush.face[2].v[2][1] = Node[Tri[i].v[1]].p[1]; - brush.face[2].v[2][2] = Node[Tri[i].v[1]].p[2]; - - // 1-2 side - brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0]; - brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1]; - brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2]; - - brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0]; - brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1]; - brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2]; - - brush.face[3].v[2][0] = (float)backface; - brush.face[3].v[2][1] = Node[Tri[i].v[2]].p[1]; - brush.face[3].v[2][2] = Node[Tri[i].v[2]].p[2]; - - // 2-0 side - brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0]; - brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1]; - brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2]; - - brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0]; - brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1]; - brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2]; - - brush.face[4].v[2][0] = (float)backface; - brush.face[4].v[2][1] = Node[Tri[i].v[0]].p[1]; - brush.face[4].v[2][2] = Node[Tri[i].v[0]].p[2]; - break; - default: - // back - brush.face[1].v[0][0] = Node[Tri[i].v[0]].p[0]; - brush.face[1].v[0][1] = Node[Tri[i].v[0]].p[1]; - brush.face[1].v[0][2] = (float)backface; - - brush.face[1].v[1][0] = Node[Tri[i].v[1]].p[0]; - brush.face[1].v[1][1] = Node[Tri[i].v[1]].p[1]; - brush.face[1].v[1][2] = (float)backface; - - brush.face[1].v[2][0] = Node[Tri[i].v[2]].p[0]; - brush.face[1].v[2][1] = Node[Tri[i].v[2]].p[1]; - brush.face[1].v[2][2] = (float)backface; - - // 0-1 side - brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0]; - brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1]; - brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2]; - - brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0]; - brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1]; - brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2]; - - brush.face[2].v[2][0] = Node[Tri[i].v[1]].p[0]; - brush.face[2].v[2][1] = Node[Tri[i].v[1]].p[1]; - brush.face[2].v[2][2] = (float)backface; - - // 1-2 side - brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0]; - brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1]; - brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2]; - - brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0]; - brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1]; - brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2]; - - brush.face[3].v[2][0] = Node[Tri[i].v[2]].p[0]; - brush.face[3].v[2][1] = Node[Tri[i].v[2]].p[1]; - brush.face[3].v[2][2] = (float)backface; - - // 2-0 side - brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0]; - brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1]; - brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2]; - - brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0]; - brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1]; - brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2]; - - brush.face[4].v[2][0] = Node[Tri[i].v[0]].p[0]; - brush.face[4].v[2][1] = Node[Tri[i].v[0]].p[1]; - brush.face[4].v[2][2] = (float)backface; - } - - for ( j = 0; j < 5; j++ ) - { - strcpy( brush.face[j].texture, - ( strlen( texture1 ) ? texture1 : texture0 ) ); - brush.face[j].Shift[0] = (float)TexOffset[0]; - brush.face[j].Shift[1] = (float)TexOffset[1]; - brush.face[j].Rotate = 0.; - brush.face[j].Scale[0] = (float)TexScale[0]; - brush.face[j].Scale[1] = (float)TexScale[1]; - brush.face[j].Contents = contents; - if ( surf ) { - brush.face[j].Surface = 0; - } - else{ - brush.face[j].Surface = SURF_HINT; - } - brush.face[j].Value = 0; - } - - if ( CheckAngle ) { - XYZVectorSubtract( brush.face[0].v[2],brush.face[0].v[0],t[0] ); - XYZVectorSubtract( brush.face[0].v[1],brush.face[0].v[2],t[1] ); - CrossProduct( t[0],t[1],SurfNormal ); - VectorNormalize( SurfNormal,SurfNormal ); - if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) { - strcpy( brush.face[0].texture,texture2 ); - } - else{ - strcpy( brush.face[0].texture,texture0 ); - } - } - else{ - strcpy( brush.face[0].texture,texture0 ); - } - - if ( surf ) { - brush.face[0].Value = ArghRad2; - } - MakeBrush( &brush ); - } - CloseFuncGroup(); +void MakeBrushes(int NumTris, NODE *Node, TRI *Tri, bool surf, + int offset, char *texture0, char *texture1, char *texture2) +{ + extern double backface; + BRUSH brush; + int contents; + int i, j; + float Steep; + vec3_t PlaneNormal, SurfNormal; + bool CheckAngle; + vec3_t t[2]; + + // if texture2 is identical to texture0, there's no need to + // check surface angle + if (!g_strcasecmp(texture0, texture2) || !strlen(texture2)) { + CheckAngle = FALSE; + } else { + CheckAngle = TRUE; + Steep = (float) cos((double) SlantAngle / 57.2957795); + switch (Plane) { + case PLANE_XY0: + PlaneNormal[0] = 0.; + PlaneNormal[1] = 0.; + PlaneNormal[2] = 1.; + break; + case PLANE_XY1: + PlaneNormal[0] = 0.; + PlaneNormal[1] = 0.; + PlaneNormal[2] = -1.; + break; + case PLANE_XZ0: + PlaneNormal[0] = 0.; + PlaneNormal[1] = 1.; + PlaneNormal[2] = 1.; + break; + case PLANE_XZ1: + PlaneNormal[0] = 0.; + PlaneNormal[1] = -1.; + PlaneNormal[2] = 1.; + break; + case PLANE_YZ0: + PlaneNormal[0] = 1.; + PlaneNormal[1] = 0.; + PlaneNormal[2] = 1.; + break; + case PLANE_YZ1: + PlaneNormal[0] = -1.; + PlaneNormal[1] = 0.; + PlaneNormal[2] = 1.; + break; + } + } + + contents = 0; + if (surf) { + if (UseDetail) { + contents += CONTENTS_DETAIL; + } + if (UseLadder) { + contents += CONTENTS_LADDER; + } + } + + OpenFuncGroup(); + for (i = 0; i < NumTris; i++) { + brush.Number = i; + brush.NumFaces = 5; + // front + brush.face[0].v[0][0] = Node[Tri[i].v[0]].p[0]; + brush.face[0].v[0][1] = Node[Tri[i].v[0]].p[1]; + brush.face[0].v[0][2] = Node[Tri[i].v[0]].p[2]; + + brush.face[0].v[1][0] = Node[Tri[i].v[2]].p[0]; + brush.face[0].v[1][1] = Node[Tri[i].v[2]].p[1]; + brush.face[0].v[1][2] = Node[Tri[i].v[2]].p[2]; + + brush.face[0].v[2][0] = Node[Tri[i].v[1]].p[0]; + brush.face[0].v[2][1] = Node[Tri[i].v[1]].p[1]; + brush.face[0].v[2][2] = Node[Tri[i].v[1]].p[2]; + + if (offset != 0) { + switch (Plane) { + case PLANE_XY0: + brush.face[0].v[0][2] += offset; + brush.face[0].v[1][2] += offset; + brush.face[0].v[1][2] += offset; + break; + case PLANE_XY1: + brush.face[0].v[0][2] -= offset; + brush.face[0].v[1][2] -= offset; + brush.face[0].v[1][2] -= offset; + break; + case PLANE_XZ0: + brush.face[0].v[0][1] += offset; + brush.face[0].v[1][1] += offset; + brush.face[0].v[1][1] += offset; + break; + case PLANE_XZ1: + brush.face[0].v[0][1] -= offset; + brush.face[0].v[1][1] -= offset; + brush.face[0].v[1][1] -= offset; + break; + case PLANE_YZ0: + brush.face[0].v[0][0] += offset; + brush.face[0].v[1][0] += offset; + brush.face[0].v[1][0] += offset; + break; + case PLANE_YZ1: + brush.face[0].v[0][0] -= offset; + brush.face[0].v[1][0] -= offset; + brush.face[0].v[1][0] -= offset; + break; + } + } + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + // back + brush.face[1].v[0][0] = Node[Tri[i].v[0]].p[0]; + brush.face[1].v[0][1] = (float) backface; + brush.face[1].v[0][2] = Node[Tri[i].v[0]].p[2]; + + brush.face[1].v[1][0] = Node[Tri[i].v[1]].p[0]; + brush.face[1].v[1][1] = (float) backface; + brush.face[1].v[1][2] = Node[Tri[i].v[1]].p[2]; + + brush.face[1].v[2][0] = Node[Tri[i].v[2]].p[0]; + brush.face[1].v[2][1] = (float) backface; + brush.face[1].v[2][2] = Node[Tri[i].v[2]].p[2]; + + // 0-1 side + brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0]; + brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1]; + brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2]; + + brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0]; + brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1]; + brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2]; + + brush.face[2].v[2][0] = Node[Tri[i].v[1]].p[0]; + brush.face[2].v[2][1] = (float) backface; + brush.face[2].v[2][2] = Node[Tri[i].v[1]].p[2]; + + // 1-2 side + brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0]; + brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1]; + brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2]; + + brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0]; + brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1]; + brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2]; + + brush.face[3].v[2][0] = Node[Tri[i].v[2]].p[0]; + brush.face[3].v[2][1] = (float) backface; + brush.face[3].v[2][2] = Node[Tri[i].v[2]].p[2]; + + // 2-0 side + brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0]; + brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1]; + brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2]; + + brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0]; + brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1]; + brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2]; + + brush.face[4].v[2][0] = Node[Tri[i].v[0]].p[0]; + brush.face[4].v[2][1] = (float) backface; + brush.face[4].v[2][2] = Node[Tri[i].v[0]].p[2]; + break; + case PLANE_YZ0: + case PLANE_YZ1: + // back + brush.face[1].v[0][0] = (float) backface; + brush.face[1].v[0][1] = Node[Tri[i].v[0]].p[1]; + brush.face[1].v[0][2] = Node[Tri[i].v[0]].p[2]; + + brush.face[1].v[1][0] = (float) backface; + brush.face[1].v[1][1] = Node[Tri[i].v[1]].p[1]; + brush.face[1].v[1][2] = Node[Tri[i].v[1]].p[2]; + + brush.face[1].v[2][0] = (float) backface; + brush.face[1].v[2][1] = Node[Tri[i].v[2]].p[1]; + brush.face[1].v[2][2] = Node[Tri[i].v[2]].p[2]; + + // 0-1 side + brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0]; + brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1]; + brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2]; + + brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0]; + brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1]; + brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2]; + + brush.face[2].v[2][0] = (float) backface; + brush.face[2].v[2][1] = Node[Tri[i].v[1]].p[1]; + brush.face[2].v[2][2] = Node[Tri[i].v[1]].p[2]; + + // 1-2 side + brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0]; + brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1]; + brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2]; + + brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0]; + brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1]; + brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2]; + + brush.face[3].v[2][0] = (float) backface; + brush.face[3].v[2][1] = Node[Tri[i].v[2]].p[1]; + brush.face[3].v[2][2] = Node[Tri[i].v[2]].p[2]; + + // 2-0 side + brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0]; + brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1]; + brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2]; + + brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0]; + brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1]; + brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2]; + + brush.face[4].v[2][0] = (float) backface; + brush.face[4].v[2][1] = Node[Tri[i].v[0]].p[1]; + brush.face[4].v[2][2] = Node[Tri[i].v[0]].p[2]; + break; + default: + // back + brush.face[1].v[0][0] = Node[Tri[i].v[0]].p[0]; + brush.face[1].v[0][1] = Node[Tri[i].v[0]].p[1]; + brush.face[1].v[0][2] = (float) backface; + + brush.face[1].v[1][0] = Node[Tri[i].v[1]].p[0]; + brush.face[1].v[1][1] = Node[Tri[i].v[1]].p[1]; + brush.face[1].v[1][2] = (float) backface; + + brush.face[1].v[2][0] = Node[Tri[i].v[2]].p[0]; + brush.face[1].v[2][1] = Node[Tri[i].v[2]].p[1]; + brush.face[1].v[2][2] = (float) backface; + + // 0-1 side + brush.face[2].v[0][0] = Node[Tri[i].v[0]].p[0]; + brush.face[2].v[0][1] = Node[Tri[i].v[0]].p[1]; + brush.face[2].v[0][2] = Node[Tri[i].v[0]].p[2]; + + brush.face[2].v[1][0] = Node[Tri[i].v[1]].p[0]; + brush.face[2].v[1][1] = Node[Tri[i].v[1]].p[1]; + brush.face[2].v[1][2] = Node[Tri[i].v[1]].p[2]; + + brush.face[2].v[2][0] = Node[Tri[i].v[1]].p[0]; + brush.face[2].v[2][1] = Node[Tri[i].v[1]].p[1]; + brush.face[2].v[2][2] = (float) backface; + + // 1-2 side + brush.face[3].v[0][0] = Node[Tri[i].v[1]].p[0]; + brush.face[3].v[0][1] = Node[Tri[i].v[1]].p[1]; + brush.face[3].v[0][2] = Node[Tri[i].v[1]].p[2]; + + brush.face[3].v[1][0] = Node[Tri[i].v[2]].p[0]; + brush.face[3].v[1][1] = Node[Tri[i].v[2]].p[1]; + brush.face[3].v[1][2] = Node[Tri[i].v[2]].p[2]; + + brush.face[3].v[2][0] = Node[Tri[i].v[2]].p[0]; + brush.face[3].v[2][1] = Node[Tri[i].v[2]].p[1]; + brush.face[3].v[2][2] = (float) backface; + + // 2-0 side + brush.face[4].v[0][0] = Node[Tri[i].v[2]].p[0]; + brush.face[4].v[0][1] = Node[Tri[i].v[2]].p[1]; + brush.face[4].v[0][2] = Node[Tri[i].v[2]].p[2]; + + brush.face[4].v[1][0] = Node[Tri[i].v[0]].p[0]; + brush.face[4].v[1][1] = Node[Tri[i].v[0]].p[1]; + brush.face[4].v[1][2] = Node[Tri[i].v[0]].p[2]; + + brush.face[4].v[2][0] = Node[Tri[i].v[0]].p[0]; + brush.face[4].v[2][1] = Node[Tri[i].v[0]].p[1]; + brush.face[4].v[2][2] = (float) backface; + } + + for (j = 0; j < 5; j++) { + strcpy(brush.face[j].texture, + (strlen(texture1) ? texture1 : texture0)); + brush.face[j].Shift[0] = (float) TexOffset[0]; + brush.face[j].Shift[1] = (float) TexOffset[1]; + brush.face[j].Rotate = 0.; + brush.face[j].Scale[0] = (float) TexScale[0]; + brush.face[j].Scale[1] = (float) TexScale[1]; + brush.face[j].Contents = contents; + if (surf) { + brush.face[j].Surface = 0; + } else { + brush.face[j].Surface = SURF_HINT; + } + brush.face[j].Value = 0; + } + + if (CheckAngle) { + XYZVectorSubtract(brush.face[0].v[2], brush.face[0].v[0], t[0]); + XYZVectorSubtract(brush.face[0].v[1], brush.face[0].v[2], t[1]); + CrossProduct(t[0], t[1], SurfNormal); + VectorNormalize(SurfNormal, SurfNormal); + if (DotProduct(SurfNormal, PlaneNormal) < Steep) { + strcpy(brush.face[0].texture, texture2); + } else { + strcpy(brush.face[0].texture, texture0); + } + } else { + strcpy(brush.face[0].texture, texture0); + } + + if (surf) { + brush.face[0].Value = ArghRad2; + } + MakeBrush(&brush); + } + CloseFuncGroup(); } // end MakeBrushes //================================================================= -void MapOut( int NumNodes,int NumTris, NODE *Node, TRI *Tri ){ - extern double backface; - extern double xmin, xmax, ymin, ymax, zmin, zmax; - BRUSH brush; - char hint[32], skip[32]; - int i, j; - int face; - /* - ghCursorCurrent = LoadCursor(NULL,IDC_WAIT); - SetCursor(ghCursorCurrent); - */ - UseDetail = 1; // this is temporary - MakeBrushes( NumTris,Node,Tri,TRUE,0,Texture[Game][0],Texture[Game][1],Texture[Game][2] ); - - if ( AddHints || GimpHints ) { - switch ( Game ) - { - case SIN: - strcpy( hint,"generic/misc/hint" ); - strcpy( skip,"generic/misc/skip" ); - break; - case HALFLIFE: - strcpy( hint,"HINT" ); - strcpy( skip,"HINT" ); - break; - case HERETIC2: - strcpy( hint,"general/hint" ); - strcpy( skip,"general/skip" ); - break; - case KINGPIN: - strcpy( hint,"common/0_hint" ); - strcpy( skip,"common/0_skip" ); - break; - case QUAKE3: - strcpy( hint,"common/hint" ); - strcpy( skip,"common/skip" ); - break; - default: - strcpy( hint,"e1u1/hint" ); - strcpy( skip,"e1u1/skip" ); - } - } - - if ( GimpHints ) { - MakeBrushes( NumTris,Node,Tri,FALSE,HINT_OFFSET,hint,hint,hint ); - } - - if ( AddHints == 1 ) { - int j0, j1, j2, k, k0, k1; - int q[4]; - int w,h,h0,h1,t,OK; - float s[3]; - double front; - int MaxHints; // We don't want a whole slew of hint brushes, which we'd get - // with low decimation values and our current placement scheme. - // Limit number of hint brushes to number of undecimated grid - // squares. - - switch ( Plane ) - { - case PLANE_XY1: - front = LessThan( zmin,32. ); - break; - case PLANE_XZ0: - front = MoreThan( ymax,32. ); - break; - case PLANE_XZ1: - front = LessThan( ymin,32. ); - break; - case PLANE_YZ0: - front = MoreThan( xmax,32. ); - break; - case PLANE_YZ1: - front = LessThan( xmin,32. ); - break; - default: - front = MoreThan( zmax,32. ); - } - - for ( i = 0; i < NumTris; i++ ) - Tri[i].flag = 0; - - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - j0 = 1; - j1 = 0; - j2 = 2; - break; - case PLANE_YZ0: - case PLANE_YZ1: - j0 = 0; - j1 = 1; - j2 = 2; - break; - default: - j0 = 2; - j1 = 0; - j2 = 1; - } - - brush.Number = 0; - brush.NumFaces = 6; - MaxHints = NH * NV - 1; - for ( w = 1; w < min( 16,NH ) && brush.Number < MaxHints; w++ ) - { - for ( h = max( 1,w / 2 ); h < min( 16,NV ) && brush.Number < MaxHints; h++ ) - { - for ( i = 0; i <= NH - w && brush.Number < MaxHints; i++ ) - { - for ( j = 0; j <= NV - h && brush.Number < MaxHints; j++ ) - { - q[0] = i * NVP1 + j; - q[2] = q[0] + w * NVP1 + h; - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ0: - case PLANE_YZ1: - q[1] = q[0] + h; - q[3] = q[2] - h; - break; - default: - q[1] = q[2] - h; - q[3] = q[0] + h; - } - for ( k = 0, OK = 1; k < NumTris && OK; k++ ) - { - if ( Tri[k].min[j1] >= max( Node[q[0]].p[j1],Node[q[2]].p[j1] ) ) { - continue; - } - if ( Tri[k].min[j2] >= max( Node[q[0]].p[j2],Node[q[2]].p[j2] ) ) { - continue; - } - if ( Tri[k].max[j1] <= min( Node[q[0]].p[j1],Node[q[2]].p[j1] ) ) { - continue; - } - if ( Tri[k].max[j2] <= min( Node[q[0]].p[j2],Node[q[2]].p[j2] ) ) { - continue; - } - - for ( h0 = 0; h0 < 4 && OK; h0++ ) - { - h1 = ( h0 + 1 ) % 4; - for ( t = 0; t < 3 && OK; t++ ) - { - s[t] = side( Node[q[h0]].p[j1],Node[q[h0]].p[j2], - Node[q[h1]].p[j1],Node[q[h1]].p[j2], - Node[Tri[k].v[t]].p[j1],Node[Tri[k].v[t]].p[j2] ); - } - if ( ( s[1] > 0 || s[2] > 0 ) && s[0] < 0 ) { - OK = 0; - } - if ( ( s[2] > 0 || s[0] > 0 ) && s[1] < 0 ) { - OK = 0; - } - if ( ( s[0] > 0 || s[1] > 0 ) && s[2] < 0 ) { - OK = 0; - } - } - } - if ( !OK ) { - continue; - } - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - // front - brush.face[0].v[0][0] = Node[q[2]].p[0]; - brush.face[0].v[0][1] = (float)front; - brush.face[0].v[0][2] = Node[q[2]].p[2]; - - brush.face[0].v[1][0] = Node[q[1]].p[0]; - brush.face[0].v[1][1] = (float)front; - brush.face[0].v[1][2] = Node[q[1]].p[2]; - - brush.face[0].v[2][0] = Node[q[0]].p[0]; - brush.face[0].v[2][1] = (float)front; - brush.face[0].v[2][2] = Node[q[0]].p[2]; - - // back - brush.face[1].v[0][0] = Node[q[0]].p[0]; - brush.face[1].v[0][1] = (float)backface; - brush.face[1].v[0][2] = Node[q[0]].p[2]; - - brush.face[1].v[1][0] = Node[q[1]].p[0]; - brush.face[1].v[1][1] = (float)backface; - brush.face[1].v[1][2] = Node[q[1]].p[2]; - - brush.face[1].v[2][0] = Node[q[2]].p[0]; - brush.face[1].v[2][1] = (float)backface; - brush.face[1].v[2][2] = Node[q[2]].p[2]; - - for ( k0 = 0; k0 < brush.NumFaces - 2; k0++ ) - { - k = k0 + 2; - k1 = ( k0 + 1 ) % ( brush.NumFaces - 2 ); - - brush.face[k].v[0][0] = Node[q[k0]].p[0]; - brush.face[k].v[0][1] = (float)front; - brush.face[k].v[0][2] = Node[q[k0]].p[2]; - - brush.face[k].v[1][0] = Node[q[k1]].p[0]; - brush.face[k].v[1][1] = (float)front; - brush.face[k].v[1][2] = Node[q[k1]].p[2]; - - brush.face[k].v[2][0] = Node[q[k1]].p[0]; - brush.face[k].v[2][1] = (float)backface; - brush.face[k].v[2][2] = Node[q[k1]].p[2]; - } - break; - case PLANE_YZ0: - case PLANE_YZ1: - // front - brush.face[0].v[0][0] = (float)front; - brush.face[0].v[0][1] = Node[q[2]].p[1]; - brush.face[0].v[0][2] = Node[q[2]].p[2]; - - brush.face[0].v[1][0] = (float)front; - brush.face[0].v[1][1] = Node[q[1]].p[1]; - brush.face[0].v[1][2] = Node[q[1]].p[2]; - - brush.face[0].v[2][0] = (float)front; - brush.face[0].v[2][1] = Node[q[0]].p[1]; - brush.face[0].v[2][2] = Node[q[0]].p[2]; - - // back - brush.face[1].v[0][0] = (float)backface; - brush.face[1].v[0][1] = Node[q[0]].p[1]; - brush.face[1].v[0][2] = Node[q[0]].p[2]; - - brush.face[1].v[1][0] = (float)backface; - brush.face[1].v[1][1] = Node[q[1]].p[1]; - brush.face[1].v[1][2] = Node[q[1]].p[2]; - - brush.face[1].v[2][0] = (float)backface; - brush.face[1].v[2][1] = Node[q[2]].p[1]; - brush.face[1].v[2][2] = Node[q[2]].p[2]; - - for ( k0 = 0; k0 < brush.NumFaces - 2; k0++ ) - { - k = k0 + 2; - k1 = ( k0 + 1 ) % ( brush.NumFaces - 2 ); - - brush.face[k].v[0][0] = (float)front; - brush.face[k].v[0][1] = Node[q[k0]].p[1]; - brush.face[k].v[0][2] = Node[q[k0]].p[2]; - - brush.face[k].v[1][0] = (float)front; - brush.face[k].v[1][1] = Node[q[k1]].p[1]; - brush.face[k].v[1][2] = Node[q[k1]].p[2]; - - brush.face[k].v[2][0] = (float)backface; - brush.face[k].v[2][1] = Node[q[k1]].p[1]; - brush.face[k].v[2][2] = Node[q[k1]].p[2]; - } - break; - default: - // front - brush.face[0].v[0][0] = Node[q[2]].p[0]; - brush.face[0].v[0][1] = Node[q[2]].p[1]; - brush.face[0].v[0][2] = (float)front; - - brush.face[0].v[1][0] = Node[q[1]].p[0]; - brush.face[0].v[1][1] = Node[q[1]].p[1]; - brush.face[0].v[1][2] = (float)front; - - brush.face[0].v[2][0] = Node[q[0]].p[0]; - brush.face[0].v[2][1] = Node[q[0]].p[1]; - brush.face[0].v[2][2] = (float)front; - - // back - brush.face[1].v[0][0] = Node[q[0]].p[0]; - brush.face[1].v[0][1] = Node[q[0]].p[1]; - brush.face[1].v[0][2] = (float)backface; - - brush.face[1].v[1][0] = Node[q[1]].p[0]; - brush.face[1].v[1][1] = Node[q[1]].p[1]; - brush.face[1].v[1][2] = (float)backface; - - brush.face[1].v[2][0] = Node[q[2]].p[0]; - brush.face[1].v[2][1] = Node[q[2]].p[1]; - brush.face[1].v[2][2] = (float)backface; - - for ( k0 = 0; k0 < brush.NumFaces - 2; k0++ ) - { - k = k0 + 2; - k1 = ( k0 + 1 ) % ( brush.NumFaces - 2 ); - - brush.face[k].v[0][0] = Node[q[k0]].p[0]; - brush.face[k].v[0][1] = Node[q[k0]].p[1]; - brush.face[k].v[0][2] = (float)front; - - brush.face[k].v[1][0] = Node[q[k1]].p[0]; - brush.face[k].v[1][1] = Node[q[k1]].p[1]; - brush.face[k].v[1][2] = (float)front; - - brush.face[k].v[2][0] = Node[q[k1]].p[0]; - brush.face[k].v[2][1] = Node[q[k1]].p[1]; - brush.face[k].v[2][2] = (float)backface; - } - break; - } // switch (Plane) - for ( face = 0; face < 6; face++ ) - { - strcpy( brush.face[face].texture,( face <= 1 ? skip : hint ) ); - brush.face[face].Shift[0] = 0; - brush.face[face].Shift[1] = 0; - brush.face[face].Rotate = 0.; - brush.face[face].Scale[0] = 1; - brush.face[face].Scale[1] = 1; - brush.face[face].Contents = CONTENTS_DETAIL; - brush.face[face].Surface = ( face <= 1 ? SURF_SKIP : SURF_HINT ); - brush.face[face].Value = 0; - } - if ( !brush.Number ) { - OpenFuncGroup(); - } - MakeBrush( &brush ); - brush.Number++; - } // for(j= - } // for(i= - } // for(h= - } // for(w= - if ( brush.Number ) { - CloseFuncGroup(); - } - } - /* - ghCursorCurrent = ghCursorDefault; - SetCursor(ghCursorCurrent); - */ +void MapOut(int NumNodes, int NumTris, NODE *Node, TRI *Tri) +{ + extern double backface; + extern double xmin, xmax, ymin, ymax, zmin, zmax; + BRUSH brush; + char hint[32], skip[32]; + int i, j; + int face; + /* + ghCursorCurrent = LoadCursor(NULL,IDC_WAIT); + SetCursor(ghCursorCurrent); + */ + UseDetail = 1; // this is temporary + MakeBrushes(NumTris, Node, Tri, TRUE, 0, Texture[Game][0], Texture[Game][1], Texture[Game][2]); + + if (AddHints || GimpHints) { + switch (Game) { + case SIN: + strcpy(hint, "generic/misc/hint"); + strcpy(skip, "generic/misc/skip"); + break; + case HALFLIFE: + strcpy(hint, "HINT"); + strcpy(skip, "HINT"); + break; + case HERETIC2: + strcpy(hint, "general/hint"); + strcpy(skip, "general/skip"); + break; + case KINGPIN: + strcpy(hint, "common/0_hint"); + strcpy(skip, "common/0_skip"); + break; + case QUAKE3: + strcpy(hint, "common/hint"); + strcpy(skip, "common/skip"); + break; + default: + strcpy(hint, "e1u1/hint"); + strcpy(skip, "e1u1/skip"); + } + } + + if (GimpHints) { + MakeBrushes(NumTris, Node, Tri, FALSE, HINT_OFFSET, hint, hint, hint); + } + + if (AddHints == 1) { + int j0, j1, j2, k, k0, k1; + int q[4]; + int w, h, h0, h1, t, OK; + float s[3]; + double front; + int MaxHints; // We don't want a whole slew of hint brushes, which we'd get + // with low decimation values and our current placement scheme. + // Limit number of hint brushes to number of undecimated grid + // squares. + + switch (Plane) { + case PLANE_XY1: + front = LessThan(zmin, 32.); + break; + case PLANE_XZ0: + front = MoreThan(ymax, 32.); + break; + case PLANE_XZ1: + front = LessThan(ymin, 32.); + break; + case PLANE_YZ0: + front = MoreThan(xmax, 32.); + break; + case PLANE_YZ1: + front = LessThan(xmin, 32.); + break; + default: + front = MoreThan(zmax, 32.); + } + + for (i = 0; i < NumTris; i++) { + Tri[i].flag = 0; + } + + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + j0 = 1; + j1 = 0; + j2 = 2; + break; + case PLANE_YZ0: + case PLANE_YZ1: + j0 = 0; + j1 = 1; + j2 = 2; + break; + default: + j0 = 2; + j1 = 0; + j2 = 1; + } + + brush.Number = 0; + brush.NumFaces = 6; + MaxHints = NH * NV - 1; + for (w = 1; w < min(16, NH) && brush.Number < MaxHints; w++) { + for (h = max(1, w / 2); h < min(16, NV) && brush.Number < MaxHints; h++) { + for (i = 0; i <= NH - w && brush.Number < MaxHints; i++) { + for (j = 0; j <= NV - h && brush.Number < MaxHints; j++) { + q[0] = i * NVP1 + j; + q[2] = q[0] + w * NVP1 + h; + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ0: + case PLANE_YZ1: + q[1] = q[0] + h; + q[3] = q[2] - h; + break; + default: + q[1] = q[2] - h; + q[3] = q[0] + h; + } + for (k = 0, OK = 1; k < NumTris && OK; k++) { + if (Tri[k].min[j1] >= max(Node[q[0]].p[j1], Node[q[2]].p[j1])) { + continue; + } + if (Tri[k].min[j2] >= max(Node[q[0]].p[j2], Node[q[2]].p[j2])) { + continue; + } + if (Tri[k].max[j1] <= min(Node[q[0]].p[j1], Node[q[2]].p[j1])) { + continue; + } + if (Tri[k].max[j2] <= min(Node[q[0]].p[j2], Node[q[2]].p[j2])) { + continue; + } + + for (h0 = 0; h0 < 4 && OK; h0++) { + h1 = (h0 + 1) % 4; + for (t = 0; t < 3 && OK; t++) { + s[t] = side(Node[q[h0]].p[j1], Node[q[h0]].p[j2], + Node[q[h1]].p[j1], Node[q[h1]].p[j2], + Node[Tri[k].v[t]].p[j1], Node[Tri[k].v[t]].p[j2]); + } + if ((s[1] > 0 || s[2] > 0) && s[0] < 0) { + OK = 0; + } + if ((s[2] > 0 || s[0] > 0) && s[1] < 0) { + OK = 0; + } + if ((s[0] > 0 || s[1] > 0) && s[2] < 0) { + OK = 0; + } + } + } + if (!OK) { + continue; + } + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + // front + brush.face[0].v[0][0] = Node[q[2]].p[0]; + brush.face[0].v[0][1] = (float) front; + brush.face[0].v[0][2] = Node[q[2]].p[2]; + + brush.face[0].v[1][0] = Node[q[1]].p[0]; + brush.face[0].v[1][1] = (float) front; + brush.face[0].v[1][2] = Node[q[1]].p[2]; + + brush.face[0].v[2][0] = Node[q[0]].p[0]; + brush.face[0].v[2][1] = (float) front; + brush.face[0].v[2][2] = Node[q[0]].p[2]; + + // back + brush.face[1].v[0][0] = Node[q[0]].p[0]; + brush.face[1].v[0][1] = (float) backface; + brush.face[1].v[0][2] = Node[q[0]].p[2]; + + brush.face[1].v[1][0] = Node[q[1]].p[0]; + brush.face[1].v[1][1] = (float) backface; + brush.face[1].v[1][2] = Node[q[1]].p[2]; + + brush.face[1].v[2][0] = Node[q[2]].p[0]; + brush.face[1].v[2][1] = (float) backface; + brush.face[1].v[2][2] = Node[q[2]].p[2]; + + for (k0 = 0; k0 < brush.NumFaces - 2; k0++) { + k = k0 + 2; + k1 = (k0 + 1) % (brush.NumFaces - 2); + + brush.face[k].v[0][0] = Node[q[k0]].p[0]; + brush.face[k].v[0][1] = (float) front; + brush.face[k].v[0][2] = Node[q[k0]].p[2]; + + brush.face[k].v[1][0] = Node[q[k1]].p[0]; + brush.face[k].v[1][1] = (float) front; + brush.face[k].v[1][2] = Node[q[k1]].p[2]; + + brush.face[k].v[2][0] = Node[q[k1]].p[0]; + brush.face[k].v[2][1] = (float) backface; + brush.face[k].v[2][2] = Node[q[k1]].p[2]; + } + break; + case PLANE_YZ0: + case PLANE_YZ1: + // front + brush.face[0].v[0][0] = (float) front; + brush.face[0].v[0][1] = Node[q[2]].p[1]; + brush.face[0].v[0][2] = Node[q[2]].p[2]; + + brush.face[0].v[1][0] = (float) front; + brush.face[0].v[1][1] = Node[q[1]].p[1]; + brush.face[0].v[1][2] = Node[q[1]].p[2]; + + brush.face[0].v[2][0] = (float) front; + brush.face[0].v[2][1] = Node[q[0]].p[1]; + brush.face[0].v[2][2] = Node[q[0]].p[2]; + + // back + brush.face[1].v[0][0] = (float) backface; + brush.face[1].v[0][1] = Node[q[0]].p[1]; + brush.face[1].v[0][2] = Node[q[0]].p[2]; + + brush.face[1].v[1][0] = (float) backface; + brush.face[1].v[1][1] = Node[q[1]].p[1]; + brush.face[1].v[1][2] = Node[q[1]].p[2]; + + brush.face[1].v[2][0] = (float) backface; + brush.face[1].v[2][1] = Node[q[2]].p[1]; + brush.face[1].v[2][2] = Node[q[2]].p[2]; + + for (k0 = 0; k0 < brush.NumFaces - 2; k0++) { + k = k0 + 2; + k1 = (k0 + 1) % (brush.NumFaces - 2); + + brush.face[k].v[0][0] = (float) front; + brush.face[k].v[0][1] = Node[q[k0]].p[1]; + brush.face[k].v[0][2] = Node[q[k0]].p[2]; + + brush.face[k].v[1][0] = (float) front; + brush.face[k].v[1][1] = Node[q[k1]].p[1]; + brush.face[k].v[1][2] = Node[q[k1]].p[2]; + + brush.face[k].v[2][0] = (float) backface; + brush.face[k].v[2][1] = Node[q[k1]].p[1]; + brush.face[k].v[2][2] = Node[q[k1]].p[2]; + } + break; + default: + // front + brush.face[0].v[0][0] = Node[q[2]].p[0]; + brush.face[0].v[0][1] = Node[q[2]].p[1]; + brush.face[0].v[0][2] = (float) front; + + brush.face[0].v[1][0] = Node[q[1]].p[0]; + brush.face[0].v[1][1] = Node[q[1]].p[1]; + brush.face[0].v[1][2] = (float) front; + + brush.face[0].v[2][0] = Node[q[0]].p[0]; + brush.face[0].v[2][1] = Node[q[0]].p[1]; + brush.face[0].v[2][2] = (float) front; + + // back + brush.face[1].v[0][0] = Node[q[0]].p[0]; + brush.face[1].v[0][1] = Node[q[0]].p[1]; + brush.face[1].v[0][2] = (float) backface; + + brush.face[1].v[1][0] = Node[q[1]].p[0]; + brush.face[1].v[1][1] = Node[q[1]].p[1]; + brush.face[1].v[1][2] = (float) backface; + + brush.face[1].v[2][0] = Node[q[2]].p[0]; + brush.face[1].v[2][1] = Node[q[2]].p[1]; + brush.face[1].v[2][2] = (float) backface; + + for (k0 = 0; k0 < brush.NumFaces - 2; k0++) { + k = k0 + 2; + k1 = (k0 + 1) % (brush.NumFaces - 2); + + brush.face[k].v[0][0] = Node[q[k0]].p[0]; + brush.face[k].v[0][1] = Node[q[k0]].p[1]; + brush.face[k].v[0][2] = (float) front; + + brush.face[k].v[1][0] = Node[q[k1]].p[0]; + brush.face[k].v[1][1] = Node[q[k1]].p[1]; + brush.face[k].v[1][2] = (float) front; + + brush.face[k].v[2][0] = Node[q[k1]].p[0]; + brush.face[k].v[2][1] = Node[q[k1]].p[1]; + brush.face[k].v[2][2] = (float) backface; + } + break; + } // switch (Plane) + for (face = 0; face < 6; face++) { + strcpy(brush.face[face].texture, (face <= 1 ? skip : hint)); + brush.face[face].Shift[0] = 0; + brush.face[face].Shift[1] = 0; + brush.face[face].Rotate = 0.; + brush.face[face].Scale[0] = 1; + brush.face[face].Scale[1] = 1; + brush.face[face].Contents = CONTENTS_DETAIL; + brush.face[face].Surface = (face <= 1 ? SURF_SKIP : SURF_HINT); + brush.face[face].Value = 0; + } + if (!brush.Number) { + OpenFuncGroup(); + } + MakeBrush(&brush); + brush.Number++; + } // for(j= + } // for(i= + } // for(h= + } // for(w= + if (brush.Number) { + CloseFuncGroup(); + } + } + /* + ghCursorCurrent = ghCursorDefault; + SetCursor(ghCursorCurrent); + */ } + //=========================================================================== -int CheckBorders( int *NumNodesUsed, int NumNodes, NODE *Node, int *NumTris, TRI **pTri ){ - int border; - int i, j, k0, k1, N; - float angle[3]; - TRI *Tri; - - N = NumNodesUsed[0]; - Tri = *pTri; - for ( i = 0; i < NumTris[0]; i++ ) - { - EdgeOnSide( Tri[i].v,&k0,&border ); - if ( border < 0 ) { - continue; - } - CalcAngles( Node, Tri[i].v, angle ); - k1 = ( k0 + 1 ) % 3; - if ( ( angle[k0] < SLIVER_ANGLE ) || ( angle[k1] < SLIVER_ANGLE ) ) { - j = Bisect( Node, border, Tri[i].v[k0], Tri[i].v[k1] ); - if ( j >= 0 ) { - if ( !Node[j].used ) { // Shouldn't be used, but... - NumNodesUsed[0]++; - Node[j].used++; - } - } - } - } - if ( NumNodesUsed[0] > N ) { - free( *pTri ); - tricall( NumNodes, Node, NumTris, NULL, pTri, "cnzBNPY" ); - Tri = *pTri; - } - return ( NumNodesUsed[0] - N ); +int CheckBorders(int *NumNodesUsed, int NumNodes, NODE *Node, int *NumTris, TRI **pTri) +{ + int border; + int i, j, k0, k1, N; + float angle[3]; + TRI *Tri; + + N = NumNodesUsed[0]; + Tri = *pTri; + for (i = 0; i < NumTris[0]; i++) { + EdgeOnSide(Tri[i].v, &k0, &border); + if (border < 0) { + continue; + } + CalcAngles(Node, Tri[i].v, angle); + k1 = (k0 + 1) % 3; + if ((angle[k0] < SLIVER_ANGLE) || (angle[k1] < SLIVER_ANGLE)) { + j = Bisect(Node, border, Tri[i].v[k0], Tri[i].v[k1]); + if (j >= 0) { + if (!Node[j].used) { // Shouldn't be used, but... + NumNodesUsed[0]++; + Node[j].used++; + } + } + } + } + if (NumNodesUsed[0] > N) { + free(*pTri); + tricall(NumNodes, Node, NumTris, NULL, pTri, "cnzBNPY"); + Tri = *pTri; + } + return (NumNodesUsed[0] - N); } diff --git a/contrib/gtkgensurf/face.cpp b/contrib/gtkgensurf/face.cpp index 77ce7dec..479c2d06 100644 --- a/contrib/gtkgensurf/face.cpp +++ b/contrib/gtkgensurf/face.cpp @@ -30,29 +30,28 @@ //vec3 vec3_origin = {0,0,0}; -void PlaneFromPoints( float *p0, float *p1, float *p2, PLANE *plane ){ - vec3 t1, t2; - vec length; - - VectorSubtract( p0, p1, t1 ); - VectorSubtract( p2, p1, t2 ); - plane->normal[0] = t1[1] * t2[2] - t1[2] * t2[1]; - plane->normal[1] = t1[2] * t2[0] - t1[0] * t2[2]; - plane->normal[2] = t1[0] * t2[1] - t1[1] * t2[0]; - - length = (vec)( sqrt( plane->normal[0] * plane->normal[0] + - plane->normal[1] * plane->normal[1] + - plane->normal[2] * plane->normal[2] ) ); - if ( length == 0 ) { - VectorClear( plane->normal ); - } - else - { - plane->normal[0] /= length; - plane->normal[1] /= length; - plane->normal[2] /= length; - } - plane->dist = DotProduct( p0, plane->normal ); +void PlaneFromPoints(float *p0, float *p1, float *p2, PLANE *plane) +{ + vec3 t1, t2; + vec length; + + VectorSubtract(p0, p1, t1); + VectorSubtract(p2, p1, t2); + plane->normal[0] = t1[1] * t2[2] - t1[2] * t2[1]; + plane->normal[1] = t1[2] * t2[0] - t1[0] * t2[2]; + plane->normal[2] = t1[0] * t2[1] - t1[1] * t2[0]; + + length = (vec) (sqrt(plane->normal[0] * plane->normal[0] + + plane->normal[1] * plane->normal[1] + + plane->normal[2] * plane->normal[2])); + if (length == 0) { + VectorClear(plane->normal); + } else { + plane->normal[0] /= length; + plane->normal[1] /= length; + plane->normal[2] /= length; + } + plane->dist = DotProduct(p0, plane->normal); } /* void VectorMA (vec3 va, vec scale, vec3 vb, vec3 vc) @@ -74,14 +73,15 @@ void PlaneFromPoints( float *p0, float *p1, float *p2, PLANE *plane ){ AllocWinding ============= */ -MY_WINDING *AllocWinding( int points ){ - MY_WINDING *w; - int s; - - s = sizeof( vec ) * 3 * points + sizeof( int ); - w = (MY_WINDING*)malloc( s ); - memset( w, 0, s ); - return w; +MY_WINDING *AllocWinding(int points) +{ + MY_WINDING *w; + int s; + + s = sizeof(vec) * 3 * points + sizeof(int); + w = (MY_WINDING *) malloc(s); + memset(w, 0, s); + return w; } /* vec VectorNormalize (vec3 in, vec3 out) @@ -109,79 +109,79 @@ MY_WINDING *AllocWinding( int points ){ BaseWindingForPlane ================= */ -MY_WINDING *BaseWindingForPlane( vec3 normal, vec dist ){ - int i, x; - vec max, v; - vec3 org, vright, vup; - MY_WINDING *w; +MY_WINDING *BaseWindingForPlane(vec3 normal, vec dist) +{ + int i, x; + vec max, v; + vec3 org, vright, vup; + MY_WINDING *w; // find the major axis - max = -BOGUS_RANGE; - x = -1; - for ( i = 0 ; i < 3; i++ ) - { - v = (vec)( fabs( normal[i] ) ); - if ( v > max ) { - x = i; - max = v; - } - } - if ( x == -1 ) { - x = 2; - } - - VectorCopy( vec3_origin,vup ); - switch ( x ) - { - case 0: - case 1: - vup[2] = 1; - break; - case 2: - vup[0] = 1; - break; - } - - v = DotProduct( vup, normal ); - VectorMA( vup, -v, normal, vup ); - VectorNormalize( vup, vup ); - - VectorScale( normal, dist, org ); - - CrossProduct( vup, normal, vright ); - - VectorScale( vup, 65536, vup ); - VectorScale( vright, 65536, vright ); + max = -BOGUS_RANGE; + x = -1; + for (i = 0; i < 3; i++) { + v = (vec) (fabs(normal[i])); + if (v > max) { + x = i; + max = v; + } + } + if (x == -1) { + x = 2; + } + + VectorCopy(vec3_origin, vup); + switch (x) { + case 0: + case 1: + vup[2] = 1; + break; + case 2: + vup[0] = 1; + break; + } + + v = DotProduct(vup, normal); + VectorMA(vup, -v, normal, vup); + VectorNormalize(vup, vup); + + VectorScale(normal, dist, org); + + CrossProduct(vup, normal, vright); + + VectorScale(vup, 65536, vup); + VectorScale(vright, 65536, vright); // project a really big axis aligned box onto the plane - w = AllocWinding( 4 ); + w = AllocWinding(4); - VectorSubtract( org, vright, w->p[0] ); - VectorAdd( w->p[0], vup, w->p[0] ); + VectorSubtract(org, vright, w->p[0]); + VectorAdd(w->p[0], vup, w->p[0]); - VectorAdd( org, vright, w->p[1] ); - VectorAdd( w->p[1], vup, w->p[1] ); + VectorAdd(org, vright, w->p[1]); + VectorAdd(w->p[1], vup, w->p[1]); - VectorAdd( org, vright, w->p[2] ); - VectorSubtract( w->p[2], vup, w->p[2] ); + VectorAdd(org, vright, w->p[2]); + VectorSubtract(w->p[2], vup, w->p[2]); - VectorSubtract( org, vright, w->p[3] ); - VectorSubtract( w->p[3], vup, w->p[3] ); + VectorSubtract(org, vright, w->p[3]); + VectorSubtract(w->p[3], vup, w->p[3]); - w->numpoints = 4; + w->numpoints = 4; - return w; + return w; } -void FreeWinding( MY_WINDING *w ){ - if ( *(unsigned *)w == 0xdeaddead ) { +void FreeWinding(MY_WINDING *w) +{ + if (*(unsigned *) w == 0xdeaddead) { // Error ("FreeWinding: freed a freed winding"); - return; - } - *(unsigned *)w = 0xdeaddead; + return; + } + *(unsigned *) w = 0xdeaddead; - free( w ); + free(w); } /* @@ -189,274 +189,267 @@ void FreeWinding( MY_WINDING *w ){ ChopWindingInPlace ============= */ -void ChopWindingInPlace( MY_WINDING **inout, vec3 normal, vec dist, vec epsilon ){ - MY_WINDING *in; - vec dists[MAX_POINTS_ON_WINDING + 4]; - int sides[MAX_POINTS_ON_WINDING + 4]; - int counts[3]; - static vec dot; // VC 4.2 optimizer bug if not static - int i, j; - vec *p1, *p2; - vec3 mid; - MY_WINDING *f; - int maxpts; - - in = *inout; - counts[0] = counts[1] = counts[2] = 0; +void ChopWindingInPlace(MY_WINDING **inout, vec3 normal, vec dist, vec epsilon) +{ + MY_WINDING *in; + vec dists[MAX_POINTS_ON_WINDING + 4]; + int sides[MAX_POINTS_ON_WINDING + 4]; + int counts[3]; + static vec dot; // VC 4.2 optimizer bug if not static + int i, j; + vec *p1, *p2; + vec3 mid; + MY_WINDING *f; + int maxpts; + + in = *inout; + counts[0] = counts[1] = counts[2] = 0; // determine sides for each point - for ( i = 0 ; i < in->numpoints ; i++ ) - { - dot = DotProduct( in->p[i], normal ); - dot -= dist; - dists[i] = dot; - if ( dot > epsilon ) { - sides[i] = SIDE_FRONT; - } - else if ( dot < -epsilon ) { - sides[i] = SIDE_BACK; - } - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - sides[i] = sides[0]; - dists[i] = dists[0]; - - if ( !counts[0] ) { - FreeWinding( in ); - *inout = NULL; - return; - } - if ( !counts[1] ) { - return; // inout stays the same - - } - maxpts = in->numpoints + 4; // cant use counts[0]+2 because - // of fp grouping errors - - f = AllocWinding( maxpts ); - - for ( i = 0 ; i < in->numpoints ; i++ ) - { - p1 = in->p[i]; - - if ( sides[i] == SIDE_ON ) { - VectorCopy( p1, f->p[f->numpoints] ); - f->numpoints++; - continue; - } - - if ( sides[i] == SIDE_FRONT ) { - VectorCopy( p1, f->p[f->numpoints] ); - f->numpoints++; - } - - if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) { - continue; - } - - // generate a split point - p2 = in->p[( i + 1 ) % in->numpoints]; - - dot = dists[i] / ( dists[i] - dists[i + 1] ); - for ( j = 0 ; j < 3 ; j++ ) - { // avoid round off error when possible - if ( normal[j] == 1 ) { - mid[j] = dist; - } - else if ( normal[j] == -1 ) { - mid[j] = -dist; - } - else{ - mid[j] = p1[j] + dot * ( p2[j] - p1[j] ); - } - } - - VectorCopy( mid, f->p[f->numpoints] ); - f->numpoints++; - } + for (i = 0; i < in->numpoints; i++) { + dot = DotProduct(in->p[i], normal); + dot -= dist; + dists[i] = dot; + if (dot > epsilon) { + sides[i] = SIDE_FRONT; + } else if (dot < -epsilon) { + sides[i] = SIDE_BACK; + } else { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + if (!counts[0]) { + FreeWinding(in); + *inout = NULL; + return; + } + if (!counts[1]) { + return; // inout stays the same + + } + maxpts = in->numpoints + 4; // cant use counts[0]+2 because + // of fp grouping errors + + f = AllocWinding(maxpts); + + for (i = 0; i < in->numpoints; i++) { + p1 = in->p[i]; + + if (sides[i] == SIDE_ON) { + VectorCopy(p1, f->p[f->numpoints]); + f->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) { + VectorCopy(p1, f->p[f->numpoints]); + f->numpoints++; + } + + if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) { + continue; + } + + // generate a split point + p2 = in->p[(i + 1) % in->numpoints]; + + dot = dists[i] / (dists[i] - dists[i + 1]); + for (j = 0; j < 3; j++) { // avoid round off error when possible + if (normal[j] == 1) { + mid[j] = dist; + } else if (normal[j] == -1) { + mid[j] = -dist; + } else { + mid[j] = p1[j] + dot * (p2[j] - p1[j]); + } + } + + VectorCopy(mid, f->p[f->numpoints]); + f->numpoints++; + } // if (f->numpoints > maxpts) // Error ("ClipWinding: points exceeded estimate"); // if (f->numpoints > MAX_POINTS_ON_WINDING) // Error ("ClipWinding: MAX_POINTS_ON_WINDING"); - FreeWinding( in ); - *inout = f; + FreeWinding(in); + *inout = f; } -void UseFaceBounds(){ - LPVOID vp; - float Dot, BestDot; - float planepts[3][3]; - int BestFace; - int i, j; - int NumFaces; - vec3 SurfNormal; - vec3 vmin,vmax; - PLANE plane[MAX_FACES * 2]; - PLANE pface; - MY_WINDING *w; - - switch ( Plane ) - { - case PLANE_XY1: - SurfNormal[0] = 0.0; - SurfNormal[1] = 0.0; - SurfNormal[2] = -1.0; - break; - case PLANE_XZ0: - SurfNormal[0] = 0.0; - SurfNormal[1] = 1.0; - SurfNormal[2] = 0.0; - break; - case PLANE_XZ1: - SurfNormal[0] = 0.0; - SurfNormal[1] = -1.0; - SurfNormal[2] = 0.0; - break; - case PLANE_YZ0: - SurfNormal[0] = 1.0; - SurfNormal[1] = 0.0; - SurfNormal[2] = 0.0; - break; - case PLANE_YZ1: - SurfNormal[0] = -1.0; - SurfNormal[1] = 0.0; - SurfNormal[2] = 0.0; - break; - default: - SurfNormal[0] = 0.0; - SurfNormal[1] = 0.0; - SurfNormal[2] = 1.0; - } +void UseFaceBounds() +{ + LPVOID vp; + float Dot, BestDot; + float planepts[3][3]; + int BestFace; + int i, j; + int NumFaces; + vec3 SurfNormal; + vec3 vmin, vmax; + PLANE plane[MAX_FACES * 2]; + PLANE pface; + MY_WINDING *w; + + switch (Plane) { + case PLANE_XY1: + SurfNormal[0] = 0.0; + SurfNormal[1] = 0.0; + SurfNormal[2] = -1.0; + break; + case PLANE_XZ0: + SurfNormal[0] = 0.0; + SurfNormal[1] = 1.0; + SurfNormal[2] = 0.0; + break; + case PLANE_XZ1: + SurfNormal[0] = 0.0; + SurfNormal[1] = -1.0; + SurfNormal[2] = 0.0; + break; + case PLANE_YZ0: + SurfNormal[0] = 1.0; + SurfNormal[1] = 0.0; + SurfNormal[2] = 0.0; + break; + case PLANE_YZ1: + SurfNormal[0] = -1.0; + SurfNormal[1] = 0.0; + SurfNormal[2] = 0.0; + break; + default: + SurfNormal[0] = 0.0; + SurfNormal[1] = 0.0; + SurfNormal[2] = 1.0; + } #if 0 - i = g_FuncTable.m_pfnAllocateSelectedBrushHandles(); - vp = g_FuncTable.m_pfnGetSelectedBrushHandle( 0 ); - NumFaces = g_FuncTable.m_pfnGetFaceCount( vp ); - - BestFace = -1; - BestDot = 0.0; - - for ( i = 0; i < NumFaces; i++ ) - { - _QERFaceData* QERFaceData = g_FuncTable.m_pfnGetFaceData( vp,i ); - planepts[0][0] = QERFaceData->m_v1[0]; - planepts[0][1] = QERFaceData->m_v1[1]; - planepts[0][2] = QERFaceData->m_v1[2]; - planepts[1][0] = QERFaceData->m_v2[0]; - planepts[1][1] = QERFaceData->m_v2[1]; - planepts[1][2] = QERFaceData->m_v2[2]; - planepts[2][0] = QERFaceData->m_v3[0]; - planepts[2][1] = QERFaceData->m_v3[1]; - planepts[2][2] = QERFaceData->m_v3[2]; - - PlaneFromPoints( planepts[0], planepts[1], planepts[2], &plane[2 * i] ); - VectorSubtract( vec3_origin, plane[2 * i].normal, plane[2 * i + 1].normal ); - plane[2 * i + 1].dist = -plane[2 * i].dist; - - Dot = DotProduct( plane[2 * i].normal,SurfNormal ); - if ( Dot > BestDot ) { - BestDot = Dot; - BestFace = i; - if ( strlen( QERFaceData->m_TextureName ) ) { - strcpy( Texture[Game][0],QERFaceData->m_TextureName ); - } - } - } - for ( i = 0; i < NumFaces; i++ ) - { - if ( i == BestFace ) { - continue; - } - _QERFaceData* QERFaceData = g_FuncTable.m_pfnGetFaceData( vp,i ); - if ( strlen( QERFaceData->m_TextureName ) ) { - if ( strcmp( Texture[Game][0],QERFaceData->m_TextureName ) ) { - strcpy( Texture[Game][1],QERFaceData->m_TextureName ); - } - } - } - - - g_FuncTable.m_pfnReleaseSelectedBrushHandles(); - - w = BaseWindingForPlane( plane[BestFace * 2].normal, plane[BestFace * 2].dist ); - - for ( i = 0 ; i < NumFaces && w; i++ ) - { - if ( BestFace == i ) { - continue; - } - ChopWindingInPlace( &w, plane[i * 2 + 1].normal, plane[i * 2 + 1].dist, 0 ); - } - if ( !w ) { - return; - } - - // Get bounding box for this face - vmin[0] = vmax[0] = w->p[0][0]; - vmin[1] = vmax[1] = w->p[0][1]; - vmin[2] = vmax[2] = w->p[0][2]; - for ( j = 1; j < w->numpoints; j++ ) - { - vmin[0] = min( vmin[0],w->p[j][0] ); - vmin[1] = min( vmin[1],w->p[j][1] ); - vmin[2] = min( vmin[2],w->p[j][2] ); - vmax[0] = max( vmax[0],w->p[j][0] ); - vmax[1] = max( vmax[1],w->p[j][1] ); - vmax[2] = max( vmax[2],w->p[j][2] ); - } - - FreeWinding( w ); - - VectorCopy( plane[BestFace * 2].normal,pface.normal ); - pface.dist = plane[BestFace * 2].dist; - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - if ( pface.normal[1] == 0. ) { - return; - } - Hll = vmin[0]; - Hur = vmax[0]; - Vll = vmin[2]; - Vur = vmax[2]; - Z00 = ( pface.dist - pface.normal[0] * Hll - pface.normal[2] * Vll ) / pface.normal[1]; - Z01 = ( pface.dist - pface.normal[0] * Hll - pface.normal[2] * Vur ) / pface.normal[1]; - Z10 = ( pface.dist - pface.normal[0] * Hur - pface.normal[2] * Vll ) / pface.normal[1]; - Z11 = ( pface.dist - pface.normal[0] * Hur - pface.normal[2] * Vur ) / pface.normal[1]; - break; - case PLANE_YZ0: - case PLANE_YZ1: - if ( pface.normal[0] == 0. ) { - return; - } - Hll = vmin[1]; - Hur = vmax[1]; - Vll = vmin[2]; - Vur = vmax[2]; - Z00 = ( pface.dist - pface.normal[1] * Hll - pface.normal[2] * Vll ) / pface.normal[0]; - Z01 = ( pface.dist - pface.normal[1] * Hll - pface.normal[2] * Vur ) / pface.normal[0]; - Z10 = ( pface.dist - pface.normal[1] * Hur - pface.normal[2] * Vll ) / pface.normal[0]; - Z11 = ( pface.dist - pface.normal[1] * Hur - pface.normal[2] * Vur ) / pface.normal[0]; - break; - default: - if ( pface.normal[2] == 0. ) { - return; - } - Hll = vmin[0]; - Hur = vmax[0]; - Vll = vmin[1]; - Vur = vmax[1]; - Z00 = ( pface.dist - pface.normal[0] * Hll - pface.normal[1] * Vll ) / pface.normal[2]; - Z01 = ( pface.dist - pface.normal[0] * Hll - pface.normal[1] * Vur ) / pface.normal[2]; - Z10 = ( pface.dist - pface.normal[0] * Hur - pface.normal[1] * Vll ) / pface.normal[2]; - Z11 = ( pface.dist - pface.normal[0] * Hur - pface.normal[1] * Vur ) / pface.normal[2]; - } + i = g_FuncTable.m_pfnAllocateSelectedBrushHandles(); + vp = g_FuncTable.m_pfnGetSelectedBrushHandle( 0 ); + NumFaces = g_FuncTable.m_pfnGetFaceCount( vp ); + + BestFace = -1; + BestDot = 0.0; + + for ( i = 0; i < NumFaces; i++ ) + { + _QERFaceData* QERFaceData = g_FuncTable.m_pfnGetFaceData( vp,i ); + planepts[0][0] = QERFaceData->m_v1[0]; + planepts[0][1] = QERFaceData->m_v1[1]; + planepts[0][2] = QERFaceData->m_v1[2]; + planepts[1][0] = QERFaceData->m_v2[0]; + planepts[1][1] = QERFaceData->m_v2[1]; + planepts[1][2] = QERFaceData->m_v2[2]; + planepts[2][0] = QERFaceData->m_v3[0]; + planepts[2][1] = QERFaceData->m_v3[1]; + planepts[2][2] = QERFaceData->m_v3[2]; + + PlaneFromPoints( planepts[0], planepts[1], planepts[2], &plane[2 * i] ); + VectorSubtract( vec3_origin, plane[2 * i].normal, plane[2 * i + 1].normal ); + plane[2 * i + 1].dist = -plane[2 * i].dist; + + Dot = DotProduct( plane[2 * i].normal,SurfNormal ); + if ( Dot > BestDot ) { + BestDot = Dot; + BestFace = i; + if ( strlen( QERFaceData->m_TextureName ) ) { + strcpy( Texture[Game][0],QERFaceData->m_TextureName ); + } + } + } + for ( i = 0; i < NumFaces; i++ ) + { + if ( i == BestFace ) { + continue; + } + _QERFaceData* QERFaceData = g_FuncTable.m_pfnGetFaceData( vp,i ); + if ( strlen( QERFaceData->m_TextureName ) ) { + if ( strcmp( Texture[Game][0],QERFaceData->m_TextureName ) ) { + strcpy( Texture[Game][1],QERFaceData->m_TextureName ); + } + } + } + + + g_FuncTable.m_pfnReleaseSelectedBrushHandles(); + + w = BaseWindingForPlane( plane[BestFace * 2].normal, plane[BestFace * 2].dist ); + + for ( i = 0 ; i < NumFaces && w; i++ ) + { + if ( BestFace == i ) { + continue; + } + ChopWindingInPlace( &w, plane[i * 2 + 1].normal, plane[i * 2 + 1].dist, 0 ); + } + if ( !w ) { + return; + } + + // Get bounding box for this face + vmin[0] = vmax[0] = w->p[0][0]; + vmin[1] = vmax[1] = w->p[0][1]; + vmin[2] = vmax[2] = w->p[0][2]; + for ( j = 1; j < w->numpoints; j++ ) + { + vmin[0] = min( vmin[0],w->p[j][0] ); + vmin[1] = min( vmin[1],w->p[j][1] ); + vmin[2] = min( vmin[2],w->p[j][2] ); + vmax[0] = max( vmax[0],w->p[j][0] ); + vmax[1] = max( vmax[1],w->p[j][1] ); + vmax[2] = max( vmax[2],w->p[j][2] ); + } + + FreeWinding( w ); + + VectorCopy( plane[BestFace * 2].normal,pface.normal ); + pface.dist = plane[BestFace * 2].dist; + switch ( Plane ) + { + case PLANE_XZ0: + case PLANE_XZ1: + if ( pface.normal[1] == 0. ) { + return; + } + Hll = vmin[0]; + Hur = vmax[0]; + Vll = vmin[2]; + Vur = vmax[2]; + Z00 = ( pface.dist - pface.normal[0] * Hll - pface.normal[2] * Vll ) / pface.normal[1]; + Z01 = ( pface.dist - pface.normal[0] * Hll - pface.normal[2] * Vur ) / pface.normal[1]; + Z10 = ( pface.dist - pface.normal[0] * Hur - pface.normal[2] * Vll ) / pface.normal[1]; + Z11 = ( pface.dist - pface.normal[0] * Hur - pface.normal[2] * Vur ) / pface.normal[1]; + break; + case PLANE_YZ0: + case PLANE_YZ1: + if ( pface.normal[0] == 0. ) { + return; + } + Hll = vmin[1]; + Hur = vmax[1]; + Vll = vmin[2]; + Vur = vmax[2]; + Z00 = ( pface.dist - pface.normal[1] * Hll - pface.normal[2] * Vll ) / pface.normal[0]; + Z01 = ( pface.dist - pface.normal[1] * Hll - pface.normal[2] * Vur ) / pface.normal[0]; + Z10 = ( pface.dist - pface.normal[1] * Hur - pface.normal[2] * Vll ) / pface.normal[0]; + Z11 = ( pface.dist - pface.normal[1] * Hur - pface.normal[2] * Vur ) / pface.normal[0]; + break; + default: + if ( pface.normal[2] == 0. ) { + return; + } + Hll = vmin[0]; + Hur = vmax[0]; + Vll = vmin[1]; + Vur = vmax[1]; + Z00 = ( pface.dist - pface.normal[0] * Hll - pface.normal[1] * Vll ) / pface.normal[2]; + Z01 = ( pface.dist - pface.normal[0] * Hll - pface.normal[1] * Vur ) / pface.normal[2]; + Z10 = ( pface.dist - pface.normal[0] * Hur - pface.normal[1] * Vll ) / pface.normal[2]; + Z11 = ( pface.dist - pface.normal[0] * Hur - pface.normal[1] * Vur ) / pface.normal[2]; + } #endif } diff --git a/contrib/gtkgensurf/font.cpp b/contrib/gtkgensurf/font.cpp index 35004bfd..0e40efe0 100644 --- a/contrib/gtkgensurf/font.cpp +++ b/contrib/gtkgensurf/font.cpp @@ -30,247 +30,251 @@ #include "gensurf.h" static const unsigned char data[2048] = { - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 207, 255, 255, 159, 255, 31, 255, 231, 159, 153, 63, 255, 255, 255, 255, - 255, 207, 255, 255, 159, 255, 207, 255, 231, 159, 153, 63, 255, 255, 255, 255, - 255, 207, 255, 255, 159, 255, 207, 255, 231, 255, 159, 63, 255, 255, 255, 255, - 7, 78, 252, 240, 145, 135, 3, 71, 38, 158, 153, 51, 19, 227, 196, 255, - 243, 140, 121, 230, 140, 51, 207, 51, 198, 156, 153, 57, 99, 204, 152, 255, - 255, 204, 51, 111, 158, 121, 206, 121, 230, 153, 153, 60, 115, 206, 60, 255, - 31, 204, 51, 127, 158, 121, 206, 121, 230, 153, 25, 62, 115, 206, 60, 255, - 199, 204, 51, 127, 158, 1, 206, 121, 230, 153, 25, 62, 115, 206, 60, 255, - 243, 204, 51, 127, 158, 249, 207, 121, 230, 153, 153, 60, 115, 206, 60, 255, - 243, 204, 51, 111, 158, 249, 207, 121, 230, 153, 153, 57, 115, 206, 60, 255, - 243, 140, 121, 230, 140, 115, 206, 51, 230, 153, 153, 51, 115, 206, 60, 255, - 7, 73, 252, 240, 145, 7, 207, 71, 230, 153, 153, 39, 115, 206, 60, 255, - 255, 255, 255, 255, 255, 255, 255, 127, 254, 255, 249, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 127, 254, 255, 249, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 57, 255, 255, 249, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 131, 255, 255, 252, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, 255, 255, 255, 255, 227, 255, - 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, 255, 255, 255, 255, 201, 255, - 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, 255, 255, 255, 255, 156, 255, - 15, 79, 252, 200, 196, 96, 32, 79, 62, 252, 15, 15, 159, 192, 156, 255, - 103, 142, 121, 198, 112, 206, 57, 79, 62, 60, 15, 15, 159, 207, 156, 255, - 243, 204, 51, 207, 120, 254, 57, 207, 156, 57, 103, 102, 206, 231, 156, 255, - 243, 204, 51, 207, 124, 252, 57, 207, 156, 25, 230, 112, 206, 231, 156, 255, - 243, 204, 51, 207, 252, 224, 57, 207, 156, 25, 230, 121, 206, 243, 156, 255, - 243, 204, 51, 207, 252, 199, 57, 207, 201, 211, 242, 240, 228, 249, 156, 255, - 243, 204, 51, 207, 252, 207, 57, 207, 201, 195, 112, 230, 228, 249, 156, 255, - 103, 142, 121, 198, 124, 206, 121, 198, 227, 231, 57, 207, 241, 252, 201, 255, - 15, 79, 252, 200, 252, 224, 227, 200, 227, 231, 57, 207, 241, 192, 227, 255, - 255, 207, 255, 207, 255, 255, 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, - 255, 207, 255, 207, 255, 255, 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, - 255, 207, 255, 207, 255, 255, 255, 255, 255, 255, 255, 255, 252, 255, 255, 255, - 255, 207, 255, 207, 255, 255, 255, 255, 255, 255, 255, 127, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 159, 15, 30, 252, 57, 224, 225, 128, 131, 7, 255, 254, 128, 127, 240, 255, - 135, 231, 204, 249, 57, 255, 252, 159, 57, 115, 126, 252, 60, 63, 231, 255, - 159, 247, 236, 249, 56, 127, 254, 159, 57, 115, 126, 252, 124, 158, 207, 255, - 159, 255, 252, 249, 56, 127, 254, 207, 57, 115, 62, 249, 124, 158, 207, 255, - 159, 255, 252, 121, 56, 112, 254, 207, 57, 115, 62, 249, 60, 207, 255, 255, - 159, 127, 62, 60, 57, 103, 224, 231, 131, 115, 158, 243, 128, 207, 255, 255, - 159, 63, 255, 57, 249, 103, 206, 231, 57, 7, 158, 243, 60, 207, 255, 255, - 159, 159, 255, 153, 249, 103, 206, 231, 57, 127, 206, 231, 124, 206, 255, 255, - 159, 207, 255, 25, 240, 103, 206, 243, 57, 127, 14, 224, 124, 158, 207, 255, - 159, 231, 239, 249, 185, 103, 206, 243, 57, 127, 230, 207, 124, 158, 207, 255, - 159, 231, 207, 249, 57, 103, 206, 243, 57, 63, 231, 207, 60, 63, 231, 255, - 159, 7, 28, 252, 121, 240, 224, 243, 131, 135, 231, 207, 128, 127, 240, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 7, 126, 128, 3, 124, 240, 249, 156, 63, 231, 57, 255, 252, 57, 159, 255, - 231, 124, 254, 243, 63, 231, 249, 156, 63, 231, 60, 255, 252, 57, 159, 255, - 231, 121, 254, 243, 159, 207, 249, 156, 63, 103, 62, 255, 248, 56, 158, 255, - 231, 121, 254, 243, 159, 207, 249, 156, 63, 39, 63, 255, 248, 56, 156, 255, - 231, 115, 254, 243, 207, 255, 249, 156, 63, 135, 63, 255, 112, 56, 152, 255, - 231, 115, 192, 3, 206, 255, 1, 156, 63, 199, 63, 255, 112, 56, 153, 255, - 231, 115, 254, 243, 207, 193, 249, 156, 63, 135, 63, 255, 36, 57, 147, 255, - 231, 115, 254, 243, 207, 207, 249, 156, 63, 39, 63, 255, 36, 57, 131, 255, - 231, 121, 254, 243, 159, 207, 249, 156, 57, 103, 62, 255, 140, 57, 135, 255, - 231, 121, 254, 243, 159, 199, 249, 156, 57, 231, 60, 255, 140, 57, 143, 255, - 231, 124, 254, 243, 63, 199, 249, 156, 147, 231, 57, 255, 220, 57, 159, 255, - 7, 126, 128, 243, 127, 208, 249, 156, 199, 231, 51, 192, 220, 57, 159, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 63, 252, 128, 63, 252, 128, 63, 28, 128, 249, 204, 79, 254, 39, 63, 255, - 159, 249, 60, 159, 249, 60, 159, 249, 249, 249, 204, 79, 158, 39, 63, 255, - 207, 243, 124, 206, 243, 124, 206, 243, 249, 249, 156, 103, 158, 103, 158, 255, - 207, 243, 124, 206, 243, 124, 206, 255, 249, 249, 156, 231, 156, 243, 204, 255, - 231, 231, 124, 230, 231, 124, 158, 255, 249, 249, 156, 231, 12, 243, 225, 255, - 231, 231, 60, 231, 231, 60, 63, 252, 249, 249, 60, 243, 12, 243, 243, 255, - 231, 231, 128, 231, 231, 128, 255, 249, 249, 249, 60, 243, 105, 249, 243, 255, - 231, 231, 252, 103, 230, 60, 255, 243, 249, 249, 124, 251, 97, 248, 225, 255, - 207, 243, 252, 207, 240, 124, 254, 243, 249, 249, 124, 248, 97, 248, 204, 255, - 207, 243, 252, 207, 241, 124, 206, 243, 249, 249, 124, 248, 243, 124, 158, 255, - 159, 249, 252, 159, 241, 124, 158, 249, 249, 115, 254, 252, 243, 60, 63, 255, - 63, 252, 252, 63, 228, 252, 60, 252, 249, 7, 255, 252, 243, 60, 63, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 243, 19, 192, 255, 252, 255, 255, 127, 14, 127, 248, 15, 252, 247, 227, 231, - 243, 243, 207, 255, 252, 255, 153, 127, 102, 62, 243, 227, 241, 193, 201, 243, - 231, 249, 231, 255, 252, 255, 60, 127, 242, 156, 231, 249, 231, 148, 201, 249, - 207, 252, 243, 255, 204, 124, 126, 126, 254, 156, 231, 57, 230, 148, 201, 252, - 207, 252, 243, 255, 204, 60, 255, 60, 255, 156, 231, 156, 204, 244, 99, 254, - 31, 254, 249, 255, 252, 159, 255, 57, 127, 158, 231, 204, 204, 244, 63, 255, - 31, 254, 252, 255, 252, 207, 255, 51, 63, 159, 231, 204, 204, 193, 159, 255, - 63, 127, 254, 255, 252, 159, 255, 57, 159, 207, 207, 204, 204, 151, 207, 248, - 63, 127, 254, 255, 252, 63, 255, 156, 159, 159, 231, 204, 228, 151, 103, 242, - 63, 63, 255, 255, 255, 127, 126, 158, 255, 159, 231, 25, 241, 148, 115, 242, - 63, 159, 127, 230, 204, 252, 60, 159, 159, 159, 231, 249, 255, 148, 121, 242, - 63, 31, 64, 230, 204, 252, 153, 159, 159, 159, 231, 227, 255, 193, 252, 248, - 255, 255, 63, 255, 231, 255, 255, 255, 255, 159, 231, 15, 252, 247, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 63, 243, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, 248, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 63, 254, 255, 195, 255, 255, 255, 255, 3, 252, 147, 255, 255, 255, 255, 255, - 159, 252, 255, 153, 255, 255, 255, 255, 243, 252, 147, 255, 255, 255, 255, 255, - 159, 252, 255, 153, 255, 243, 255, 255, 243, 252, 147, 255, 255, 255, 255, 255, - 159, 252, 204, 60, 255, 243, 255, 255, 243, 252, 0, 255, 255, 255, 255, 255, - 63, 254, 204, 60, 255, 243, 128, 255, 243, 252, 201, 255, 255, 255, 255, 255, - 63, 254, 225, 60, 255, 243, 255, 255, 243, 252, 201, 255, 255, 255, 255, 255, - 31, 126, 128, 60, 127, 128, 255, 255, 243, 252, 201, 255, 255, 255, 255, 255, - 159, 228, 225, 60, 193, 243, 128, 255, 243, 252, 201, 255, 255, 255, 255, 255, - 207, 240, 204, 60, 255, 243, 255, 255, 243, 124, 128, 255, 255, 255, 255, 255, - 207, 249, 204, 60, 255, 243, 255, 255, 243, 252, 228, 255, 255, 255, 255, 255, - 207, 240, 255, 60, 255, 243, 255, 255, 243, 252, 228, 255, 255, 255, 255, 255, - 31, 242, 255, 60, 255, 255, 255, 255, 243, 252, 228, 255, 255, 255, 255, 255, - 255, 255, 255, 60, 255, 255, 255, 255, 243, 252, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 153, 255, 255, 255, 0, 242, 252, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 153, 255, 255, 255, 255, 243, 252, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 195, 255, 255, 255, 255, 3, 252, 255, 255, 255, 255, 255, 255 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 207, 255, 255, 159, 255, 31, 255, 231, 159, 153, 63, 255, 255, 255, 255, + 255, 207, 255, 255, 159, 255, 207, 255, 231, 159, 153, 63, 255, 255, 255, 255, + 255, 207, 255, 255, 159, 255, 207, 255, 231, 255, 159, 63, 255, 255, 255, 255, + 7, 78, 252, 240, 145, 135, 3, 71, 38, 158, 153, 51, 19, 227, 196, 255, + 243, 140, 121, 230, 140, 51, 207, 51, 198, 156, 153, 57, 99, 204, 152, 255, + 255, 204, 51, 111, 158, 121, 206, 121, 230, 153, 153, 60, 115, 206, 60, 255, + 31, 204, 51, 127, 158, 121, 206, 121, 230, 153, 25, 62, 115, 206, 60, 255, + 199, 204, 51, 127, 158, 1, 206, 121, 230, 153, 25, 62, 115, 206, 60, 255, + 243, 204, 51, 127, 158, 249, 207, 121, 230, 153, 153, 60, 115, 206, 60, 255, + 243, 204, 51, 111, 158, 249, 207, 121, 230, 153, 153, 57, 115, 206, 60, 255, + 243, 140, 121, 230, 140, 115, 206, 51, 230, 153, 153, 51, 115, 206, 60, 255, + 7, 73, 252, 240, 145, 7, 207, 71, 230, 153, 153, 39, 115, 206, 60, 255, + 255, 255, 255, 255, 255, 255, 255, 127, 254, 255, 249, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 127, 254, 255, 249, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 57, 255, 255, 249, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 131, 255, 255, 252, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, 255, 255, 255, 255, 227, 255, + 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, 255, 255, 255, 255, 201, 255, + 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, 255, 255, 255, 255, 156, 255, + 15, 79, 252, 200, 196, 96, 32, 79, 62, 252, 15, 15, 159, 192, 156, 255, + 103, 142, 121, 198, 112, 206, 57, 79, 62, 60, 15, 15, 159, 207, 156, 255, + 243, 204, 51, 207, 120, 254, 57, 207, 156, 57, 103, 102, 206, 231, 156, 255, + 243, 204, 51, 207, 124, 252, 57, 207, 156, 25, 230, 112, 206, 231, 156, 255, + 243, 204, 51, 207, 252, 224, 57, 207, 156, 25, 230, 121, 206, 243, 156, 255, + 243, 204, 51, 207, 252, 199, 57, 207, 201, 211, 242, 240, 228, 249, 156, 255, + 243, 204, 51, 207, 252, 207, 57, 207, 201, 195, 112, 230, 228, 249, 156, 255, + 103, 142, 121, 198, 124, 206, 121, 198, 227, 231, 57, 207, 241, 252, 201, 255, + 15, 79, 252, 200, 252, 224, 227, 200, 227, 231, 57, 207, 241, 192, 227, 255, + 255, 207, 255, 207, 255, 255, 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, + 255, 207, 255, 207, 255, 255, 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, + 255, 207, 255, 207, 255, 255, 255, 255, 255, 255, 255, 255, 252, 255, 255, 255, + 255, 207, 255, 207, 255, 255, 255, 255, 255, 255, 255, 127, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 159, 15, 30, 252, 57, 224, 225, 128, 131, 7, 255, 254, 128, 127, 240, 255, + 135, 231, 204, 249, 57, 255, 252, 159, 57, 115, 126, 252, 60, 63, 231, 255, + 159, 247, 236, 249, 56, 127, 254, 159, 57, 115, 126, 252, 124, 158, 207, 255, + 159, 255, 252, 249, 56, 127, 254, 207, 57, 115, 62, 249, 124, 158, 207, 255, + 159, 255, 252, 121, 56, 112, 254, 207, 57, 115, 62, 249, 60, 207, 255, 255, + 159, 127, 62, 60, 57, 103, 224, 231, 131, 115, 158, 243, 128, 207, 255, 255, + 159, 63, 255, 57, 249, 103, 206, 231, 57, 7, 158, 243, 60, 207, 255, 255, + 159, 159, 255, 153, 249, 103, 206, 231, 57, 127, 206, 231, 124, 206, 255, 255, + 159, 207, 255, 25, 240, 103, 206, 243, 57, 127, 14, 224, 124, 158, 207, 255, + 159, 231, 239, 249, 185, 103, 206, 243, 57, 127, 230, 207, 124, 158, 207, 255, + 159, 231, 207, 249, 57, 103, 206, 243, 57, 63, 231, 207, 60, 63, 231, 255, + 159, 7, 28, 252, 121, 240, 224, 243, 131, 135, 231, 207, 128, 127, 240, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 7, 126, 128, 3, 124, 240, 249, 156, 63, 231, 57, 255, 252, 57, 159, 255, + 231, 124, 254, 243, 63, 231, 249, 156, 63, 231, 60, 255, 252, 57, 159, 255, + 231, 121, 254, 243, 159, 207, 249, 156, 63, 103, 62, 255, 248, 56, 158, 255, + 231, 121, 254, 243, 159, 207, 249, 156, 63, 39, 63, 255, 248, 56, 156, 255, + 231, 115, 254, 243, 207, 255, 249, 156, 63, 135, 63, 255, 112, 56, 152, 255, + 231, 115, 192, 3, 206, 255, 1, 156, 63, 199, 63, 255, 112, 56, 153, 255, + 231, 115, 254, 243, 207, 193, 249, 156, 63, 135, 63, 255, 36, 57, 147, 255, + 231, 115, 254, 243, 207, 207, 249, 156, 63, 39, 63, 255, 36, 57, 131, 255, + 231, 121, 254, 243, 159, 207, 249, 156, 57, 103, 62, 255, 140, 57, 135, 255, + 231, 121, 254, 243, 159, 199, 249, 156, 57, 231, 60, 255, 140, 57, 143, 255, + 231, 124, 254, 243, 63, 199, 249, 156, 147, 231, 57, 255, 220, 57, 159, 255, + 7, 126, 128, 243, 127, 208, 249, 156, 199, 231, 51, 192, 220, 57, 159, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 63, 252, 128, 63, 252, 128, 63, 28, 128, 249, 204, 79, 254, 39, 63, 255, + 159, 249, 60, 159, 249, 60, 159, 249, 249, 249, 204, 79, 158, 39, 63, 255, + 207, 243, 124, 206, 243, 124, 206, 243, 249, 249, 156, 103, 158, 103, 158, 255, + 207, 243, 124, 206, 243, 124, 206, 255, 249, 249, 156, 231, 156, 243, 204, 255, + 231, 231, 124, 230, 231, 124, 158, 255, 249, 249, 156, 231, 12, 243, 225, 255, + 231, 231, 60, 231, 231, 60, 63, 252, 249, 249, 60, 243, 12, 243, 243, 255, + 231, 231, 128, 231, 231, 128, 255, 249, 249, 249, 60, 243, 105, 249, 243, 255, + 231, 231, 252, 103, 230, 60, 255, 243, 249, 249, 124, 251, 97, 248, 225, 255, + 207, 243, 252, 207, 240, 124, 254, 243, 249, 249, 124, 248, 97, 248, 204, 255, + 207, 243, 252, 207, 241, 124, 206, 243, 249, 249, 124, 248, 243, 124, 158, 255, + 159, 249, 252, 159, 241, 124, 158, 249, 249, 115, 254, 252, 243, 60, 63, 255, + 63, 252, 252, 63, 228, 252, 60, 252, 249, 7, 255, 252, 243, 60, 63, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 243, 19, 192, 255, 252, 255, 255, 127, 14, 127, 248, 15, 252, 247, 227, 231, + 243, 243, 207, 255, 252, 255, 153, 127, 102, 62, 243, 227, 241, 193, 201, 243, + 231, 249, 231, 255, 252, 255, 60, 127, 242, 156, 231, 249, 231, 148, 201, 249, + 207, 252, 243, 255, 204, 124, 126, 126, 254, 156, 231, 57, 230, 148, 201, 252, + 207, 252, 243, 255, 204, 60, 255, 60, 255, 156, 231, 156, 204, 244, 99, 254, + 31, 254, 249, 255, 252, 159, 255, 57, 127, 158, 231, 204, 204, 244, 63, 255, + 31, 254, 252, 255, 252, 207, 255, 51, 63, 159, 231, 204, 204, 193, 159, 255, + 63, 127, 254, 255, 252, 159, 255, 57, 159, 207, 207, 204, 204, 151, 207, 248, + 63, 127, 254, 255, 252, 63, 255, 156, 159, 159, 231, 204, 228, 151, 103, 242, + 63, 63, 255, 255, 255, 127, 126, 158, 255, 159, 231, 25, 241, 148, 115, 242, + 63, 159, 127, 230, 204, 252, 60, 159, 159, 159, 231, 249, 255, 148, 121, 242, + 63, 31, 64, 230, 204, 252, 153, 159, 159, 159, 231, 227, 255, 193, 252, 248, + 255, 255, 63, 255, 231, 255, 255, 255, 255, 159, 231, 15, 252, 247, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 63, 243, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, 248, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 63, 254, 255, 195, 255, 255, 255, 255, 3, 252, 147, 255, 255, 255, 255, 255, + 159, 252, 255, 153, 255, 255, 255, 255, 243, 252, 147, 255, 255, 255, 255, 255, + 159, 252, 255, 153, 255, 243, 255, 255, 243, 252, 147, 255, 255, 255, 255, 255, + 159, 252, 204, 60, 255, 243, 255, 255, 243, 252, 0, 255, 255, 255, 255, 255, + 63, 254, 204, 60, 255, 243, 128, 255, 243, 252, 201, 255, 255, 255, 255, 255, + 63, 254, 225, 60, 255, 243, 255, 255, 243, 252, 201, 255, 255, 255, 255, 255, + 31, 126, 128, 60, 127, 128, 255, 255, 243, 252, 201, 255, 255, 255, 255, 255, + 159, 228, 225, 60, 193, 243, 128, 255, 243, 252, 201, 255, 255, 255, 255, 255, + 207, 240, 204, 60, 255, 243, 255, 255, 243, 124, 128, 255, 255, 255, 255, 255, + 207, 249, 204, 60, 255, 243, 255, 255, 243, 252, 228, 255, 255, 255, 255, 255, + 207, 240, 255, 60, 255, 243, 255, 255, 243, 252, 228, 255, 255, 255, 255, 255, + 31, 242, 255, 60, 255, 255, 255, 255, 243, 252, 228, 255, 255, 255, 255, 255, + 255, 255, 255, 60, 255, 255, 255, 255, 243, 252, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 153, 255, 255, 255, 0, 242, 252, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 153, 255, 255, 255, 255, 243, 252, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 195, 255, 255, 255, 255, 3, 252, 255, 255, 255, 255, 255, 255 }; -typedef struct -{ - unsigned char width; - float left, right, top, bottom; +typedef struct { + unsigned char width; + float left, right, top, bottom; } LC_TXFVERT; static LC_TXFVERT glyphs[93]; static GLuint texture; -void texfont_init(){ - if ( texture != 0 ) { - return; - } +void texfont_init() +{ + if (texture != 0) { + return; + } - int i, j, x, y; - float inv = 1.0f / 128; - const char *charlines[16] = { - "abcdefghijklmn", "opqrstuvwxyz0", "123456789ABC", "DEFGHIJKLMN", - "OPQRSTUVWX", "YZ,.!;:<>/?{}@$%", "&*()-+=_[] #" - }; - unsigned char lefts[7][17] = { - { 1, 11, 21, 30, 40, 50, 56, 66, 76, 80, 84, 93, 97, 111, 121 }, - { 1, 11, 21, 31, 38, 47, 53, 63, 72, 86, 94, 103, 111, 120 }, - { 1, 10, 19, 28, 37, 46, 55, 64, 73, 82, 94, 106, 118, }, - { 1, 13, 24, 34, 47, 59, 64, 73, 84, 94, 108, 120 }, - { 1, 14, 25, 38, 50, 61, 71, 83, 94, 109, 120 }, - { 1, 12, 22, 26, 30, 35, 39, 43, 52, 61, 65, 75, 81, 87, 103, 112, 125 }, - { 3, 14, 23, 28, 33, 38, 47, 56, 65, 70, 75, 79, 88 } - }; - // tops = 1 20 39 58 77 96 112 (+16) - memset( glyphs, 0, sizeof( glyphs ) ); + int i, j, x, y; + float inv = 1.0f / 128; + const char *charlines[16] = { + "abcdefghijklmn", "opqrstuvwxyz0", "123456789ABC", "DEFGHIJKLMN", + "OPQRSTUVWX", "YZ,.!;:<>/?{}@$%", "&*()-+=_[] #" + }; + unsigned char lefts[7][17] = { + {1, 11, 21, 30, 40, 50, 56, 66, 76, 80, 84, 93, 97, 111, 121}, + {1, 11, 21, 31, 38, 47, 53, 63, 72, 86, 94, 103, 111, 120}, + {1, 10, 19, 28, 37, 46, 55, 64, 73, 82, 94, 106, 118,}, + {1, 13, 24, 34, 47, 59, 64, 73, 84, 94, 108, 120}, + {1, 14, 25, 38, 50, 61, 71, 83, 94, 109, 120}, + {1, 12, 22, 26, 30, 35, 39, 43, 52, 61, 65, 75, 81, 87, 103, 112, 125}, + {3, 14, 23, 28, 33, 38, 47, 56, 65, 70, 75, 79, 88} + }; + // tops = 1 20 39 58 77 96 112 (+16) + memset(glyphs, 0, sizeof(glyphs)); - // ASCII 32-125 - for ( i = 32; i < 126; i++ ) - for ( x = 0; x < 7; x++ ) - for ( y = 0; charlines[x][y]; y++ ) - if ( charlines[x][y] == i ) { - glyphs[i - 32].width = lefts[x][y + 1] - lefts[x][y]; - glyphs[i - 32].left = (float)lefts[x][y] * inv; - glyphs[i - 32].right = (float)( lefts[x][y + 1] ) * inv; + // ASCII 32-125 + for (i = 32; i < 126; i++) { + for (x = 0; x < 7; x++) { + for (y = 0; charlines[x][y]; y++) { + if (charlines[x][y] == i) { + glyphs[i - 32].width = lefts[x][y + 1] - lefts[x][y]; + glyphs[i - 32].left = (float) lefts[x][y] * inv; + glyphs[i - 32].right = (float) (lefts[x][y + 1]) * inv; - if ( x != 6 ) { - glyphs[i - 32].top = (float)( 1 + 19 * x ); - } - else{ - glyphs[i - 32].top = 112; - } - glyphs[i - 32].bottom = glyphs[i - 32].top + 16; - glyphs[i - 32].top *= inv; - glyphs[i - 32].bottom *= inv; - } + if (x != 6) { + glyphs[i - 32].top = (float) (1 + 19 * x); + } else { + glyphs[i - 32].top = 112; + } + glyphs[i - 32].bottom = glyphs[i - 32].top + 16; + glyphs[i - 32].top *= inv; + glyphs[i - 32].bottom *= inv; + } + } + } + } - g_GLTable.m_pfn_qglGenTextures( 1, &texture ); - g_GLTable.m_pfn_qglBindTexture( GL_TEXTURE_2D, texture ); - g_GLTable.m_pfn_qglDisable( GL_TEXTURE_GEN_S ); - g_GLTable.m_pfn_qglDisable( GL_TEXTURE_GEN_T ); - g_GLTable.m_pfn_qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - g_GLTable.m_pfn_qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - g_GLTable.m_pfn_qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); - g_GLTable.m_pfn_qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - // g_GLTable.m_pfn_qglPixelStorei (GL_UNPACK_ALIGNMENT, 1); + g_GLTable.m_pfn_qglGenTextures(1, &texture); + g_GLTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, texture); + g_GLTable.m_pfn_qglDisable(GL_TEXTURE_GEN_S); + g_GLTable.m_pfn_qglDisable(GL_TEXTURE_GEN_T); + g_GLTable.m_pfn_qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + g_GLTable.m_pfn_qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + g_GLTable.m_pfn_qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + g_GLTable.m_pfn_qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // g_GLTable.m_pfn_qglPixelStorei (GL_UNPACK_ALIGNMENT, 1); - unsigned char *buf = (unsigned char*)malloc( 128 * 128 ); - memset( buf, 255, 128 * 128 ); + unsigned char *buf = (unsigned char *) malloc(128 * 128); + memset(buf, 255, 128 * 128); - for ( i = 0; i < 2048; i++ ) - for ( j = 0; j < 8; j++ ) - if ( ( data[i] & ( 1 << j ) ) != 0 ) { - buf[i * 8 + j] = 0; - } + for (i = 0; i < 2048; i++) { + for (j = 0; j < 8; j++) { + if ((data[i] & (1 << j)) != 0) { + buf[i * 8 + j] = 0; + } + } + } - g_GLTable.m_pfn_qglTexImage2D( GL_TEXTURE_2D, 0, GL_INTENSITY4, 128, 128, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, buf ); - free( buf ); + g_GLTable.m_pfn_qglTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4, 128, 128, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, buf); + free(buf); } -void texfont_write( const char *text, int l, int t ){ - if ( texture == 0 ) { - return; - } +void texfont_write(const char *text, int l, int t) +{ + if (texture == 0) { + return; + } - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); - g_GLTable.m_pfn_qglBindTexture( GL_TEXTURE_2D, texture ); - g_GLTable.m_pfn_qglEnable( GL_TEXTURE_2D ); - // g_GLTable.m_pfn_qglTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - g_GLTable.m_pfn_qglAlphaFunc( GL_GREATER, 0.0625 ); - g_GLTable.m_pfn_qglEnable( GL_ALPHA_TEST ); + g_GLTable.m_pfn_qglColor3f(0, 1, 0); + g_GLTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, texture); + g_GLTable.m_pfn_qglEnable(GL_TEXTURE_2D); + // g_GLTable.m_pfn_qglTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + g_GLTable.m_pfn_qglAlphaFunc(GL_GREATER, 0.0625); + g_GLTable.m_pfn_qglEnable(GL_ALPHA_TEST); - g_GLTable.m_pfn_qglBegin( GL_QUADS ); - for ( const char* p = text; *p; p++ ) - { - if ( *p < 32 || *p > 125 ) { - continue; - } - if ( glyphs[*p - 32].width == 0 ) { - continue; - } + g_GLTable.m_pfn_qglBegin(GL_QUADS); + for (const char *p = text; *p; p++) { + if (*p < 32 || *p > 125) { + continue; + } + if (glyphs[*p - 32].width == 0) { + continue; + } - g_GLTable.m_pfn_qglTexCoord2f( glyphs[*p - 32].left, glyphs[*p - 32].top ); - g_GLTable.m_pfn_qglVertex2i( l, t ); - g_GLTable.m_pfn_qglTexCoord2f( glyphs[*p - 32].left, glyphs[*p - 32].bottom ); - g_GLTable.m_pfn_qglVertex2i( l, t - 16 ); - g_GLTable.m_pfn_qglTexCoord2f( glyphs[*p - 32].right, glyphs[*p - 32].bottom ); - g_GLTable.m_pfn_qglVertex2i( l + glyphs[*p - 32].width, t - 16 ); - g_GLTable.m_pfn_qglTexCoord2f( glyphs[*p - 32].right, glyphs[*p - 32].top ); - g_GLTable.m_pfn_qglVertex2i( l + glyphs[*p - 32].width, t ); - l += glyphs[*p - 32].width; - } - g_GLTable.m_pfn_qglEnd(); + g_GLTable.m_pfn_qglTexCoord2f(glyphs[*p - 32].left, glyphs[*p - 32].top); + g_GLTable.m_pfn_qglVertex2i(l, t); + g_GLTable.m_pfn_qglTexCoord2f(glyphs[*p - 32].left, glyphs[*p - 32].bottom); + g_GLTable.m_pfn_qglVertex2i(l, t - 16); + g_GLTable.m_pfn_qglTexCoord2f(glyphs[*p - 32].right, glyphs[*p - 32].bottom); + g_GLTable.m_pfn_qglVertex2i(l + glyphs[*p - 32].width, t - 16); + g_GLTable.m_pfn_qglTexCoord2f(glyphs[*p - 32].right, glyphs[*p - 32].top); + g_GLTable.m_pfn_qglVertex2i(l + glyphs[*p - 32].width, t); + l += glyphs[*p - 32].width; + } + g_GLTable.m_pfn_qglEnd(); - g_GLTable.m_pfn_qglDisable( GL_ALPHA_TEST ); - g_GLTable.m_pfn_qglDisable( GL_TEXTURE_2D ); - g_GLTable.m_pfn_qglBindTexture( GL_TEXTURE_2D, 0 ); + g_GLTable.m_pfn_qglDisable(GL_ALPHA_TEST); + g_GLTable.m_pfn_qglDisable(GL_TEXTURE_2D); + g_GLTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, 0); } diff --git a/contrib/gtkgensurf/gendlgs.cpp b/contrib/gtkgensurf/gendlgs.cpp index e64a6598..0c3b7b42 100644 --- a/contrib/gtkgensurf/gendlgs.cpp +++ b/contrib/gtkgensurf/gendlgs.cpp @@ -31,10 +31,10 @@ #define TEXTURE_TAB 4 //#define BUFF_SIZE 32768 -#define ENABLE_WIDGET( name,enable ) \ - gtk_widget_set_sensitive( g_object_get_data( G_OBJECT( g_pWnd , ( name ) ) ), ( enable ) ) -#define CHECK_WIDGET( name,check ) \ - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), name ) ), check ) +#define ENABLE_WIDGET(name, enable) \ + gtk_widget_set_sensitive( g_object_get_data( G_OBJECT( g_pWnd , ( name ) ) ), ( enable ) ) +#define CHECK_WIDGET(name, check) \ + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), name ) ), check ) static GtkWidget *game_radios[NUMGAMES]; static GtkWidget *wave_radios[5]; @@ -45,7 +45,8 @@ static int WasDetail; static GtkTooltips *tooltips; static int FirstPassComplete = 0; -void About( GtkWidget *parent ){ +void About(GtkWidget *parent) +{ /* char *icon_xpm[] = { "32 32 4 1", @@ -87,336 +88,332 @@ void About( GtkWidget *parent ){ "................................" }; */ - // leo: I'm too lazy to create a nice about box - // ^Fishman - I am lazy too :P. - g_FuncTable.m_pfnMessageBox( parent, "GtkGenSurf 1.05\n\n" - "Original version\n" - "David Hyde (rascal@vicksburg.com)\n\n" - "Porting\n" - "Leonardo Zide (leo@lokigames.com)\n\n" - "Enhancements\n" - "Pablo Zurita (pablo@qeradiant.com)\n" - "Hydra (hydra@hydras-world.com)", - "About GtkGenSurf", eMB_OK ); + // leo: I'm too lazy to create a nice about box + // ^Fishman - I am lazy too :P. + g_FuncTable.m_pfnMessageBox(parent, "GtkGenSurf 1.05\n\n" + "Original version\n" + "David Hyde (rascal@vicksburg.com)\n\n" + "Porting\n" + "Leonardo Zide (leo@lokigames.com)\n\n" + "Enhancements\n" + "Pablo Zurita (pablo@qeradiant.com)\n" + "Hydra (hydra@hydras-world.com)", + "About GtkGenSurf", eMB_OK); } // ============================================================================= // main dialog -static void SetupControls(){ - switch ( current_tab ) - { - case GENERAL_TAB: - break; - - case EXTENTS_TAB: - if ( Game != QUAKE3 ) { - gtk_widget_hide( g_object_get_data( G_OBJECT( g_pWnd , "use_patches" ) ) ); - ENABLE_WIDGET( "use_patches", FALSE ); - } - else - { - gtk_widget_show( g_object_get_data( G_OBJECT( g_pWnd , "use_patches" ) ) ); - ENABLE_WIDGET( "use_patches", TRUE ); - } - - if ( Game == QUAKE3 && UsePatches != 0 ) { - ENABLE_WIDGET( "decimate", FALSE ); - } - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "snap_text" ) ), "Snap to grid:" ); // ^Fishman - Snap to grid. - break; - - case BITMAP_TAB: - if ( WaveType != WAVE_BITMAP ) { - ENABLE_WIDGET( "bmp_file", FALSE ); - ENABLE_WIDGET( "bmp_file_browse", FALSE ); - ENABLE_WIDGET( "bmp_black", FALSE ); - ENABLE_WIDGET( "bmp_white", FALSE ); - ENABLE_WIDGET( "bmp_text1", FALSE ); - ENABLE_WIDGET( "bmp_text2", FALSE ); - ENABLE_WIDGET( "bmp_text3", FALSE ); - ENABLE_WIDGET( "bmp_reload", FALSE ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_note" ) ), - "These options are disabled unless \"From Bitmap\"\n" - "is selected as the Waveform on the General tab." ); - } - else - { - ENABLE_WIDGET( "bmp_file", TRUE ); - ENABLE_WIDGET( "bmp_file_browse", TRUE ); - ENABLE_WIDGET( "bmp_black", TRUE ); - ENABLE_WIDGET( "bmp_white", TRUE ); - ENABLE_WIDGET( "bmp_text1", TRUE ); - ENABLE_WIDGET( "bmp_text2", TRUE ); - ENABLE_WIDGET( "bmp_text3", TRUE ); - ENABLE_WIDGET( "bmp_reload", strlen( gbmp.name ) != 0 ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_note" ) ), - "GenSurf works only with 8-bit bitmaps. Color indices are\n" - "mapped to values for each vertex. Generally, gray scale\n" - "images are stored with black as color 0, white as color 255." ); - } - break; - - case FIXPOINTS_TAB: - ENABLE_WIDGET( "fix_value", ( NumVerticesSelected != 0 ) ); - ENABLE_WIDGET( "fix_value_text", ( NumVerticesSelected != 0 ) ); - ENABLE_WIDGET( "fix_free", ( NumVerticesSelected != 0 ) ); - ENABLE_WIDGET( "fix_range", ( ( NumVerticesSelected != 0 ) && ( WaveType != WAVE_ROUGH_ONLY ) ) ); - ENABLE_WIDGET( "fix_range_text", ( ( NumVerticesSelected != 0 ) && ( WaveType != WAVE_ROUGH_ONLY ) ) ); - ENABLE_WIDGET( "fix_rate", ( ( NumVerticesSelected != 0 ) && ( WaveType != WAVE_ROUGH_ONLY ) ) ); - ENABLE_WIDGET( "fix_rate_text", ( ( NumVerticesSelected != 0 ) && ( WaveType != WAVE_ROUGH_ONLY ) ) ); - break; - - case TEXTURE_TAB: - ENABLE_WIDGET( "texture2", ( UsePatches == 0 ) ); - ENABLE_WIDGET( "texture3", ( UsePatches == 0 ) ); - ENABLE_WIDGET( "tex_slant", ( UsePatches == 0 ) ); - ENABLE_WIDGET( "detail", ( UsePatches == 0 ) ); - if ( Game != QUAKE3 ) { - ENABLE_WIDGET( "terrain_ent", FALSE ); // ^Fishman - Adds terrain key to func_group. - ENABLE_WIDGET( "hint", ( UsePatches == 0 ) ); - } - break; - } - - switch ( WaveType ) - { - case WAVE_HCYLINDER: - case WAVE_VCYLINDER: - ENABLE_WIDGET( "amplitude", TRUE ); - ENABLE_WIDGET( "wavelength", TRUE ); - ENABLE_WIDGET( "z00", TRUE ); - ENABLE_WIDGET( "z01", TRUE ); - ENABLE_WIDGET( "z10", TRUE ); - ENABLE_WIDGET( "z11", TRUE ); - ENABLE_WIDGET( "linearborder", TRUE ); - ENABLE_WIDGET( "go", TRUE ); - break; - case WAVE_BITMAP: - ENABLE_WIDGET( "amplitude", FALSE ); - ENABLE_WIDGET( "wavelength", FALSE ); - ENABLE_WIDGET( "z00", FALSE ); - ENABLE_WIDGET( "z01", FALSE ); - ENABLE_WIDGET( "z10", FALSE ); - ENABLE_WIDGET( "z11", FALSE ); - ENABLE_WIDGET( "linearborder", FALSE ); - ENABLE_WIDGET( "go", ( gbmp.colors != NULL ? TRUE : FALSE ) ); - break; - case WAVE_ROUGH_ONLY: - ENABLE_WIDGET( "amplitude", FALSE ); - ENABLE_WIDGET( "wavelength", FALSE ); - ENABLE_WIDGET( "z00", TRUE ); - ENABLE_WIDGET( "z01", TRUE ); - ENABLE_WIDGET( "z10", TRUE ); - ENABLE_WIDGET( "z11", TRUE ); - ENABLE_WIDGET( "linearborder", TRUE ); - ENABLE_WIDGET( "go", TRUE ); - break; - default: - ENABLE_WIDGET( "amplitude", TRUE ); - ENABLE_WIDGET( "wavelength", TRUE ); - ENABLE_WIDGET( "z00", TRUE ); - ENABLE_WIDGET( "z01", TRUE ); - ENABLE_WIDGET( "z10", TRUE ); - ENABLE_WIDGET( "z11", TRUE ); - ENABLE_WIDGET( "linearborder", TRUE ); - ENABLE_WIDGET( "go", TRUE ); - } - - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmin_text" ) ), "X:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmax_text" ) ), "X:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmin_text" ) ), "Z:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmax_text" ) ), "Z:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nh_text" ) ), "X:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nv_text" ) ), "Z:" ); - break; - case PLANE_YZ0: - case PLANE_YZ1: - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmin_text" ) ), "Y:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmax_text" ) ), "Y:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmin_text" ) ), "Z:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmax_text" ) ), "Z:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nh_text" ) ), "Y:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nv_text" ) ), "Z:" ); - break; - default: - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmin_text" ) ), "X:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmax_text" ) ), "X:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmin_text" ) ), "Y:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmax_text" ) ), "Y:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nh_text" ) ), "X:" ); - gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nv_text" ) ), "Y:" ); - break; - } +static void SetupControls() +{ + switch (current_tab) { + case GENERAL_TAB: + break; + + case EXTENTS_TAB: + if (Game != QUAKE3) { + gtk_widget_hide(g_object_get_data(G_OBJECT(g_pWnd, "use_patches"))); + ENABLE_WIDGET("use_patches", FALSE); + } else { + gtk_widget_show(g_object_get_data(G_OBJECT(g_pWnd, "use_patches"))); + ENABLE_WIDGET("use_patches", TRUE); + } + + if (Game == QUAKE3 && UsePatches != 0) { + ENABLE_WIDGET("decimate", FALSE); + } + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "snap_text")), + "Snap to grid:"); // ^Fishman - Snap to grid. + break; + + case BITMAP_TAB: + if (WaveType != WAVE_BITMAP) { + ENABLE_WIDGET("bmp_file", FALSE); + ENABLE_WIDGET("bmp_file_browse", FALSE); + ENABLE_WIDGET("bmp_black", FALSE); + ENABLE_WIDGET("bmp_white", FALSE); + ENABLE_WIDGET("bmp_text1", FALSE); + ENABLE_WIDGET("bmp_text2", FALSE); + ENABLE_WIDGET("bmp_text3", FALSE); + ENABLE_WIDGET("bmp_reload", FALSE); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "bmp_note")), + "These options are disabled unless \"From Bitmap\"\n" + "is selected as the Waveform on the General tab."); + } else { + ENABLE_WIDGET("bmp_file", TRUE); + ENABLE_WIDGET("bmp_file_browse", TRUE); + ENABLE_WIDGET("bmp_black", TRUE); + ENABLE_WIDGET("bmp_white", TRUE); + ENABLE_WIDGET("bmp_text1", TRUE); + ENABLE_WIDGET("bmp_text2", TRUE); + ENABLE_WIDGET("bmp_text3", TRUE); + ENABLE_WIDGET("bmp_reload", strlen(gbmp.name) != 0); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "bmp_note")), + "GenSurf works only with 8-bit bitmaps. Color indices are\n" + "mapped to values for each vertex. Generally, gray scale\n" + "images are stored with black as color 0, white as color 255."); + } + break; + + case FIXPOINTS_TAB: + ENABLE_WIDGET("fix_value", (NumVerticesSelected != 0)); + ENABLE_WIDGET("fix_value_text", (NumVerticesSelected != 0)); + ENABLE_WIDGET("fix_free", (NumVerticesSelected != 0)); + ENABLE_WIDGET("fix_range", ((NumVerticesSelected != 0) && (WaveType != WAVE_ROUGH_ONLY))); + ENABLE_WIDGET("fix_range_text", ((NumVerticesSelected != 0) && (WaveType != WAVE_ROUGH_ONLY))); + ENABLE_WIDGET("fix_rate", ((NumVerticesSelected != 0) && (WaveType != WAVE_ROUGH_ONLY))); + ENABLE_WIDGET("fix_rate_text", ((NumVerticesSelected != 0) && (WaveType != WAVE_ROUGH_ONLY))); + break; + + case TEXTURE_TAB: + ENABLE_WIDGET("texture2", (UsePatches == 0)); + ENABLE_WIDGET("texture3", (UsePatches == 0)); + ENABLE_WIDGET("tex_slant", (UsePatches == 0)); + ENABLE_WIDGET("detail", (UsePatches == 0)); + if (Game != QUAKE3) { + ENABLE_WIDGET("terrain_ent", FALSE); // ^Fishman - Adds terrain key to func_group. + ENABLE_WIDGET("hint", (UsePatches == 0)); + } + break; + } + + switch (WaveType) { + case WAVE_HCYLINDER: + case WAVE_VCYLINDER: + ENABLE_WIDGET("amplitude", TRUE); + ENABLE_WIDGET("wavelength", TRUE); + ENABLE_WIDGET("z00", TRUE); + ENABLE_WIDGET("z01", TRUE); + ENABLE_WIDGET("z10", TRUE); + ENABLE_WIDGET("z11", TRUE); + ENABLE_WIDGET("linearborder", TRUE); + ENABLE_WIDGET("go", TRUE); + break; + case WAVE_BITMAP: + ENABLE_WIDGET("amplitude", FALSE); + ENABLE_WIDGET("wavelength", FALSE); + ENABLE_WIDGET("z00", FALSE); + ENABLE_WIDGET("z01", FALSE); + ENABLE_WIDGET("z10", FALSE); + ENABLE_WIDGET("z11", FALSE); + ENABLE_WIDGET("linearborder", FALSE); + ENABLE_WIDGET("go", (gbmp.colors != NULL ? TRUE : FALSE)); + break; + case WAVE_ROUGH_ONLY: + ENABLE_WIDGET("amplitude", FALSE); + ENABLE_WIDGET("wavelength", FALSE); + ENABLE_WIDGET("z00", TRUE); + ENABLE_WIDGET("z01", TRUE); + ENABLE_WIDGET("z10", TRUE); + ENABLE_WIDGET("z11", TRUE); + ENABLE_WIDGET("linearborder", TRUE); + ENABLE_WIDGET("go", TRUE); + break; + default: + ENABLE_WIDGET("amplitude", TRUE); + ENABLE_WIDGET("wavelength", TRUE); + ENABLE_WIDGET("z00", TRUE); + ENABLE_WIDGET("z01", TRUE); + ENABLE_WIDGET("z10", TRUE); + ENABLE_WIDGET("z11", TRUE); + ENABLE_WIDGET("linearborder", TRUE); + ENABLE_WIDGET("go", TRUE); + } + + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "hmin_text")), "X:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "hmax_text")), "X:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "vmin_text")), "Z:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "vmax_text")), "Z:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "nh_text")), "X:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "nv_text")), "Z:"); + break; + case PLANE_YZ0: + case PLANE_YZ1: + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "hmin_text")), "Y:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "hmax_text")), "Y:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "vmin_text")), "Z:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "vmax_text")), "Z:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "nh_text")), "Y:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "nv_text")), "Z:"); + break; + default: + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "hmin_text")), "X:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "hmax_text")), "X:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "vmin_text")), "Y:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "vmax_text")), "Y:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "nh_text")), "X:"); + gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(g_pWnd), "nv_text")), "Y:"); + break; + } } // SetDlgValues fills in text boxes and initializes other input controls -static void SetDlgValues( int tab ){ - char Text[256]; - char RForm[16] = "%.5g"; - int i; - - switch ( tab ) - { - case GENERAL_TAB: - // Hell if I know why, but in the release build the 2nd pass thru the - // set_sensitive loop for game_radios crashes. No need to do this more - // than once anyhow. - if ( !FirstPassComplete ) { - for ( i = 0; i < NUMGAMES; i++ ) - gtk_widget_set_sensitive( game_radios[i], ( i == Game ? TRUE : FALSE ) ); - for ( i = 0; i < 6; i++ ) - gtk_widget_set_sensitive( plane_radios[i], ( i == Plane ? TRUE : FALSE ) ); - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( game_radios[Game] ), TRUE ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( plane_radios[Plane] ), TRUE ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( wave_radios[WaveType] ), TRUE ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "random" ) ), - RandomSeed ); - sprintf( Text, RForm, WaveLength ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "wavelength" ) ), Text ); - sprintf( Text, RForm, Amplitude ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "amplitude" ) ), Text ); - sprintf( Text, RForm, Roughness ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "roughness" ) ), Text ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data - ( G_OBJECT( g_pWnd ), "main_antialiasing" ) ), Antialiasing ); - break; - - case EXTENTS_TAB: - sprintf( Text,RForm,Hll ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "hmin" ) ), Text ); - sprintf( Text,RForm,Vll ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "vmin" ) ), Text ); - sprintf( Text,RForm,Hur ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "hmax" ) ), Text ); - sprintf( Text,RForm,Vur ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "vmax" ) ), Text ); - sprintf( Text,RForm,Z00 ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "z00" ) ), Text ); - sprintf( Text,RForm,Z01 ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "z01" ) ), Text ); - sprintf( Text,RForm,Z10 ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "z10" ) ), Text ); - sprintf( Text,RForm,Z11 ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "z11" ) ), Text ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "nh" ) ), NH ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "nv" ) ), NV ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "sp" ) ), SP ); // ^Fishman - Snap to grid. - - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data - ( G_OBJECT( g_pWnd ), "linearborder" ) ), FixBorders ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data - ( G_OBJECT( g_pWnd ), "use_patches" ) ), UsePatches ); - gtk_adjustment_set_value( GTK_ADJUSTMENT( g_object_get_data( G_OBJECT( g_pWnd ), "decimate_adj" ) ), - Decimate ); - - if ( Game == QUAKE3 && UsePatches ) { - gtk_widget_set_sensitive( g_object_get_data( G_OBJECT( g_pWnd , "decimate" ) ), FALSE ); - - if ( NH % 2 ) { - NH++; - if ( NH > MAX_ROWS ) { - NH -= 2; - } - SetDlgValues( current_tab ); - } - - if ( NV % 2 ) { - NV++; - if ( NV > MAX_ROWS ) { - NV -= 2; - } - SetDlgValues( current_tab ); - } - if ( NH % 2 ) { - NH++; - } - if ( NH < 2 ) { - NH = 2; - } - if ( NH > MAX_ROWS ) { - NH = MAX_ROWS; - } - if ( NV % 2 ) { - NV++; - } - if ( NV < 2 ) { - NV = 2; - } - if ( NV > MAX_ROWS ) { - NV = MAX_ROWS; - } - - gpointer spin = g_object_get_data( G_OBJECT( g_pWnd ), "nh" ); - GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( spin ) ); - adj->lower = 2; - gtk_adjustment_changed( adj ); - spin = g_object_get_data( G_OBJECT( g_pWnd ), "nv" ); - adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( spin ) ); - adj->lower = 2; - gtk_adjustment_changed( adj ); - } - else - { - gtk_widget_set_sensitive( g_object_get_data( G_OBJECT( g_pWnd , "decimate" ) ), TRUE ); - - gpointer spin = g_object_get_data( G_OBJECT( g_pWnd ), "nh" ); - GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( spin ) ); - adj->lower = 1; - gtk_adjustment_changed( adj ); - spin = g_object_get_data( G_OBJECT( g_pWnd ), "nv" ); - adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( spin ) ); - adj->lower = 1; - gtk_adjustment_changed( adj ); - } - - gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "nh" ) ), NH ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "nv" ) ), NV ); - - break; - - case BITMAP_TAB: - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_file" ) ), gbmp.name ); - sprintf( Text,"%g",gbmp.black_value ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_black" ) ), Text ); - sprintf( Text,"%g",gbmp.white_value ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_white" ) ), Text ); - break; - - case FIXPOINTS_TAB: - break; - - case TEXTURE_TAB: - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texture1" ) ), Texture[Game][0] ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texture2" ) ), Texture[Game][1] ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texture3" ) ), Texture[Game][2] ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "tex_slant" ) ), - SlantAngle ); - sprintf( Text,RForm,TexOffset[0] ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texoffsetx" ) ), Text ); - sprintf( Text,RForm,TexOffset[1] ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texoffsety" ) ), Text ); - sprintf( Text,RForm,TexScale[0] ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texscalex" ) ), Text ); - sprintf( Text,RForm,TexScale[1] ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texscaley" ) ), Text ); - CHECK_WIDGET( "detail", UseDetail ); - - if ( Game == QUAKE3 ) { - ENABLE_WIDGET( "hint", FALSE ); - AddHints = 0; - } - else{ - ENABLE_WIDGET( "hint", TRUE ); - } - CHECK_WIDGET( "hint", AddHints ); - - /* +static void SetDlgValues(int tab) +{ + char Text[256]; + char RForm[16] = "%.5g"; + int i; + + switch (tab) { + case GENERAL_TAB: + // Hell if I know why, but in the release build the 2nd pass thru the + // set_sensitive loop for game_radios crashes. No need to do this more + // than once anyhow. + if (!FirstPassComplete) { + for (i = 0; i < NUMGAMES; i++) { + gtk_widget_set_sensitive(game_radios[i], (i == Game ? TRUE : FALSE)); + } + for (i = 0; i < 6; i++) { + gtk_widget_set_sensitive(plane_radios[i], (i == Plane ? TRUE : FALSE)); + } + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(game_radios[Game]), TRUE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(plane_radios[Plane]), TRUE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wave_radios[WaveType]), TRUE); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "random")), + RandomSeed); + sprintf(Text, RForm, WaveLength); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "wavelength")), Text); + sprintf(Text, RForm, Amplitude); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "amplitude")), Text); + sprintf(Text, RForm, Roughness); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "roughness")), Text); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data + (G_OBJECT(g_pWnd), "main_antialiasing")), + Antialiasing); + break; + + case EXTENTS_TAB: + sprintf(Text, RForm, Hll); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "hmin")), Text); + sprintf(Text, RForm, Vll); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "vmin")), Text); + sprintf(Text, RForm, Hur); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "hmax")), Text); + sprintf(Text, RForm, Vur); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "vmax")), Text); + sprintf(Text, RForm, Z00); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "z00")), Text); + sprintf(Text, RForm, Z01); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "z01")), Text); + sprintf(Text, RForm, Z10); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "z10")), Text); + sprintf(Text, RForm, Z11); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "z11")), Text); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "nh")), NH); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "nv")), NV); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "sp")), + SP); // ^Fishman - Snap to grid. + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data + (G_OBJECT(g_pWnd), "linearborder")), FixBorders); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data + (G_OBJECT(g_pWnd), "use_patches")), UsePatches); + gtk_adjustment_set_value(GTK_ADJUSTMENT(g_object_get_data(G_OBJECT(g_pWnd), "decimate_adj")), + Decimate); + + if (Game == QUAKE3 && UsePatches) { + gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(g_pWnd, "decimate")), FALSE); + + if (NH % 2) { + NH++; + if (NH > MAX_ROWS) { + NH -= 2; + } + SetDlgValues(current_tab); + } + + if (NV % 2) { + NV++; + if (NV > MAX_ROWS) { + NV -= 2; + } + SetDlgValues(current_tab); + } + if (NH % 2) { + NH++; + } + if (NH < 2) { + NH = 2; + } + if (NH > MAX_ROWS) { + NH = MAX_ROWS; + } + if (NV % 2) { + NV++; + } + if (NV < 2) { + NV = 2; + } + if (NV > MAX_ROWS) { + NV = MAX_ROWS; + } + + gpointer spin = g_object_get_data(G_OBJECT(g_pWnd), "nh"); + GtkAdjustment *adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); + adj->lower = 2; + gtk_adjustment_changed(adj); + spin = g_object_get_data(G_OBJECT(g_pWnd), "nv"); + adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); + adj->lower = 2; + gtk_adjustment_changed(adj); + } else { + gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(g_pWnd, "decimate")), TRUE); + + gpointer spin = g_object_get_data(G_OBJECT(g_pWnd), "nh"); + GtkAdjustment *adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); + adj->lower = 1; + gtk_adjustment_changed(adj); + spin = g_object_get_data(G_OBJECT(g_pWnd), "nv"); + adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); + adj->lower = 1; + gtk_adjustment_changed(adj); + } + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "nh")), NH); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "nv")), NV); + + break; + + case BITMAP_TAB: + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "bmp_file")), gbmp.name); + sprintf(Text, "%g", gbmp.black_value); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "bmp_black")), Text); + sprintf(Text, "%g", gbmp.white_value); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "bmp_white")), Text); + break; + + case FIXPOINTS_TAB: + break; + + case TEXTURE_TAB: + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "texture1")), Texture[Game][0]); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "texture2")), Texture[Game][1]); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "texture3")), Texture[Game][2]); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "tex_slant")), + SlantAngle); + sprintf(Text, RForm, TexOffset[0]); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "texoffsetx")), Text); + sprintf(Text, RForm, TexOffset[1]); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "texoffsety")), Text); + sprintf(Text, RForm, TexScale[0]); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "texscalex")), Text); + sprintf(Text, RForm, TexScale[1]); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "texscaley")), Text); + CHECK_WIDGET("detail", UseDetail); + + if (Game == QUAKE3) { + ENABLE_WIDGET("hint", FALSE); + AddHints = 0; + } else { + ENABLE_WIDGET("hint", TRUE); + } + CHECK_WIDGET("hint", AddHints); + + /* if (Game==SIN) { // ArghRad doesn't currently support SiN @@ -430,8 +427,8 @@ static void SetDlgValues( int tab ){ } */ - if ( Game == QUAKE3 ) { - /* + if (Game == QUAKE3) { + /* // ArghRad sun is inapplicable (so far) EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2), 0); EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN), 0); @@ -444,7 +441,7 @@ static void SetDlgValues( int tab ){ SetDlgItemText(hwndDisplay,DLG_TEX_USEPAK,"Use pk3 file"); SetDlgItemText(hwndDisplay,DLG_TEX_PAK_TEXT,"PK3:"); */ - } + } /*trix if(Game==HERETIC2) { @@ -458,7 +455,7 @@ static void SetDlgValues( int tab ){ SetDlgItemText(hwndDisplay,DLG_TEX_USEPAK,"Use pak file"); SetDlgItemText(hwndDisplay,DLG_TEX_PAK_TEXT,"Pak:"); } */ - /* + /* if(Game==HALFLIFE) { // A bunch of controls aren't applicable to HL @@ -496,55 +493,55 @@ static void SetDlgValues( int tab ){ SetDlgItemText(hwndDisplay,DLG_TEX_PAK_TEXT,"Sin:"); } */ - break; - } - SetupControls(); + break; + } + SetupControls(); } -static void ReadDlgValues( int tab ){ - // char Text[256]; - // int i; - - switch ( tab ) - { - case GENERAL_TAB: - gpointer spin; - Roughness = atof( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "roughness" ) ) ) ); - WaveLength = atof( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "wavelength" ) ) ) ); - Amplitude = atof( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "amplitude" ) ) ) ); - spin = g_object_get_data( G_OBJECT( g_pWnd ), "random" ); - RandomSeed = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spin ) ); - break; - - case EXTENTS_TAB: - SP = atoi( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "sp" ) ) ) ); - NH = atoi( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "nh" ) ) ) ); - NV = atoi( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "nv" ) ) ) ); - - if ( Game == QUAKE3 && UsePatches != 0 ) { - if ( NH % 2 ) { - NH++; - } - if ( NH < 2 ) { - NH = 2; - } - if ( NH > MAX_ROWS ) { - NH = MAX_ROWS; - } - if ( NV % 2 ) { - NV++; - } - if ( NV < 2 ) { - NV = 2; - } - if ( NV > MAX_ROWS ) { - NV = MAX_ROWS; - } - } - break; +static void ReadDlgValues(int tab) +{ + // char Text[256]; + // int i; + + switch (tab) { + case GENERAL_TAB: + gpointer spin; + Roughness = atof(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "roughness")))); + WaveLength = atof(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "wavelength")))); + Amplitude = atof(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "amplitude")))); + spin = g_object_get_data(G_OBJECT(g_pWnd), "random"); + RandomSeed = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin)); + break; + + case EXTENTS_TAB: + SP = atoi(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "sp")))); + NH = atoi(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "nh")))); + NV = atoi(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "nv")))); + + if (Game == QUAKE3 && UsePatches != 0) { + if (NH % 2) { + NH++; + } + if (NH < 2) { + NH = 2; + } + if (NH > MAX_ROWS) { + NH = MAX_ROWS; + } + if (NV % 2) { + NV++; + } + if (NV < 2) { + NV = 2; + } + if (NV > MAX_ROWS) { + NV = MAX_ROWS; + } + } + break; #if 0 - case BITMAP_TAB: + case BITMAP_TAB: if ( WaveType == WAVE_BITMAP ) { GetDlgItemText( hwnd,DLG_BMP_FILE,gbmp.name,sizeof( gbmp.name ) ); @@ -635,128 +632,139 @@ static void ReadDlgValues( int tab ){ ArghRad2 = atoi( Text ); break; #endif - } + } } // ============================================================================= // main dialog callbacks -static void switch_page( GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data ){ - if ( current_tab != page_num ) { - if ( page_num == FIXPOINTS_TAB ) { - OldPreview = Preview; - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), - "main_preview" ) ), TRUE ); - VertexMode = 1; - UpdatePreview( true ); - NumVerticesSelected = 0; - } - - if ( current_tab == FIXPOINTS_TAB ) { - if ( !OldPreview ) { - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), - "main_preview" ) ), FALSE ); - } - VertexMode = 0; - UpdatePreview( true ); - NumVerticesSelected = 0; - } - - if ( page_num == TEXTURE_TAB ) { - WasDetail = UseDetail; - if ( AddHints ) { - UseDetail = 1; - ENABLE_WIDGET( "detail", FALSE ); - } - } - - ReadDlgValues( current_tab ); - current_tab = page_num; - SetDlgValues( current_tab ); - } +static void switch_page(GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data) +{ + if (current_tab != page_num) { + if (page_num == FIXPOINTS_TAB) { + OldPreview = Preview; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), + "main_preview")), TRUE); + VertexMode = 1; + UpdatePreview(true); + NumVerticesSelected = 0; + } + + if (current_tab == FIXPOINTS_TAB) { + if (!OldPreview) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), + "main_preview")), FALSE); + } + VertexMode = 0; + UpdatePreview(true); + NumVerticesSelected = 0; + } + + if (page_num == TEXTURE_TAB) { + WasDetail = UseDetail; + if (AddHints) { + UseDetail = 1; + ENABLE_WIDGET("detail", FALSE); + } + } + + ReadDlgValues(current_tab); + current_tab = page_num; + SetDlgValues(current_tab); + } } -static gint main_close( GtkWidget *widget, gpointer data ){ - gtk_widget_hide( g_pWnd ); - gtk_widget_hide( g_pWndPreview ); +static gint main_close(GtkWidget *widget, gpointer data) +{ + gtk_widget_hide(g_pWnd); + gtk_widget_hide(g_pWndPreview); - return TRUE; + return TRUE; } -static void main_save( GtkWidget *widget, gpointer data ){ - ReadDlgValues( current_tab ); - SaveSetup( g_pWnd ); +static void main_save(GtkWidget *widget, gpointer data) +{ + ReadDlgValues(current_tab); + SaveSetup(g_pWnd); } -static void main_open( GtkWidget *widget, gpointer data ){ - OpenSetup( g_pWnd, 0 ); - for ( int i = 0; i < 5; i++ ) - SetDlgValues( i ); - ShowPreview(); +static void main_open(GtkWidget *widget, gpointer data) +{ + OpenSetup(g_pWnd, 0); + for (int i = 0; i < 5; i++) { + SetDlgValues(i); + } + ShowPreview(); } -static void main_defaults( GtkWidget *widget, gpointer data ){ - OpenSetup( g_pWnd, 1 ); - for ( int i = 0; i < 5; i++ ) - SetDlgValues( i ); - ShowPreview(); +static void main_defaults(GtkWidget *widget, gpointer data) +{ + OpenSetup(g_pWnd, 1); + for (int i = 0; i < 5; i++) { + SetDlgValues(i); + } + ShowPreview(); } -static void main_preview( GtkWidget *widget, gpointer data ){ - Preview = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ); - ShowPreview(); +static void main_preview(GtkWidget *widget, gpointer data) +{ + Preview = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + ShowPreview(); } // ^Fishman - Antializing for the preview window. -static void main_antialiasing( GtkWidget *widget, gpointer data ){ - Antialiasing = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ); - UpdatePreview( true ); +static void main_antialiasing(GtkWidget *widget, gpointer data) +{ + Antialiasing = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + UpdatePreview(true); } -static void main_about( GtkWidget *widget, gpointer data ){ - About( g_pWnd ); +static void main_about(GtkWidget *widget, gpointer data) +{ + About(g_pWnd); } -static void main_go( GtkWidget *widget, gpointer data ){ - GtkWidget *notebook = g_object_get_data( G_OBJECT( g_pWnd , "notebook" ) ); - char Text[256]; - - ReadDlgValues( current_tab ); - if ( NH < 1 || NH > MAX_ROWS ) { - sprintf( Text, "The number of divisions must be > 0 and no greater than %d.", MAX_ROWS ); - g_FuncTable.m_pfnMessageBox( g_pWnd, Text, "GenSurf", eMB_OK, eMB_ICONWARNING ); - gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB ); - return; - } - - if ( NV < 1 || NV > MAX_ROWS ) { - sprintf( Text, "The number of divisions must be > 0 and no greater than %d.", MAX_ROWS ); - g_FuncTable.m_pfnMessageBox( g_pWnd, Text, "GenSurf", eMB_OK, eMB_ICONWARNING ); - gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB ); - return; - } - - if ( Hll >= Hur ) { - g_FuncTable.m_pfnMessageBox( g_pWnd, "The \"lower-left\" values must be less than " - "the corresponding \"upper-right\" values in " - "the \"Extent\" box.","GenSurf", eMB_OK, eMB_ICONWARNING ); - gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB ); - return; - } - - if ( Vll >= Vur ) { - g_FuncTable.m_pfnMessageBox( g_pWnd,"The \"lower-left\" values must be less than " - "the corresponding \"upper-right\" values in " - "the \"Extent\" box.","GenSurf", eMB_OK, eMB_ICONWARNING ); - gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB ); - return; - } - - if ( !strlen( Texture[Game][0] ) ) { - g_FuncTable.m_pfnMessageBox( g_pWnd, "You must supply a texture name.", "GenSurf", eMB_OK, eMB_ICONWARNING ); - gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB ); - return; - } +static void main_go(GtkWidget *widget, gpointer data) +{ + GtkWidget *notebook = g_object_get_data(G_OBJECT(g_pWnd, "notebook")); + char Text[256]; + + ReadDlgValues(current_tab); + if (NH < 1 || NH > MAX_ROWS) { + sprintf(Text, "The number of divisions must be > 0 and no greater than %d.", MAX_ROWS); + g_FuncTable.m_pfnMessageBox(g_pWnd, Text, "GenSurf", eMB_OK, eMB_ICONWARNING); + gtk_notebook_set_page(GTK_NOTEBOOK(notebook), EXTENTS_TAB); + return; + } + + if (NV < 1 || NV > MAX_ROWS) { + sprintf(Text, "The number of divisions must be > 0 and no greater than %d.", MAX_ROWS); + g_FuncTable.m_pfnMessageBox(g_pWnd, Text, "GenSurf", eMB_OK, eMB_ICONWARNING); + gtk_notebook_set_page(GTK_NOTEBOOK(notebook), EXTENTS_TAB); + return; + } + + if (Hll >= Hur) { + g_FuncTable.m_pfnMessageBox(g_pWnd, "The \"lower-left\" values must be less than " + "the corresponding \"upper-right\" values in " + "the \"Extent\" box.", "GenSurf", eMB_OK, eMB_ICONWARNING); + gtk_notebook_set_page(GTK_NOTEBOOK(notebook), EXTENTS_TAB); + return; + } + + if (Vll >= Vur) { + g_FuncTable.m_pfnMessageBox(g_pWnd, "The \"lower-left\" values must be less than " + "the corresponding \"upper-right\" values in " + "the \"Extent\" box.", "GenSurf", eMB_OK, eMB_ICONWARNING); + gtk_notebook_set_page(GTK_NOTEBOOK(notebook), EXTENTS_TAB); + return; + } + + if (!strlen(Texture[Game][0])) { + g_FuncTable.m_pfnMessageBox(g_pWnd, "You must supply a texture name.", "GenSurf", eMB_OK, eMB_ICONWARNING); + gtk_notebook_set_page(GTK_NOTEBOOK(notebook), EXTENTS_TAB); + return; + } /* if (Decimate>0 && GimpHints!=0) { @@ -767,94 +775,100 @@ static void main_go( GtkWidget *widget, gpointer data ){ GimpHints = 0; } */ - gtk_widget_hide( g_pWnd ); - if ( g_pWndPreview ) { - gtk_widget_hide( g_pWndPreview ); - } + gtk_widget_hide(g_pWnd); + if (g_pWndPreview) { + gtk_widget_hide(g_pWndPreview); + } - GenerateMap(); - WriteIniFile( gszIni ); + GenerateMap(); + WriteIniFile(gszIni); } // ============================================================================= // general tab callbacks -static void general_game( GtkToggleButton *widget, gpointer data ){ - if ( gtk_toggle_button_get_active( widget ) ) { - Game = GPOINTER_TO_INT( data ); - UpdatePreview( TRUE ); - } +static void general_game(GtkToggleButton *widget, gpointer data) +{ + if (gtk_toggle_button_get_active(widget)) { + Game = GPOINTER_TO_INT(data); + UpdatePreview(TRUE); + } } -static void general_plane( GtkToggleButton *widget, gpointer data ){ - if ( gtk_toggle_button_get_active( widget ) ) { - Plane = GPOINTER_TO_INT( data ); - SetupControls(); - UpdatePreview( TRUE ); - } +static void general_plane(GtkToggleButton *widget, gpointer data) +{ + if (gtk_toggle_button_get_active(widget)) { + Plane = GPOINTER_TO_INT(data); + SetupControls(); + UpdatePreview(TRUE); + } } -static void general_wave( GtkToggleButton *widget, gpointer data ){ - if ( gtk_toggle_button_get_active( widget ) ) { - WaveType = GPOINTER_TO_INT( data ); - SetupControls(); - UpdatePreview( TRUE ); - } +static void general_wave(GtkToggleButton *widget, gpointer data) +{ + if (gtk_toggle_button_get_active(widget)) { + WaveType = GPOINTER_TO_INT(data); + SetupControls(); + UpdatePreview(TRUE); + } } -static void general_random( GtkAdjustment *adj, gpointer data ){ - int nPos = (int)adj->value; +static void general_random(GtkAdjustment *adj, gpointer data) +{ + int nPos = (int) adj->value; - if ( RandomSeed != nPos ) { - RandomSeed = nPos; - UpdatePreview( true ); - } + if (RandomSeed != nPos) { + RandomSeed = nPos; + UpdatePreview(true); + } } // ============================================================================= // extents tab callbacks -static void extents_linearborder( GtkToggleButton *check, gpointer data ){ - FixBorders = gtk_toggle_button_get_active( check ); - UpdatePreview( true ); +static void extents_linearborder(GtkToggleButton *check, gpointer data) +{ + FixBorders = gtk_toggle_button_get_active(check); + UpdatePreview(true); } -static void extents_use_patches( GtkToggleButton *check, gpointer data ){ - if ( Game != QUAKE3 ) { - return; - } +static void extents_use_patches(GtkToggleButton *check, gpointer data) +{ + if (Game != QUAKE3) { + return; + } - UsePatches = gtk_toggle_button_get_active( check ); - SetDlgValues( current_tab ); - SetupControls(); - UpdatePreview( true ); + UsePatches = gtk_toggle_button_get_active(check); + SetDlgValues(current_tab); + SetupControls(); + UpdatePreview(true); } -static void extents_nhnv_spin( GtkAdjustment *adj, int *data ){ - int nPos = (int)adj->value; - - if ( *data != nPos ) { - if ( Game == QUAKE3 && UsePatches && ( nPos % 2 ) ) { - if ( *data < nPos ) { - *data += 2; - } - else{ - *data -= 2; - } - gtk_adjustment_set_value( adj, *data ); - } - else{ - *data = nPos; - } - UpdatePreview( true ); - } +static void extents_nhnv_spin(GtkAdjustment *adj, int *data) +{ + int nPos = (int) adj->value; + + if (*data != nPos) { + if (Game == QUAKE3 && UsePatches && (nPos % 2)) { + if (*data < nPos) { + *data += 2; + } else { + *data -= 2; + } + gtk_adjustment_set_value(adj, *data); + } else { + *data = nPos; + } + UpdatePreview(true); + } } -static void extents_decimate( GtkAdjustment *adj, gpointer data ){ - int nPos = (int)adj->value; +static void extents_decimate(GtkAdjustment *adj, gpointer data) +{ + int nPos = (int) adj->value; - Decimate = nPos; - UpdatePreview( true ); + Decimate = nPos; + UpdatePreview(true); } // Hydra : snap to grid begin @@ -867,1216 +881,1237 @@ static void extents_decimate( GtkAdjustment *adj, gpointer data ){ }*/ // ^Fishman - Modified version of Hydra's snap to grid code. -static void extents_snaptogrid_spin( GtkAdjustment *adj, int *data ){ - int nPos = (int)adj->value; - SnapToGrid = nPos; - UpdatePreview( true ); +static void extents_snaptogrid_spin(GtkAdjustment *adj, int *data) +{ + int nPos = (int) adj->value; + SnapToGrid = nPos; + UpdatePreview(true); } // ============================================================================= // bitmap tab callbacks -static gint bitmap_file_entryfocusout( GtkWidget* widget, GdkEventFocus* event, gpointer data ){ - char filename[NAME_MAX]; - - strcpy( filename, gtk_entry_get_text( GTK_ENTRY( widget ) ) ); - if ( strcmp( filename,gbmp.name ) ) { - strcpy( gbmp.name,filename ); - if ( strlen( gbmp.name ) ) { - OpenBitmap(); - } - ENABLE_WIDGET( "go", ( gbmp.colors != NULL ? TRUE : FALSE ) ); - } - return FALSE; +static gint bitmap_file_entryfocusout(GtkWidget *widget, GdkEventFocus *event, gpointer data) +{ + char filename[NAME_MAX]; + + strcpy(filename, gtk_entry_get_text(GTK_ENTRY(widget))); + if (strcmp(filename, gbmp.name)) { + strcpy(gbmp.name, filename); + if (strlen(gbmp.name)) { + OpenBitmap(); + } + ENABLE_WIDGET("go", (gbmp.colors != NULL ? TRUE : FALSE)); + } + return FALSE; } -static void bitmap_browse( GtkWidget *widget, gpointer data ){ - const char *filename; - char *ptr; +static void bitmap_browse(GtkWidget *widget, gpointer data) +{ + const char *filename; + char *ptr; - filename = g_FuncTable.m_pfnFileDialog( g_pWnd, TRUE, "Bitmap File", gbmp.defpath ); + filename = g_FuncTable.m_pfnFileDialog(g_pWnd, TRUE, "Bitmap File", gbmp.defpath); - if ( filename != NULL ) { - strcpy( gbmp.name, filename ); + if (filename != NULL) { + strcpy(gbmp.name, filename); - ptr = strrchr( filename, G_DIR_SEPARATOR ); - if ( ptr != NULL ) { - *( ptr + 1 ) = '\0'; - strcpy( gbmp.defpath, filename ); - } + ptr = strrchr(filename, G_DIR_SEPARATOR); + if (ptr != NULL) { + *(ptr + 1) = '\0'; + strcpy(gbmp.defpath, filename); + } - OpenBitmap(); - ENABLE_WIDGET( "go", ( gbmp.colors != NULL ? TRUE : FALSE ) ); - } + OpenBitmap(); + ENABLE_WIDGET("go", (gbmp.colors != NULL ? TRUE : FALSE)); + } } -static void bitmap_reload( GtkWidget *widget, gpointer data ){ - strcpy( gbmp.name, gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_file" ) ) ) ); - if ( strlen( gbmp.name ) ) { - OpenBitmap(); - ENABLE_WIDGET( "go", ( gbmp.colors != NULL ? TRUE : FALSE ) ); - } - else{ - ENABLE_WIDGET( "go", FALSE ); - } +static void bitmap_reload(GtkWidget *widget, gpointer data) +{ + strcpy(gbmp.name, gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "bmp_file")))); + if (strlen(gbmp.name)) { + OpenBitmap(); + ENABLE_WIDGET("go", (gbmp.colors != NULL ? TRUE : FALSE)); + } else { + ENABLE_WIDGET("go", FALSE); + } } // ============================================================================= // fix points tab callbacks -static gint fix_value_entryfocusout( GtkWidget* widget, GdkEventFocus *event, gpointer data ){ - int i = atoi( gtk_entry_get_text( GTK_ENTRY( widget ) ) ), k; - char Text[32]; - - if ( i < -65536 || i > 65536 ) { - gdk_beep(); - g_FuncTable.m_pfnMessageBox( g_pWnd, "The value must be between -65536 and 65536, inclusive.", - "GenSurf", eMB_OK, eMB_ICONWARNING ); - sprintf( Text, "%d", (int)xyz[Vertex[0].i][Vertex[0].j].fixed_value ); - gtk_entry_set_text( GTK_ENTRY( widget ), Text ); - gtk_window_set_focus( widget.window(), widget ); - } - else if ( i != xyz[Vertex[0].i][Vertex[0].j].fixed_value ) { - for ( k = 0; k < NumVerticesSelected; k++ ) - xyz[Vertex[k].i][Vertex[k].j].fixed_value = i; - - gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "fix_value" ) ), - (int)xyz[Vertex[0].i][Vertex[0].j].fixed_value ); - UpdatePreview( true ); - } - return FALSE; +static gint fix_value_entryfocusout(GtkWidget *widget, GdkEventFocus *event, gpointer data) +{ + int i = atoi(gtk_entry_get_text(GTK_ENTRY(widget))), k; + char Text[32]; + + if (i < -65536 || i > 65536) { + gdk_beep(); + g_FuncTable.m_pfnMessageBox(g_pWnd, "The value must be between -65536 and 65536, inclusive.", + "GenSurf", eMB_OK, eMB_ICONWARNING); + sprintf(Text, "%d", (int) xyz[Vertex[0].i][Vertex[0].j].fixed_value); + gtk_entry_set_text(GTK_ENTRY(widget), Text); + gtk_window_set_focus(widget.window(), widget); + } else if (i != xyz[Vertex[0].i][Vertex[0].j].fixed_value) { + for (k = 0; k < NumVerticesSelected; k++) { + xyz[Vertex[k].i][Vertex[k].j].fixed_value = i; + } + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "fix_value")), + (int) xyz[Vertex[0].i][Vertex[0].j].fixed_value); + UpdatePreview(true); + } + return FALSE; } -static void fix_value_changed( GtkAdjustment *adj, gpointer data ){ - int k, i = (int)adj->value; +static void fix_value_changed(GtkAdjustment *adj, gpointer data) +{ + int k, i = (int) adj->value; - if ( xyz[Vertex[0].i][Vertex[0].j].fixed_value != i ) { - for ( k = 0; k < NumVerticesSelected; k++ ) - xyz[Vertex[k].i][Vertex[k].j].fixed_value = i; - UpdatePreview( true ); - } + if (xyz[Vertex[0].i][Vertex[0].j].fixed_value != i) { + for (k = 0; k < NumVerticesSelected; k++) { + xyz[Vertex[k].i][Vertex[k].j].fixed_value = i; + } + UpdatePreview(true); + } } -static gint fix_range_entryfocusout( GtkWidget *widget, GdkEventFocus *event, gpointer data ){ - int i = atoi( gtk_entry_get_text( GTK_ENTRY( widget ) ) ), k; - - if ( i != xyz[Vertex[0].i][Vertex[0].j].range ) { - for ( k = 0; k < NumVerticesSelected; k++ ) - xyz[Vertex[k].i][Vertex[k].j].range = i; - UpdatePreview( true ); - } - return FALSE; +static gint fix_range_entryfocusout(GtkWidget *widget, GdkEventFocus *event, gpointer data) +{ + int i = atoi(gtk_entry_get_text(GTK_ENTRY(widget))), k; + + if (i != xyz[Vertex[0].i][Vertex[0].j].range) { + for (k = 0; k < NumVerticesSelected; k++) { + xyz[Vertex[k].i][Vertex[k].j].range = i; + } + UpdatePreview(true); + } + return FALSE; } -static gint fix_rate_entryfocusout( GtkWidget *widget, GdkEventFocus *event, gpointer data ){ - double r = atof( gtk_entry_get_text( GTK_ENTRY( widget ) ) ); - int k; - - if ( r != xyz[Vertex[0].i][Vertex[0].j].rate ) { - for ( k = 0; k < NumVerticesSelected; k++ ) - xyz[Vertex[k].i][Vertex[k].j].rate = r; - UpdatePreview( true ); - } - return FALSE; +static gint fix_rate_entryfocusout(GtkWidget *widget, GdkEventFocus *event, gpointer data) +{ + double r = atof(gtk_entry_get_text(GTK_ENTRY(widget))); + int k; + + if (r != xyz[Vertex[0].i][Vertex[0].j].rate) { + for (k = 0; k < NumVerticesSelected; k++) { + xyz[Vertex[k].i][Vertex[k].j].rate = r; + } + UpdatePreview(true); + } + return FALSE; } -static void fix_free( GtkWidget *widget, gpointer data ){ - int k; +static void fix_free(GtkWidget *widget, gpointer data) +{ + int k; - for ( k = 0; k < NumVerticesSelected; k++ ) - xyz[Vertex[k].i][Vertex[k].j].fixed = 0; - NumVerticesSelected = 0; - SetupControls(); - UpdatePreview( true ); + for (k = 0; k < NumVerticesSelected; k++) { + xyz[Vertex[k].i][Vertex[k].j].fixed = 0; + } + NumVerticesSelected = 0; + SetupControls(); + UpdatePreview(true); } -static void fix_freeall( GtkWidget *widget, gpointer data ){ - int i, j; +static void fix_freeall(GtkWidget *widget, gpointer data) +{ + int i, j; - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - xyz[i][j].fixed = 0; - } - fix_free( NULL, data ); // keep these together + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + xyz[i][j].fixed = 0; + } + } + fix_free(NULL, data); // keep these together } -void vertex_selected(){ - char Text[32]; - int k; - - SetupControls(); - - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - for ( k = 0; k < NumVerticesSelected; k++ ) - xyz[Vertex[k].i][Vertex[k].j].fixed_value = xyz[Vertex[0].i][Vertex[0].j].p[1]; - break; - case PLANE_YZ0: - case PLANE_YZ1: - for ( k = 0; k < NumVerticesSelected; k++ ) - xyz[Vertex[k].i][Vertex[k].j].fixed_value = xyz[Vertex[0].i][Vertex[0].j].p[0]; - break; - default: - for ( k = 0; k < NumVerticesSelected; k++ ) - xyz[Vertex[k].i][Vertex[k].j].fixed_value = xyz[Vertex[0].i][Vertex[0].j].p[2]; - break; - } - - gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "fix_value" ) ), - (int)xyz[Vertex[0].i][Vertex[0].j].fixed_value ); - - sprintf( Text,"%d",(int)xyz[Vertex[0].i][Vertex[0].j].range ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "fix_range" ) ), Text ); - sprintf( Text,"%.5g",xyz[Vertex[0].i][Vertex[0].j].rate ); - gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "fix_rate" ) ), Text ); - - for ( k = 0; k < NumVerticesSelected; k++ ) - xyz[Vertex[k].i][Vertex[k].j].fixed = 1; - - UpdatePreview( true ); +void vertex_selected() +{ + char Text[32]; + int k; + + SetupControls(); + + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + for (k = 0; k < NumVerticesSelected; k++) { + xyz[Vertex[k].i][Vertex[k].j].fixed_value = xyz[Vertex[0].i][Vertex[0].j].p[1]; + } + break; + case PLANE_YZ0: + case PLANE_YZ1: + for (k = 0; k < NumVerticesSelected; k++) { + xyz[Vertex[k].i][Vertex[k].j].fixed_value = xyz[Vertex[0].i][Vertex[0].j].p[0]; + } + break; + default: + for (k = 0; k < NumVerticesSelected; k++) { + xyz[Vertex[k].i][Vertex[k].j].fixed_value = xyz[Vertex[0].i][Vertex[0].j].p[2]; + } + break; + } + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "fix_value")), + (int) xyz[Vertex[0].i][Vertex[0].j].fixed_value); + + sprintf(Text, "%d", (int) xyz[Vertex[0].i][Vertex[0].j].range); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "fix_range")), Text); + sprintf(Text, "%.5g", xyz[Vertex[0].i][Vertex[0].j].rate); + gtk_entry_set_text(GTK_ENTRY(g_object_get_data(G_OBJECT(g_pWnd), "fix_rate")), Text); + + for (k = 0; k < NumVerticesSelected; k++) { + xyz[Vertex[k].i][Vertex[k].j].fixed = 1; + } + + UpdatePreview(true); } // ============================================================================= // texture tab callbacks -static void texture_detail( GtkToggleButton *check, gpointer data ){ - UseDetail = gtk_toggle_button_get_active( check ); - WasDetail = UseDetail; +static void texture_detail(GtkToggleButton *check, gpointer data) +{ + UseDetail = gtk_toggle_button_get_active(check); + WasDetail = UseDetail; } -static void texture_hint( GtkToggleButton *check, gpointer data ){ - AddHints = gtk_toggle_button_get_active( check ); - if ( AddHints == 1 ) { - UseDetail = 1; - ENABLE_WIDGET( "detail", FALSE ); - } - else - { - UseDetail = WasDetail; - ENABLE_WIDGET( "detail", FALSE ); - } - CHECK_WIDGET( "detail", UseDetail ); +static void texture_hint(GtkToggleButton *check, gpointer data) +{ + AddHints = gtk_toggle_button_get_active(check); + if (AddHints == 1) { + UseDetail = 1; + ENABLE_WIDGET("detail", FALSE); + } else { + UseDetail = WasDetail; + ENABLE_WIDGET("detail", FALSE); + } + CHECK_WIDGET("detail", UseDetail); } // ^Fishman - Add terrain key to func_group. -static void texture_terrainent( GtkToggleButton *check, gpointer data ){ - AddTerrainKey = gtk_toggle_button_get_active( check ); +static void texture_terrainent(GtkToggleButton *check, gpointer data) +{ + AddTerrainKey = gtk_toggle_button_get_active(check); } -static void texture_set( int index, const char* name ){ - strcpy( Texture[Game][index], name ); +static void texture_set(int index, const char *name) +{ + strcpy(Texture[Game][index], name); } -static gint texture_entryfocusout( GtkWidget* widget, GdkEventFocus* event, gpointer data ){ - texture_set( GPOINTER_TO_INT( data ), gtk_entry_get_text( GTK_ENTRY( widget ) ) ); - return FALSE; +static gint texture_entryfocusout(GtkWidget *widget, GdkEventFocus *event, gpointer data) +{ + texture_set(GPOINTER_TO_INT(data), gtk_entry_get_text(GTK_ENTRY(widget))); + return FALSE; } // ============================================================================= // misc stuff -static void UpdateVariable( GtkEntry *entry, GdkEventFocus *event, double *data ){ - double x = atof( gtk_entry_get_text( entry ) ); +static void UpdateVariable(GtkEntry *entry, GdkEventFocus *event, double *data) +{ + double x = atof(gtk_entry_get_text(entry)); - if ( x != *data ) { - *data = x; - UpdatePreview( true ); - } + if (x != *data) { + *data = x; + UpdatePreview(true); + } } -static gint doublevariable_entryfocusout( GtkWidget* widget, GdkEventFocus* event, gpointer data ){ - UpdateVariable( GTK_ENTRY( widget ), event, reinterpret_cast( data ) ); - return FALSE; +static gint doublevariable_entryfocusout(GtkWidget *widget, GdkEventFocus *event, gpointer data) +{ + UpdateVariable(GTK_ENTRY(widget), event, reinterpret_cast( data )); + return FALSE; } // ============================================================================= // create tooltips -void create_tooltips(){ - tooltips = gtk_tooltips_new(); - - // Main - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "go" ) ), - "Accept all input and generate a surface in Q3Radiant", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "open" ) ), - "Open a previously saved GenSurf settings file.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "save" ) ), - "Save all settings to a file.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "defaults" ) ), - "Restore default values from DEFAULTS.SRF. If this file does not exist, GenSurf " - "initializes all input parameters to reasonable values. You can create your own " - "default surface by setting all parameters to your liking, then saving a settings " - "file as DEFAULTS.SRF with the Save As button.", - "" ); - - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "main_preview" ) ), - "View a wire-frame representation of the surface", - "" ); - - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "main_antialiasing" ) ), - "The lines in the preview window are antialiased for better quality", - "" ); - - // General tab - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - wave_radios[0] , - "Builds a surface with alternating hills and valleys. Uses the general form Z=cos(X) " - "x sin(Y)", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - wave_radios[1] , - "Builds a surface with ridges parallel to the vertical axis.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - wave_radios[2] , - "Builds a surface with ridges parallel to the horizontal axis.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - wave_radios[3] , - "Builds a map from a bitmap image representing a contour plot. Click the \"Bitmap\" " - "tab to select the image. GenSurf only supports 256-color (8 bit) " - "bitmaps. GenSurf will work with any 256-color bitmap, but gray scale bitmaps are a bit " - "more intuitive.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - wave_radios[4] , - "Builds a random surface using the Plasma Cloud technique. Variance is controlled " - "by the Roughness input. To build a surface with completely random values not " - "dependent on neighboring vertices, use one of the other waveforms with 0 amplitude.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "wavelength" ) ), - "Enter the wavelength (distance between crests). NOTE: Wavelengths equal to the grid " - "size or 2 times the grid size will result in 0 amplitudes. For best results, the " - "wavelength value should be at least 4 times the grid size (extents divided by the " - "number of divisions", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "amplitude" ) ), - "Enter the height of hills/ridges.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "roughness" ) ), - "Enter the roughness value (noise) for the surface. For fractal surfaces, this value " - "is used as a variance in the fractal calculations.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "random" ) ), - "Seed value for the pseudo-random number generator.", - "" ); - // Extents tab - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "hmin" ) ), - "Minimum horizontal coordinate of the surface, i.e. X for a surface parallel to " - "the XY or XZ planes, Y for a surface parallel to the YZ plane. For best results, " - "the extents (maximum-minimum values) in a given direction should be evenly " - "divisible by the number of divisions in that direction.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "hmax" ) ), - "Maximum horizontal coordinate of the surface, i.e. X for a surface parallel to " - "the XY or XZ planes, Y for a surface parallel to the YZ plane. For best results, " - "the extents (maximum-minimum values) in a given direction should be evenly " - "divisible by the number of divisions in that direction.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "vmin" ) ), - "Minimum vertical coordinate of the surface, i.e. Y for a surface parallel to " - "the XY plane, Z for a surface parallel to the XZ or YZ planes. For best results, " - "the extents (maximum-minimum values) in a given direction should be evenly " - "divisible by the number of divisions in that direction.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "vmax" ) ), - "Maximum vertical coordinate of the surface, i.e. Y for a surface parallel to " - "the XY plane, Z for a surface parallel to the XZ or YZ planes. For best results, " - "the extents (maximum-minimum values) in a given direction should be evenly " - "divisible by the number of divisions in that direction.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "nh" ) ), - "Number of divisions in the horizontal direction. For best results, the extents " - "in a given direction should be evenly divisible by the number of divisions in " - "that direction.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "nv" ) ), - "Number of divisions in the vertical direction. For best results, the extents " - "in a given direction should be evenly divisible by the number of divisions in " - "that direction.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "use_patches" ) ), - "Produce one or more curved patches in the shape of your selected surface rather " - "than producing solid brushes. Depending on the size of your surface (and the " - "user's graphic detail settings, which you cannot control), curved surfaces will " - "be represented in the game by a very large number of polygons. Read the warnings " - "concerning curved surfaces on the GenSurf web page before using this feature.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "decimate" ) ), - "Use the slider to control the number of vertices discarded by GenSurf. For many " - "surfaces, you can produce roughly the same shape surface with a high decimation " - "value. This will generally result in a map with lower polygon counts (and better " - "in-game performance). However, this feature should NOT be used for large terrain " - "surfaces in Q3", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "z00" ) ), - "Enter the height of the surface at the lower left corner. This value will likely " - "be modified unless \"Linear Borders\" is checked.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "z01" ) ), - "Enter the height of the surface at the upper left corner. This value will likely " - "be modified unless \"Linear Borders\" is checked.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "z10" ) ), - "Enter the height of the surface at the lower right corner. This value will likely " - "be modified unless \"Linear Borders\" is checked.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "z11" ) ), - "Enter the height of the surface at the upper right corner. This value will likely " - "be modified unless \"Linear Borders\" is checked.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "linearborder" ) ), - "Restrict the edges of the surface to a straight line. This will help match up " - "brush edges if you drop this surface into another map.", - "" ); - // Bitmap tab - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "bmp_file" ) ), - "Type the name of an 8-bit bitmap image file, or click Browse to select an image " - "from a list of those available on your system.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "bmp_file_browse" ) ), - "Select a bitmap image file from a list of those available on your system.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "bmp_reload" ) ), - "Reload the selected bitmap file after making changes in an external image editor.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "bmp_black" ) ), - "Enter the value corresponding to color index 0 in the bitmap file. For gray scale " - "images, color 0 is normally black.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "bmp_white" ) ), - "Enter the value corresponding to color index 255 in the bitmap file. For gray scale " - "images, color 255 is normally white.", - "" ); - // Fixpoints tab - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "fix_value" ) ), - "Enter a value for the selected vertex. This value will not be adjusted when applying " - "a waveform or roughness to the surface. Unlock this vertex (so that it will be " - "adjusted normally) by clicking \"Free\". This vertex will influence vertices within " - "the \"Range affected\" of this vertex.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "fix_range" ) ), - "Enter the range away from the selected vertex that other vertices will be affected. " - "Use 0 if you don't want other vertices to be influenced by the currently selected " - "one. Note: this box is disabled if you've chosen the fractal generator, as it uses " - "a completely different method for determining values.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "fix_rate" ) ), - "Enter a rate of change for the surface affected by the fixed value. 0 gives a smooth " - "sinusoidal curve, values less than 0 give progressively sharper spikes, and values " - "greater than 0 take on a square shape. Values less than -30 or greater than 30 are " - "set to -30 and 30, respectively. Note that this entry will have no effect unless " - "you also specify a \"range affected\".", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "fix_free" ) ), - "Click this to free (unlock the value of) the currently selected vertex.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "fix_freeall" ) ), - "Click this to free (unlock the values of) all vertices.", - "" ); - // Texture tab - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "texture1" ) ), - "Enter the name of the texture or shader used for the surface faces.", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "texture2" ) ), - "Enter the name of the texture or shader used for faces other than the surface. Under " - "normal circumstances this should be \"common/caulk\"", - "" ); - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "texture3" ) ), - "Enter the name of the texture or shader used for \"steep\" surface faces, where \"steep\" " - "is the angle specified below. If this entry is left blank or if the \"steep\" angle is 0, " - "all surface faces will use the texture specified by \"Surface\".", - "" ); - - gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ), - g_object_get_data( G_OBJECT( g_pWnd , "detail" ) ), - "Check this box to use the detail content property on the generated brushes. Compile " - "times will be considerably shorter if the detail property is used, though the surface " - "will not block visibility at all. If you use the detail property, you should make sure " - "that \"common/caulk\" is used for the non-surface faces, or the polygon count will be " - "much higher than necessary.", - "" ); +void create_tooltips() +{ + tooltips = gtk_tooltips_new(); + + // Main + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "go")), + "Accept all input and generate a surface in Q3Radiant", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "open")), + "Open a previously saved GenSurf settings file.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "save")), + "Save all settings to a file.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "defaults")), + "Restore default values from DEFAULTS.SRF. If this file does not exist, GenSurf " + "initializes all input parameters to reasonable values. You can create your own " + "default surface by setting all parameters to your liking, then saving a settings " + "file as DEFAULTS.SRF with the Save As button.", + ""); + + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "main_preview")), + "View a wire-frame representation of the surface", + ""); + + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "main_antialiasing")), + "The lines in the preview window are antialiased for better quality", + ""); + + // General tab + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + wave_radios[0], + "Builds a surface with alternating hills and valleys. Uses the general form Z=cos(X) " + "x sin(Y)", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + wave_radios[1], + "Builds a surface with ridges parallel to the vertical axis.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + wave_radios[2], + "Builds a surface with ridges parallel to the horizontal axis.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + wave_radios[3], + "Builds a map from a bitmap image representing a contour plot. Click the \"Bitmap\" " + "tab to select the image. GenSurf only supports 256-color (8 bit) " + "bitmaps. GenSurf will work with any 256-color bitmap, but gray scale bitmaps are a bit " + "more intuitive.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + wave_radios[4], + "Builds a random surface using the Plasma Cloud technique. Variance is controlled " + "by the Roughness input. To build a surface with completely random values not " + "dependent on neighboring vertices, use one of the other waveforms with 0 amplitude.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "wavelength")), + "Enter the wavelength (distance between crests). NOTE: Wavelengths equal to the grid " + "size or 2 times the grid size will result in 0 amplitudes. For best results, the " + "wavelength value should be at least 4 times the grid size (extents divided by the " + "number of divisions", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "amplitude")), + "Enter the height of hills/ridges.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "roughness")), + "Enter the roughness value (noise) for the surface. For fractal surfaces, this value " + "is used as a variance in the fractal calculations.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "random")), + "Seed value for the pseudo-random number generator.", + ""); + // Extents tab + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "hmin")), + "Minimum horizontal coordinate of the surface, i.e. X for a surface parallel to " + "the XY or XZ planes, Y for a surface parallel to the YZ plane. For best results, " + "the extents (maximum-minimum values) in a given direction should be evenly " + "divisible by the number of divisions in that direction.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "hmax")), + "Maximum horizontal coordinate of the surface, i.e. X for a surface parallel to " + "the XY or XZ planes, Y for a surface parallel to the YZ plane. For best results, " + "the extents (maximum-minimum values) in a given direction should be evenly " + "divisible by the number of divisions in that direction.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "vmin")), + "Minimum vertical coordinate of the surface, i.e. Y for a surface parallel to " + "the XY plane, Z for a surface parallel to the XZ or YZ planes. For best results, " + "the extents (maximum-minimum values) in a given direction should be evenly " + "divisible by the number of divisions in that direction.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "vmax")), + "Maximum vertical coordinate of the surface, i.e. Y for a surface parallel to " + "the XY plane, Z for a surface parallel to the XZ or YZ planes. For best results, " + "the extents (maximum-minimum values) in a given direction should be evenly " + "divisible by the number of divisions in that direction.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "nh")), + "Number of divisions in the horizontal direction. For best results, the extents " + "in a given direction should be evenly divisible by the number of divisions in " + "that direction.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "nv")), + "Number of divisions in the vertical direction. For best results, the extents " + "in a given direction should be evenly divisible by the number of divisions in " + "that direction.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "use_patches")), + "Produce one or more curved patches in the shape of your selected surface rather " + "than producing solid brushes. Depending on the size of your surface (and the " + "user's graphic detail settings, which you cannot control), curved surfaces will " + "be represented in the game by a very large number of polygons. Read the warnings " + "concerning curved surfaces on the GenSurf web page before using this feature.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "decimate")), + "Use the slider to control the number of vertices discarded by GenSurf. For many " + "surfaces, you can produce roughly the same shape surface with a high decimation " + "value. This will generally result in a map with lower polygon counts (and better " + "in-game performance). However, this feature should NOT be used for large terrain " + "surfaces in Q3", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "z00")), + "Enter the height of the surface at the lower left corner. This value will likely " + "be modified unless \"Linear Borders\" is checked.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "z01")), + "Enter the height of the surface at the upper left corner. This value will likely " + "be modified unless \"Linear Borders\" is checked.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "z10")), + "Enter the height of the surface at the lower right corner. This value will likely " + "be modified unless \"Linear Borders\" is checked.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "z11")), + "Enter the height of the surface at the upper right corner. This value will likely " + "be modified unless \"Linear Borders\" is checked.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "linearborder")), + "Restrict the edges of the surface to a straight line. This will help match up " + "brush edges if you drop this surface into another map.", + ""); + // Bitmap tab + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "bmp_file")), + "Type the name of an 8-bit bitmap image file, or click Browse to select an image " + "from a list of those available on your system.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "bmp_file_browse")), + "Select a bitmap image file from a list of those available on your system.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "bmp_reload")), + "Reload the selected bitmap file after making changes in an external image editor.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "bmp_black")), + "Enter the value corresponding to color index 0 in the bitmap file. For gray scale " + "images, color 0 is normally black.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "bmp_white")), + "Enter the value corresponding to color index 255 in the bitmap file. For gray scale " + "images, color 255 is normally white.", + ""); + // Fixpoints tab + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "fix_value")), + "Enter a value for the selected vertex. This value will not be adjusted when applying " + "a waveform or roughness to the surface. Unlock this vertex (so that it will be " + "adjusted normally) by clicking \"Free\". This vertex will influence vertices within " + "the \"Range affected\" of this vertex.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "fix_range")), + "Enter the range away from the selected vertex that other vertices will be affected. " + "Use 0 if you don't want other vertices to be influenced by the currently selected " + "one. Note: this box is disabled if you've chosen the fractal generator, as it uses " + "a completely different method for determining values.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "fix_rate")), + "Enter a rate of change for the surface affected by the fixed value. 0 gives a smooth " + "sinusoidal curve, values less than 0 give progressively sharper spikes, and values " + "greater than 0 take on a square shape. Values less than -30 or greater than 30 are " + "set to -30 and 30, respectively. Note that this entry will have no effect unless " + "you also specify a \"range affected\".", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "fix_free")), + "Click this to free (unlock the value of) the currently selected vertex.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "fix_freeall")), + "Click this to free (unlock the values of) all vertices.", + ""); + // Texture tab + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "texture1")), + "Enter the name of the texture or shader used for the surface faces.", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "texture2")), + "Enter the name of the texture or shader used for faces other than the surface. Under " + "normal circumstances this should be \"common/caulk\"", + ""); + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "texture3")), + "Enter the name of the texture or shader used for \"steep\" surface faces, where \"steep\" " + "is the angle specified below. If this entry is left blank or if the \"steep\" angle is 0, " + "all surface faces will use the texture specified by \"Surface\".", + ""); + + gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), + g_object_get_data(G_OBJECT(g_pWnd, "detail")), + "Check this box to use the detail content property on the generated brushes. Compile " + "times will be considerably shorter if the detail property is used, though the surface " + "will not block visibility at all. If you use the detail property, you should make sure " + "that \"common/caulk\" is used for the non-surface faces, or the polygon count will be " + "much higher than necessary.", + ""); } // ============================================================================= // create main dialog -GtkWidget* create_main_dialog(){ - GtkWidget *hbox2, *button, *notebook, *table2; - GtkWidget *check, *spin, *radio, *label, *entry, *scale; - ui::Adjustment adj; - GSList *group; - int i; - const char *games[] = { "Quake 2", "Half-Life", "SiN", "Heretic 2", "Kingpin", "Genesis3D", "Quake 3 Arena" }; - const char *waveforms[] = { "Alternating hill/valley", "Cylindrical left-to-right", "Cylindrical top-to-bottom", - "From bitmap", "Fractal" }; - const char *orientations[] = { "Ground surface", "Ceiling", "Wall facing 0", "Wall facing 90", - "Wall facing 180","Wall facing 270" }; - - auto dlg = g_pWnd = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( dlg, gszCaption ); - dlg.connect( "delete_event", G_CALLBACK( main_close ), NULL ); - // dlg.connect( "destroy", G_CALLBACK (gtk_widget_destroy), NULL); - gtk_window_set_transient_for( dlg, g_pRadiantWnd ); - - auto hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - dlg.add(hbox); - gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 ); - - notebook = gtk_notebook_new(); - notebook.show(); - hbox.pack_start( notebook, TRUE, TRUE, 0 ); - notebook.connect( "switch_page", - G_CALLBACK( switch_page ), NULL ); - gtk_notebook_set_tab_pos( GTK_NOTEBOOK( notebook ), GTK_POS_TOP ); - g_object_set_data( G_OBJECT( dlg ), "notebook", notebook ); - - table = ui::Table( 2, 2, FALSE ); - table.show(); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); +GtkWidget *create_main_dialog() +{ + GtkWidget *hbox2, *button, *notebook, *table2; + GtkWidget *check, *spin, *radio, *label, *entry, *scale; + ui::Adjustment adj; + GSList *group; + int i; + const char *games[] = {"Quake 2", "Half-Life", "SiN", "Heretic 2", "Kingpin", "Genesis3D", "Quake 3 Arena"}; + const char *waveforms[] = {"Alternating hill/valley", "Cylindrical left-to-right", "Cylindrical top-to-bottom", + "From bitmap", "Fractal"}; + const char *orientations[] = {"Ground surface", "Ceiling", "Wall facing 0", "Wall facing 90", + "Wall facing 180", "Wall facing 270"}; + + auto dlg = g_pWnd = ui::Window(ui::window_type::TOP); + gtk_window_set_title(dlg, gszCaption); + dlg.connect("delete_event", G_CALLBACK(main_close), NULL); + // dlg.connect( "destroy", G_CALLBACK (gtk_widget_destroy), NULL); + gtk_window_set_transient_for(dlg, g_pRadiantWnd); + + auto hbox = ui::HBox(FALSE, 5); + hbox.show(); + dlg.add(hbox); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + + notebook = gtk_notebook_new(); + notebook.show(); + hbox.pack_start(notebook, TRUE, TRUE, 0); + notebook.connect("switch_page", + G_CALLBACK(switch_page), NULL); + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP); + g_object_set_data(G_OBJECT(dlg), "notebook", notebook); + + table = ui::Table(2, 2, FALSE); + table.show(); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "General" ); - label.show(); - gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), table, label ); - - auto frame = ui::Frame( "Game" ); - frame.show(); - table.attach(frame, {0, 1, 0, 1}); - - auto vbox = ui::VBox( TRUE, 5 ); - vbox.show(); - frame.add(vbox); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - for ( i = 0, group = NULL; i < NUMGAMES; i++ ) - { - radio = gtk_radio_button_new_with_label( group, games[i] ); - radio.show(); - vbox.pack_start( radio, TRUE, TRUE, 0 ); - group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radio ) ); - game_radios[i] = radio; - radio.connect( "toggled", G_CALLBACK( general_game ), GINT_TO_POINTER( i ) ); - } - - frame = ui::Frame( "Waveform" ); - frame.show(); - table.attach(frame, {1, 2, 0, 1}); - - vbox = ui::VBox( TRUE, 5 ); - vbox.show(); - frame.add(vbox); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - for ( i = 0, group = NULL; i < 5; i++ ) - { - radio = gtk_radio_button_new_with_label( group, waveforms[i] ); - radio.show(); - vbox.pack_start( radio, TRUE, TRUE, 0 ); - group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radio ) ); - wave_radios[i] = radio; - radio.connect( "toggled", G_CALLBACK( general_wave ), GINT_TO_POINTER( i ) ); - } - - frame = ui::Frame( "Orientation" ); - frame.show(); - table.attach(frame, {0, 1, 1, 2}); - - vbox = ui::VBox( TRUE, 5 ); - vbox.show(); - frame.add(vbox); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - for ( i = 0, group = NULL; i < 6; i++ ) - { - radio = gtk_radio_button_new_with_label( group, orientations[i] ); - radio.show(); - vbox.pack_start( radio, TRUE, TRUE, 0 ); - group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radio ) ); - plane_radios[i] = radio; - radio.connect( "toggled", G_CALLBACK( general_plane ), GINT_TO_POINTER( i ) ); - } - - table2 = ui::Table( 4, 2, FALSE ); - table2.show(); + label = ui::Label("General"); + label.show(); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), table, label); + + auto frame = ui::Frame("Game"); + frame.show(); + table.attach(frame, {0, 1, 0, 1}); + + auto vbox = ui::VBox(TRUE, 5); + vbox.show(); + frame.add(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + for (i = 0, group = NULL; i < NUMGAMES; i++) { + radio = gtk_radio_button_new_with_label(group, games[i]); + radio.show(); + vbox.pack_start(radio, TRUE, TRUE, 0); + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); + game_radios[i] = radio; + radio.connect("toggled", G_CALLBACK(general_game), GINT_TO_POINTER(i)); + } + + frame = ui::Frame("Waveform"); + frame.show(); + table.attach(frame, {1, 2, 0, 1}); + + vbox = ui::VBox(TRUE, 5); + vbox.show(); + frame.add(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + for (i = 0, group = NULL; i < 5; i++) { + radio = gtk_radio_button_new_with_label(group, waveforms[i]); + radio.show(); + vbox.pack_start(radio, TRUE, TRUE, 0); + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); + wave_radios[i] = radio; + radio.connect("toggled", G_CALLBACK(general_wave), GINT_TO_POINTER(i)); + } + + frame = ui::Frame("Orientation"); + frame.show(); + table.attach(frame, {0, 1, 1, 2}); + + vbox = ui::VBox(TRUE, 5); + vbox.show(); + frame.add(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + for (i = 0, group = NULL; i < 6; i++) { + radio = gtk_radio_button_new_with_label(group, orientations[i]); + radio.show(); + vbox.pack_start(radio, TRUE, TRUE, 0); + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); + plane_radios[i] = radio; + radio.connect("toggled", G_CALLBACK(general_plane), GINT_TO_POINTER(i)); + } + + table2 = ui::Table(4, 2, FALSE); + table2.show(); gtk_table_set_row_spacings(table2, 5); gtk_table_set_col_spacings(table2, 5); - table.attach(table2, {1, 2, 1, 2}); - - label = ui::Label( "Wavelength:" ); - label.show(); - table2.attach(label, {0, 1, 0, 1}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT ); - - label = ui::Label( "Max. amplitude:" ); - label.show(); - table2.attach(label, {0, 1, 1, 2}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT ); - - label = ui::Label( "Roughness:" ); - label.show(); + table.attach(table2, {1, 2, 1, 2}); + + label = ui::Label("Wavelength:"); + label.show(); + table2.attach(label, {0, 1, 0, 1}); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); + + label = ui::Label("Max. amplitude:"); + label.show(); + table2.attach(label, {0, 1, 1, 2}); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); + + label = ui::Label("Roughness:"); + label.show(); table2.attach(label, {0, 1, 2, 3}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT ); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); - label = ui::Label( "Random seed:" ); - label.show(); + label = ui::Label("Random seed:"); + label.show(); table2.attach(label, {0, 1, 3, 4}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT ); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); - entry = ui::Entry(); - entry.show(); + entry = ui::Entry(); + entry.show(); table2.attach(entry, {1, 2, 0, 1}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "wavelength", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &WaveLength ); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "wavelength", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &WaveLength); - entry = ui::Entry(); - entry.show(); + entry = ui::Entry(); + entry.show(); table2.attach(entry, {1, 2, 1, 2}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "amplitude", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Amplitude ); - - entry = ui::Entry(); - entry.show(); - table2.attach(entry, {1, 2, 2, 3}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "roughness", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Roughness ); - - adj = ui::Adjustment( 1, 1, 32767, 1, 10, 0 ); - adj.connect( "value_changed", G_CALLBACK( general_random ), NULL ); - spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); - table2.attach(spin, {1, 2, 3, 4}); - spin.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "random", spin ); - - vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - label = ui::Label( "Extents" ); - label.show(); - gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), vbox, label ); - - hbox2 = ui::HBox( FALSE, 5 ); - hbox2.show(); - vbox.pack_start( hbox2, FALSE, TRUE, 0 ); - - frame = ui::Frame( "Extents" ); - frame.show(); - hbox2.pack_start( frame, TRUE, TRUE, 0 ); - - auto table = ui::Table( 3, 4, FALSE ); - table.show(); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); - frame.add(table); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "amplitude", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Amplitude); + + entry = ui::Entry(); + entry.show(); + table2.attach(entry, {1, 2, 2, 3}); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "roughness", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Roughness); + + adj = ui::Adjustment(1, 1, 32767, 1, 10, 0); + adj.connect("value_changed", G_CALLBACK(general_random), NULL); + spin = ui::SpinButton(adj, 1, 0); + spin.show(); + table2.attach(spin, {1, 2, 3, 4}); + spin.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "random", spin); + + vbox = ui::VBox(FALSE, 5); + vbox.show(); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + label = ui::Label("Extents"); + label.show(); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); + + hbox2 = ui::HBox(FALSE, 5); + hbox2.show(); + vbox.pack_start(hbox2, FALSE, TRUE, 0); + + frame = ui::Frame("Extents"); + frame.show(); + hbox2.pack_start(frame, TRUE, TRUE, 0); + + auto table = ui::Table(3, 4, FALSE); + table.show(); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + frame.add(table); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "X:" ); - label.show(); - table.attach( label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "hmin_text", label ); - - label = ui::Label( "X:" ); - label.show(); - table.attach(label, {2, 3, 1, 2}, {GTK_FILL, GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "hmax_text", label ); - - label = ui::Label( "Y:" ); - label.show(); - table.attach(label, {0, 1, 2, 3}, {GTK_FILL, GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "vmin_text", label ); - - label = ui::Label( "Y:" ); - label.show(); - table.attach(label, {2, 3, 2, 3}, {GTK_FILL, GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "vmax_text", label ); - - label = ui::Label( "Lower-left" ); - label.show(); - table.attach(label, {1, 2, 0, 1}, {GTK_FILL, GTK_FILL}); - - label = ui::Label( "Upper-right" ); - label.show(); - table.attach(label, {3, 4, 0, 1},, {GTK_FILL, GTK_FILL}); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 1, 2}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "hmin", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Hll ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {3, 4, 1, 2}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "hmax", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Hur ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 2, 3}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "vmin", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Vll ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {3, 4, 2, 3}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "vmax", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Vur ); - - frame = ui::Frame( "Divisions" ); - frame.show(); - hbox2.pack_start( frame, TRUE, TRUE, 0 ); - - table = ui::Table( 2, 2, FALSE ); - table.show(); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); - frame.add(table); + label = ui::Label("X:"); + label.show(); + table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "hmin_text", label); + + label = ui::Label("X:"); + label.show(); + table.attach(label, {2, 3, 1, 2}, {GTK_FILL, GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "hmax_text", label); + + label = ui::Label("Y:"); + label.show(); + table.attach(label, {0, 1, 2, 3}, {GTK_FILL, GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "vmin_text", label); + + label = ui::Label("Y:"); + label.show(); + table.attach(label, {2, 3, 2, 3}, {GTK_FILL, GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "vmax_text", label); + + label = ui::Label("Lower-left"); + label.show(); + table.attach(label, {1, 2, 0, 1}, {GTK_FILL, GTK_FILL}); + + label = ui::Label("Upper-right"); + label.show(); + table.attach(label, {3, 4, 0, 1}, , {GTK_FILL, GTK_FILL}); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 1, 2}); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "hmin", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Hll); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {3, 4, 1, 2}); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "hmax", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Hur); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 2, 3}); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "vmin", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Vll); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {3, 4, 2, 3}); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "vmax", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Vur); + + frame = ui::Frame("Divisions"); + frame.show(); + hbox2.pack_start(frame, TRUE, TRUE, 0); + + table = ui::Table(2, 2, FALSE); + table.show(); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + frame.add(table); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "X:" ); - label.show(); - table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_EXPAND | GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "nh_text", label ); - - label = ui::Label( "Y:" ); - label.show(); - table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_EXPAND | GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "nv_text", label ); - - adj = ui::Adjustment( 8, 1, MAX_ROWS, 1, 10, 0 ); - adj.connect( "value_changed", G_CALLBACK( extents_nhnv_spin ), &NH ); - spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); - table.attach(spin, {1, 2, 0, 1}); - spin.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "nh", spin ); - - adj = ui::Adjustment( 8, 1, MAX_ROWS, 1, 10, 0 ); - adj.connect( "value_changed", G_CALLBACK( extents_nhnv_spin ), &NV ); - spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); - table.attach(spin, {1, 2, 1, 2}); - spin.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "nv", spin ); - - check = ui::CheckButton( "Use Bezier patches" ); - check.show(); - vbox.pack_start( check, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "use_patches", check ); - check.connect( "toggled", G_CALLBACK( extents_use_patches ), NULL ); - - // ^Fishman - Snap to grid, replaced scroll bar with a texbox. - label = ui::Label( "Snap to grid:" ); - label.show(); - vbox.pack_start( label, FALSE, TRUE, 0 ); - gtk_object_set_data( GTK_OBJECT( dlg ), "snap_text", label ); - - adj = ui::Adjustment( 8, 0, 256, 1, 10, 0 ); - adj.connect( "value_changed", G_CALLBACK( extents_snaptogrid_spin ), &SP ); - spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); - vbox.pack_start( spin, FALSE, TRUE, 0 ); - spin.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "sp", spin ); - // ^Fishman - End of Snap to grid code. - - hbox2 = ui::HBox( FALSE, 5 ); - hbox2.show(); - vbox.pack_start( hbox2, FALSE, TRUE, 10 ); - - label = ui::Label( "Decimate:" ); - label.show(); - hbox2.pack_start( label, FALSE, TRUE, 0 ); - - adj = ui::Adjustment( 0, 0, 110, 1, 10, 0 ); - adj.connect( "value_changed", G_CALLBACK( extents_decimate ), NULL ); - g_object_set_data( G_OBJECT( dlg ), "decimate_adj", adj ); - scale = ui::HScale( adj ); - scale.show(); - hbox2.pack_start( scale, TRUE, TRUE, 0 ); - gtk_scale_set_value_pos( GTK_SCALE( scale ), GTK_POS_RIGHT ); - gtk_scale_set_digits( GTK_SCALE( scale ), 0 ); - g_object_set_data( G_OBJECT( dlg ), "decimate", scale ); - - frame = ui::Frame( "Corner values" ); - frame.show(); - vbox.pack_start( frame, FALSE, TRUE, 0 ); - - table = ui::Table( 3, 4, FALSE ); - table.show(); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); - frame.add(table); + label = ui::Label("X:"); + label.show(); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_EXPAND | GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "nh_text", label); + + label = ui::Label("Y:"); + label.show(); + table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_EXPAND | GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "nv_text", label); + + adj = ui::Adjustment(8, 1, MAX_ROWS, 1, 10, 0); + adj.connect("value_changed", G_CALLBACK(extents_nhnv_spin), &NH); + spin = ui::SpinButton(adj, 1, 0); + spin.show(); + table.attach(spin, {1, 2, 0, 1}); + spin.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "nh", spin); + + adj = ui::Adjustment(8, 1, MAX_ROWS, 1, 10, 0); + adj.connect("value_changed", G_CALLBACK(extents_nhnv_spin), &NV); + spin = ui::SpinButton(adj, 1, 0); + spin.show(); + table.attach(spin, {1, 2, 1, 2}); + spin.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "nv", spin); + + check = ui::CheckButton("Use Bezier patches"); + check.show(); + vbox.pack_start(check, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "use_patches", check); + check.connect("toggled", G_CALLBACK(extents_use_patches), NULL); + + // ^Fishman - Snap to grid, replaced scroll bar with a texbox. + label = ui::Label("Snap to grid:"); + label.show(); + vbox.pack_start(label, FALSE, TRUE, 0); + gtk_object_set_data(GTK_OBJECT(dlg), "snap_text", label); + + adj = ui::Adjustment(8, 0, 256, 1, 10, 0); + adj.connect("value_changed", G_CALLBACK(extents_snaptogrid_spin), &SP); + spin = ui::SpinButton(adj, 1, 0); + spin.show(); + vbox.pack_start(spin, FALSE, TRUE, 0); + spin.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "sp", spin); + // ^Fishman - End of Snap to grid code. + + hbox2 = ui::HBox(FALSE, 5); + hbox2.show(); + vbox.pack_start(hbox2, FALSE, TRUE, 10); + + label = ui::Label("Decimate:"); + label.show(); + hbox2.pack_start(label, FALSE, TRUE, 0); + + adj = ui::Adjustment(0, 0, 110, 1, 10, 0); + adj.connect("value_changed", G_CALLBACK(extents_decimate), NULL); + g_object_set_data(G_OBJECT(dlg), "decimate_adj", adj); + scale = ui::HScale(adj); + scale.show(); + hbox2.pack_start(scale, TRUE, TRUE, 0); + gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_RIGHT); + gtk_scale_set_digits(GTK_SCALE(scale), 0); + g_object_set_data(G_OBJECT(dlg), "decimate", scale); + + frame = ui::Frame("Corner values"); + frame.show(); + vbox.pack_start(frame, FALSE, TRUE, 0); + + table = ui::Table(3, 4, FALSE); + table.show(); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + frame.add(table); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "Upper-left:" ); - label.show(); - table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL}); - - label = ui::Label( "Lower-left:" ); - label.show(); - table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL}); - - label = ui::Label( "Upper-right:" ); - label.show(); - table.attach(label, {2, 3, 0, 1}, {GTK_FILL, GTK_FILL}); - - label = ui::Label( "Lower-right:" ); - label.show(); - table.attach(label, {2, 3, 1, 2}, {GTK_FILL, GTK_FILL}); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 0, 1}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "z01", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Z01 ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 1, 2}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "z00", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Z00 ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {3, 4, 0, 1}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "z11", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Z11 ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {3, 4, 1, 2}); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "z10", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Z10 ); - - check = ui::CheckButton( "Linear borders" ); - check.show(); - table.attach(check, {0, 4, 2, 3}); - g_object_set_data( G_OBJECT( dlg ), "linearborder", check ); - check.connect( "toggled", G_CALLBACK( extents_linearborder ), NULL ); - - vbox = ui::VBox( FALSE, 10 ); - vbox.show(); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - label = ui::Label( "Bitmap" ); - label.show(); - gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), vbox, label ); - - label = ui::Label( "" ); - label.show(); - vbox.pack_start( label, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "bmp_note", label ); - - table = ui::Table( 2, 2, FALSE ); - table.show(); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); - vbox.pack_start( table, FALSE, TRUE, 0 ); + label = ui::Label("Upper-left:"); + label.show(); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL}); + + label = ui::Label("Lower-left:"); + label.show(); + table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL}); + + label = ui::Label("Upper-right:"); + label.show(); + table.attach(label, {2, 3, 0, 1}, {GTK_FILL, GTK_FILL}); + + label = ui::Label("Lower-right:"); + label.show(); + table.attach(label, {2, 3, 1, 2}, {GTK_FILL, GTK_FILL}); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 0, 1}); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "z01", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Z01); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 1, 2}); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "z00", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Z00); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {3, 4, 0, 1}); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "z11", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Z11); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {3, 4, 1, 2}); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "z10", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &Z10); + + check = ui::CheckButton("Linear borders"); + check.show(); + table.attach(check, {0, 4, 2, 3}); + g_object_set_data(G_OBJECT(dlg), "linearborder", check); + check.connect("toggled", G_CALLBACK(extents_linearborder), NULL); + + vbox = ui::VBox(FALSE, 10); + vbox.show(); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + label = ui::Label("Bitmap"); + label.show(); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); + + label = ui::Label(""); + label.show(); + vbox.pack_start(label, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "bmp_note", label); + + table = ui::Table(2, 2, FALSE); + table.show(); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + vbox.pack_start(table, FALSE, TRUE, 0); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "Filename:" ); - label.show(); - table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "bmp_text1", label ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "bmp_file", entry ); - entry.connect( "focus_out_event", G_CALLBACK( bitmap_file_entryfocusout ), NULL ); - - hbox2 = ui::HBox( TRUE, 5 ); - hbox2.show(); - table.attach(hbox2, {1, 2, 1, 2}, {0, GTK_EXPAND | GTK_FILL}); - - button = ui::Button( "Browse..." ); - button.show(); - hbox2.pack_start( button, FALSE, FALSE, 0 ); - button.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "bmp_file_browse", button ); - button.connect( "clicked", G_CALLBACK( bitmap_browse ), NULL ); - - button = ui::Button( "Reload" ); - button.show(); - hbox2.pack_start( button, FALSE, FALSE, 0 ); - button.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "bmp_reload", button ); - button.connect( "clicked", G_CALLBACK( bitmap_reload ), NULL ); - - table = ui::Table( 2, 2, TRUE ); - table.show(); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); - vbox.pack_start( table, FALSE, TRUE, 0 ); + label = ui::Label("Filename:"); + label.show(); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "bmp_text1", label); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "bmp_file", entry); + entry.connect("focus_out_event", G_CALLBACK(bitmap_file_entryfocusout), NULL); + + hbox2 = ui::HBox(TRUE, 5); + hbox2.show(); + table.attach(hbox2, {1, 2, 1, 2}, {0, GTK_EXPAND | GTK_FILL}); + + button = ui::Button("Browse..."); + button.show(); + hbox2.pack_start(button, FALSE, FALSE, 0); + button.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "bmp_file_browse", button); + button.connect("clicked", G_CALLBACK(bitmap_browse), NULL); + + button = ui::Button("Reload"); + button.show(); + hbox2.pack_start(button, FALSE, FALSE, 0); + button.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "bmp_reload", button); + button.connect("clicked", G_CALLBACK(bitmap_reload), NULL); + + table = ui::Table(2, 2, TRUE); + table.show(); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + vbox.pack_start(table, FALSE, TRUE, 0); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "Map color 0 to:" ); - label.show(); - table.attach(label, {0, 1, 0, 1}, {GTK_FILL | GTK_EXPAND, GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "bmp_text2", label ); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT ); - - label = ui::Label( "Map color 255 to:" ); - label.show(); - table.attach(label, {0, 1, 1, 2}, {GTK_FILL | GTK_EXPAND, GTK_FILL}); - g_object_set_data( G_OBJECT( dlg ), "bmp_text3", label ); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT ); - - hbox2 = ui::HBox( FALSE, 5 ); - hbox2.show(); - table.attach(hbox2, {1, 2, 0, 1}); - - entry = ui::Entry(); - entry.show(); - hbox2.pack_start( entry, FALSE, FALSE, 0 ); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "bmp_black", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &gbmp.black_value ); - - hbox2 = ui::HBox( FALSE, 5 ); - hbox2.show(); - table.attach(hbox2, {1, 2, 1, 2}); - - entry = ui::Entry(); - entry.show(); - hbox2.pack_start( entry, FALSE, FALSE, 0 ); - entry.dimensions( 50, -1 ); - g_object_set_data( G_OBJECT( dlg ), "bmp_white", entry ); - entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &gbmp.white_value ); - - vbox = ui::VBox( FALSE, 10 ); - vbox.show(); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - label = ui::Label( "Fix Points" ); - label.show(); - gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), vbox, label ); - - label = ui::Label( "Click on a vertex in the lower half of the preview window,\n" - "then use the arrow keys or text box to assign a value.\n" - "Use Ctrl+Click to select multiple vertices/toggle a\n" - "selection. Use Shift+Click to select a range of vertices.\n\n" - "Click \"Free\" to unlock a vertex. Vertices within \"Range\n" - "affected\" will be influenced by this vertex." ); - label.show(); - vbox.pack_start( label, FALSE, TRUE, 0 ); - - table = ui::Table( 3, 3, FALSE ); - table.show(); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); - vbox.pack_start( table, FALSE, TRUE, 0 ); + label = ui::Label("Map color 0 to:"); + label.show(); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL | GTK_EXPAND, GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "bmp_text2", label); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); + + label = ui::Label("Map color 255 to:"); + label.show(); + table.attach(label, {0, 1, 1, 2}, {GTK_FILL | GTK_EXPAND, GTK_FILL}); + g_object_set_data(G_OBJECT(dlg), "bmp_text3", label); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); + + hbox2 = ui::HBox(FALSE, 5); + hbox2.show(); + table.attach(hbox2, {1, 2, 0, 1}); + + entry = ui::Entry(); + entry.show(); + hbox2.pack_start(entry, FALSE, FALSE, 0); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "bmp_black", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &gbmp.black_value); + + hbox2 = ui::HBox(FALSE, 5); + hbox2.show(); + table.attach(hbox2, {1, 2, 1, 2}); + + entry = ui::Entry(); + entry.show(); + hbox2.pack_start(entry, FALSE, FALSE, 0); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(dlg), "bmp_white", entry); + entry.connect("focus_out_event", G_CALLBACK(doublevariable_entryfocusout), &gbmp.white_value); + + vbox = ui::VBox(FALSE, 10); + vbox.show(); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + label = ui::Label("Fix Points"); + label.show(); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); + + label = ui::Label("Click on a vertex in the lower half of the preview window,\n" + "then use the arrow keys or text box to assign a value.\n" + "Use Ctrl+Click to select multiple vertices/toggle a\n" + "selection. Use Shift+Click to select a range of vertices.\n\n" + "Click \"Free\" to unlock a vertex. Vertices within \"Range\n" + "affected\" will be influenced by this vertex."); + label.show(); + vbox.pack_start(label, FALSE, TRUE, 0); + + table = ui::Table(3, 3, FALSE); + table.show(); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + vbox.pack_start(table, FALSE, TRUE, 0); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "Value:" ); - label.show(); - table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - g_object_set_data( G_OBJECT( dlg ), "fix_value_text", label ); - - label = ui::Label( "Range affected:" ); - label.show(); - table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - g_object_set_data( G_OBJECT( dlg ), "fix_range_text", label ); - - label = ui::Label( "Rate of change:" ); - label.show(); - table.attach(label, {0, 1, 2, 3}, {GTK_FILL, GTK_FILL}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - g_object_set_data( G_OBJECT( dlg ), "fix_rate_text", label ); - - adj = ui::Adjustment( 0, -65536, 65536, 1, 16, 0 ); - adj.connect( "value_changed", G_CALLBACK( fix_value_changed ), NULL ); - spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); - table.attach(spin, {1, 2, 0, 1}, {GTK_EXPAND, GTK_EXPAND}); - spin.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "fix_value", spin ); - spin.connect( "focus_out_event", G_CALLBACK( fix_value_entryfocusout ), NULL ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND, GTK_FILL}); - entry.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "fix_range", entry ); - entry.connect( "focus_out_event", G_CALLBACK( fix_range_entryfocusout ), NULL ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 2, 3}, {GTK_EXPAND, GTK_FILL}); - entry.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "fix_rate", entry ); - entry.connect( "focus_out_event", G_CALLBACK( fix_rate_entryfocusout ), NULL ); - - button = ui::Button( "Free" ); - button.show(); - table.attach(button, {2, 3, 0, 1}, {GTK_EXPAND, GTK_FILL}); - button.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "fix_free", button ); - button.connect( "clicked", G_CALLBACK( fix_free ), NULL ); - - button = ui::Button( "Free All" ); - button.show(); - table.attach(button, {2, 3, 1, 2}, {GTK_EXPAND, GTK_FILL}); - button.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "fix_freeall", button ); - button.connect( "clicked", G_CALLBACK( fix_freeall ), NULL ); - - vbox = ui::VBox( FALSE, 10 ); - vbox.show(); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - label = ui::Label( "Texture" ); - label.show(); - gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), vbox, label ); - - // ^Fishman - Modified to add more labels and textboxes. - table = ui::Table( 5, 2, FALSE ); - table.show(); - vbox.pack_start( table, FALSE, TRUE, 0 ); + label = ui::Label("Value:"); + label.show(); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL}); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + g_object_set_data(G_OBJECT(dlg), "fix_value_text", label); + + label = ui::Label("Range affected:"); + label.show(); + table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL}); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + g_object_set_data(G_OBJECT(dlg), "fix_range_text", label); + + label = ui::Label("Rate of change:"); + label.show(); + table.attach(label, {0, 1, 2, 3}, {GTK_FILL, GTK_FILL}); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + g_object_set_data(G_OBJECT(dlg), "fix_rate_text", label); + + adj = ui::Adjustment(0, -65536, 65536, 1, 16, 0); + adj.connect("value_changed", G_CALLBACK(fix_value_changed), NULL); + spin = ui::SpinButton(adj, 1, 0); + spin.show(); + table.attach(spin, {1, 2, 0, 1}, {GTK_EXPAND, GTK_EXPAND}); + spin.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "fix_value", spin); + spin.connect("focus_out_event", G_CALLBACK(fix_value_entryfocusout), NULL); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND, GTK_FILL}); + entry.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "fix_range", entry); + entry.connect("focus_out_event", G_CALLBACK(fix_range_entryfocusout), NULL); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 2, 3}, {GTK_EXPAND, GTK_FILL}); + entry.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "fix_rate", entry); + entry.connect("focus_out_event", G_CALLBACK(fix_rate_entryfocusout), NULL); + + button = ui::Button("Free"); + button.show(); + table.attach(button, {2, 3, 0, 1}, {GTK_EXPAND, GTK_FILL}); + button.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "fix_free", button); + button.connect("clicked", G_CALLBACK(fix_free), NULL); + + button = ui::Button("Free All"); + button.show(); + table.attach(button, {2, 3, 1, 2}, {GTK_EXPAND, GTK_FILL}); + button.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "fix_freeall", button); + button.connect("clicked", G_CALLBACK(fix_freeall), NULL); + + vbox = ui::VBox(FALSE, 10); + vbox.show(); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + label = ui::Label("Texture"); + label.show(); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); + + // ^Fishman - Modified to add more labels and textboxes. + table = ui::Table(5, 2, FALSE); + table.show(); + vbox.pack_start(table, FALSE, TRUE, 0); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "Surface:" ); - label.show(); - table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - - label = ui::Label( "Other:" ); - label.show(); - table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - - label = ui::Label( "Steep:" ); - label.show(); - table.attach(label, {0, 1, 2, 3}, {GTK_FILL, GTK_FILL}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - entry.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "texture1", entry ); - entry.connect( "focus_out_event", G_CALLBACK( texture_entryfocusout ), GINT_TO_POINTER( 0 ) ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - entry.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "texture2", entry ); - entry.connect( "focus_out_event", G_CALLBACK( texture_entryfocusout ), GINT_TO_POINTER( 1 ) ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 2, 3}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - entry.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "texture3", entry ); - - hbox2 = ui::HBox( FALSE, 5 ); - hbox2.show(); - vbox.pack_start( hbox2, FALSE, TRUE, 0 ); - - label = ui::Label( "\"Steep\" angle:" ); - label.show(); - hbox2.pack_start( label, FALSE, TRUE, 0 ); - - adj = ui::Adjustment( 60, 0, 90, 1, 10, 0 ); - spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); - hbox2.pack_start( spin, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "tex_slant", spin ); - - table = ui::Table( 2, 4, TRUE ); - table.show(); - vbox.pack_start( table, FALSE, TRUE, 0 ); + label = ui::Label("Surface:"); + label.show(); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL}); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + + label = ui::Label("Other:"); + label.show(); + table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL}); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + + label = ui::Label("Steep:"); + label.show(); + table.attach(label, {0, 1, 2, 3}, {GTK_FILL, GTK_FILL}); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + entry.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "texture1", entry); + entry.connect("focus_out_event", G_CALLBACK(texture_entryfocusout), GINT_TO_POINTER(0)); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + entry.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "texture2", entry); + entry.connect("focus_out_event", G_CALLBACK(texture_entryfocusout), GINT_TO_POINTER(1)); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 2, 3}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + entry.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "texture3", entry); + + hbox2 = ui::HBox(FALSE, 5); + hbox2.show(); + vbox.pack_start(hbox2, FALSE, TRUE, 0); + + label = ui::Label("\"Steep\" angle:"); + label.show(); + hbox2.pack_start(label, FALSE, TRUE, 0); + + adj = ui::Adjustment(60, 0, 90, 1, 10, 0); + spin = ui::SpinButton(adj, 1, 0); + spin.show(); + hbox2.pack_start(spin, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "tex_slant", spin); + + table = ui::Table(2, 4, TRUE); + table.show(); + vbox.pack_start(table, FALSE, TRUE, 0); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "Offset " ); - label.show(); - table.attach(label, {0, 2, 0, 1}, {GTK_FILL, GTK_FILL}); - - label = ui::Label( "Scale " ); - label.show(); - table.attach(label, {2, 4, 0, 1}, {GTK_FILL, GTK_FILL}); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - entry.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "texoffsetx", entry ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - entry.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "texoffsety", entry ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {2, 3, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - entry.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "texscalex", entry ); - - entry = ui::Entry(); - entry.show(); - table.attach(entry, {3, 4, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - entry.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "texscaley", entry ); - - - - check = ui::CheckButton( "Use detail brushes" ); - check.show(); - vbox.pack_start( check, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "detail", check ); - check.connect( "toggled", G_CALLBACK( texture_detail ), NULL ); - - check = ui::CheckButton( "Detail hint brushes" ); - check.show(); - vbox.pack_start( check, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "hint", check ); - check.connect( "toggled", G_CALLBACK( texture_hint ), NULL ); - - // ^Fishman - Add terrain key to func_group. - check = ui::CheckButton( "Add terrain key" ); - check.show(); - vbox.pack_start( check, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "terrain_ent", check ); - check.connect( "toggled", G_CALLBACK( texture_terrainent ), NULL ); - - vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - hbox.pack_start( vbox, FALSE, TRUE, 0 ); - - button = ui::Button( "OK" ); - button.show(); - vbox.pack_start( button, FALSE, TRUE, 0 ); - button.dimensions( 60, -1 ); - g_object_set_data( G_OBJECT( dlg ), "go", button ); - button.connect( "clicked", G_CALLBACK( main_go ), NULL ); - - label = ui::Label( "Settings:" ); - label.show(); - vbox.pack_start( label, FALSE, TRUE, 0 ); - - button = ui::Button( "Open..." ); - button.show(); - vbox.pack_start( button, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "open", button ); - button.connect( "clicked", G_CALLBACK( main_open ), NULL ); - - button = ui::Button( "Save as..." ); - button.show(); - vbox.pack_start( button, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "save", button ); - button.connect( "clicked", G_CALLBACK( main_save ), NULL ); - - button = ui::Button( "Defaults" ); - button.show(); - vbox.pack_start( button, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "defaults", button ); - button.connect( "clicked", G_CALLBACK( main_defaults ), NULL ); - - button = ui::Button( "About..." ); - button.show(); - vbox.pack_start( button, FALSE, TRUE, 0 ); - button.connect( "clicked", G_CALLBACK( main_about ), NULL ); - - check = ui::CheckButton( "Preview" ); - check.show(); - vbox.pack_start( check, FALSE, TRUE, 0 ); - check.connect( "toggled", G_CALLBACK( main_preview ), NULL ); - g_object_set_data( G_OBJECT( dlg ), "main_preview", check ); - - // ^Fishman - Antializing for the preview window. - check = ui::CheckButton( "Antialised lines" ); - check.show(); - vbox.pack_start( check, FALSE, TRUE, 0 ); - g_object_set_data( G_OBJECT( dlg ), "main_antialiasing", check ); - check.connect( "toggled", G_CALLBACK( main_antialiasing ), NULL ); - - for ( i = 0; i < 5; i++ ) - SetDlgValues( i ); - - CreateViewWindow(); - - create_tooltips(); - - FirstPassComplete = 1; - - return dlg; + label = ui::Label("Offset "); + label.show(); + table.attach(label, {0, 2, 0, 1}, {GTK_FILL, GTK_FILL}); + + label = ui::Label("Scale "); + label.show(); + table.attach(label, {2, 4, 0, 1}, {GTK_FILL, GTK_FILL}); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + entry.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "texoffsetx", entry); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + entry.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "texoffsety", entry); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {2, 3, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + entry.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "texscalex", entry); + + entry = ui::Entry(); + entry.show(); + table.attach(entry, {3, 4, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); + entry.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "texscaley", entry); + + + check = ui::CheckButton("Use detail brushes"); + check.show(); + vbox.pack_start(check, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "detail", check); + check.connect("toggled", G_CALLBACK(texture_detail), NULL); + + check = ui::CheckButton("Detail hint brushes"); + check.show(); + vbox.pack_start(check, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "hint", check); + check.connect("toggled", G_CALLBACK(texture_hint), NULL); + + // ^Fishman - Add terrain key to func_group. + check = ui::CheckButton("Add terrain key"); + check.show(); + vbox.pack_start(check, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "terrain_ent", check); + check.connect("toggled", G_CALLBACK(texture_terrainent), NULL); + + vbox = ui::VBox(FALSE, 5); + vbox.show(); + hbox.pack_start(vbox, FALSE, TRUE, 0); + + button = ui::Button("OK"); + button.show(); + vbox.pack_start(button, FALSE, TRUE, 0); + button.dimensions(60, -1); + g_object_set_data(G_OBJECT(dlg), "go", button); + button.connect("clicked", G_CALLBACK(main_go), NULL); + + label = ui::Label("Settings:"); + label.show(); + vbox.pack_start(label, FALSE, TRUE, 0); + + button = ui::Button("Open..."); + button.show(); + vbox.pack_start(button, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "open", button); + button.connect("clicked", G_CALLBACK(main_open), NULL); + + button = ui::Button("Save as..."); + button.show(); + vbox.pack_start(button, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "save", button); + button.connect("clicked", G_CALLBACK(main_save), NULL); + + button = ui::Button("Defaults"); + button.show(); + vbox.pack_start(button, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "defaults", button); + button.connect("clicked", G_CALLBACK(main_defaults), NULL); + + button = ui::Button("About..."); + button.show(); + vbox.pack_start(button, FALSE, TRUE, 0); + button.connect("clicked", G_CALLBACK(main_about), NULL); + + check = ui::CheckButton("Preview"); + check.show(); + vbox.pack_start(check, FALSE, TRUE, 0); + check.connect("toggled", G_CALLBACK(main_preview), NULL); + g_object_set_data(G_OBJECT(dlg), "main_preview", check); + + // ^Fishman - Antializing for the preview window. + check = ui::CheckButton("Antialised lines"); + check.show(); + vbox.pack_start(check, FALSE, TRUE, 0); + g_object_set_data(G_OBJECT(dlg), "main_antialiasing", check); + check.connect("toggled", G_CALLBACK(main_antialiasing), NULL); + + for (i = 0; i < 5; i++) { + SetDlgValues(i); + } + + CreateViewWindow(); + + create_tooltips(); + + FirstPassComplete = 1; + + return dlg; } #if 0 -HWND hwndDisplay = (HWND)NULL; + HWND hwndDisplay = (HWND)NULL; HWND ghwndTab = (HWND)NULL; int iTab = 0; Rect rcTab; diff --git a/contrib/gtkgensurf/genmap.cpp b/contrib/gtkgensurf/genmap.cpp index a31bfbcb..ce55785e 100644 --- a/contrib/gtkgensurf/genmap.cpp +++ b/contrib/gtkgensurf/genmap.cpp @@ -22,10 +22,10 @@ #include #include "gensurf.h" -double xmin,xmax,ymin,ymax,zmin,zmax; +double xmin, xmax, ymin, ymax, zmin, zmax; double backface; extern double dh, dv; -FILE *fmap; +FILE *fmap; XYZ xyz[MAX_ROWS + 1][MAX_ROWS + 1]; int contents; int surface[3]; @@ -41,216 +41,191 @@ int surface[3]; #include "scenelib.h" -scene::Node* h_func_group; -scene::Node* h_worldspawn; +scene::Node *h_func_group; +scene::Node *h_worldspawn; //============================================================= // Hydra : snap-to-grid begin -double CalculateSnapValue( double value ){ - long snapvalue; - - // simple uncomplicated snapping, rounding both UP and DOWN to the nearest - // grid unit. - if ( SnapToGrid > 0 ) { - snapvalue = (int)value / SnapToGrid; - if ( (long)value % SnapToGrid < ( SnapToGrid / 2 ) ) { // Snap Downwards if less than halfway between to grid units - value = snapvalue * SnapToGrid; - } - else{ // Snap Upwards if more than halfway between to grid units - value = ( snapvalue + 1 ) * SnapToGrid; - } - } - return value; +double CalculateSnapValue(double value) +{ + long snapvalue; + + // simple uncomplicated snapping, rounding both UP and DOWN to the nearest + // grid unit. + if (SnapToGrid > 0) { + snapvalue = (int) value / SnapToGrid; + if ((long) value % SnapToGrid < (SnapToGrid / 2)) { // Snap Downwards if less than halfway between to grid units + value = snapvalue * SnapToGrid; + } else { // Snap Upwards if more than halfway between to grid units + value = (snapvalue + 1) * SnapToGrid; + } + } + return value; } // Hydra : snap-to-grid end //============================================================= -bool ValidSurface(){ - if ( WaveType == WAVE_BITMAP && !gbmp.colors ) { - return FALSE; - } - if ( NH < 1 ) { - return FALSE; - } - if ( NH > MAX_ROWS ) { - return FALSE; - } - if ( NV < 1 ) { - return FALSE; - } - if ( NV > MAX_ROWS ) { - return FALSE; - } - if ( Hll >= Hur ) { - return FALSE; - } - if ( Vll >= Vur ) { - return FALSE; - } - return TRUE; +bool ValidSurface() +{ + if (WaveType == WAVE_BITMAP && !gbmp.colors) { + return FALSE; + } + if (NH < 1) { + return FALSE; + } + if (NH > MAX_ROWS) { + return FALSE; + } + if (NV < 1) { + return FALSE; + } + if (NV > MAX_ROWS) { + return FALSE; + } + if (Hll >= Hur) { + return FALSE; + } + if (Vll >= Vur) { + return FALSE; + } + return TRUE; } //============================================================= -int MapPatches(){ - int NH_remain; - int NV_remain; - int NH_patch; - int NV_patch; - int BrushNum = 0; - int i, j, k1, k2, k3; - int i0, j0, ii; - char szOops[128]; - - dh = ( Hur - Hll ) / NH; - dv = ( Vur - Vll ) / NV; - - // Generate control points in pp array to give desired values currently - // in p array. - switch ( Plane ) - { - case PLANE_XY0: - case PLANE_XY1: - k1 = 0; - k2 = 1; - k3 = 2; - break; - case PLANE_XZ0: - case PLANE_XZ1: - k1 = 0; - k2 = 2; - k3 = 1; - break; - case PLANE_YZ0: - case PLANE_YZ1: - k1 = 1; - k2 = 2; - k3 = 0; - break; - } - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - xyz[i][j].pp[k1] = xyz[i][j].p[k1]; - xyz[i][j].pp[k2] = xyz[i][j].p[k2]; - } - } - for ( i = 0; i <= NH; i += 2 ) - { - for ( j = 0; j <= NV; j += 2 ) - xyz[i][j].pp[k3] = xyz[i][j].p[k3]; - } - for ( i = 1; i < NH; i += 2 ) - { - for ( j = 0; j <= NV; j += 2 ) - { - xyz[i][j].pp[k3] = ( 4 * xyz[i][j].p[k3] - xyz[i - 1][j].p[k3] - xyz[i + 1][j].p[k3] ) / 2; - } - } - for ( j = 1; j < NV; j += 2 ) - { - for ( i = 0; i <= NH; i += 2 ) - { - xyz[i][j].pp[k3] = ( 4 * xyz[i][j].p[k3] - xyz[i][j - 1].p[k3] - xyz[i][j + 1].p[k3] ) / 2; - } - } - for ( i = 1; i < NH; i += 2 ) - { - for ( j = 1; j < NV; j += 2 ) - { - xyz[i][j].pp[k3] = ( 16 * xyz[i][j].p[k3] - xyz[i - 1][j - 1].p[k3] - 2 * xyz[i][j - 1].p[k3] - - xyz[i + 1][j - 1].p[k3] - 2 * xyz[i - 1][j].p[k3] - 2 * xyz[i + 1][j].p[k3] - - xyz[i - 1][j + 1].p[k3] - 2 * xyz[i][j + 1].p[k3] - xyz[i + 1][j + 1].p[k3] ) / 4; - } - } - - NH_remain = NH + 1; - i0 = 0; - while ( NH_remain > 1 ) - { - if ( ( ( NH_remain - 1 ) % 14 ) == 0 ) { - NH_patch = 15; - } - else if ( ( ( NH_remain - 1 ) % 12 ) == 0 ) { - NH_patch = 13; - } - else if ( ( ( NH_remain - 1 ) % 10 ) == 0 ) { - NH_patch = 11; - } - else if ( ( ( NH_remain - 1 ) % 8 ) == 0 ) { - NH_patch = 9; - } - else if ( ( ( NH_remain - 1 ) % 6 ) == 0 ) { - NH_patch = 7; - } - else if ( ( ( NH_remain - 1 ) % 4 ) == 0 ) { - NH_patch = 5; - } - else if ( ( ( NH_remain - 1 ) % 2 ) == 0 ) { - NH_patch = 3; - } - else if ( NH_remain > 16 ) { - NH_patch = 7; - } - else if ( NH_remain > 4 ) { - NH_patch = 5; - } - else{ - NH_patch = 3; - } - while ( NH_patch > 3 && ( NH_patch - 1 ) * dh > 512 ) - NH_patch -= 2; - NH_remain -= ( NH_patch - 1 ); - if ( NH_remain < 0 ) { - sprintf( szOops,"Oops... screwed up with NH=%d",NH ); - g_FuncTable.m_pfnMessageBox( NULL,szOops,"Uh oh" ); - } - NV_remain = NV + 1; - j0 = 0; - while ( NV_remain > 1 ) - { - if ( ( ( NV_remain - 1 ) % 14 ) == 0 ) { - NV_patch = 15; - } - else if ( ( ( NV_remain - 1 ) % 12 ) == 0 ) { - NV_patch = 13; - } - else if ( ( ( NV_remain - 1 ) % 10 ) == 0 ) { - NV_patch = 11; - } - else if ( ( ( NV_remain - 1 ) % 8 ) == 0 ) { - NV_patch = 9; - } - else if ( ( ( NV_remain - 1 ) % 6 ) == 0 ) { - NV_patch = 7; - } - else if ( ( ( NV_remain - 1 ) % 4 ) == 0 ) { - NV_patch = 5; - } - else if ( ( ( NV_remain - 1 ) % 2 ) == 0 ) { - NV_patch = 3; - } - else if ( NV_remain > 16 ) { - NV_patch = 7; - } - else if ( NV_remain > 4 ) { - NV_patch = 5; - } - else{ - NV_patch = 3; - } - while ( NV_patch > 3 && ( NV_patch - 1 ) * dh > 512 ) - NV_patch -= 2; - NV_remain -= ( NV_patch - 1 ); - if ( NV_remain < 0 ) { - sprintf( szOops,"Oops... screwed up with NV=%d",NV ); - g_FuncTable.m_pfnMessageBox( NULL,szOops,"Uh oh" ); - } - - scene::Node* patch = MakePatch(); +int MapPatches() +{ + int NH_remain; + int NV_remain; + int NH_patch; + int NV_patch; + int BrushNum = 0; + int i, j, k1, k2, k3; + int i0, j0, ii; + char szOops[128]; + + dh = (Hur - Hll) / NH; + dv = (Vur - Vll) / NV; + + // Generate control points in pp array to give desired values currently + // in p array. + switch (Plane) { + case PLANE_XY0: + case PLANE_XY1: + k1 = 0; + k2 = 1; + k3 = 2; + break; + case PLANE_XZ0: + case PLANE_XZ1: + k1 = 0; + k2 = 2; + k3 = 1; + break; + case PLANE_YZ0: + case PLANE_YZ1: + k1 = 1; + k2 = 2; + k3 = 0; + break; + } + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + xyz[i][j].pp[k1] = xyz[i][j].p[k1]; + xyz[i][j].pp[k2] = xyz[i][j].p[k2]; + } + } + for (i = 0; i <= NH; i += 2) { + for (j = 0; j <= NV; j += 2) { + xyz[i][j].pp[k3] = xyz[i][j].p[k3]; + } + } + for (i = 1; i < NH; i += 2) { + for (j = 0; j <= NV; j += 2) { + xyz[i][j].pp[k3] = (4 * xyz[i][j].p[k3] - xyz[i - 1][j].p[k3] - xyz[i + 1][j].p[k3]) / 2; + } + } + for (j = 1; j < NV; j += 2) { + for (i = 0; i <= NH; i += 2) { + xyz[i][j].pp[k3] = (4 * xyz[i][j].p[k3] - xyz[i][j - 1].p[k3] - xyz[i][j + 1].p[k3]) / 2; + } + } + for (i = 1; i < NH; i += 2) { + for (j = 1; j < NV; j += 2) { + xyz[i][j].pp[k3] = (16 * xyz[i][j].p[k3] - xyz[i - 1][j - 1].p[k3] - 2 * xyz[i][j - 1].p[k3] + - xyz[i + 1][j - 1].p[k3] - 2 * xyz[i - 1][j].p[k3] - 2 * xyz[i + 1][j].p[k3] + - xyz[i - 1][j + 1].p[k3] - 2 * xyz[i][j + 1].p[k3] - xyz[i + 1][j + 1].p[k3]) / 4; + } + } + + NH_remain = NH + 1; + i0 = 0; + while (NH_remain > 1) { + if (((NH_remain - 1) % 14) == 0) { + NH_patch = 15; + } else if (((NH_remain - 1) % 12) == 0) { + NH_patch = 13; + } else if (((NH_remain - 1) % 10) == 0) { + NH_patch = 11; + } else if (((NH_remain - 1) % 8) == 0) { + NH_patch = 9; + } else if (((NH_remain - 1) % 6) == 0) { + NH_patch = 7; + } else if (((NH_remain - 1) % 4) == 0) { + NH_patch = 5; + } else if (((NH_remain - 1) % 2) == 0) { + NH_patch = 3; + } else if (NH_remain > 16) { + NH_patch = 7; + } else if (NH_remain > 4) { + NH_patch = 5; + } else { + NH_patch = 3; + } + while (NH_patch > 3 && (NH_patch - 1) * dh > 512) { + NH_patch -= 2; + } + NH_remain -= (NH_patch - 1); + if (NH_remain < 0) { + sprintf(szOops, "Oops... screwed up with NH=%d", NH); + g_FuncTable.m_pfnMessageBox(NULL, szOops, "Uh oh"); + } + NV_remain = NV + 1; + j0 = 0; + while (NV_remain > 1) { + if (((NV_remain - 1) % 14) == 0) { + NV_patch = 15; + } else if (((NV_remain - 1) % 12) == 0) { + NV_patch = 13; + } else if (((NV_remain - 1) % 10) == 0) { + NV_patch = 11; + } else if (((NV_remain - 1) % 8) == 0) { + NV_patch = 9; + } else if (((NV_remain - 1) % 6) == 0) { + NV_patch = 7; + } else if (((NV_remain - 1) % 4) == 0) { + NV_patch = 5; + } else if (((NV_remain - 1) % 2) == 0) { + NV_patch = 3; + } else if (NV_remain > 16) { + NV_patch = 7; + } else if (NV_remain > 4) { + NV_patch = 5; + } else { + NV_patch = 3; + } + while (NV_patch > 3 && (NV_patch - 1) * dh > 512) { + NV_patch -= 2; + } + NV_remain -= (NV_patch - 1); + if (NV_remain < 0) { + sprintf(szOops, "Oops... screwed up with NV=%d", NV); + g_FuncTable.m_pfnMessageBox(NULL, szOops, "Uh oh"); + } + + scene::Node *patch = MakePatch(); #if 0 - b->pPatch->setDims( NH_patch, NV_patch ); + b->pPatch->setDims( NH_patch, NV_patch ); for ( i = 0; i < NH_patch; i++ ) { switch ( Plane ) @@ -274,1379 +249,1299 @@ int MapPatches(){ } b->pPatch->UpdateCachedData(); #endif - BrushNum++; - j0 += NV_patch - 1; - } - i0 += NH_patch - 1; - } - return BrushNum; + BrushNum++; + j0 += NV_patch - 1; + } + i0 += NH_patch - 1; + } + return BrushNum; } //============================================================= -void MapBrushes(){ - char hint[128]; - char skip[128]; - char sidetext[64]; - char surftext[64]; - char surftext2[64]; - char surft[64]; - float Steep; - vec3_t PlaneNormal,SurfNormal; - vec3_t t[2]; - int i, j, k; - int surf; - bool CheckAngle; - BRUSH brush; - XYZ v[8]; - - strcpy( surftext,Texture[Game][0] ); - strcpy( sidetext,( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) ); - strcpy( surftext2,( strlen( Texture[Game][2] ) ? Texture[Game][2] : Texture[Game][0] ) ); - - // if surftext2 is identical to surftext, there's no need to - // check surface angle - if ( !g_strcasecmp( surftext,surftext2 ) ) { - CheckAngle = FALSE; - } - else - { - CheckAngle = TRUE; - Steep = (float)cos( (double)SlantAngle / 57.2957795 ); - switch ( Plane ) - { - case PLANE_XY0: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break; - case PLANE_XY1: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = -1.; break; - case PLANE_XZ0: PlaneNormal[0] = 0.; PlaneNormal[1] = 1.; PlaneNormal[2] = 1.; break; - case PLANE_XZ1: PlaneNormal[0] = 0.; PlaneNormal[1] = -1.; PlaneNormal[2] = 1.; break; - case PLANE_YZ0: PlaneNormal[0] = 1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break; - case PLANE_YZ1: PlaneNormal[0] = -1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break; - } - } - - OpenFuncGroup(); - - for ( i = 0; i < NH; i++ ) - { - for ( j = 0; j < NV; j++ ) - { - if ( ( i + j ) % 2 ) { - VectorCopy( xyz[i ][j ].p, v[0].p ); - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - VectorCopy( xyz[i + 1][j ].p, v[1].p ); - VectorCopy( xyz[i + 1][j + 1].p, v[2].p ); - break; - default: - VectorCopy( xyz[i + 1][j + 1].p, v[1].p ); - VectorCopy( xyz[i + 1][j ].p, v[2].p ); - } - } - else - { - VectorCopy( xyz[i ][j ].p, v[0].p ); - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - VectorCopy( xyz[i + 1][j ].p, v[1].p ); - VectorCopy( xyz[i ][j + 1].p, v[2].p ); - break; - default: - VectorCopy( xyz[i ][j + 1].p, v[1].p ); - VectorCopy( xyz[i + 1][j ].p, v[2].p ); - } - } - VectorCopy( v[0].p,v[3].p ); - VectorCopy( v[1].p,v[4].p ); - VectorCopy( v[2].p,v[5].p ); - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - v[0].p[1] = backface; - v[1].p[1] = backface; - v[2].p[1] = backface; - break; - case PLANE_YZ0: - case PLANE_YZ1: - v[3].p[0] = backface; - v[4].p[0] = backface; - v[5].p[0] = backface; - break; - default: - v[3].p[2] = backface; - v[4].p[2] = backface; - v[5].p[2] = backface; - } - - brush.Number = i * NV * 2 + j * 2; - brush.NumFaces = 5; - XYZtoV( &v[0],&brush.face[0].v[0] ); - XYZtoV( &v[3],&brush.face[0].v[1] ); - XYZtoV( &v[4],&brush.face[0].v[2] ); - strcpy( brush.face[0].texture, - ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) ); - brush.face[0].Shift[0] = (float)TexOffset[0]; - brush.face[0].Shift[1] = (float)TexOffset[1]; - brush.face[0].Rotate = 0.; - brush.face[0].Scale[0] = (float)TexScale[0]; - brush.face[0].Scale[1] = (float)TexScale[1]; - brush.face[0].Contents = contents; - brush.face[0].Surface = surface[1]; - brush.face[0].Value = 0; - - XYZtoV( &v[1],&brush.face[1].v[0] ); - XYZtoV( &v[4],&brush.face[1].v[1] ); - XYZtoV( &v[5],&brush.face[1].v[2] ); - strcpy( brush.face[1].texture, - ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) ); - brush.face[1].Shift[0] = (float)TexOffset[0]; - brush.face[1].Shift[1] = (float)TexOffset[1]; - brush.face[1].Rotate = 0.; - brush.face[1].Scale[0] = (float)TexScale[0]; - brush.face[1].Scale[1] = (float)TexScale[1]; - brush.face[1].Contents = contents; - brush.face[1].Surface = surface[1]; - brush.face[1].Value = 0; - - XYZtoV( &v[2],&brush.face[2].v[0] ); - XYZtoV( &v[5],&brush.face[2].v[1] ); - XYZtoV( &v[3],&brush.face[2].v[2] ); - strcpy( brush.face[2].texture, - ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) ); - brush.face[2].Shift[0] = (float)TexOffset[0]; - brush.face[2].Shift[1] = (float)TexOffset[1]; - brush.face[2].Rotate = 0.; - brush.face[2].Scale[0] = (float)TexScale[0]; - brush.face[2].Scale[1] = (float)TexScale[1]; - brush.face[2].Contents = contents; - brush.face[2].Surface = surface[1]; - brush.face[2].Value = 0; - - if ( CheckAngle && ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ) ) { - XYZVectorSubtract( v[4].p,v[3].p,t[0] ); - XYZVectorSubtract( v[5].p,v[4].p,t[1] ); - CrossProduct( t[0],t[1],SurfNormal ); - VectorNormalize( SurfNormal,SurfNormal ); - if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) { - strcpy( surft,surftext2 ); - surf = surface[2]; - } - else - { - strcpy( surft,surftext ); - surf = surface[0]; - } - } - else - { - strcpy( surft,surftext ); - surf = surface[0]; - } - - XYZtoV( &v[3],&brush.face[3].v[0] ); - XYZtoV( &v[5],&brush.face[3].v[1] ); - XYZtoV( &v[4],&brush.face[3].v[2] ); - strcpy( brush.face[3].texture, - ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext ) ); - brush.face[3].Shift[0] = (float)TexOffset[0]; - brush.face[3].Shift[1] = (float)TexOffset[1]; - brush.face[3].Rotate = 0.; - brush.face[3].Scale[0] = (float)TexScale[0]; - brush.face[3].Scale[1] = (float)TexScale[1]; - brush.face[3].Contents = contents; - brush.face[3].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1] ); - brush.face[3].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0 ); - - if ( CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1 ) { - XYZVectorSubtract( v[2].p,v[0].p,t[0] ); - XYZVectorSubtract( v[1].p,v[2].p,t[1] ); - CrossProduct( t[0],t[1],SurfNormal ); - VectorNormalize( SurfNormal,SurfNormal ); - if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) { - strcpy( surft,surftext2 ); - surf = surface[2]; - } - else - { - strcpy( surft,surftext ); - surf = surface[0]; - } - } - else - { - strcpy( surft,surftext ); - surf = surface[0]; - } - - XYZtoV( &v[0],&brush.face[4].v[0] ); - XYZtoV( &v[1],&brush.face[4].v[1] ); - XYZtoV( &v[2],&brush.face[4].v[2] ); - strcpy( brush.face[4].texture, - ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft ) ); - brush.face[4].Shift[0] = (float)TexOffset[0]; - brush.face[4].Shift[1] = (float)TexOffset[1]; - brush.face[4].Rotate = 0.; - brush.face[4].Scale[0] = (float)TexScale[0]; - brush.face[4].Scale[1] = (float)TexScale[1]; - brush.face[4].Contents = contents; - brush.face[4].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf ); - brush.face[4].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2 ); - - MakeBrush( &brush ); - if ( ( i + j ) % 2 ) { - VectorCopy( xyz[i ][j + 1].p,v[0].p ); - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - VectorCopy( xyz[i ][j ].p,v[1].p ); - VectorCopy( xyz[i + 1][j + 1].p,v[2].p ); - break; - default: - VectorCopy( xyz[i + 1][j + 1].p,v[1].p ); - VectorCopy( xyz[i ][j ].p,v[2].p ); - } - } - else - { - VectorCopy( xyz[i ][j + 1].p,v[0].p ); - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - VectorCopy( xyz[i + 1][j ].p,v[1].p ); - VectorCopy( xyz[i + 1][j + 1].p,v[2].p ); - break; - default: - VectorCopy( xyz[i + 1][j + 1].p,v[1].p ); - VectorCopy( xyz[i + 1][j ].p,v[2].p ); - } - } - VectorCopy( v[0].p,v[3].p ); - VectorCopy( v[1].p,v[4].p ); - VectorCopy( v[2].p,v[5].p ); - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - v[0].p[1] = backface; - v[1].p[1] = backface; - v[2].p[1] = backface; - break; - case PLANE_YZ0: - case PLANE_YZ1: - v[3].p[0] = backface; - v[4].p[0] = backface; - v[5].p[0] = backface; - break; - default: - v[3].p[2] = backface; - v[4].p[2] = backface; - v[5].p[2] = backface; - } - brush.Number = i * NV * 2 + j * 2 + 1; - brush.NumFaces = 5; - XYZtoV( &v[0],&brush.face[0].v[0] ); - XYZtoV( &v[3],&brush.face[0].v[1] ); - XYZtoV( &v[4],&brush.face[0].v[2] ); - strcpy( brush.face[0].texture, - ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) ); - brush.face[0].Shift[0] = (float)TexOffset[0]; - brush.face[0].Shift[1] = (float)TexOffset[1]; - brush.face[0].Rotate = 0.; - brush.face[0].Scale[0] = (float)TexScale[0]; - brush.face[0].Scale[1] = (float)TexScale[1]; - brush.face[0].Contents = contents; - brush.face[0].Surface = surface[1]; - brush.face[0].Value = 0; - - XYZtoV( &v[1],&brush.face[1].v[0] ); - XYZtoV( &v[4],&brush.face[1].v[1] ); - XYZtoV( &v[5],&brush.face[1].v[2] ); - strcpy( brush.face[1].texture, - ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) ); - brush.face[1].Shift[0] = (float)TexOffset[0]; - brush.face[1].Shift[1] = (float)TexOffset[1]; - brush.face[1].Rotate = 0.; - brush.face[1].Scale[0] = (float)TexScale[0]; - brush.face[1].Scale[1] = (float)TexScale[1]; - brush.face[1].Contents = contents; - brush.face[1].Surface = surface[1]; - brush.face[1].Value = 0; - - XYZtoV( &v[2],&brush.face[2].v[0] ); - XYZtoV( &v[5],&brush.face[2].v[1] ); - XYZtoV( &v[3],&brush.face[2].v[2] ); - strcpy( brush.face[2].texture, - ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) ); - brush.face[2].Shift[0] = (float)TexOffset[0]; - brush.face[2].Shift[1] = (float)TexOffset[1]; - brush.face[2].Rotate = 0.; - brush.face[2].Scale[0] = (float)TexScale[0]; - brush.face[2].Scale[1] = (float)TexScale[1]; - brush.face[2].Contents = contents; - brush.face[2].Surface = surface[1]; - brush.face[2].Value = 0; - - if ( CheckAngle && ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ) ) { - XYZVectorSubtract( v[4].p,v[3].p,t[0] ); - XYZVectorSubtract( v[5].p,v[4].p,t[1] ); - CrossProduct( t[0],t[1],SurfNormal ); - VectorNormalize( SurfNormal,SurfNormal ); - if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) { - strcpy( surft,surftext2 ); - surf = surface[2]; - } - else - { - strcpy( surft,surftext ); - surf = surface[0]; - } - } - else - { - strcpy( surft,surftext ); - surf = surface[0]; - } - XYZtoV( &v[3],&brush.face[3].v[0] ); - XYZtoV( &v[5],&brush.face[3].v[1] ); - XYZtoV( &v[4],&brush.face[3].v[2] ); - strcpy( brush.face[3].texture, - ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext ) ); - brush.face[3].Shift[0] = (float)TexOffset[0]; - brush.face[3].Shift[1] = (float)TexOffset[1]; - brush.face[3].Rotate = 0.; - brush.face[3].Scale[0] = (float)TexScale[0]; - brush.face[3].Scale[1] = (float)TexScale[1]; - brush.face[3].Contents = contents; - brush.face[3].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1] ); - brush.face[3].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0 ); - - if ( CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1 ) { - XYZVectorSubtract( v[2].p,v[0].p,t[0] ); - XYZVectorSubtract( v[1].p,v[2].p,t[1] ); - CrossProduct( t[0],t[1],SurfNormal ); - VectorNormalize( SurfNormal,SurfNormal ); - if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) { - strcpy( surft,surftext2 ); - surf = surface[2]; - } - else - { - strcpy( surft,surftext ); - surf = surface[0]; - } - } - else - { - strcpy( surft,surftext ); - surf = surface[0]; - } - XYZtoV( &v[0],&brush.face[4].v[0] ); - XYZtoV( &v[1],&brush.face[4].v[1] ); - XYZtoV( &v[2],&brush.face[4].v[2] ); - strcpy( brush.face[4].texture, - ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft ) ); - brush.face[4].Shift[0] = (float)TexOffset[0]; - brush.face[4].Shift[1] = (float)TexOffset[1]; - brush.face[4].Rotate = 0.; - brush.face[4].Scale[0] = (float)TexScale[0]; - brush.face[4].Scale[1] = (float)TexScale[1]; - brush.face[4].Contents = contents; - brush.face[4].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf ); - brush.face[4].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2 ); - - MakeBrush( &brush ); - } - } - CloseFuncGroup(); - - if ( AddHints || GimpHints ) { - int detail, i1, j1, N; - double front; - - switch ( Game ) - { - case HALFLIFE: - strcpy( hint,"HINT" ); - strcpy( skip,"HINT" ); - break; - case SIN: - strcpy( hint,"generic/misc/hint" ); - strcpy( skip,"generic/misc/skip" ); - break; - case HERETIC2: - strcpy( hint,"general/hint" ); - strcpy( skip,"general/hint" ); // Heretic2 doesn't have a skip texture - break; - case KINGPIN: - strcpy( hint,"common/0_hint" ); - strcpy( skip,"common/0_skip" ); - break; - case GENESIS3D: - strcpy( hint,"hint" ); - strcpy( skip,"hint" ); - break; - case QUAKE3: - strcpy( hint,"textures/common/hint" ); - strcpy( skip,"textures/common/skip" ); - break; - default: - strcpy( hint,"e1u1/hint" ); - strcpy( skip,"e1u1/skip" ); - } - - OpenFuncGroup(); - - if ( AddHints == 1 ) { - detail = CONTENTS_DETAIL; - N = 0; - for ( i = 0; i < NH; i++ ) - { - i1 = i + 1; - - for ( j = 0; j < NV; j++ ) - { - - // For detail hint brushes, no need to use a hint brush over - // EVERY grid square... it would be redundant. Instead use - // a checkerboard pattern - if ( ( i + j ) % 2 ) { - continue; - } - - j1 = j + 1; - - VectorCopy( xyz[i ][j ].p, v[0].p ); - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - VectorCopy( xyz[i1][j ].p, v[1].p ); - VectorCopy( xyz[i1][j1].p, v[2].p ); - VectorCopy( xyz[i ][j1].p, v[3].p ); - break; - default: - VectorCopy( xyz[i ][j1].p, v[1].p ); - VectorCopy( xyz[i1][j1].p, v[2].p ); - VectorCopy( xyz[i1][j ].p, v[3].p ); - } - - VectorCopy( v[0].p,v[4].p ); - VectorCopy( v[1].p,v[5].p ); - VectorCopy( v[2].p,v[6].p ); - VectorCopy( v[3].p,v[7].p ); - - switch ( Plane ) - { - case PLANE_XY1: - front = LessThan( zmin,32. ); - v[4].p[2] = backface; - v[5].p[2] = backface; - v[6].p[2] = backface; - v[7].p[2] = backface; - break; - case PLANE_XZ0: - front = MoreThan( ymax,32. ); - v[0].p[1] = backface; - v[1].p[1] = backface; - v[2].p[1] = backface; - v[3].p[1] = backface; - break; - case PLANE_XZ1: - front = LessThan( ymin,32. ); - v[0].p[1] = backface; - v[1].p[1] = backface; - v[2].p[1] = backface; - v[3].p[1] = backface; - break; - case PLANE_YZ0: - front = MoreThan( xmax,32. ); - v[4].p[0] = backface; - v[5].p[0] = backface; - v[6].p[0] = backface; - v[7].p[0] = backface; - break; - case PLANE_YZ1: - front = LessThan( xmin,32. ); - v[4].p[0] = backface; - v[5].p[0] = backface; - v[6].p[0] = backface; - v[7].p[0] = backface; - break; - default: - front = MoreThan( zmax,32. ); - v[4].p[2] = backface; - v[5].p[2] = backface; - v[6].p[2] = backface; - v[7].p[2] = backface; - } - - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - v[4].p[1] = front; - v[5].p[1] = v[4].p[1]; - v[6].p[1] = v[4].p[1]; - v[7].p[1] = v[4].p[1]; - break; - case PLANE_YZ0: - case PLANE_YZ1: - v[0].p[0] = front; - v[1].p[0] = v[0].p[0]; - v[2].p[0] = v[0].p[0]; - v[3].p[0] = v[0].p[0]; - break; - default: - v[0].p[2] = front; - v[1].p[2] = v[0].p[2]; - v[2].p[2] = v[0].p[2]; - v[3].p[2] = v[0].p[2]; - } - - brush.NumFaces = 6; - brush.Number = N; - XYZtoV( &v[0],&brush.face[0].v[0] ); - XYZtoV( &v[1],&brush.face[0].v[1] ); - XYZtoV( &v[2],&brush.face[0].v[2] ); - strcpy( brush.face[0].texture,skip ); - brush.face[0].Shift[0] = 0.; - brush.face[0].Shift[1] = 0.; - brush.face[0].Rotate = 0.; - brush.face[0].Scale[0] = 1.; - brush.face[0].Scale[1] = 1.; - brush.face[0].Contents = detail; - brush.face[0].Surface = SURF_SKIP; - brush.face[0].Value = 0; - - XYZtoV( &v[4],&brush.face[1].v[0] ); - XYZtoV( &v[7],&brush.face[1].v[1] ); - XYZtoV( &v[6],&brush.face[1].v[2] ); - strcpy( brush.face[1].texture,skip ); - brush.face[1].Shift[0] = 0.; - brush.face[1].Shift[1] = 0.; - brush.face[1].Rotate = 0.; - brush.face[1].Scale[0] = 1.; - brush.face[1].Scale[1] = 1.; - brush.face[1].Contents = detail; - brush.face[1].Surface = SURF_SKIP; - brush.face[1].Value = 0; - - XYZtoV( &v[0],&brush.face[2].v[0] ); - XYZtoV( &v[4],&brush.face[2].v[1] ); - XYZtoV( &v[5],&brush.face[2].v[2] ); - strcpy( brush.face[2].texture,hint ); - brush.face[2].Shift[0] = 0.; - brush.face[2].Shift[1] = 0.; - brush.face[2].Rotate = 0.; - brush.face[2].Scale[0] = 1.; - brush.face[2].Scale[1] = 1.; - brush.face[2].Contents = detail; - brush.face[2].Surface = SURF_HINT; - brush.face[2].Value = 0; - - XYZtoV( &v[1],&brush.face[3].v[0] ); - XYZtoV( &v[5],&brush.face[3].v[1] ); - XYZtoV( &v[6],&brush.face[3].v[2] ); - strcpy( brush.face[3].texture,hint ); - brush.face[3].Shift[0] = 0.; - brush.face[3].Shift[1] = 0.; - brush.face[3].Rotate = 0.; - brush.face[3].Scale[0] = 1.; - brush.face[3].Scale[1] = 1.; - brush.face[3].Contents = detail; - brush.face[3].Surface = SURF_HINT; - brush.face[3].Value = 0; - - XYZtoV( &v[2],&brush.face[4].v[0] ); - XYZtoV( &v[6],&brush.face[4].v[1] ); - XYZtoV( &v[7],&brush.face[4].v[2] ); - strcpy( brush.face[4].texture,hint ); - brush.face[4].Shift[0] = 0.; - brush.face[4].Shift[1] = 0.; - brush.face[4].Rotate = 0.; - brush.face[4].Scale[0] = 1.; - brush.face[4].Scale[1] = 1.; - brush.face[4].Contents = detail; - brush.face[4].Surface = SURF_HINT; - brush.face[4].Value = 0; - - XYZtoV( &v[3],&brush.face[5].v[0] ); - XYZtoV( &v[7],&brush.face[5].v[1] ); - XYZtoV( &v[4],&brush.face[5].v[2] ); - strcpy( brush.face[5].texture,hint ); - brush.face[5].Shift[0] = 0.; - brush.face[5].Shift[1] = 0.; - brush.face[5].Rotate = 0.; - brush.face[5].Scale[0] = 1.; - brush.face[5].Scale[1] = 1.; - brush.face[5].Contents = detail; - brush.face[5].Surface = SURF_HINT; - brush.face[5].Value = 0; - - MakeBrush( &brush ); - N++; - } - } - } - if ( GimpHints ) { - N = 0; - // these brush parameters never change - brush.NumFaces = 5; - for ( i = 0; i < 6; i++ ) - { - strcpy( brush.face[i].texture,hint ); - brush.face[i].Shift[0] = 0.; - brush.face[i].Shift[1] = 0.; - brush.face[i].Rotate = 0.; - brush.face[i].Scale[0] = 1.; - brush.face[i].Scale[1] = 1.; - brush.face[i].Contents = 0; - brush.face[i].Surface = SURF_HINT; - brush.face[i].Value = 0; - } - for ( i = 0; i < NH; i++ ) - { - for ( j = 0; j < NV; j++ ) - { - for ( k = 0; k < 2; k++ ) - { - if ( k == 0 ) { - if ( ( i + j ) % 2 ) { - VectorCopy( xyz[i ][j ].p, v[0].p ); - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - VectorCopy( xyz[i + 1][j ].p, v[1].p ); - VectorCopy( xyz[i + 1][j + 1].p, v[2].p ); - break; - default: - VectorCopy( xyz[i + 1][j + 1].p, v[1].p ); - VectorCopy( xyz[i + 1][j ].p, v[2].p ); - } - } - else - { - VectorCopy( xyz[i ][j ].p, v[0].p ); - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - VectorCopy( xyz[i + 1][j ].p, v[1].p ); - VectorCopy( xyz[i ][j + 1].p, v[2].p ); - break; - default: - VectorCopy( xyz[i ][j + 1].p, v[1].p ); - VectorCopy( xyz[i + 1][j ].p, v[2].p ); - } - } - } - else - { - if ( ( i + j ) % 2 ) { - VectorCopy( xyz[i ][j + 1].p,v[0].p ); - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - VectorCopy( xyz[i ][j ].p,v[1].p ); - VectorCopy( xyz[i + 1][j + 1].p,v[2].p ); - break; - default: - VectorCopy( xyz[i + 1][j + 1].p,v[1].p ); - VectorCopy( xyz[i ][j ].p,v[2].p ); - } - } - else - { - VectorCopy( xyz[i ][j + 1].p,v[0].p ); - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - VectorCopy( xyz[i + 1][j ].p,v[1].p ); - VectorCopy( xyz[i + 1][j + 1].p,v[2].p ); - break; - default: - VectorCopy( xyz[i + 1][j + 1].p,v[1].p ); - VectorCopy( xyz[i + 1][j ].p,v[2].p ); - } - } - } - VectorCopy( v[0].p,v[3].p ); - VectorCopy( v[1].p,v[4].p ); - VectorCopy( v[2].p,v[5].p ); - switch ( Plane ) - { - case PLANE_XY0: - v[0].p[2] += HINT_OFFSET; - v[1].p[2] += HINT_OFFSET; - v[2].p[2] += HINT_OFFSET; +void MapBrushes() +{ + char hint[128]; + char skip[128]; + char sidetext[64]; + char surftext[64]; + char surftext2[64]; + char surft[64]; + float Steep; + vec3_t PlaneNormal, SurfNormal; + vec3_t t[2]; + int i, j, k; + int surf; + bool CheckAngle; + BRUSH brush; + XYZ v[8]; + + strcpy(surftext, Texture[Game][0]); + strcpy(sidetext, (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0])); + strcpy(surftext2, (strlen(Texture[Game][2]) ? Texture[Game][2] : Texture[Game][0])); + + // if surftext2 is identical to surftext, there's no need to + // check surface angle + if (!g_strcasecmp(surftext, surftext2)) { + CheckAngle = FALSE; + } else { + CheckAngle = TRUE; + Steep = (float) cos((double) SlantAngle / 57.2957795); + switch (Plane) { + case PLANE_XY0: + PlaneNormal[0] = 0.; + PlaneNormal[1] = 0.; + PlaneNormal[2] = 1.; + break; + case PLANE_XY1: + PlaneNormal[0] = 0.; + PlaneNormal[1] = 0.; + PlaneNormal[2] = -1.; + break; + case PLANE_XZ0: + PlaneNormal[0] = 0.; + PlaneNormal[1] = 1.; + PlaneNormal[2] = 1.; + break; + case PLANE_XZ1: + PlaneNormal[0] = 0.; + PlaneNormal[1] = -1.; + PlaneNormal[2] = 1.; + break; + case PLANE_YZ0: + PlaneNormal[0] = 1.; + PlaneNormal[1] = 0.; + PlaneNormal[2] = 1.; + break; + case PLANE_YZ1: + PlaneNormal[0] = -1.; + PlaneNormal[1] = 0.; + PlaneNormal[2] = 1.; + break; + } + } + + OpenFuncGroup(); + + for (i = 0; i < NH; i++) { + for (j = 0; j < NV; j++) { + if ((i + j) % 2) { + VectorCopy(xyz[i][j].p, v[0].p); + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + VectorCopy(xyz[i + 1][j].p, v[1].p); + VectorCopy(xyz[i + 1][j + 1].p, v[2].p); + break; + default: + VectorCopy(xyz[i + 1][j + 1].p, v[1].p); + VectorCopy(xyz[i + 1][j].p, v[2].p); + } + } else { + VectorCopy(xyz[i][j].p, v[0].p); + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + VectorCopy(xyz[i + 1][j].p, v[1].p); + VectorCopy(xyz[i][j + 1].p, v[2].p); + break; + default: + VectorCopy(xyz[i][j + 1].p, v[1].p); + VectorCopy(xyz[i + 1][j].p, v[2].p); + } + } + VectorCopy(v[0].p, v[3].p); + VectorCopy(v[1].p, v[4].p); + VectorCopy(v[2].p, v[5].p); + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + v[0].p[1] = backface; + v[1].p[1] = backface; + v[2].p[1] = backface; + break; + case PLANE_YZ0: + case PLANE_YZ1: + v[3].p[0] = backface; + v[4].p[0] = backface; + v[5].p[0] = backface; + break; + default: + v[3].p[2] = backface; + v[4].p[2] = backface; + v[5].p[2] = backface; + } + + brush.Number = i * NV * 2 + j * 2; + brush.NumFaces = 5; + XYZtoV(&v[0], &brush.face[0].v[0]); + XYZtoV(&v[3], &brush.face[0].v[1]); + XYZtoV(&v[4], &brush.face[0].v[2]); + strcpy(brush.face[0].texture, + (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0])); + brush.face[0].Shift[0] = (float) TexOffset[0]; + brush.face[0].Shift[1] = (float) TexOffset[1]; + brush.face[0].Rotate = 0.; + brush.face[0].Scale[0] = (float) TexScale[0]; + brush.face[0].Scale[1] = (float) TexScale[1]; + brush.face[0].Contents = contents; + brush.face[0].Surface = surface[1]; + brush.face[0].Value = 0; + + XYZtoV(&v[1], &brush.face[1].v[0]); + XYZtoV(&v[4], &brush.face[1].v[1]); + XYZtoV(&v[5], &brush.face[1].v[2]); + strcpy(brush.face[1].texture, + (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0])); + brush.face[1].Shift[0] = (float) TexOffset[0]; + brush.face[1].Shift[1] = (float) TexOffset[1]; + brush.face[1].Rotate = 0.; + brush.face[1].Scale[0] = (float) TexScale[0]; + brush.face[1].Scale[1] = (float) TexScale[1]; + brush.face[1].Contents = contents; + brush.face[1].Surface = surface[1]; + brush.face[1].Value = 0; + + XYZtoV(&v[2], &brush.face[2].v[0]); + XYZtoV(&v[5], &brush.face[2].v[1]); + XYZtoV(&v[3], &brush.face[2].v[2]); + strcpy(brush.face[2].texture, + (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0])); + brush.face[2].Shift[0] = (float) TexOffset[0]; + brush.face[2].Shift[1] = (float) TexOffset[1]; + brush.face[2].Rotate = 0.; + brush.face[2].Scale[0] = (float) TexScale[0]; + brush.face[2].Scale[1] = (float) TexScale[1]; + brush.face[2].Contents = contents; + brush.face[2].Surface = surface[1]; + brush.face[2].Value = 0; + + if (CheckAngle && (Plane == PLANE_XZ0 || Plane == PLANE_XZ1)) { + XYZVectorSubtract(v[4].p, v[3].p, t[0]); + XYZVectorSubtract(v[5].p, v[4].p, t[1]); + CrossProduct(t[0], t[1], SurfNormal); + VectorNormalize(SurfNormal, SurfNormal); + if (DotProduct(SurfNormal, PlaneNormal) < Steep) { + strcpy(surft, surftext2); + surf = surface[2]; + } else { + strcpy(surft, surftext); + surf = surface[0]; + } + } else { + strcpy(surft, surftext); + surf = surface[0]; + } + + XYZtoV(&v[3], &brush.face[3].v[0]); + XYZtoV(&v[5], &brush.face[3].v[1]); + XYZtoV(&v[4], &brush.face[3].v[2]); + strcpy(brush.face[3].texture, + (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext)); + brush.face[3].Shift[0] = (float) TexOffset[0]; + brush.face[3].Shift[1] = (float) TexOffset[1]; + brush.face[3].Rotate = 0.; + brush.face[3].Scale[0] = (float) TexScale[0]; + brush.face[3].Scale[1] = (float) TexScale[1]; + brush.face[3].Contents = contents; + brush.face[3].Surface = (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1]); + brush.face[3].Value = (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0); + + if (CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1) { + XYZVectorSubtract(v[2].p, v[0].p, t[0]); + XYZVectorSubtract(v[1].p, v[2].p, t[1]); + CrossProduct(t[0], t[1], SurfNormal); + VectorNormalize(SurfNormal, SurfNormal); + if (DotProduct(SurfNormal, PlaneNormal) < Steep) { + strcpy(surft, surftext2); + surf = surface[2]; + } else { + strcpy(surft, surftext); + surf = surface[0]; + } + } else { + strcpy(surft, surftext); + surf = surface[0]; + } + + XYZtoV(&v[0], &brush.face[4].v[0]); + XYZtoV(&v[1], &brush.face[4].v[1]); + XYZtoV(&v[2], &brush.face[4].v[2]); + strcpy(brush.face[4].texture, + (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft)); + brush.face[4].Shift[0] = (float) TexOffset[0]; + brush.face[4].Shift[1] = (float) TexOffset[1]; + brush.face[4].Rotate = 0.; + brush.face[4].Scale[0] = (float) TexScale[0]; + brush.face[4].Scale[1] = (float) TexScale[1]; + brush.face[4].Contents = contents; + brush.face[4].Surface = (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf); + brush.face[4].Value = (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2); + + MakeBrush(&brush); + if ((i + j) % 2) { + VectorCopy(xyz[i][j + 1].p, v[0].p); + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + VectorCopy(xyz[i][j].p, v[1].p); + VectorCopy(xyz[i + 1][j + 1].p, v[2].p); + break; + default: + VectorCopy(xyz[i + 1][j + 1].p, v[1].p); + VectorCopy(xyz[i][j].p, v[2].p); + } + } else { + VectorCopy(xyz[i][j + 1].p, v[0].p); + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + VectorCopy(xyz[i + 1][j].p, v[1].p); + VectorCopy(xyz[i + 1][j + 1].p, v[2].p); + break; + default: + VectorCopy(xyz[i + 1][j + 1].p, v[1].p); + VectorCopy(xyz[i + 1][j].p, v[2].p); + } + } + VectorCopy(v[0].p, v[3].p); + VectorCopy(v[1].p, v[4].p); + VectorCopy(v[2].p, v[5].p); + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + v[0].p[1] = backface; + v[1].p[1] = backface; + v[2].p[1] = backface; + break; + case PLANE_YZ0: + case PLANE_YZ1: + v[3].p[0] = backface; + v[4].p[0] = backface; + v[5].p[0] = backface; + break; + default: + v[3].p[2] = backface; + v[4].p[2] = backface; + v[5].p[2] = backface; + } + brush.Number = i * NV * 2 + j * 2 + 1; + brush.NumFaces = 5; + XYZtoV(&v[0], &brush.face[0].v[0]); + XYZtoV(&v[3], &brush.face[0].v[1]); + XYZtoV(&v[4], &brush.face[0].v[2]); + strcpy(brush.face[0].texture, + (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0])); + brush.face[0].Shift[0] = (float) TexOffset[0]; + brush.face[0].Shift[1] = (float) TexOffset[1]; + brush.face[0].Rotate = 0.; + brush.face[0].Scale[0] = (float) TexScale[0]; + brush.face[0].Scale[1] = (float) TexScale[1]; + brush.face[0].Contents = contents; + brush.face[0].Surface = surface[1]; + brush.face[0].Value = 0; + + XYZtoV(&v[1], &brush.face[1].v[0]); + XYZtoV(&v[4], &brush.face[1].v[1]); + XYZtoV(&v[5], &brush.face[1].v[2]); + strcpy(brush.face[1].texture, + (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0])); + brush.face[1].Shift[0] = (float) TexOffset[0]; + brush.face[1].Shift[1] = (float) TexOffset[1]; + brush.face[1].Rotate = 0.; + brush.face[1].Scale[0] = (float) TexScale[0]; + brush.face[1].Scale[1] = (float) TexScale[1]; + brush.face[1].Contents = contents; + brush.face[1].Surface = surface[1]; + brush.face[1].Value = 0; + + XYZtoV(&v[2], &brush.face[2].v[0]); + XYZtoV(&v[5], &brush.face[2].v[1]); + XYZtoV(&v[3], &brush.face[2].v[2]); + strcpy(brush.face[2].texture, + (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0])); + brush.face[2].Shift[0] = (float) TexOffset[0]; + brush.face[2].Shift[1] = (float) TexOffset[1]; + brush.face[2].Rotate = 0.; + brush.face[2].Scale[0] = (float) TexScale[0]; + brush.face[2].Scale[1] = (float) TexScale[1]; + brush.face[2].Contents = contents; + brush.face[2].Surface = surface[1]; + brush.face[2].Value = 0; + + if (CheckAngle && (Plane == PLANE_XZ0 || Plane == PLANE_XZ1)) { + XYZVectorSubtract(v[4].p, v[3].p, t[0]); + XYZVectorSubtract(v[5].p, v[4].p, t[1]); + CrossProduct(t[0], t[1], SurfNormal); + VectorNormalize(SurfNormal, SurfNormal); + if (DotProduct(SurfNormal, PlaneNormal) < Steep) { + strcpy(surft, surftext2); + surf = surface[2]; + } else { + strcpy(surft, surftext); + surf = surface[0]; + } + } else { + strcpy(surft, surftext); + surf = surface[0]; + } + XYZtoV(&v[3], &brush.face[3].v[0]); + XYZtoV(&v[5], &brush.face[3].v[1]); + XYZtoV(&v[4], &brush.face[3].v[2]); + strcpy(brush.face[3].texture, + (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext)); + brush.face[3].Shift[0] = (float) TexOffset[0]; + brush.face[3].Shift[1] = (float) TexOffset[1]; + brush.face[3].Rotate = 0.; + brush.face[3].Scale[0] = (float) TexScale[0]; + brush.face[3].Scale[1] = (float) TexScale[1]; + brush.face[3].Contents = contents; + brush.face[3].Surface = (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1]); + brush.face[3].Value = (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0); + + if (CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1) { + XYZVectorSubtract(v[2].p, v[0].p, t[0]); + XYZVectorSubtract(v[1].p, v[2].p, t[1]); + CrossProduct(t[0], t[1], SurfNormal); + VectorNormalize(SurfNormal, SurfNormal); + if (DotProduct(SurfNormal, PlaneNormal) < Steep) { + strcpy(surft, surftext2); + surf = surface[2]; + } else { + strcpy(surft, surftext); + surf = surface[0]; + } + } else { + strcpy(surft, surftext); + surf = surface[0]; + } + XYZtoV(&v[0], &brush.face[4].v[0]); + XYZtoV(&v[1], &brush.face[4].v[1]); + XYZtoV(&v[2], &brush.face[4].v[2]); + strcpy(brush.face[4].texture, + (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft)); + brush.face[4].Shift[0] = (float) TexOffset[0]; + brush.face[4].Shift[1] = (float) TexOffset[1]; + brush.face[4].Rotate = 0.; + brush.face[4].Scale[0] = (float) TexScale[0]; + brush.face[4].Scale[1] = (float) TexScale[1]; + brush.face[4].Contents = contents; + brush.face[4].Surface = (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf); + brush.face[4].Value = (Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2); + + MakeBrush(&brush); + } + } + CloseFuncGroup(); + + if (AddHints || GimpHints) { + int detail, i1, j1, N; + double front; + + switch (Game) { + case HALFLIFE: + strcpy(hint, "HINT"); + strcpy(skip, "HINT"); + break; + case SIN: + strcpy(hint, "generic/misc/hint"); + strcpy(skip, "generic/misc/skip"); + break; + case HERETIC2: + strcpy(hint, "general/hint"); + strcpy(skip, "general/hint"); // Heretic2 doesn't have a skip texture + break; + case KINGPIN: + strcpy(hint, "common/0_hint"); + strcpy(skip, "common/0_skip"); + break; + case GENESIS3D: + strcpy(hint, "hint"); + strcpy(skip, "hint"); + break; + case QUAKE3: + strcpy(hint, "textures/common/hint"); + strcpy(skip, "textures/common/skip"); + break; + default: + strcpy(hint, "e1u1/hint"); + strcpy(skip, "e1u1/skip"); + } + + OpenFuncGroup(); + + if (AddHints == 1) { + detail = CONTENTS_DETAIL; + N = 0; + for (i = 0; i < NH; i++) { + i1 = i + 1; + + for (j = 0; j < NV; j++) { + + // For detail hint brushes, no need to use a hint brush over + // EVERY grid square... it would be redundant. Instead use + // a checkerboard pattern + if ((i + j) % 2) { + continue; + } + + j1 = j + 1; + + VectorCopy(xyz[i][j].p, v[0].p); + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + VectorCopy(xyz[i1][j].p, v[1].p); + VectorCopy(xyz[i1][j1].p, v[2].p); + VectorCopy(xyz[i][j1].p, v[3].p); + break; + default: + VectorCopy(xyz[i][j1].p, v[1].p); + VectorCopy(xyz[i1][j1].p, v[2].p); + VectorCopy(xyz[i1][j].p, v[3].p); + } + + VectorCopy(v[0].p, v[4].p); + VectorCopy(v[1].p, v[5].p); + VectorCopy(v[2].p, v[6].p); + VectorCopy(v[3].p, v[7].p); + + switch (Plane) { + case PLANE_XY1: + front = LessThan(zmin, 32.); + v[4].p[2] = backface; + v[5].p[2] = backface; + v[6].p[2] = backface; + v[7].p[2] = backface; + break; + case PLANE_XZ0: + front = MoreThan(ymax, 32.); + v[0].p[1] = backface; + v[1].p[1] = backface; + v[2].p[1] = backface; + v[3].p[1] = backface; + break; + case PLANE_XZ1: + front = LessThan(ymin, 32.); + v[0].p[1] = backface; + v[1].p[1] = backface; + v[2].p[1] = backface; + v[3].p[1] = backface; + break; + case PLANE_YZ0: + front = MoreThan(xmax, 32.); + v[4].p[0] = backface; + v[5].p[0] = backface; + v[6].p[0] = backface; + v[7].p[0] = backface; + break; + case PLANE_YZ1: + front = LessThan(xmin, 32.); + v[4].p[0] = backface; + v[5].p[0] = backface; + v[6].p[0] = backface; + v[7].p[0] = backface; + break; + default: + front = MoreThan(zmax, 32.); + v[4].p[2] = backface; + v[5].p[2] = backface; + v[6].p[2] = backface; + v[7].p[2] = backface; + } + + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + v[4].p[1] = front; + v[5].p[1] = v[4].p[1]; + v[6].p[1] = v[4].p[1]; + v[7].p[1] = v[4].p[1]; + break; + case PLANE_YZ0: + case PLANE_YZ1: + v[0].p[0] = front; + v[1].p[0] = v[0].p[0]; + v[2].p[0] = v[0].p[0]; + v[3].p[0] = v[0].p[0]; + break; + default: + v[0].p[2] = front; + v[1].p[2] = v[0].p[2]; + v[2].p[2] = v[0].p[2]; + v[3].p[2] = v[0].p[2]; + } + + brush.NumFaces = 6; + brush.Number = N; + XYZtoV(&v[0], &brush.face[0].v[0]); + XYZtoV(&v[1], &brush.face[0].v[1]); + XYZtoV(&v[2], &brush.face[0].v[2]); + strcpy(brush.face[0].texture, skip); + brush.face[0].Shift[0] = 0.; + brush.face[0].Shift[1] = 0.; + brush.face[0].Rotate = 0.; + brush.face[0].Scale[0] = 1.; + brush.face[0].Scale[1] = 1.; + brush.face[0].Contents = detail; + brush.face[0].Surface = SURF_SKIP; + brush.face[0].Value = 0; + + XYZtoV(&v[4], &brush.face[1].v[0]); + XYZtoV(&v[7], &brush.face[1].v[1]); + XYZtoV(&v[6], &brush.face[1].v[2]); + strcpy(brush.face[1].texture, skip); + brush.face[1].Shift[0] = 0.; + brush.face[1].Shift[1] = 0.; + brush.face[1].Rotate = 0.; + brush.face[1].Scale[0] = 1.; + brush.face[1].Scale[1] = 1.; + brush.face[1].Contents = detail; + brush.face[1].Surface = SURF_SKIP; + brush.face[1].Value = 0; + + XYZtoV(&v[0], &brush.face[2].v[0]); + XYZtoV(&v[4], &brush.face[2].v[1]); + XYZtoV(&v[5], &brush.face[2].v[2]); + strcpy(brush.face[2].texture, hint); + brush.face[2].Shift[0] = 0.; + brush.face[2].Shift[1] = 0.; + brush.face[2].Rotate = 0.; + brush.face[2].Scale[0] = 1.; + brush.face[2].Scale[1] = 1.; + brush.face[2].Contents = detail; + brush.face[2].Surface = SURF_HINT; + brush.face[2].Value = 0; + + XYZtoV(&v[1], &brush.face[3].v[0]); + XYZtoV(&v[5], &brush.face[3].v[1]); + XYZtoV(&v[6], &brush.face[3].v[2]); + strcpy(brush.face[3].texture, hint); + brush.face[3].Shift[0] = 0.; + brush.face[3].Shift[1] = 0.; + brush.face[3].Rotate = 0.; + brush.face[3].Scale[0] = 1.; + brush.face[3].Scale[1] = 1.; + brush.face[3].Contents = detail; + brush.face[3].Surface = SURF_HINT; + brush.face[3].Value = 0; + + XYZtoV(&v[2], &brush.face[4].v[0]); + XYZtoV(&v[6], &brush.face[4].v[1]); + XYZtoV(&v[7], &brush.face[4].v[2]); + strcpy(brush.face[4].texture, hint); + brush.face[4].Shift[0] = 0.; + brush.face[4].Shift[1] = 0.; + brush.face[4].Rotate = 0.; + brush.face[4].Scale[0] = 1.; + brush.face[4].Scale[1] = 1.; + brush.face[4].Contents = detail; + brush.face[4].Surface = SURF_HINT; + brush.face[4].Value = 0; + + XYZtoV(&v[3], &brush.face[5].v[0]); + XYZtoV(&v[7], &brush.face[5].v[1]); + XYZtoV(&v[4], &brush.face[5].v[2]); + strcpy(brush.face[5].texture, hint); + brush.face[5].Shift[0] = 0.; + brush.face[5].Shift[1] = 0.; + brush.face[5].Rotate = 0.; + brush.face[5].Scale[0] = 1.; + brush.face[5].Scale[1] = 1.; + brush.face[5].Contents = detail; + brush.face[5].Surface = SURF_HINT; + brush.face[5].Value = 0; + + MakeBrush(&brush); + N++; + } + } + } + if (GimpHints) { + N = 0; + // these brush parameters never change + brush.NumFaces = 5; + for (i = 0; i < 6; i++) { + strcpy(brush.face[i].texture, hint); + brush.face[i].Shift[0] = 0.; + brush.face[i].Shift[1] = 0.; + brush.face[i].Rotate = 0.; + brush.face[i].Scale[0] = 1.; + brush.face[i].Scale[1] = 1.; + brush.face[i].Contents = 0; + brush.face[i].Surface = SURF_HINT; + brush.face[i].Value = 0; + } + for (i = 0; i < NH; i++) { + for (j = 0; j < NV; j++) { + for (k = 0; k < 2; k++) { + if (k == 0) { + if ((i + j) % 2) { + VectorCopy(xyz[i][j].p, v[0].p); + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + VectorCopy(xyz[i + 1][j].p, v[1].p); + VectorCopy(xyz[i + 1][j + 1].p, v[2].p); + break; + default: + VectorCopy(xyz[i + 1][j + 1].p, v[1].p); + VectorCopy(xyz[i + 1][j].p, v[2].p); + } + } else { + VectorCopy(xyz[i][j].p, v[0].p); + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + VectorCopy(xyz[i + 1][j].p, v[1].p); + VectorCopy(xyz[i][j + 1].p, v[2].p); + break; + default: + VectorCopy(xyz[i][j + 1].p, v[1].p); + VectorCopy(xyz[i + 1][j].p, v[2].p); + } + } + } else { + if ((i + j) % 2) { + VectorCopy(xyz[i][j + 1].p, v[0].p); + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + VectorCopy(xyz[i][j].p, v[1].p); + VectorCopy(xyz[i + 1][j + 1].p, v[2].p); + break; + default: + VectorCopy(xyz[i + 1][j + 1].p, v[1].p); + VectorCopy(xyz[i][j].p, v[2].p); + } + } else { + VectorCopy(xyz[i][j + 1].p, v[0].p); + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + VectorCopy(xyz[i + 1][j].p, v[1].p); + VectorCopy(xyz[i + 1][j + 1].p, v[2].p); + break; + default: + VectorCopy(xyz[i + 1][j + 1].p, v[1].p); + VectorCopy(xyz[i + 1][j].p, v[2].p); + } + } + } + VectorCopy(v[0].p, v[3].p); + VectorCopy(v[1].p, v[4].p); + VectorCopy(v[2].p, v[5].p); + switch (Plane) { + case PLANE_XY0: + v[0].p[2] += HINT_OFFSET; + v[1].p[2] += HINT_OFFSET; + v[2].p[2] += HINT_OFFSET; // v[3].p[2] = backface; // v[4].p[2] = backface; // v[5].p[2] = backface; - break; - case PLANE_XY1: - v[0].p[2] -= HINT_OFFSET; - v[1].p[2] -= HINT_OFFSET; - v[2].p[2] -= HINT_OFFSET; + break; + case PLANE_XY1: + v[0].p[2] -= HINT_OFFSET; + v[1].p[2] -= HINT_OFFSET; + v[2].p[2] -= HINT_OFFSET; // v[3].p[2] = backface; // v[4].p[2] = backface; // v[5].p[2] = backface; - break; - case PLANE_XZ0: + break; + case PLANE_XZ0: // v[0].p[1] = backface; // v[1].p[1] = backface; // v[2].p[1] = backface; - v[3].p[1] += HINT_OFFSET; - v[4].p[1] += HINT_OFFSET; - v[5].p[1] += HINT_OFFSET; - break; - case PLANE_XZ1: + v[3].p[1] += HINT_OFFSET; + v[4].p[1] += HINT_OFFSET; + v[5].p[1] += HINT_OFFSET; + break; + case PLANE_XZ1: // v[0].p[1] = backface; // v[1].p[1] = backface; // v[2].p[1] = backface; - v[3].p[1] -= HINT_OFFSET; - v[4].p[1] -= HINT_OFFSET; - v[5].p[1] -= HINT_OFFSET; - break; - case PLANE_YZ0: - v[0].p[0] += HINT_OFFSET; - v[1].p[0] += HINT_OFFSET; - v[2].p[0] += HINT_OFFSET; + v[3].p[1] -= HINT_OFFSET; + v[4].p[1] -= HINT_OFFSET; + v[5].p[1] -= HINT_OFFSET; + break; + case PLANE_YZ0: + v[0].p[0] += HINT_OFFSET; + v[1].p[0] += HINT_OFFSET; + v[2].p[0] += HINT_OFFSET; // v[3].p[0] = backface; // v[4].p[0] = backface; // v[5].p[0] = backface; - break; - case PLANE_YZ1: - v[0].p[0] -= HINT_OFFSET; - v[1].p[0] -= HINT_OFFSET; - v[2].p[0] -= HINT_OFFSET; + break; + case PLANE_YZ1: + v[0].p[0] -= HINT_OFFSET; + v[1].p[0] -= HINT_OFFSET; + v[2].p[0] -= HINT_OFFSET; // v[3].p[0] = backface; // v[4].p[0] = backface; // v[5].p[0] = backface; - break; - } - brush.Number = N; - XYZtoV( &v[0],&brush.face[0].v[0] ); - XYZtoV( &v[3],&brush.face[0].v[1] ); - XYZtoV( &v[4],&brush.face[0].v[2] ); - - XYZtoV( &v[1],&brush.face[1].v[0] ); - XYZtoV( &v[4],&brush.face[1].v[1] ); - XYZtoV( &v[5],&brush.face[1].v[2] ); - - XYZtoV( &v[2],&brush.face[2].v[0] ); - XYZtoV( &v[5],&brush.face[2].v[1] ); - XYZtoV( &v[3],&brush.face[2].v[2] ); - - XYZtoV( &v[3],&brush.face[3].v[0] ); - XYZtoV( &v[5],&brush.face[3].v[1] ); - XYZtoV( &v[4],&brush.face[3].v[2] ); - - XYZtoV( &v[0],&brush.face[4].v[0] ); - XYZtoV( &v[1],&brush.face[4].v[1] ); - XYZtoV( &v[2],&brush.face[4].v[2] ); - - MakeBrush( &brush ); - N++; - } - } - } - } // endif AddHints==1 - CloseFuncGroup(); - } + break; + } + brush.Number = N; + XYZtoV(&v[0], &brush.face[0].v[0]); + XYZtoV(&v[3], &brush.face[0].v[1]); + XYZtoV(&v[4], &brush.face[0].v[2]); + + XYZtoV(&v[1], &brush.face[1].v[0]); + XYZtoV(&v[4], &brush.face[1].v[1]); + XYZtoV(&v[5], &brush.face[1].v[2]); + + XYZtoV(&v[2], &brush.face[2].v[0]); + XYZtoV(&v[5], &brush.face[2].v[1]); + XYZtoV(&v[3], &brush.face[2].v[2]); + + XYZtoV(&v[3], &brush.face[3].v[0]); + XYZtoV(&v[5], &brush.face[3].v[1]); + XYZtoV(&v[4], &brush.face[3].v[2]); + + XYZtoV(&v[0], &brush.face[4].v[0]); + XYZtoV(&v[1], &brush.face[4].v[1]); + XYZtoV(&v[2], &brush.face[4].v[2]); + + MakeBrush(&brush); + N++; + } + } + } + } // endif AddHints==1 + CloseFuncGroup(); + } } // end MapBrushes //============================================================= -void GenerateMap(){ - extern void MapOut( int,int,NODE *,TRI * ); - extern bool SingleBrushSelected; - int ntri; - - if ( !ValidSurface() ) { - return; - } - /* +void GenerateMap() +{ + extern void MapOut(int, int, NODE *, TRI *); + extern bool SingleBrushSelected; + int ntri; + + if (!ValidSurface()) { + return; + } + /* ghCursorCurrent = LoadCursor(NULL,IDC_WAIT); SetCursor(ghCursorCurrent); */ #if 0 - if ( SingleBrushSelected ) { + if ( SingleBrushSelected ) { g_FuncTable.m_pfnDeleteSelection(); } #endif - GenerateXYZ(); - ntri = NH * NV * 2; + GenerateXYZ(); + ntri = NH * NV * 2; - if ( Game == QUAKE3 && UsePatches != 0 ) { - MapPatches(); - } + if (Game == QUAKE3 && UsePatches != 0) { + MapPatches(); + } - if ( Decimate > 0 && ( Game != QUAKE3 || UsePatches == 0 ) ) { - MapOut( gNumNodes,gNumTris,gNode,gTri ); - /* + if (Decimate > 0 && (Game != QUAKE3 || UsePatches == 0)) { + MapOut(gNumNodes, gNumTris, gNode, gTri); + /* ghCursorCurrent = ghCursorDefault; SetCursor(ghCursorCurrent); */ - return; - } - - contents = 0; - // HL doesn't have detail property - if ( ( Game != HALFLIFE ) && UseDetail ) { - contents += CONTENTS_DETAIL; - } - // HL and Q3 don't have ladder property - if ( ( Game != HALFLIFE && Game != QUAKE3 ) && UseLadder ) { - contents += CONTENTS_LADDER; - } - // Genesis requires solid property to be set explicitly - if ( Game == GENESIS3D ) { - contents |= CONTENTS_SOLID; - } - // Heretic 2 uses different sounds (in surface props) for different texture types - if ( Game == HERETIC2 ) { - surface[0] = GetDefSurfaceProps( Texture[Game][0] ); - surface[1] = GetDefSurfaceProps( Texture[Game][1] ); - surface[2] = GetDefSurfaceProps( Texture[Game][2] ); - } - else - { - surface[0] = 0; - surface[1] = 0; - surface[2] = 0; - } - if ( Game != QUAKE3 || UsePatches == 0 ) { - MapBrushes(); - } - - /* + return; + } + + contents = 0; + // HL doesn't have detail property + if ((Game != HALFLIFE) && UseDetail) { + contents += CONTENTS_DETAIL; + } + // HL and Q3 don't have ladder property + if ((Game != HALFLIFE && Game != QUAKE3) && UseLadder) { + contents += CONTENTS_LADDER; + } + // Genesis requires solid property to be set explicitly + if (Game == GENESIS3D) { + contents |= CONTENTS_SOLID; + } + // Heretic 2 uses different sounds (in surface props) for different texture types + if (Game == HERETIC2) { + surface[0] = GetDefSurfaceProps(Texture[Game][0]); + surface[1] = GetDefSurfaceProps(Texture[Game][1]); + surface[2] = GetDefSurfaceProps(Texture[Game][2]); + } else { + surface[0] = 0; + surface[1] = 0; + surface[2] = 0; + } + if (Game != QUAKE3 || UsePatches == 0) { + MapBrushes(); + } + + /* ghCursorCurrent = ghCursorDefault; SetCursor(ghCursorCurrent); */ } //============================================================= -void GenerateXYZ(){ - extern void MakeDecimatedMap( int *, int *, NODE * *, TRI * * ); - double zl, zu; - double wh, wv; - int NHalfcycles; - double a,v,h,ha,va; - double delta, dr, rate; - double range, maxrange; - double r; - int i, j, k, N; - int i0, i1, j0, j1; - int ii, jj; +void GenerateXYZ() +{ + extern void MakeDecimatedMap(int *, int *, NODE **, TRI **); + double zl, zu; + double wh, wv; + int NHalfcycles; + double a, v, h, ha, va; + double delta, dr, rate; + double range, maxrange; + double r; + int i, j, k, N; + int i0, i1, j0, j1; + int ii, jj; // FILE *f; // char CSV[64]; - if ( !ValidSurface() ) { - return; - } - - srand( 1 ); - srand( RandomSeed ); - - dh = ( Hur - Hll ) / NH; - dv = ( Vur - Vll ) / NV; - - // H & V - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - xyz[i][j].p[0] = Hll + i * dh; - xyz[i][j].p[2] = Vll + j * dv; - break; - case PLANE_YZ0: - case PLANE_YZ1: - xyz[i][j].p[1] = Hll + i * dh; - xyz[i][j].p[2] = Vll + j * dv; - break; - default: - xyz[i][j].p[0] = Hll + i * dh; - xyz[i][j].p[1] = Vll + j * dv; - } - } - } - - if ( WaveType == WAVE_BITMAP ) { - GenerateBitmapMapping(); - } - /* + if (!ValidSurface()) { + return; + } + + srand(1); + srand(RandomSeed); + + dh = (Hur - Hll) / NH; + dv = (Vur - Vll) / NV; + + // H & V + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + xyz[i][j].p[0] = Hll + i * dh; + xyz[i][j].p[2] = Vll + j * dv; + break; + case PLANE_YZ0: + case PLANE_YZ1: + xyz[i][j].p[1] = Hll + i * dh; + xyz[i][j].p[2] = Vll + j * dv; + break; + default: + xyz[i][j].p[0] = Hll + i * dh; + xyz[i][j].p[1] = Vll + j * dv; + } + } + } + + if (WaveType == WAVE_BITMAP) { + GenerateBitmapMapping(); + } + /* else if(WaveType == WAVE_FORMULA) DoFormula(); */ - else - { - // Initialize Z values using bilinear interpolation - for ( i = 0; i <= NH; i++ ) - { - zl = Z00 + i * ( Z10 - Z00 ) / NH; - zu = Z01 + i * ( Z11 - Z01 ) / NH; - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - for ( j = 0; j <= NV; j++ ) - xyz[i][j].p[1] = zl + j * ( zu - zl ) / NV; - break; - case PLANE_YZ0: - case PLANE_YZ1: - for ( j = 0; j <= NV; j++ ) - xyz[i][j].p[0] = zl + j * ( zu - zl ) / NV; - break; - default: - for ( j = 0; j <= NV; j++ ) - xyz[i][j].p[2] = zl + j * ( zu - zl ) / NV; - } - } - } - - switch ( WaveType ) - { - case WAVE_COS_SIN: - if ( FixBorders ) { - NHalfcycles = (int)( ( Hur - Hll ) / ( WaveLength / 2. ) ); - NHalfcycles = max( NHalfcycles,1 ); - wh = 2. * ( Hur - Hll ) / NHalfcycles; - NHalfcycles = (int)( ( Vur - Vll ) / ( WaveLength / 2. ) ); - wv = 2. * ( Vur - Vll ) / NHalfcycles; - NHalfcycles = max( NHalfcycles,1 ); - i0 = 1; - i1 = NH - 1; - j0 = 1; - j1 = NV - 1; - } - else - { - wh = WaveLength; - wv = WaveLength; - i0 = 0; - i1 = NH; - j0 = 0; - j1 = NV; - } - - for ( i = i0; i <= i1; i++ ) - { - h = Hll + i * dh; - ha = ( ( h - Hll ) / wh ) * 2. * PI - PI / 2.; - for ( j = j0; j <= j1; j++ ) - { - v = Vll + j * dv; - va = ( ( v - Vll ) / wv ) * 2. * PI; - a = Amplitude * cos( ha ) * sin( va ); - switch ( Plane ) - { - case PLANE_XY1: - xyz[i][j].p[2] -= a; - break; - case PLANE_XZ0: - xyz[i][j].p[1] += a; - break; - case PLANE_XZ1: - xyz[i][j].p[1] -= a; - break; - case PLANE_YZ0: - xyz[i][j].p[0] += a; - break; - case PLANE_YZ1: - xyz[i][j].p[0] -= a; - break; - default: - xyz[i][j].p[2] += a; - } - } - } - break; - case WAVE_HCYLINDER: - for ( i = 0; i <= NH; i++ ) - { - h = Hll + i * dh; - ha = ( ( h - Hll ) / WaveLength ) * 2. * PI - PI / 2.; - for ( j = 0; j <= NV; j++ ) - { - a = Amplitude * cos( ha ); - switch ( Plane ) - { - case PLANE_XY1: - xyz[i][j].p[2] -= a; - break; - case PLANE_XZ0: - xyz[i][j].p[1] += a; - break; - case PLANE_XZ1: - xyz[i][j].p[1] -= a; - break; - case PLANE_YZ0: - xyz[i][j].p[0] += a; - break; - case PLANE_YZ1: - xyz[i][j].p[0] -= a; - break; - default: - xyz[i][j].p[2] += a; - } - } - } - break; - case WAVE_VCYLINDER: - for ( i = 0; i <= NH; i++ ) - { - h = Hll + i * dh; - for ( j = 0; j <= NV; j++ ) - { - v = Vll + j * dv; - va = ( ( v - Vll ) / WaveLength ) * 2. * PI; - a = Amplitude * sin( va ); - switch ( Plane ) - { - case PLANE_XY1: - xyz[i][j].p[2] -= a; - break; - case PLANE_XZ0: - xyz[i][j].p[1] += a; - break; - case PLANE_XZ1: - xyz[i][j].p[1] -= a; - break; - case PLANE_YZ0: - xyz[i][j].p[0] += a; - break; - case PLANE_YZ1: - xyz[i][j].p[0] -= a; - break; - default: - xyz[i][j].p[2] += a; - } - } - } - break; - case WAVE_ROUGH_ONLY: - PlasmaCloud(); - break; - } - - if ( WaveType != WAVE_ROUGH_ONLY ) { - // Fixed values - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - if ( xyz[i][j].fixed ) { - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - xyz[i][j].p[1] = xyz[i][j].fixed_value; - break; - case PLANE_YZ0: - case PLANE_YZ1: - xyz[i][j].p[0] = xyz[i][j].fixed_value; - break; - default: - xyz[i][j].p[2] = xyz[i][j].fixed_value; - } - - if ( xyz[i][j].range > 0 ) { - maxrange = pow( xyz[i][j].range,2 ); // so we don't have to do sqrt's - i0 = i - (int)( floor( xyz[i][j].range / dh - 0.5 ) + 1 ); - i1 = i + i - i0; - j0 = j - (int)( floor( xyz[i][j].range / dv - 0.5 ) + 1 ); - j1 = j + j - j0; - if ( FixBorders ) { - i0 = max( i0,1 ); - i1 = min( i1,NH - 1 ); - j0 = max( j0,1 ); - j1 = min( j1,NV - 1 ); - } - else - { - i0 = max( i0,0 ); - i1 = min( i1,NH ); - j0 = max( j0,0 ); - j1 = min( j1,NV ); - } - for ( ii = i0; ii <= i1; ii++ ) - { - for ( jj = j0; jj <= j1; jj++ ) - { - if ( ii == i && jj == j ) { - continue; - } - range = pow( dh * ( i - ii ), 2 ) + pow( dv * ( j - jj ), 2 ); - if ( range > maxrange ) { - continue; - } - dr = sqrt( range / maxrange ); - rate = max( -30.,min( xyz[i][j].rate,30. ) ); - if ( rate < -1. ) { - delta = pow( ( 1. - dr ),-rate + 1. ); - } - else if ( rate < 0. ) { - delta = ( 1 + rate ) * 0.5 * ( cos( dr * PI ) + 1.0 ) - - rate*pow( ( 1. - dr ),2 ); - } - else if ( rate == 0. ) { - delta = 0.5 * ( cos( dr * PI ) + 1.0 ); - } - else if ( rate <= 1. ) { - delta = ( 1. - rate ) * 0.5 * ( cos( dr * PI ) + 1.0 ) + - rate * ( 1. - pow( dr,2 ) ); - } - else - { - delta = 1. - pow( dr,rate + 1 ); - } - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - xyz[ii][jj].p[1] += ( xyz[i][j].p[1] - xyz[ii][jj].p[1] ) * delta; - break; - case PLANE_YZ0: - case PLANE_YZ1: - xyz[ii][jj].p[0] += ( xyz[i][j].p[0] - xyz[ii][jj].p[0] ) * delta; - break; - default: - xyz[ii][jj].p[2] += ( xyz[i][j].p[2] - xyz[ii][jj].p[2] ) * delta; - } - } - } - } - } - } - } - } - - if ( ( Roughness > 0. ) && ( WaveType != WAVE_ROUGH_ONLY ) ) { - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - if ( CanEdit( i,j ) && !xyz[i][j].fixed ) { - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - xyz[i][j].p[1] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ); - break; - case PLANE_YZ0: - case PLANE_YZ1: - xyz[i][j].p[0] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ); - break; - default: - xyz[i][j].p[2] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ); - } - } - else{ - r = rand(); // We still get a random number, so that fixing points - } - // doesn't change the sequence. - - } - } - } - - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - for ( k = 0; k < 3; k++ ) - { - xyz[i][j].p[k] = Nearest( xyz[i][j].p[k],2.0 ); - } - } - } - - // Find minima and maxima - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - xmin = Hll; - xmax = Hur; - zmin = Vll; - zmax = Vur; - ymin = xyz[0][0].p[1]; - ymax = ymin; - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - ymin = min( ymin,xyz[i][j].p[1] ); - ymax = max( ymax,xyz[i][j].p[1] ); - } - } - break; - case PLANE_YZ0: - case PLANE_YZ1: - ymin = Hll; - ymax = Hur; - zmin = Vll; - zmax = Vur; - xmin = xyz[0][0].p[0]; - xmax = ymin; - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - xmin = min( xmin,xyz[i][j].p[0] ); - xmax = max( xmax,xyz[i][j].p[0] ); - } - } - break; - break; - default: - xmin = Hll; - xmax = Hur; - ymin = Vll; - ymax = Vur; - zmin = xyz[0][0].p[2]; - zmax = zmin; - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - zmin = min( zmin,xyz[i][j].p[2] ); - zmax = max( zmax,xyz[i][j].p[2] ); - } - } - } - - xmin = Nearest( xmin,2. ); - xmax = Nearest( xmax,2. ); - ymin = Nearest( ymin,2. ); - ymax = Nearest( ymax,2. ); - zmin = Nearest( zmin,2. ); - zmax = Nearest( zmax,2. ); - - switch ( Plane ) - { - case PLANE_XY1: - backface = AtLeast( zmax + 32.,32. ); - break; - case PLANE_XZ0: - backface = NoMoreThan( ymin - 32.,32. ); - break; - case PLANE_XZ1: - backface = AtLeast( ymax + 32.,32. ); - break; - case PLANE_YZ0: - backface = NoMoreThan( xmin - 32.,32. ); - break; - case PLANE_YZ1: - backface = AtLeast( xmax + 32.,32. ); - break; - default: - backface = NoMoreThan( zmin - 32.,32. ); - } - - if ( gNode ) { - free( gNode ); - free( gTri ); - gNode = (NODE *)NULL; - gTri = (TRI *)NULL; - } - if ( Decimate > 0 && ( Game != QUAKE3 || UsePatches == 0 ) ) { - MakeDecimatedMap( &gNumNodes,&gNumTris,&gNode,&gTri ); - } - else - { - gNumNodes = ( NH + 1 ) * ( NV + 1 ); - gNumTris = NH * NV * 2; - gNode = (NODE *) malloc( gNumNodes * sizeof( NODE ) ); - gTri = (TRI *) malloc( gNumTris * sizeof( TRI ) ); - - for ( i = 0,N = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++, N++ ) - { - gNode[N].used = 1; - gNode[N].p[0] = (float)xyz[i][j].p[0]; - gNode[N].p[1] = (float)xyz[i][j].p[1]; - gNode[N].p[2] = (float)xyz[i][j].p[2]; - } - } - - for ( i = 0; i < NH; i++ ) - { - for ( j = 0; j < NV; j++ ) - { - k = i * NV * 2 + j * 2; - if ( ( i + j ) % 2 ) { - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - gTri[k ].v[0] = i * ( NV + 1 ) + j; - gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1; - gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j; - gTri[k + 1].v[0] = i * ( NV + 1 ) + j; - gTri[k + 1].v[1] = i * ( NV + 1 ) + j + 1; - gTri[k + 1].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1; - break; - default: - gTri[k ].v[0] = i * ( NV + 1 ) + j; - gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j; - gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1; - gTri[k + 1].v[0] = i * ( NV + 1 ) + j; - gTri[k + 1].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1; - gTri[k + 1].v[2] = i * ( NV + 1 ) + j + 1; - } - } - else - { - switch ( Plane ) - { - case PLANE_XY1: - case PLANE_XZ1: - case PLANE_YZ1: - gTri[k ].v[0] = i * ( NV + 1 ) + j; - gTri[k ].v[1] = i * ( NV + 1 ) + j + 1; - gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j; - gTri[k + 1].v[0] = ( i + 1 ) * ( NV + 1 ) + j; - gTri[k + 1].v[1] = i * ( NV + 1 ) + j + 1; - gTri[k + 1].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1; - break; - default: - gTri[k ].v[0] = i * ( NV + 1 ) + j; - gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j; - gTri[k ].v[2] = i * ( NV + 1 ) + j + 1; - gTri[k + 1].v[0] = ( i + 1 ) * ( NV + 1 ) + j; - gTri[k + 1].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1; - gTri[k + 1].v[2] = i * ( NV + 1 ) + j + 1; - } - } - } - } - } + else { + // Initialize Z values using bilinear interpolation + for (i = 0; i <= NH; i++) { + zl = Z00 + i * (Z10 - Z00) / NH; + zu = Z01 + i * (Z11 - Z01) / NH; + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + for (j = 0; j <= NV; j++) { + xyz[i][j].p[1] = zl + j * (zu - zl) / NV; + } + break; + case PLANE_YZ0: + case PLANE_YZ1: + for (j = 0; j <= NV; j++) { + xyz[i][j].p[0] = zl + j * (zu - zl) / NV; + } + break; + default: + for (j = 0; j <= NV; j++) { + xyz[i][j].p[2] = zl + j * (zu - zl) / NV; + } + } + } + } + + switch (WaveType) { + case WAVE_COS_SIN: + if (FixBorders) { + NHalfcycles = (int) ((Hur - Hll) / (WaveLength / 2.)); + NHalfcycles = max(NHalfcycles, 1); + wh = 2. * (Hur - Hll) / NHalfcycles; + NHalfcycles = (int) ((Vur - Vll) / (WaveLength / 2.)); + wv = 2. * (Vur - Vll) / NHalfcycles; + NHalfcycles = max(NHalfcycles, 1); + i0 = 1; + i1 = NH - 1; + j0 = 1; + j1 = NV - 1; + } else { + wh = WaveLength; + wv = WaveLength; + i0 = 0; + i1 = NH; + j0 = 0; + j1 = NV; + } + + for (i = i0; i <= i1; i++) { + h = Hll + i * dh; + ha = ((h - Hll) / wh) * 2. * PI - PI / 2.; + for (j = j0; j <= j1; j++) { + v = Vll + j * dv; + va = ((v - Vll) / wv) * 2. * PI; + a = Amplitude * cos(ha) * sin(va); + switch (Plane) { + case PLANE_XY1: + xyz[i][j].p[2] -= a; + break; + case PLANE_XZ0: + xyz[i][j].p[1] += a; + break; + case PLANE_XZ1: + xyz[i][j].p[1] -= a; + break; + case PLANE_YZ0: + xyz[i][j].p[0] += a; + break; + case PLANE_YZ1: + xyz[i][j].p[0] -= a; + break; + default: + xyz[i][j].p[2] += a; + } + } + } + break; + case WAVE_HCYLINDER: + for (i = 0; i <= NH; i++) { + h = Hll + i * dh; + ha = ((h - Hll) / WaveLength) * 2. * PI - PI / 2.; + for (j = 0; j <= NV; j++) { + a = Amplitude * cos(ha); + switch (Plane) { + case PLANE_XY1: + xyz[i][j].p[2] -= a; + break; + case PLANE_XZ0: + xyz[i][j].p[1] += a; + break; + case PLANE_XZ1: + xyz[i][j].p[1] -= a; + break; + case PLANE_YZ0: + xyz[i][j].p[0] += a; + break; + case PLANE_YZ1: + xyz[i][j].p[0] -= a; + break; + default: + xyz[i][j].p[2] += a; + } + } + } + break; + case WAVE_VCYLINDER: + for (i = 0; i <= NH; i++) { + h = Hll + i * dh; + for (j = 0; j <= NV; j++) { + v = Vll + j * dv; + va = ((v - Vll) / WaveLength) * 2. * PI; + a = Amplitude * sin(va); + switch (Plane) { + case PLANE_XY1: + xyz[i][j].p[2] -= a; + break; + case PLANE_XZ0: + xyz[i][j].p[1] += a; + break; + case PLANE_XZ1: + xyz[i][j].p[1] -= a; + break; + case PLANE_YZ0: + xyz[i][j].p[0] += a; + break; + case PLANE_YZ1: + xyz[i][j].p[0] -= a; + break; + default: + xyz[i][j].p[2] += a; + } + } + } + break; + case WAVE_ROUGH_ONLY: + PlasmaCloud(); + break; + } + + if (WaveType != WAVE_ROUGH_ONLY) { + // Fixed values + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + if (xyz[i][j].fixed) { + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + xyz[i][j].p[1] = xyz[i][j].fixed_value; + break; + case PLANE_YZ0: + case PLANE_YZ1: + xyz[i][j].p[0] = xyz[i][j].fixed_value; + break; + default: + xyz[i][j].p[2] = xyz[i][j].fixed_value; + } + + if (xyz[i][j].range > 0) { + maxrange = pow(xyz[i][j].range, 2); // so we don't have to do sqrt's + i0 = i - (int) (floor(xyz[i][j].range / dh - 0.5) + 1); + i1 = i + i - i0; + j0 = j - (int) (floor(xyz[i][j].range / dv - 0.5) + 1); + j1 = j + j - j0; + if (FixBorders) { + i0 = max(i0, 1); + i1 = min(i1, NH - 1); + j0 = max(j0, 1); + j1 = min(j1, NV - 1); + } else { + i0 = max(i0, 0); + i1 = min(i1, NH); + j0 = max(j0, 0); + j1 = min(j1, NV); + } + for (ii = i0; ii <= i1; ii++) { + for (jj = j0; jj <= j1; jj++) { + if (ii == i && jj == j) { + continue; + } + range = pow(dh * (i - ii), 2) + pow(dv * (j - jj), 2); + if (range > maxrange) { + continue; + } + dr = sqrt(range / maxrange); + rate = max(-30., min(xyz[i][j].rate, 30.)); + if (rate < -1.) { + delta = pow((1. - dr), -rate + 1.); + } else if (rate < 0.) { + delta = (1 + rate) * 0.5 * (cos(dr * PI) + 1.0) - + rate * pow((1. - dr), 2); + } else if (rate == 0.) { + delta = 0.5 * (cos(dr * PI) + 1.0); + } else if (rate <= 1.) { + delta = (1. - rate) * 0.5 * (cos(dr * PI) + 1.0) + + rate * (1. - pow(dr, 2)); + } else { + delta = 1. - pow(dr, rate + 1); + } + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + xyz[ii][jj].p[1] += (xyz[i][j].p[1] - xyz[ii][jj].p[1]) * delta; + break; + case PLANE_YZ0: + case PLANE_YZ1: + xyz[ii][jj].p[0] += (xyz[i][j].p[0] - xyz[ii][jj].p[0]) * delta; + break; + default: + xyz[ii][jj].p[2] += (xyz[i][j].p[2] - xyz[ii][jj].p[2]) * delta; + } + } + } + } + } + } + } + } + + if ((Roughness > 0.) && (WaveType != WAVE_ROUGH_ONLY)) { + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + if (CanEdit(i, j) && !xyz[i][j].fixed) { + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + xyz[i][j].p[1] += -Roughness / 2. + Roughness * ((double) rand() / (double) RAND_MAX); + break; + case PLANE_YZ0: + case PLANE_YZ1: + xyz[i][j].p[0] += -Roughness / 2. + Roughness * ((double) rand() / (double) RAND_MAX); + break; + default: + xyz[i][j].p[2] += -Roughness / 2. + Roughness * ((double) rand() / (double) RAND_MAX); + } + } else { + r = rand(); // We still get a random number, so that fixing points + } + // doesn't change the sequence. + + } + } + } + + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + for (k = 0; k < 3; k++) { + xyz[i][j].p[k] = Nearest(xyz[i][j].p[k], 2.0); + } + } + } + + // Find minima and maxima + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + xmin = Hll; + xmax = Hur; + zmin = Vll; + zmax = Vur; + ymin = xyz[0][0].p[1]; + ymax = ymin; + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + ymin = min(ymin, xyz[i][j].p[1]); + ymax = max(ymax, xyz[i][j].p[1]); + } + } + break; + case PLANE_YZ0: + case PLANE_YZ1: + ymin = Hll; + ymax = Hur; + zmin = Vll; + zmax = Vur; + xmin = xyz[0][0].p[0]; + xmax = ymin; + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + xmin = min(xmin, xyz[i][j].p[0]); + xmax = max(xmax, xyz[i][j].p[0]); + } + } + break; + break; + default: + xmin = Hll; + xmax = Hur; + ymin = Vll; + ymax = Vur; + zmin = xyz[0][0].p[2]; + zmax = zmin; + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + zmin = min(zmin, xyz[i][j].p[2]); + zmax = max(zmax, xyz[i][j].p[2]); + } + } + } + + xmin = Nearest(xmin, 2.); + xmax = Nearest(xmax, 2.); + ymin = Nearest(ymin, 2.); + ymax = Nearest(ymax, 2.); + zmin = Nearest(zmin, 2.); + zmax = Nearest(zmax, 2.); + + switch (Plane) { + case PLANE_XY1: + backface = AtLeast(zmax + 32., 32.); + break; + case PLANE_XZ0: + backface = NoMoreThan(ymin - 32., 32.); + break; + case PLANE_XZ1: + backface = AtLeast(ymax + 32., 32.); + break; + case PLANE_YZ0: + backface = NoMoreThan(xmin - 32., 32.); + break; + case PLANE_YZ1: + backface = AtLeast(xmax + 32., 32.); + break; + default: + backface = NoMoreThan(zmin - 32., 32.); + } + + if (gNode) { + free(gNode); + free(gTri); + gNode = (NODE *) NULL; + gTri = (TRI *) NULL; + } + if (Decimate > 0 && (Game != QUAKE3 || UsePatches == 0)) { + MakeDecimatedMap(&gNumNodes, &gNumTris, &gNode, &gTri); + } else { + gNumNodes = (NH + 1) * (NV + 1); + gNumTris = NH * NV * 2; + gNode = (NODE *) malloc(gNumNodes * sizeof(NODE)); + gTri = (TRI *) malloc(gNumTris * sizeof(TRI)); + + for (i = 0, N = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++, N++) { + gNode[N].used = 1; + gNode[N].p[0] = (float) xyz[i][j].p[0]; + gNode[N].p[1] = (float) xyz[i][j].p[1]; + gNode[N].p[2] = (float) xyz[i][j].p[2]; + } + } + + for (i = 0; i < NH; i++) { + for (j = 0; j < NV; j++) { + k = i * NV * 2 + j * 2; + if ((i + j) % 2) { + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + gTri[k].v[0] = i * (NV + 1) + j; + gTri[k].v[1] = (i + 1) * (NV + 1) + j + 1; + gTri[k].v[2] = (i + 1) * (NV + 1) + j; + gTri[k + 1].v[0] = i * (NV + 1) + j; + gTri[k + 1].v[1] = i * (NV + 1) + j + 1; + gTri[k + 1].v[2] = (i + 1) * (NV + 1) + j + 1; + break; + default: + gTri[k].v[0] = i * (NV + 1) + j; + gTri[k].v[1] = (i + 1) * (NV + 1) + j; + gTri[k].v[2] = (i + 1) * (NV + 1) + j + 1; + gTri[k + 1].v[0] = i * (NV + 1) + j; + gTri[k + 1].v[1] = (i + 1) * (NV + 1) + j + 1; + gTri[k + 1].v[2] = i * (NV + 1) + j + 1; + } + } else { + switch (Plane) { + case PLANE_XY1: + case PLANE_XZ1: + case PLANE_YZ1: + gTri[k].v[0] = i * (NV + 1) + j; + gTri[k].v[1] = i * (NV + 1) + j + 1; + gTri[k].v[2] = (i + 1) * (NV + 1) + j; + gTri[k + 1].v[0] = (i + 1) * (NV + 1) + j; + gTri[k + 1].v[1] = i * (NV + 1) + j + 1; + gTri[k + 1].v[2] = (i + 1) * (NV + 1) + j + 1; + break; + default: + gTri[k].v[0] = i * (NV + 1) + j; + gTri[k].v[1] = (i + 1) * (NV + 1) + j; + gTri[k].v[2] = i * (NV + 1) + j + 1; + gTri[k + 1].v[0] = (i + 1) * (NV + 1) + j; + gTri[k + 1].v[1] = (i + 1) * (NV + 1) + j + 1; + gTri[k + 1].v[2] = i * (NV + 1) + j + 1; + } + } + } + } + } /* sprintf(CSV,"csv%03d.csv",Decimate); f = fopen(CSV,"w"); @@ -1657,386 +1552,389 @@ void GenerateXYZ(){ } fclose(f); */ - for ( i = 0; i < gNumTris; i++ ) - PlaneFromPoints( gNode[gTri[i].v[0]].p, - gNode[gTri[i].v[1]].p, - gNode[gTri[i].v[2]].p, - &gTri[i].plane ); - - // Hydra: snap-to-grid begin - if ( SnapToGrid > 0 ) { - for ( i = 0; i < NH; i++ ) - { - for ( j = 0; j < NV; j++ ) - { - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - xyz[i][j].p[1] = CalculateSnapValue( xyz[i][j].p[1] ); - break; - case PLANE_YZ0: - case PLANE_YZ1: - xyz[i][j].p[0] = CalculateSnapValue( xyz[i][j].p[0] ); - break; - default: - xyz[i][j].p[2] = CalculateSnapValue( xyz[i][j].p[2] ); - } - } - } - } - // Hydra: snap-to-grid end + for (i = 0; i < gNumTris; i++) { + PlaneFromPoints(gNode[gTri[i].v[0]].p, + gNode[gTri[i].v[1]].p, + gNode[gTri[i].v[2]].p, + &gTri[i].plane); + } + + // Hydra: snap-to-grid begin + if (SnapToGrid > 0) { + for (i = 0; i < NH; i++) { + for (j = 0; j < NV; j++) { + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + xyz[i][j].p[1] = CalculateSnapValue(xyz[i][j].p[1]); + break; + case PLANE_YZ0: + case PLANE_YZ1: + xyz[i][j].p[0] = CalculateSnapValue(xyz[i][j].p[0]); + break; + default: + xyz[i][j].p[2] = CalculateSnapValue(xyz[i][j].p[2]); + } + } + } + } + // Hydra: snap-to-grid end } -//============================================================= -double Nearest( double x, double dx ){ - double xx; - xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx; - if ( fabs( xx ) < dx / 2 ) { - xx = 0.; - } - return xx; -} //============================================================= -double NoMoreThan( double x, double dx ){ - double xx; - - xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx; - if ( xx > x ) { - xx -= dx; - } - return xx; +double Nearest(double x, double dx) +{ + double xx; + + xx = (double) (floor(x / dx - 0.5) + 1.) * dx; + if (fabs(xx) < dx / 2) { + xx = 0.; + } + return xx; } -//============================================================= -double AtLeast( double x, double dx ){ - double xx; - xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx; - if ( xx < x ) { - xx += dx; - } - return xx; -} //============================================================= -double LessThan( double x,double dx ){ - double xx; +double NoMoreThan(double x, double dx) +{ + double xx; + + xx = (double) (floor(x / dx - 0.5) + 1.) * dx; + if (xx > x) { + xx -= dx; + } + return xx; +} - xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx; - if ( xx >= x ) { - xx -= dx; - } - return xx; +//============================================================= +double AtLeast(double x, double dx) +{ + double xx; + + xx = (double) (floor(x / dx - 0.5) + 1.) * dx; + if (xx < x) { + xx += dx; + } + return xx; } + //============================================================= -double MoreThan( double x,double dx ){ - double xx; +double LessThan(double x, double dx) +{ + double xx; + + xx = (double) (floor(x / dx - 0.5) + 1.) * dx; + if (xx >= x) { + xx -= dx; + } + return xx; +} - xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx; - while ( xx <= x ) - xx += dx; - return xx; +//============================================================= +double MoreThan(double x, double dx) +{ + double xx; + + xx = (double) (floor(x / dx - 0.5) + 1.) * dx; + while (xx <= x) { + xx += dx; + } + return xx; } + //============================================================= -void SubdividePlasma( int i0,int j0,int i1,int j1 ){ - int i, j; - double z1, z2; - double r; // NOTE: This is used to keep the random number sequence the same - // when we fix a point. If we did NOT do this, then simply - // fixing a point at its current value would change the entire - // surface. - - i = ( i0 + i1 ) / 2; - j = ( j0 + j1 ) / 2; - if ( i1 > i0 + 1 ) { - if ( !xyz[i][j0].done ) { - xyz[i][j0].pp[2] = xyz[i0][j0].pp[2] + - ( xyz[i1][j0].pp[2] - xyz[i0][j0].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 ) + - ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) ); - xyz[i][j0].done = 1; - } - else{ - r = rand(); - } - if ( ( j1 > j0 ) && ( !xyz[i][j1].done ) ) { - xyz[i][j1].pp[2] = xyz[i0][j1].pp[2] + - ( xyz[i1][j1].pp[2] - xyz[i0][j1].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 ) + - ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) ); - xyz[i][j1].done = 1; - } - else{ - r = rand(); - } - } - if ( j1 > j0 + 1 ) { - if ( !xyz[i0][j].done ) { - xyz[i0][j].pp[2] = xyz[i0][j0].pp[2] + - ( xyz[i0][j1].pp[2] - xyz[i0][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 ) + - ( (double)( j - j0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) ); - xyz[i0][j].done = 1; - } - else{ - r = rand(); - } - if ( ( i1 > i0 ) && ( !xyz[i1][j].done ) ) { - xyz[i1][j].pp[2] = xyz[i1][j0].pp[2] + - ( xyz[i1][j1].pp[2] - xyz[i1][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 ) + - ( (double)( j - j0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) ); - xyz[i1][j].done = 1; - } - else{ - r = rand(); - } - } - if ( ( i1 > i0 + 1 ) && ( j1 > j0 + 1 ) ) { - if ( !xyz[i][j].done ) { - z1 = xyz[i0][j].pp[2] + - ( xyz[i1][j].pp[2] - xyz[i0][j].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 ); - z2 = xyz[i][j0].pp[2] + - ( xyz[i][j1].pp[2] - xyz[i][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 ); - xyz[i][j].pp[2] = ( z1 + z2 ) / 2. + - ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) ); - xyz[i][j].done = 1; - } - else{ - r = rand(); - } - } - if ( i > i0 + 1 || j > j0 + 1 ) { - SubdividePlasma( i0,j0,i,j ); - } - if ( i1 > i + 1 || j > j0 + 1 ) { - SubdividePlasma( i,j0,i1,j ); - } - if ( i > i0 + 1 || j1 > j0 + 1 ) { - SubdividePlasma( i0,j,i,j1 ); - } - if ( i1 > i + 1 || j1 > j0 + 1 ) { - SubdividePlasma( i,j,i1,j1 ); - } +void SubdividePlasma(int i0, int j0, int i1, int j1) +{ + int i, j; + double z1, z2; + double r; // NOTE: This is used to keep the random number sequence the same + // when we fix a point. If we did NOT do this, then simply + // fixing a point at its current value would change the entire + // surface. + + i = (i0 + i1) / 2; + j = (j0 + j1) / 2; + if (i1 > i0 + 1) { + if (!xyz[i][j0].done) { + xyz[i][j0].pp[2] = xyz[i0][j0].pp[2] + + (xyz[i1][j0].pp[2] - xyz[i0][j0].pp[2]) * (double) (i - i0) / (double) (i1 - i0) + + ((double) (i - i0)) * + (-Roughness / 2. + Roughness * ((double) rand() / (double) RAND_MAX)); + xyz[i][j0].done = 1; + } else { + r = rand(); + } + if ((j1 > j0) && (!xyz[i][j1].done)) { + xyz[i][j1].pp[2] = xyz[i0][j1].pp[2] + + (xyz[i1][j1].pp[2] - xyz[i0][j1].pp[2]) * (double) (i - i0) / (double) (i1 - i0) + + ((double) (i - i0)) * + (-Roughness / 2. + Roughness * ((double) rand() / (double) RAND_MAX)); + xyz[i][j1].done = 1; + } else { + r = rand(); + } + } + if (j1 > j0 + 1) { + if (!xyz[i0][j].done) { + xyz[i0][j].pp[2] = xyz[i0][j0].pp[2] + + (xyz[i0][j1].pp[2] - xyz[i0][j0].pp[2]) * (double) (j - j0) / (double) (j1 - j0) + + ((double) (j - j0)) * + (-Roughness / 2. + Roughness * ((double) rand() / (double) RAND_MAX)); + xyz[i0][j].done = 1; + } else { + r = rand(); + } + if ((i1 > i0) && (!xyz[i1][j].done)) { + xyz[i1][j].pp[2] = xyz[i1][j0].pp[2] + + (xyz[i1][j1].pp[2] - xyz[i1][j0].pp[2]) * (double) (j - j0) / (double) (j1 - j0) + + ((double) (j - j0)) * + (-Roughness / 2. + Roughness * ((double) rand() / (double) RAND_MAX)); + xyz[i1][j].done = 1; + } else { + r = rand(); + } + } + if ((i1 > i0 + 1) && (j1 > j0 + 1)) { + if (!xyz[i][j].done) { + z1 = xyz[i0][j].pp[2] + + (xyz[i1][j].pp[2] - xyz[i0][j].pp[2]) * (double) (i - i0) / (double) (i1 - i0); + z2 = xyz[i][j0].pp[2] + + (xyz[i][j1].pp[2] - xyz[i][j0].pp[2]) * (double) (j - j0) / (double) (j1 - j0); + xyz[i][j].pp[2] = (z1 + z2) / 2. + + ((double) (i - i0)) * + (-Roughness / 2. + Roughness * ((double) rand() / (double) RAND_MAX)); + xyz[i][j].done = 1; + } else { + r = rand(); + } + } + if (i > i0 + 1 || j > j0 + 1) { + SubdividePlasma(i0, j0, i, j); + } + if (i1 > i + 1 || j > j0 + 1) { + SubdividePlasma(i, j0, i1, j); + } + if (i > i0 + 1 || j1 > j0 + 1) { + SubdividePlasma(i0, j, i, j1); + } + if (i1 > i + 1 || j1 > j0 + 1) { + SubdividePlasma(i, j, i1, j1); + } } + //================================================================================== -void PlasmaCloud(){ - int i, j; - /* use pp[2] values until done to avoid messing with a bunch of +void PlasmaCloud() +{ + int i, j; + /* use pp[2] values until done to avoid messing with a bunch of switch statements */ - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - if ( FixedPoint( i,j ) ) { - xyz[i][j].done = 1; - } - else{ - xyz[i][j].done = 0; - } - } - } - - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - if ( xyz[i][j].fixed ) { - xyz[i][j].pp[2] = xyz[i][j].fixed_value; - } - else{ - xyz[i][j].pp[2] = xyz[i][j].p[1]; - } - } - } - break; - case PLANE_YZ0: - case PLANE_YZ1: - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - if ( xyz[i][j].fixed ) { - xyz[i][j].pp[2] = xyz[i][j].fixed_value; - } - else{ - xyz[i][j].pp[2] = xyz[i][j].p[0]; - } - } - } - break; - default: - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - if ( xyz[i][j].fixed ) { - xyz[i][j].pp[2] = xyz[i][j].fixed_value; - } - else{ - xyz[i][j].pp[2] = xyz[i][j].p[2]; - } - } - } - break; - } - SubdividePlasma( 0,0,NH,NV ); - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - xyz[i][j].p[1] = xyz[i][j].pp[2]; - } - } - break; - case PLANE_YZ0: - case PLANE_YZ1: - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - xyz[i][j].p[0] = xyz[i][j].pp[2]; - } - } - break; - default: - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - xyz[i][j].p[2] = xyz[i][j].pp[2]; - } - } - break; - } + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + if (FixedPoint(i, j)) { + xyz[i][j].done = 1; + } else { + xyz[i][j].done = 0; + } + } + } + + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + if (xyz[i][j].fixed) { + xyz[i][j].pp[2] = xyz[i][j].fixed_value; + } else { + xyz[i][j].pp[2] = xyz[i][j].p[1]; + } + } + } + break; + case PLANE_YZ0: + case PLANE_YZ1: + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + if (xyz[i][j].fixed) { + xyz[i][j].pp[2] = xyz[i][j].fixed_value; + } else { + xyz[i][j].pp[2] = xyz[i][j].p[0]; + } + } + } + break; + default: + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + if (xyz[i][j].fixed) { + xyz[i][j].pp[2] = xyz[i][j].fixed_value; + } else { + xyz[i][j].pp[2] = xyz[i][j].p[2]; + } + } + } + break; + } + SubdividePlasma(0, 0, NH, NV); + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + xyz[i][j].p[1] = xyz[i][j].pp[2]; + } + } + break; + case PLANE_YZ0: + case PLANE_YZ1: + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + xyz[i][j].p[0] = xyz[i][j].pp[2]; + } + } + break; + default: + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + xyz[i][j].p[2] = xyz[i][j].pp[2]; + } + } + break; + } } + //=========================================================================== -bool FixedPoint( int i, int j ){ - if ( xyz[i][j].fixed ) { - return TRUE; - } - return !CanEdit( i,j ); +bool FixedPoint(int i, int j) +{ + if (xyz[i][j].fixed) { + return TRUE; + } + return !CanEdit(i, j); } + //=========================================================================== -bool CanEdit( int i, int j ){ - if ( FixBorders && ( ( WaveType == WAVE_COS_SIN ) || ( WaveType == WAVE_ROUGH_ONLY ) ) ) { - if ( i == 0 ) { - return FALSE; - } - if ( i == NH ) { - return FALSE; - } - if ( j == 0 ) { - return FALSE; - } - if ( j == NV ) { - return FALSE; - } - } - if ( i == 0 && j == 0 ) { - return FALSE; - } - if ( i == NH && j == 0 ) { - return FALSE; - } - if ( i == 0 && j == NV ) { - return FALSE; - } - if ( i == NH && j == NV ) { - return FALSE; - } - return TRUE; +bool CanEdit(int i, int j) +{ + if (FixBorders && ((WaveType == WAVE_COS_SIN) || (WaveType == WAVE_ROUGH_ONLY))) { + if (i == 0) { + return FALSE; + } + if (i == NH) { + return FALSE; + } + if (j == 0) { + return FALSE; + } + if (j == NV) { + return FALSE; + } + } + if (i == 0 && j == 0) { + return FALSE; + } + if (i == NH && j == 0) { + return FALSE; + } + if (i == 0 && j == NV) { + return FALSE; + } + if (i == NH && j == NV) { + return FALSE; + } + return TRUE; } + /*============================================================================ TriangleFromPoint Determines which triangle in the gTri array bounds the input point. Doesn't do anything special with border points. */ -int TriangleFromPoint( double x, double y ){ - int j, tri; - - if ( !gTri ) { - return -1; - } - - for ( j = 0, tri = -1; j < gNumTris && tri == -1; j++ ) - { - if ( side( x,y, - gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1], - gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1] ) < 0. ) { - continue; - } - if ( side( x,y, - gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1], - gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1] ) < 0. ) { - continue; - } - if ( side( x,y, - gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1], - gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1] ) < 0. ) { - continue; - } - tri = j; - } - - return tri; +int TriangleFromPoint(double x, double y) +{ + int j, tri; + + if (!gTri) { + return -1; + } + + for (j = 0, tri = -1; j < gNumTris && tri == -1; j++) { + if (side(x, y, + gNode[gTri[j].v[0]].p[0], gNode[gTri[j].v[0]].p[1], + gNode[gTri[j].v[1]].p[0], gNode[gTri[j].v[1]].p[1]) < 0.) { + continue; + } + if (side(x, y, + gNode[gTri[j].v[1]].p[0], gNode[gTri[j].v[1]].p[1], + gNode[gTri[j].v[2]].p[0], gNode[gTri[j].v[2]].p[1]) < 0.) { + continue; + } + if (side(x, y, + gNode[gTri[j].v[2]].p[0], gNode[gTri[j].v[2]].p[1], + gNode[gTri[j].v[0]].p[0], gNode[gTri[j].v[0]].p[1]) < 0.) { + continue; + } + tri = j; + } + + return tri; } + /*============================================================================ PlayerStartZ Determines minimum height to place the player start such that he doesn't intersect any surface brushes. */ -int PlayerStartZ( double x, double y ){ - int k,t[5]; - double z, zt; - - if ( !gTri ) { - return (int)zmax; - } - - t[0] = TriangleFromPoint( x,y ); - t[1] = TriangleFromPoint( x + PlayerBox[Game].x[0],y + PlayerBox[Game].y[0] ); - t[2] = TriangleFromPoint( x + PlayerBox[Game].x[0],y + PlayerBox[Game].y[1] ); - t[3] = TriangleFromPoint( x + PlayerBox[Game].x[1],y + PlayerBox[Game].y[0] ); - t[4] = TriangleFromPoint( x + PlayerBox[Game].x[1],y + PlayerBox[Game].y[1] ); - z = zmin; - for ( k = 0; k < 5; k++ ) - { - zt = ( gTri[t[k]].plane.dist - - gTri[t[k]].plane.normal[0] * x - - gTri[t[k]].plane.normal[1] * y ) / - gTri[t[k]].plane.normal[2]; - z = max( z,zt ); - } - return (int)( AtLeast( z,2. ) - PlayerBox[Game].z[0] ); +int PlayerStartZ(double x, double y) +{ + int k, t[5]; + double z, zt; + + if (!gTri) { + return (int) zmax; + } + + t[0] = TriangleFromPoint(x, y); + t[1] = TriangleFromPoint(x + PlayerBox[Game].x[0], y + PlayerBox[Game].y[0]); + t[2] = TriangleFromPoint(x + PlayerBox[Game].x[0], y + PlayerBox[Game].y[1]); + t[3] = TriangleFromPoint(x + PlayerBox[Game].x[1], y + PlayerBox[Game].y[0]); + t[4] = TriangleFromPoint(x + PlayerBox[Game].x[1], y + PlayerBox[Game].y[1]); + z = zmin; + for (k = 0; k < 5; k++) { + zt = (gTri[t[k]].plane.dist - + gTri[t[k]].plane.normal[0] * x - + gTri[t[k]].plane.normal[1] * y) / + gTri[t[k]].plane.normal[2]; + z = max(z, zt); + } + return (int) (AtLeast(z, 2.) - PlayerBox[Game].z[0]); } + //============================================================= -void XYZtoV( XYZ *xyz, vec3 *v ){ - v[0][0] = (vec)Nearest( xyz->p[0],2. ); - v[0][1] = (vec)Nearest( xyz->p[1],2. ); - v[0][2] = (vec)Nearest( xyz->p[2],2. ); +void XYZtoV(XYZ *xyz, vec3 *v) +{ + v[0][0] = (vec) Nearest(xyz->p[0], 2.); + v[0][1] = (vec) Nearest(xyz->p[1], 2.); + v[0][2] = (vec) Nearest(xyz->p[2], 2.); } //============================================================= -scene::Node* MakePatch( void ){ - scene::Node* patch = Patch_AllocNode(); +scene::Node *MakePatch(void) +{ + scene::Node *patch = Patch_AllocNode(); #if 0 - patch->m_patch->SetShader( Texture[Game][0] ); + patch->m_patch->SetShader( Texture[Game][0] ); #endif - Node_getTraversable( h_worldspawn )->insert( patch ); - return patch; + Node_getTraversable(h_worldspawn)->insert(patch); + return patch; } //============================================================= -void MakeBrush( BRUSH *brush ){ - NodePtr node( Brush_AllocNode() ); +void MakeBrush(BRUSH *brush) +{ + NodePtr node(Brush_AllocNode()); #if 0 - for ( int i = 0; i < brush->NumFaces; i++ ) + for ( int i = 0; i < brush->NumFaces; i++ ) { _QERFaceData QERFaceData; if ( !strncmp( brush->face[i].texture, "textures/", 9 ) ) { @@ -2069,20 +1967,24 @@ void MakeBrush( BRUSH *brush ){ } #endif - Node_getTraversable( h_func_group )->insert( node ); + Node_getTraversable(h_func_group)->insert(node); } + //============================================================= -void OpenFuncGroup(){ - h_func_group = GlobalEntityCreator().createEntity( "func_group" ); - h_func_group->IncRef(); - if ( AddTerrainKey ) { - h_func_group->m_entity->setkeyvalue( "terrain", "1" ); - } +void OpenFuncGroup() +{ + h_func_group = GlobalEntityCreator().createEntity("func_group"); + h_func_group->IncRef(); + if (AddTerrainKey) { + h_func_group->m_entity->setkeyvalue("terrain", "1"); + } } + //============================================================= -void CloseFuncGroup(){ - h_func_group->DecRef(); - if ( g_FuncTable.m_pfnSysUpdateWindows != NULL ) { - g_FuncTable.m_pfnSysUpdateWindows( W_ALL ); - } +void CloseFuncGroup() +{ + h_func_group->DecRef(); + if (g_FuncTable.m_pfnSysUpdateWindows != NULL) { + g_FuncTable.m_pfnSysUpdateWindows(W_ALL); + } } diff --git a/contrib/gtkgensurf/gensurf.cpp b/contrib/gtkgensurf/gensurf.cpp index 1be8b135..8c998778 100644 --- a/contrib/gtkgensurf/gensurf.cpp +++ b/contrib/gtkgensurf/gensurf.cpp @@ -40,7 +40,7 @@ double TexScale[2]; double WaveLength; double Hll, Hur, Vll, Vur; double Z00, Z01, Z10, Z11; -ELEMENT Vertex[( MAX_ROWS + 1 ) * ( MAX_ROWS + 1 )]; +ELEMENT Vertex[(MAX_ROWS + 1) * (MAX_ROWS + 1)]; int AddHints; int ArghRad2; int AutoOverwrite; @@ -77,17 +77,17 @@ GtkWidget *g_pRadiantWnd; // ghwnd_main; */GtkWidget *g_pWndPreview; GtkWidget *g_pPreviewWidget; MYBITMAP gbmp; -NODE *gNode = (NODE *)NULL; -TRI *gTri = (TRI *)NULL; +NODE *gNode = (NODE *) NULL; +TRI *gTri = (TRI *) NULL; int Game; -bounding_box PlayerBox[NUMGAMES] = { {{-16., 16.}, {-16., 16.}, {-24., 32.}}, // Quake2 - {{-16., 16.}, {-16., 16.}, {-36., 36.}}, // Half-Life - {{-16., 16.}, {-16., 16.}, {-32., 32.}}, // SiN - {{-16., 16.}, {-16., 16.}, {-24., 32.}}, // Heretic2 (guess) - {{-16., 16.}, {-16., 16.}, {-24., 32.}}, // KingPin (guess) - {{-30., 30.}, {-30., 30.}, {-10.,160.}}, // Genesis3D (no idea) - {{-16., 16.}, {-16., 16.}, {-24., 32.}}}; // Quake3 (not sure) +bounding_box PlayerBox[NUMGAMES] = {{{-16., 16.}, {-16., 16.}, {-24., 32.}}, // Quake2 + {{-16., 16.}, {-16., 16.}, {-36., 36.}}, // Half-Life + {{-16., 16.}, {-16., 16.}, {-32., 32.}}, // SiN + {{-16., 16.}, {-16., 16.}, {-24., 32.}}, // Heretic2 (guess) + {{-16., 16.}, {-16., 16.}, {-24., 32.}}, // KingPin (guess) + {{-30., 30.}, {-30., 30.}, {-10., 160.}}, // Genesis3D (no idea) + {{-16., 16.}, {-16., 16.}, {-24., 32.}}}; // Quake3 (not sure) //char gszOutputDir[NUMGAMES][NAME_MAX]; //char gszTextureDir[NUMGAMES][NAME_MAX]; char Texture[NUMGAMES][3][64]; @@ -96,19 +96,20 @@ char Texture[NUMGAMES][3][64]; //int UsePak[NUMGAMES]; //char GameDir[NUMGAMES][NAME_MAX]; -char GameName[NUMGAMES][16] = {"Quake2", "Half-Life", "SiN", "Heretic2", "Kingpin", "Genesis3D", "Quake3" }; +char GameName[NUMGAMES][16] = {"Quake2", "Half-Life", "SiN", "Heretic2", "Kingpin", "Genesis3D", "Quake3"}; -bool GenSurfInit(){ - strcpy( gszVersion, "1.05" ); - strcpy( gszCaption, "GtkGenSurf" ); - if ( strlen( gszVersion ) ) { - strcat( gszCaption, " v" ); - strcat( gszCaption, gszVersion ); - } +bool GenSurfInit() +{ + strcpy(gszVersion, "1.05"); + strcpy(gszCaption, "GtkGenSurf"); + if (strlen(gszVersion)) { + strcat(gszCaption, " v"); + strcat(gszCaption, gszVersion); + } - strcpy( gszIni, g_FuncTable.m_pfnProfileGetDirectory() ); - strcat( gszIni, "gensurf.ini" ); + strcpy(gszIni, g_FuncTable.m_pfnProfileGetDirectory()); + strcat(gszIni, "gensurf.ini"); /*if (g_FuncTable.m_pfnReadProjectKey != NULL) { @@ -129,214 +130,203 @@ bool GenSurfInit(){ Game = QUAKE3; } else */ - Game = QUAKE3; + Game = QUAKE3; - if ( g_pWnd == NULL ) { - g_pWnd = create_main_dialog(); - } + if (g_pWnd == NULL) { + g_pWnd = create_main_dialog(); + } - ReadIniFile( gszIni ); + ReadIniFile(gszIni); - return true; + return true; } // Reads default values #define OPTS_SECTION "Options" -void ReadIniFile( const char *file ){ - char *Text; - float x1,x2,x3,x4; - int i; - - Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "Amplitude", "" ); - if ( strlen( Text ) ) { - Amplitude = atof( Text ); - } - else{ - Amplitude = 128; - } - - Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "Roughness", "" ); - if ( strlen( Text ) ) { - Roughness = atof( Text ); - } - else{ - Roughness = 16; - } - - Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "WaveLength", "" ); - if ( strlen( Text ) ) { - WaveLength = atof( Text ); - } - else{ - WaveLength = 1024; - } - - Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "Extents", "" ); - if ( strlen( Text ) ) { - sscanf( Text,"%f,%f,%f,%f",&x1,&x2,&x3,&x4 ); - Hll = x1; - Vll = x2; - Hur = x3; - Vur = x4; - } - else - { - Hll = -512; - Vll = -512; - Hur = 512; - Vur = 512; - } - - Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "CornerValues", "" ); - if ( strlen( Text ) ) { - sscanf( Text,"%f,%f,%f,%f",&x1,&x2,&x3,&x4 ); - Z00 = x1; - Z01 = x2; - Z10 = x3; - Z11 = x4; - } - else - { - Z00 = 0.; - Z01 = 0.; - Z10 = 0.; - Z11 = 0.; - } - - Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "TextureOffset", "" ); - if ( strlen( Text ) ) { - sscanf( Text,"%f,%f",&x1,&x2 ); - TexOffset[0] = x1; - TexOffset[1] = x2; - } - else - { - TexOffset[0] = 0.; - TexOffset[1] = 0.; - } - - Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION,"TextureScale","" ); - if ( strlen( Text ) ) { - sscanf( Text,"%f,%f",&x1,&x2 ); - TexScale[0] = x1; - TexScale[1] = x2; - if ( TexScale[0] == 0. ) { - TexScale[0] = 1.0; - } - if ( TexScale[1] == 0. ) { - TexScale[1] = 1.0; - } - } - else - { - TexScale[0] = 1.; - TexScale[1] = 1.; - } - - NH = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"NH",8 ); - NH = max( 1,min( NH,MAX_ROWS ) ); - NV = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"NV",8 ); - NV = max( 1,min( NV,MAX_ROWS ) ); +void ReadIniFile(const char *file) +{ + char *Text; + float x1, x2, x3, x4; + int i; + + Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "Amplitude", ""); + if (strlen(Text)) { + Amplitude = atof(Text); + } else { + Amplitude = 128; + } + + Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "Roughness", ""); + if (strlen(Text)) { + Roughness = atof(Text); + } else { + Roughness = 16; + } + + Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "WaveLength", ""); + if (strlen(Text)) { + WaveLength = atof(Text); + } else { + WaveLength = 1024; + } + + Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "Extents", ""); + if (strlen(Text)) { + sscanf(Text, "%f,%f,%f,%f", &x1, &x2, &x3, &x4); + Hll = x1; + Vll = x2; + Hur = x3; + Vur = x4; + } else { + Hll = -512; + Vll = -512; + Hur = 512; + Vur = 512; + } + + Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "CornerValues", ""); + if (strlen(Text)) { + sscanf(Text, "%f,%f,%f,%f", &x1, &x2, &x3, &x4); + Z00 = x1; + Z01 = x2; + Z10 = x3; + Z11 = x4; + } else { + Z00 = 0.; + Z01 = 0.; + Z10 = 0.; + Z11 = 0.; + } + + Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "TextureOffset", ""); + if (strlen(Text)) { + sscanf(Text, "%f,%f", &x1, &x2); + TexOffset[0] = x1; + TexOffset[1] = x2; + } else { + TexOffset[0] = 0.; + TexOffset[1] = 0.; + } + + Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "TextureScale", ""); + if (strlen(Text)) { + sscanf(Text, "%f,%f", &x1, &x2); + TexScale[0] = x1; + TexScale[1] = x2; + if (TexScale[0] == 0.) { + TexScale[0] = 1.0; + } + if (TexScale[1] == 0.) { + TexScale[1] = 1.0; + } + } else { + TexScale[0] = 1.; + TexScale[1] = 1.; + } + + NH = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "NH", 8); + NH = max(1, min(NH, MAX_ROWS)); + NV = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "NV", 8); + NV = max(1, min(NV, MAX_ROWS)); // Decimate = GetPrivateProfileInt(OPTS_SECTION,"Decimate",0,file); // Decimate = max(0,min(Decimate,100)); - AddHints = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"AddHints",0 ); - ArghRad2 = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"ArghRad2",0 ); - AutoOverwrite = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"AutoOverwrite",0 ); - FixBorders = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"FixBorders",1 ); - HideBackFaces = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"HideBackFaces",0 ); - Plane = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Plane",0 ); - Preview = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Preview", 0 ); - Antialiasing = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Antialiasing",0 ); // ^Fishman - Antializing for the preview window. - RandomSeed = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"RandomSeed",1 ); - Skybox = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Skybox",0 ); - UseDetail = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"UseDetail",0 ); - AddTerrainKey = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"AddTerrainKey",0 ); // ^Fishman - Add terrain key to func_group. - UseLadder = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"UseLadder",0 ); - WaveType = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"WaveType",0 ); - vid_x = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"vid_x", 0 ); - vid_y = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"vid_y", 0 ); - view_x = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_x",0 ); - view_y = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_y",0 ); - view_cx = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_cx",0 ); - view_cy = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_cy",0 ); - - UsePatches = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"UsePatches",0 ); - - SlantAngle = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"SlantAngle",60 ); - GimpHints = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"GimpHints",0 ); - - for ( i = 0; i < NUMGAMES; i++ ) - { - // strcpy (gszOutputDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"OutputDir","")); - strcpy( Texture[i][0], g_FuncTable.m_pfnProfileLoadString( file, GameName[i], "Texture", "" ) ); - strcpy( Texture[i][1], g_FuncTable.m_pfnProfileLoadString( file, GameName[i], "Texture2", "" ) ); - strcpy( Texture[i][2], g_FuncTable.m_pfnProfileLoadString( file, GameName[i], "Texture3", "" ) ); - // strcpy (gszTextureDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"TextureDir","")); - // UsePak[i] = GetPrivateProfileInt(GameName[i],"UsePak",0); - // strcpy (pakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"PakFile","")); - // strcpy (lastpakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"LastPakFile","")); - // strcpy (GameDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"GameDir","\0")); - } - /* - if(!strlen(gszTextureDir[QUAKE2])) - strcpy(gszTextureDir[QUAKE2],"c:\\quake2\\baseq2\\textures\\"); - if(!strlen(gszTextureDir[KINGPIN])) - strcpy(gszTextureDir[KINGPIN],"c:\\kingpin\\main\\textures\\"); - */ - if ( !strlen( Texture[QUAKE2][0] ) ) { - strcpy( Texture[QUAKE2][0], "textures/e1u1/grass1_4" ); - } - if ( !strlen( Texture[HALFLIFE][0] ) ) { - strcpy( Texture[HALFLIFE][0], "textures/OUT_GRND1" ); - } - if ( !strlen( Texture[SIN][0] ) ) { - strcpy( Texture[SIN][0], "textures/generic/floor_organic/fl_grass" ); - } - if ( !strlen( Texture[HERETIC2][0] ) ) { - strcpy( Texture[HERETIC2][0], "textures/canyon/canyon05" ); - } - if ( !strlen( Texture[KINGPIN][0] ) ) { - strcpy( Texture[KINGPIN][0], "textures/bricks/s_sr_m3" ); - } - if ( !strlen( Texture[GENESIS3D][0] ) ) { - strcpy( Texture[GENESIS3D][0],"textures/rock13" ); - } - if ( !strlen( Texture[QUAKE3][0] ) ) { - strcpy( Texture[QUAKE3][0], "textures/organics/grass3" ); - } - if ( !strlen( Texture[QUAKE3][1] ) ) { - strcpy( Texture[QUAKE3][1], "textures/common/caulk" ); - } - strcpy( gbmp.name, g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","Filename","" ) ); - - - gbmp.colors = NULL; - if ( strlen( gbmp.name ) ) { - OpenBitmap(); - } - - strcpy( gbmp.defpath, g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","DefaultPath","" ) ); - - Text = g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","BlackValue","" ); - if ( strlen( Text ) ) { - gbmp.black_value = atof( Text ); - } - else{ - gbmp.black_value = 0; - } - - Text = g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","WhiteValue","" ); - if ( strlen( Text ) ) { - gbmp.white_value = atof( Text ); - } - else{ - gbmp.white_value = 256.; - } + AddHints = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "AddHints", 0); + ArghRad2 = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "ArghRad2", 0); + AutoOverwrite = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "AutoOverwrite", 0); + FixBorders = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "FixBorders", 1); + HideBackFaces = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "HideBackFaces", 0); + Plane = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "Plane", 0); + Preview = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "Preview", 0); + Antialiasing = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "Antialiasing", + 0); // ^Fishman - Antializing for the preview window. + RandomSeed = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "RandomSeed", 1); + Skybox = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "Skybox", 0); + UseDetail = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "UseDetail", 0); + AddTerrainKey = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "AddTerrainKey", + 0); // ^Fishman - Add terrain key to func_group. + UseLadder = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "UseLadder", 0); + WaveType = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "WaveType", 0); + vid_x = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "vid_x", 0); + vid_y = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "vid_y", 0); + view_x = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "view_x", 0); + view_y = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "view_y", 0); + view_cx = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "view_cx", 0); + view_cy = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "view_cy", 0); + + UsePatches = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "UsePatches", 0); + + SlantAngle = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "SlantAngle", 60); + GimpHints = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "GimpHints", 0); + + for (i = 0; i < NUMGAMES; i++) { + // strcpy (gszOutputDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"OutputDir","")); + strcpy(Texture[i][0], g_FuncTable.m_pfnProfileLoadString(file, GameName[i], "Texture", "")); + strcpy(Texture[i][1], g_FuncTable.m_pfnProfileLoadString(file, GameName[i], "Texture2", "")); + strcpy(Texture[i][2], g_FuncTable.m_pfnProfileLoadString(file, GameName[i], "Texture3", "")); + // strcpy (gszTextureDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"TextureDir","")); + // UsePak[i] = GetPrivateProfileInt(GameName[i],"UsePak",0); + // strcpy (pakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"PakFile","")); + // strcpy (lastpakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"LastPakFile","")); + // strcpy (GameDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"GameDir","\0")); + } + /* + if(!strlen(gszTextureDir[QUAKE2])) + strcpy(gszTextureDir[QUAKE2],"c:\\quake2\\baseq2\\textures\\"); + if(!strlen(gszTextureDir[KINGPIN])) + strcpy(gszTextureDir[KINGPIN],"c:\\kingpin\\main\\textures\\"); + */ + if (!strlen(Texture[QUAKE2][0])) { + strcpy(Texture[QUAKE2][0], "textures/e1u1/grass1_4"); + } + if (!strlen(Texture[HALFLIFE][0])) { + strcpy(Texture[HALFLIFE][0], "textures/OUT_GRND1"); + } + if (!strlen(Texture[SIN][0])) { + strcpy(Texture[SIN][0], "textures/generic/floor_organic/fl_grass"); + } + if (!strlen(Texture[HERETIC2][0])) { + strcpy(Texture[HERETIC2][0], "textures/canyon/canyon05"); + } + if (!strlen(Texture[KINGPIN][0])) { + strcpy(Texture[KINGPIN][0], "textures/bricks/s_sr_m3"); + } + if (!strlen(Texture[GENESIS3D][0])) { + strcpy(Texture[GENESIS3D][0], "textures/rock13"); + } + if (!strlen(Texture[QUAKE3][0])) { + strcpy(Texture[QUAKE3][0], "textures/organics/grass3"); + } + if (!strlen(Texture[QUAKE3][1])) { + strcpy(Texture[QUAKE3][1], "textures/common/caulk"); + } + strcpy(gbmp.name, g_FuncTable.m_pfnProfileLoadString(file, "Bitmap", "Filename", "")); + + + gbmp.colors = NULL; + if (strlen(gbmp.name)) { + OpenBitmap(); + } + + strcpy(gbmp.defpath, g_FuncTable.m_pfnProfileLoadString(file, "Bitmap", "DefaultPath", "")); + + Text = g_FuncTable.m_pfnProfileLoadString(file, "Bitmap", "BlackValue", ""); + if (strlen(Text)) { + gbmp.black_value = atof(Text); + } else { + gbmp.black_value = 0; + } + + Text = g_FuncTable.m_pfnProfileLoadString(file, "Bitmap", "WhiteValue", ""); + if (strlen(Text)) { + gbmp.white_value = atof(Text); + } else { + gbmp.white_value = 256.; + } } /* @@ -348,141 +338,141 @@ void ReadIniFile( const char *file ){ FIXME: make this buffer size safe someday ============ */ -char *va( const char *format, ... ){ - va_list argptr; - static char string[1024]; +char *va(const char *format, ...) +{ + va_list argptr; + static char string[1024]; - va_start( argptr, format ); - vsprintf( string, format,argptr ); - va_end( argptr ); + va_start(argptr, format); + vsprintf(string, format, argptr); + va_end(argptr); - return string; + return string; } // Writes current values to INI file -void WriteIniFile( const char *file ){ - int i; - - g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "Amplitude", va( "%g",Amplitude ) ); - g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "Roughness", va( "%g",Roughness ) ); - g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "WaveLength", va( "%g",WaveLength ) ); - g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "Extents", va( "%g,%g,%g,%g",Hll,Vll,Hur,Vur ) ); - g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "CornerValues", va( "%g,%g,%g,%g",Z00,Z01,Z10,Z11 ) ); - g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "TextureOffset",va( "%g,%g",TexOffset[0],TexOffset[1] ) ); - g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "TextureScale", va( "%g,%g",TexScale[0],TexScale[1] ) ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "NH", NH ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "NV", NV ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "AddHints", AddHints ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "ArghRad2", ArghRad2 ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "AutoOverwrite", AutoOverwrite ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "FixBorders", FixBorders ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Plane", Plane ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Preview", Preview ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Antialiasing", Antialiasing ); // ^Fishman - Antializing for the preview window. - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "RandomSeed", RandomSeed ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Skybox", Skybox ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "UseDetail", UseDetail ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "AddTerrainKey", AddTerrainKey ); // ^Fishman - Add terrain key to func_group. - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "UseLadder", UseLadder ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "WaveType", WaveType ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "vid_x", vid_x ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "vid_y", vid_y ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_x", view_x ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_y", view_y ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_cx", view_cx ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_cy", view_cy ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "UsePatches", UsePatches ); - g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "SlantAngle", SlantAngle ); - for ( i = 0; i < NUMGAMES; i++ ) - { - g_FuncTable.m_pfnProfileSaveString( file, GameName[i], "Texture", Texture[i][0] ); - g_FuncTable.m_pfnProfileSaveString( file, GameName[i], "Texture2", Texture[i][1] ); - g_FuncTable.m_pfnProfileSaveString( file, GameName[i], "Texture3", Texture[i][2] ); - } - - g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "Filename", gbmp.name ); - g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "DefaultPath", gbmp.defpath ); - g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "BlackValue", va( "%g",gbmp.black_value ) ); - g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "WhiteValue", va( "%g",gbmp.white_value ) ); +void WriteIniFile(const char *file) +{ + int i; + + g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "Amplitude", va("%g", Amplitude)); + g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "Roughness", va("%g", Roughness)); + g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "WaveLength", va("%g", WaveLength)); + g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "Extents", va("%g,%g,%g,%g", Hll, Vll, Hur, Vur)); + g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "CornerValues", va("%g,%g,%g,%g", Z00, Z01, Z10, Z11)); + g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "TextureOffset", va("%g,%g", TexOffset[0], TexOffset[1])); + g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "TextureScale", va("%g,%g", TexScale[0], TexScale[1])); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "NH", NH); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "NV", NV); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "AddHints", AddHints); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "ArghRad2", ArghRad2); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "AutoOverwrite", AutoOverwrite); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "FixBorders", FixBorders); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "Plane", Plane); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "Preview", Preview); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "Antialiasing", + Antialiasing); // ^Fishman - Antializing for the preview window. + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "RandomSeed", RandomSeed); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "Skybox", Skybox); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "UseDetail", UseDetail); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "AddTerrainKey", + AddTerrainKey); // ^Fishman - Add terrain key to func_group. + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "UseLadder", UseLadder); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "WaveType", WaveType); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "vid_x", vid_x); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "vid_y", vid_y); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "view_x", view_x); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "view_y", view_y); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "view_cx", view_cx); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "view_cy", view_cy); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "UsePatches", UsePatches); + g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "SlantAngle", SlantAngle); + for (i = 0; i < NUMGAMES; i++) { + g_FuncTable.m_pfnProfileSaveString(file, GameName[i], "Texture", Texture[i][0]); + g_FuncTable.m_pfnProfileSaveString(file, GameName[i], "Texture2", Texture[i][1]); + g_FuncTable.m_pfnProfileSaveString(file, GameName[i], "Texture3", Texture[i][2]); + } + + g_FuncTable.m_pfnProfileSaveString(file, "Bitmap", "Filename", gbmp.name); + g_FuncTable.m_pfnProfileSaveString(file, "Bitmap", "DefaultPath", gbmp.defpath); + g_FuncTable.m_pfnProfileSaveString(file, "Bitmap", "BlackValue", va("%g", gbmp.black_value)); + g_FuncTable.m_pfnProfileSaveString(file, "Bitmap", "WhiteValue", va("%g", gbmp.white_value)); //g_FuncTable.m_pfnProfileSaveString (file, "Formula", "Formula", ExcelFunc ); } -void UpdatePreview( bool DataChange ){ - if ( g_pWndPreview && gtk_widget_get_visible( g_pWndPreview ) ) { - if ( DataChange ) { - GenerateXYZ(); - } +void UpdatePreview(bool DataChange) +{ + if (g_pWndPreview && gtk_widget_get_visible(g_pWndPreview)) { + if (DataChange) { + GenerateXYZ(); + } - gtk_widget_draw( g_pPreviewWidget, NULL ); - } + gtk_widget_draw(g_pPreviewWidget, NULL); + } } -void SaveSetup( GtkWidget *parent ){ - const char *name = g_FuncTable.m_pfnFileDialog( parent, false, "Save GenSurf Settings", - g_FuncTable.m_pfnProfileGetDirectory() ); - - if ( name != NULL ) { - char key[32], text[32]; - int i, j; - - WriteIniFile( name ); - g_FuncTable.m_pfnProfileSaveString( name, OPTS_SECTION,"MapFile",gszMapFile ); - sprintf( text,"0x%04x",FileAppend ); - g_FuncTable.m_pfnProfileSaveString( name, OPTS_SECTION,"Append",text ); - sprintf( text,"0x%04x",Decimate ); - g_FuncTable.m_pfnProfileSaveString( name, OPTS_SECTION,"Decimate",text ); - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - if ( xyz[i][j].fixed ) { - sprintf( key,"I%dJ%d",i,j ); - sprintf( text,"%g %g %g", xyz[i][j].fixed_value, xyz[i][j].range, xyz[i][j].rate ); - g_FuncTable.m_pfnProfileSaveString( name, "FixedPoints",key,text ); - } - } - } - } +void SaveSetup(GtkWidget *parent) +{ + const char *name = g_FuncTable.m_pfnFileDialog(parent, false, "Save GenSurf Settings", + g_FuncTable.m_pfnProfileGetDirectory()); + + if (name != NULL) { + char key[32], text[32]; + int i, j; + + WriteIniFile(name); + g_FuncTable.m_pfnProfileSaveString(name, OPTS_SECTION, "MapFile", gszMapFile); + sprintf(text, "0x%04x", FileAppend); + g_FuncTable.m_pfnProfileSaveString(name, OPTS_SECTION, "Append", text); + sprintf(text, "0x%04x", Decimate); + g_FuncTable.m_pfnProfileSaveString(name, OPTS_SECTION, "Decimate", text); + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + if (xyz[i][j].fixed) { + sprintf(key, "I%dJ%d", i, j); + sprintf(text, "%g %g %g", xyz[i][j].fixed_value, xyz[i][j].range, xyz[i][j].rate); + g_FuncTable.m_pfnProfileSaveString(name, "FixedPoints", key, text); + } + } + } + } } -void OpenSetup( GtkWidget *parent, int UseDefaults ){ - const char *name; - char key[32], *text; - float value,range,rate; - int i, j; - - if ( UseDefaults ) { - name = g_strdup( "plugins/defaults.srf" ); // dummy string - } - else{ - name = g_FuncTable.m_pfnFileDialog( parent, true, "Open GenSurf Settings", - g_FuncTable.m_pfnProfileGetDirectory() ); - } - - if ( name != NULL ) { - ReadIniFile( name ); - Decimate = g_FuncTable.m_pfnProfileLoadInt( name, OPTS_SECTION,"Decimate",0 ); - Decimate = max( 0,min( Decimate,100 ) ); - - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - sprintf( key,"I%dJ%d",i,j ); - text = g_FuncTable.m_pfnProfileLoadString( name, "FixedPoints", key, "" ); - if ( strlen( text ) ) { - xyz[i][j].fixed = 1; - xyz[i][j].rate = 0.; - sscanf( text,"%g %g %g",&value,&range,&rate ); - xyz[i][j].fixed_value = value; - xyz[i][j].range = range; - xyz[i][j].rate = rate; - } - else{ - xyz[i][j].fixed = 0; - } - } - } - } +void OpenSetup(GtkWidget *parent, int UseDefaults) +{ + const char *name; + char key[32], *text; + float value, range, rate; + int i, j; + + if (UseDefaults) { + name = g_strdup("plugins/defaults.srf"); // dummy string + } else { + name = g_FuncTable.m_pfnFileDialog(parent, true, "Open GenSurf Settings", + g_FuncTable.m_pfnProfileGetDirectory()); + } + + if (name != NULL) { + ReadIniFile(name); + Decimate = g_FuncTable.m_pfnProfileLoadInt(name, OPTS_SECTION, "Decimate", 0); + Decimate = max(0, min(Decimate, 100)); + + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + sprintf(key, "I%dJ%d", i, j); + text = g_FuncTable.m_pfnProfileLoadString(name, "FixedPoints", key, ""); + if (strlen(text)) { + xyz[i][j].fixed = 1; + xyz[i][j].rate = 0.; + sscanf(text, "%g %g %g", &value, &range, &rate); + xyz[i][j].fixed_value = value; + xyz[i][j].range = range; + xyz[i][j].rate = rate; + } else { + xyz[i][j].fixed = 0; + } + } + } + } } diff --git a/contrib/gtkgensurf/gensurf.h b/contrib/gtkgensurf/gensurf.h index 84a78cd6..39d763a4 100644 --- a/contrib/gtkgensurf/gensurf.h +++ b/contrib/gtkgensurf/gensurf.h @@ -27,23 +27,32 @@ #include "mathlib.h" #include "iscenegraph.h" + #define USE_QERTABLE_DEFINE + #include "qerplugin.h" + extern _QERFuncTable_1 g_FuncTable; #include "irender.h" #include "iselection.h" #define USE_ENTITYTABLE_DEFINE + #include "ientity.h" + extern _QEREntityTable __ENTITYTABLENAME; #define USE_PATCHTABLE_DEFINE + #include "ipatch.h" + extern _QERPatchTable __PATCHTABLENAME; #define USE_BRUSHTABLE_DEFINE + #include "ibrush.h" + extern _QERBrushTable __BRUSHTABLENAME; #include "igl.h" @@ -59,7 +68,9 @@ extern _QERBrushTable __BRUSHTABLENAME; //#if GDEF_OS_LINUX || GDEF_OS_MACOS #if 1 + #include + #else template inline T min( T x, T y ) { return ( x < y ) ? x : y; } @@ -72,24 +83,25 @@ typedef struct { long left, top, right, bottom; } Rect; #define NAME_MAX 255 -typedef void* LPVOID; -typedef char* LPSTR; +typedef void *LPVOID; +typedef char *LPSTR; //#endif -inline bool PtInRect( Rect *rc, Point pt ){ - if ( pt.x < rc->left ) { - return false; - } - if ( pt.x > rc->right ) { - return false; - } - if ( pt.y < rc->bottom ) { - return false; - } - if ( pt.y > rc->top ) { - return false; - } - return true; +inline bool PtInRect(Rect *rc, Point pt) +{ + if (pt.x < rc->left) { + return false; + } + if (pt.x > rc->right) { + return false; + } + if (pt.y < rc->bottom) { + return false; + } + if (pt.y > rc->top) { + return false; + } + return true; } #define NUMGAMES 7 @@ -102,8 +114,8 @@ inline bool PtInRect( Rect *rc, Point pt ){ #define HINT_OFFSET 96 #define PI 3.14159265358979224 -#define RadiansToDegrees( a ) ( floor( a * 57.2957795 - 0.5 ) + 1. ) -#define DegreesToRadians( a ) ( a / 57.2957795 ) +#define RadiansToDegrees(a) ( floor( a * 57.2957795 - 0.5 ) + 1. ) +#define DegreesToRadians(a) ( a / 57.2957795 ) #define BOGUS_RANGE 65536 /* @@ -114,8 +126,8 @@ inline bool PtInRect( Rect *rc, Point pt ){ #define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];} #define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];} */ -#define XYZVectorSubtract( a,b,c ) {c[0] = (float)a[0] - (float)b[0]; c[1] = (float)a[1] - (float)b[1]; c[2] = (float)a[2] - (float)b[2]; } -#define side( u1,v1,u2,v2,u3,v3 ) ( v3 - v1 ) * ( u2 - u1 ) - ( u3 - u1 ) * ( v2 - v1 ) +#define XYZVectorSubtract(a, b, c) {c[0] = (float)a[0] - (float)b[0]; c[1] = (float)a[1] - (float)b[1]; c[2] = (float)a[2] - (float)b[2]; } +#define side(u1, v1, u2, v2, u3, v3) ( v3 - v1 ) * ( u2 - u1 ) - ( u3 - u1 ) * ( v2 - v1 ) #define QUAKE2 0 #define HALFLIFE 1 @@ -134,189 +146,211 @@ typedef float vec; typedef vec vec3[3]; typedef vec vec2[2]; -typedef struct -{ - vec3 v[3]; - char texture[64]; - float Shift[2]; - float Rotate; - float Scale[2]; - int Contents; - int Surface; - int Value; +typedef struct { + vec3 v[3]; + char texture[64]; + float Shift[2]; + float Rotate; + float Scale[2]; + int Contents; + int Surface; + int Value; } FACE; -typedef struct -{ - vec3 normal; - vec dist; +typedef struct { + vec3 normal; + vec dist; } PLANE; -typedef struct -{ - int numpoints; - vec3 p[4]; // variable sized +typedef struct { + int numpoints; + vec3 p[4]; // variable sized } MY_WINDING; -typedef struct -{ - int Number; - int NumFaces; - FACE face[MAX_FACES_PER_BRUSH]; +typedef struct { + int Number; + int NumFaces; + FACE face[MAX_FACES_PER_BRUSH]; } BRUSH; -typedef struct tagXYZ -{ - int fixed; - int done; - double p[3]; - double pp[3]; // these used only for general 3D projection (not isometric) - double fixed_value; - double range; - double rate; +typedef struct tagXYZ { + int fixed; + int done; + double p[3]; + double pp[3]; // these used only for general 3D projection (not isometric) + double fixed_value; + double range; + double rate; } XYZ; // Q2 PAK file structures -typedef struct -{ - char id[4]; // Should be 'PACK' - int dstart; // Offest in the file to the directory - int dsize; // Size in bytes of the directory, same as num_items*64 +typedef struct { + char id[4]; // Should be 'PACK' + int dstart; // Offest in the file to the directory + int dsize; // Size in bytes of the directory, same as num_items*64 } pak_header_t; -typedef struct -{ - char name[56]; // The name of the item, normal C string - int start; // Offset in .pak file to start of item - int size; // Size of item in bytes +typedef struct { + char name[56]; // The name of the item, normal C string + int start; // Offset in .pak file to start of item + int size; // Size of item in bytes } pak_item_t; // SiN .SIN structures #define SINPAKHEADER ( ( 'K' << 24 ) + ( 'A' << 16 ) + ( 'P' << 8 ) + 'S' ) #define MAX_PAK_FILENAME_LENGTH 120 -typedef struct -{ - char name[MAX_PAK_FILENAME_LENGTH]; - int filepos, filelen; +typedef struct { + char name[MAX_PAK_FILENAME_LENGTH]; + int filepos, filelen; } dpackfile_t; -typedef struct -{ - int ident; // == IDPAKHEADER - int dirofs; - int dirlen; +typedef struct { + int ident; // == IDPAKHEADER + int dirofs; + int dirlen; } dpackheader_t; // Half-Life WAD file structures -typedef struct -{ - char identification[4]; // should be WAD2 or 2DAW - int numlumps; - int infotableofs; +typedef struct { + char identification[4]; // should be WAD2 or 2DAW + int numlumps; + int infotableofs; } wadinfo_t; -typedef struct -{ - int filepos; - int disksize; - int size; // uncompressed - char type; - char compression; - char pad1, pad2; - char name[16]; // must be null terminated +typedef struct { + int filepos; + int disksize; + int size; // uncompressed + char type; + char compression; + char pad1, pad2; + char name[16]; // must be null terminated } lumpinfo_t; -typedef struct -{ - int signature; - short version; - short bitflag; - short compression_method; - short modfiletime; - short modfiledate; - int crc; - int compressed_size; - int uncompressed_size; - short filename_size; - short extra_size; +typedef struct { + int signature; + short version; + short bitflag; + short compression_method; + short modfiletime; + short modfiledate; + int crc; + int compressed_size; + int uncompressed_size; + short filename_size; + short extra_size; } zipheader_t; -typedef struct -{ - double x[2]; - double y[2]; - double z[2]; +typedef struct { + double x[2]; + double y[2]; + double z[2]; } bounding_box; -typedef struct -{ - float p[3]; - int used; - int tri; - float error; - int fixed; +typedef struct { + float p[3]; + int used; + int tri; + float error; + int fixed; } NODE; -typedef struct -{ - int v[3]; - int n[3]; // indices of neighboring triangles - PLANE plane; - int flag; - float min[3]; - float max[3]; +typedef struct { + int v[3]; + int n[3]; // indices of neighboring triangles + PLANE plane; + int flag; + float min[3]; + float max[3]; } TRI; //--------------- bitmap.c ----------------------------- bool OpenBitmap(); -double CalculateSnapValue( double value ); + +double CalculateSnapValue(double value); + void GenerateBitmapMapping(); + //--------------- face.c ------------------------------- -void PlaneFromPoints( float *, float *, float *, PLANE * ); +void PlaneFromPoints(float *, float *, float *, PLANE *); + //void CrossProduct (vec3 v1, vec3 v2, vec3 cross); //vec VectorNormalize (vec3 in, vec3 out); //--------------- gendlg.c ----------------------------- -GtkWidget* create_main_dialog(); -void About( GtkWidget *parent ); +GtkWidget *create_main_dialog(); + +void About(GtkWidget *parent); + //--------------- genmap.c ----------------------------- -double AtLeast( double,double ); -bool CanEdit( int, int ); +double AtLeast(double, double); + +bool CanEdit(int, int); + void CloseFuncGroup(); -bool FixedPoint( int,int ); + +bool FixedPoint(int, int); + void GenerateMap(); + void GenerateXYZ(); -double LessThan( double,double ); -void MakeBrush( BRUSH * ); -double MoreThan( double,double ); -double Nearest( double,double ); -double NoMoreThan( double,double ); + +double LessThan(double, double); + +void MakeBrush(BRUSH *); + +double MoreThan(double, double); + +double Nearest(double, double); + +double NoMoreThan(double, double); + void OpenFuncGroup(); + void PlasmaCloud(); -int PlayerStartZ( double,double ); -void SubdividePlasma( int,int,int,int ); + +int PlayerStartZ(double, double); + +void SubdividePlasma(int, int, int, int); + bool ValidSurface(); -void XYZtoV( XYZ *, vec3 * ); -scene::Node* MakePatch( void ); + +void XYZtoV(XYZ *, vec3 *); + +scene::Node *MakePatch(void); //---------------- gensurf.c --------------------------- bool GenSurfInit(); -void ReadIniFile( const char * ); -void WriteIniFile( const char * ); -void OpenSetup( GtkWidget*,int ); -void SaveSetup( GtkWidget* ); + +void ReadIniFile(const char *); + +void WriteIniFile(const char *); + +void OpenSetup(GtkWidget *, int); + +void SaveSetup(GtkWidget *); + //---------------- heretic.c --------------------------- -int GetDefSurfaceProps( char * ); +int GetDefSurfaceProps(char *); + //---------------- view.c ------------------------------ void CreateViewWindow(); -void DrawGrid( Rect ); -void DrawPreview( Rect ); + +void DrawGrid(Rect); + +void DrawPreview(Rect); + void evaluate(); -void GetScaleFactor( Rect ); -void project( XYZ * ); -void Scale( Rect,XYZ,Point * ); + +void GetScaleFactor(Rect); + +void project(XYZ *); + +void Scale(Rect, XYZ, Point *); + void ShowPreview(); -void UpdatePreview( bool ); + +void UpdatePreview(bool); //---------------- plugin.c ----------------------------- void UseFaceBounds(); @@ -347,19 +381,18 @@ extern _QEREntityTable g_EntityTable; #define MSG_VERTEX_SELECTED WM_USER + 1 -typedef struct tagMYBITMAP -{ - char name[NAME_MAX]; - char defpath[NAME_MAX]; - double black_value; - double white_value; - int width, height; - unsigned char* colors; +typedef struct tagMYBITMAP { + char name[NAME_MAX]; + char defpath[NAME_MAX]; + double black_value; + double white_value; + int width, height; + unsigned char *colors; } MYBITMAP; typedef struct tagELEMENT { - int i; - int j; + int i; + int j; } ELEMENT; extern char gszAppDir[NAME_MAX]; @@ -376,7 +409,7 @@ extern double WaveLength; extern double Hll, Hur, Vll, Vur; extern double Z00, Z01, Z10, Z11; extern double yaw, pitch, roll; -extern ELEMENT Vertex[( MAX_ROWS + 1 ) * ( MAX_ROWS + 1 )]; +extern ELEMENT Vertex[(MAX_ROWS + 1) * (MAX_ROWS + 1)]; extern int AddHints; extern int ArghRad2; extern int AutoOverwrite; @@ -416,11 +449,11 @@ extern ui::Window g_pRadiantWnd; extern ui::Window g_pWnd; /*extern HWND ghwndAngles; extern HWND ghwndFix; - */extern GtkWidget *g_pWndPreview; + */extern GtkWidget *g_pWndPreview; extern GtkWidget *g_pPreviewWidget; extern MYBITMAP gbmp; -extern NODE *gNode; -extern TRI *gTri; +extern NODE *gNode; +extern TRI *gTri; extern XYZ xyz[MAX_ROWS + 1][MAX_ROWS + 1]; extern int Game; diff --git a/contrib/gtkgensurf/heretic.cpp b/contrib/gtkgensurf/heretic.cpp index e07a378b..a6fc5693 100644 --- a/contrib/gtkgensurf/heretic.cpp +++ b/contrib/gtkgensurf/heretic.cpp @@ -24,126 +24,125 @@ // Heretic 2 - specific routines -typedef struct palette_s -{ - guint8 r,g,b; +typedef struct palette_s { + guint8 r, g, b; } palette_t; #define MIP_VERSION 2 #define PAL_SIZE 256 #define MIPLEVELS 16 -typedef struct miptex_s -{ - int version; - char name[32]; - unsigned width[MIPLEVELS], height[MIPLEVELS]; - unsigned offsets[MIPLEVELS]; // four mip maps stored - char animname[32]; // next frame in animation chain - palette_t palette[PAL_SIZE]; - int flags; - int contents; - int value; +typedef struct miptex_s { + int version; + char name[32]; + unsigned width[MIPLEVELS], height[MIPLEVELS]; + unsigned offsets[MIPLEVELS]; // four mip maps stored + char animname[32]; // next frame in animation chain + palette_t palette[PAL_SIZE]; + int flags; + int contents; + int value; } miptex_t; //============================================================= -int GetDefSurfaceProps( char *Tex ){ - return 0; // leo: only used for Heretic 2, fix later - /* - char path[NAME_MAX]; - char *p; - int flags; - miptex_t *mt; - FILE *f; - int length; - int pos; +int GetDefSurfaceProps(char *Tex) +{ + return 0; // leo: only used for Heretic 2, fix later + /* + char path[NAME_MAX]; + char *p; + int flags; + miptex_t *mt; + FILE *f; + int length; + int pos; - if(Game != HERETIC2) return 0; - if(!strlen(Tex)) return 0; + if(Game != HERETIC2) return 0; + if(!strlen(Tex)) return 0; - mt = NULL; - flags = 0; - if(UsePak[Game]) - { - FILE *fpak; - pak_header_t pakheader; - pak_item_t pakitem; - int i; - int num; - int numitems; + mt = NULL; + flags = 0; + if(UsePak[Game]) + { + FILE *fpak; + pak_header_t pakheader; + pak_item_t pakitem; + int i; + int num; + int numitems; - if (NULL != (fpak = fopen(pakfile[Game], "rb"))) - { - sprintf(path,"textures/%s.m8",Tex); - g_strdown(path); - num=fread(&pakheader,1,sizeof(pak_header_t),fpak); - if((size_t)num < sizeof(pak_header_t)) - { - fclose(fpak); - return 0; - } - if(strncmp(pakheader.id,"PACK",4)) - { - fclose(fpak); - return 0; - } - numitems = pakheader.dsize/sizeof(pak_item_t); - fseek(fpak,pakheader.dstart,SEEK_SET); - for(i=0; iflags; - free(mt); - } - } - } - fclose(fpak); - } - } - else - { - // Assume .map will be output to gamedir/maps, then back up - // to the gamedir and append /textures. Ugly but it should work - strcpy(path,gszMapFile); - g_strdown(path); - p = strstr(path,"maps"); - if(!p) return 0; - p[0] = '\0'; - strcat(path,"textures/"); - strcat(path,Tex); - strcat(path,".m8"); - f = fopen (path, "rb"); - if (!f) - flags = 0; - else - { - pos = ftell (f); - fseek (f, 0, SEEK_END); - length = ftell (f); - fseek (f, pos, SEEK_SET); - if((mt = (miptex_t*)malloc(length+1))==NULL) - flags = 0; - else - { - ((char *)mt)[length] = 0; - fread(mt, 1, length, f); - fclose (f); - flags = mt->flags; - free(mt); - } - } - } - return flags; - */ + if (NULL != (fpak = fopen(pakfile[Game], "rb"))) + { + sprintf(path,"textures/%s.m8",Tex); + g_strdown(path); + num=fread(&pakheader,1,sizeof(pak_header_t),fpak); + if((size_t)num < sizeof(pak_header_t)) + { + fclose(fpak); + return 0; + } + if(strncmp(pakheader.id,"PACK",4)) + { + fclose(fpak); + return 0; + } + numitems = pakheader.dsize/sizeof(pak_item_t); + fseek(fpak,pakheader.dstart,SEEK_SET); + for(i=0; iflags; + free(mt); + } + } + } + fclose(fpak); + } + } + else + { + // Assume .map will be output to gamedir/maps, then back up + // to the gamedir and append /textures. Ugly but it should work + strcpy(path,gszMapFile); + g_strdown(path); + p = strstr(path,"maps"); + if(!p) return 0; + p[0] = '\0'; + strcat(path,"textures/"); + strcat(path,Tex); + strcat(path,".m8"); + f = fopen (path, "rb"); + if (!f) + flags = 0; + else + { + pos = ftell (f); + fseek (f, 0, SEEK_END); + length = ftell (f); + fseek (f, pos, SEEK_SET); + if((mt = (miptex_t*)malloc(length+1))==NULL) + flags = 0; + else + { + ((char *)mt)[length] = 0; + fread(mt, 1, length, f); + fclose (f); + flags = mt->flags; + free(mt); + } + } + } + return flags; + */ } diff --git a/contrib/gtkgensurf/plugin.cpp b/contrib/gtkgensurf/plugin.cpp index 6acaa4b9..38eeeea4 100644 --- a/contrib/gtkgensurf/plugin.cpp +++ b/contrib/gtkgensurf/plugin.cpp @@ -31,117 +31,115 @@ bool g_bInitDone; #include "iplugin.h" -const char* QERPlug_Init( void* hApp, void* pMainWidget ){ - g_pRadiantWnd = (GtkWidget*)pMainWidget; +const char *QERPlug_Init(void *hApp, void *pMainWidget) +{ + g_pRadiantWnd = (GtkWidget *) pMainWidget; - return "GenSurf for Q3Radiant"; + return "GenSurf for Q3Radiant"; } -const char* QERPlug_GetName(){ - return "GtkGenSurf"; +const char *QERPlug_GetName() +{ + return "GtkGenSurf"; } -const char* QERPlug_GetCommandList(){ - return "Wall facing 270...;Wall facing 180...;Wall facing 90...;Wall facing 0...;" - "Ceiling...;Ground surface...;-;About..."; +const char *QERPlug_GetCommandList() +{ + return "Wall facing 270...;Wall facing 180...;Wall facing 90...;Wall facing 0...;" + "Ceiling...;Ground surface...;-;About..."; } // vMin/vMax provide the bounds of the selection, they are zero if there is no selection // if there is a selection, bSingleBrush will be true if a single brush is selected // if so, typical plugin behaviour (such as primitive creation) would use the bounds as // a rule to create the primitive, then delete the selection -void QERPlug_Dispatch( const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush ){ - bool Generate = false; - - if ( !g_bInitDone ) { - if ( GenSurfInit() ) { - g_bInitDone = true; - } - } - - if ( !strcmp( p, "Ground surface..." ) ) { - SingleBrushSelected = bSingleBrush; - Plane = PLANE_XY0; - if ( SingleBrushSelected ) { - Hll = vMin[0]; - Vll = vMin[1]; - Hur = vMax[0]; - Vur = vMax[1]; - Z00 = Z01 = Z10 = Z11 = vMax[2]; - } - Generate = true; - } - else if ( !strcmp( p, "Ceiling..." ) ) { - SingleBrushSelected = bSingleBrush; - Plane = PLANE_XY1; - if ( SingleBrushSelected ) { - Hll = vMin[0]; - Vll = vMin[1]; - Hur = vMax[0]; - Vur = vMax[1]; - Z00 = Z01 = Z10 = Z11 = vMin[2]; - } - Generate = true; - } - else if ( !strcmp( p, "Wall facing 0..." ) ) { - SingleBrushSelected = bSingleBrush; - Plane = PLANE_YZ0; - if ( SingleBrushSelected ) { - Hll = vMin[1]; - Vll = vMin[2]; - Hur = vMax[1]; - Vur = vMax[2]; - Z00 = Z01 = Z10 = Z11 = vMax[0]; - } - Generate = true; - } - else if ( !strcmp( p, "Wall facing 90..." ) ) { - SingleBrushSelected = bSingleBrush; - Plane = PLANE_XZ0; - if ( SingleBrushSelected ) { - Hll = vMin[0]; - Vll = vMin[2]; - Hur = vMax[0]; - Vur = vMax[2]; - Z00 = Z01 = Z10 = Z11 = vMax[1]; - } - Generate = true; - } - else if ( !strcmp( p, "Wall facing 180..." ) ) { - SingleBrushSelected = bSingleBrush; - Plane = PLANE_YZ1; - if ( SingleBrushSelected ) { - Hll = vMin[1]; - Vll = vMin[2]; - Hur = vMax[1]; - Vur = vMax[2]; - Z00 = Z01 = Z10 = Z11 = vMin[0]; - } - Generate = true; - } - else if ( !strcmp( p, "Wall facing 270..." ) ) { - SingleBrushSelected = bSingleBrush; - Plane = PLANE_XZ1; - if ( SingleBrushSelected ) { - Hll = vMin[0]; - Vll = vMin[2]; - Hur = vMax[0]; - Vur = vMax[2]; - Z00 = Z01 = Z10 = Z11 = vMin[1]; - } - Generate = true; - } - else if ( !strcmp( p,"About..." ) ) { - About( g_pRadiantWnd ); - } - - if ( Generate ) { - if ( SingleBrushSelected ) { - UseFaceBounds(); - } - - g_pWnd.show(); - } +void QERPlug_Dispatch(const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush) +{ + bool Generate = false; + + if (!g_bInitDone) { + if (GenSurfInit()) { + g_bInitDone = true; + } + } + + if (!strcmp(p, "Ground surface...")) { + SingleBrushSelected = bSingleBrush; + Plane = PLANE_XY0; + if (SingleBrushSelected) { + Hll = vMin[0]; + Vll = vMin[1]; + Hur = vMax[0]; + Vur = vMax[1]; + Z00 = Z01 = Z10 = Z11 = vMax[2]; + } + Generate = true; + } else if (!strcmp(p, "Ceiling...")) { + SingleBrushSelected = bSingleBrush; + Plane = PLANE_XY1; + if (SingleBrushSelected) { + Hll = vMin[0]; + Vll = vMin[1]; + Hur = vMax[0]; + Vur = vMax[1]; + Z00 = Z01 = Z10 = Z11 = vMin[2]; + } + Generate = true; + } else if (!strcmp(p, "Wall facing 0...")) { + SingleBrushSelected = bSingleBrush; + Plane = PLANE_YZ0; + if (SingleBrushSelected) { + Hll = vMin[1]; + Vll = vMin[2]; + Hur = vMax[1]; + Vur = vMax[2]; + Z00 = Z01 = Z10 = Z11 = vMax[0]; + } + Generate = true; + } else if (!strcmp(p, "Wall facing 90...")) { + SingleBrushSelected = bSingleBrush; + Plane = PLANE_XZ0; + if (SingleBrushSelected) { + Hll = vMin[0]; + Vll = vMin[2]; + Hur = vMax[0]; + Vur = vMax[2]; + Z00 = Z01 = Z10 = Z11 = vMax[1]; + } + Generate = true; + } else if (!strcmp(p, "Wall facing 180...")) { + SingleBrushSelected = bSingleBrush; + Plane = PLANE_YZ1; + if (SingleBrushSelected) { + Hll = vMin[1]; + Vll = vMin[2]; + Hur = vMax[1]; + Vur = vMax[2]; + Z00 = Z01 = Z10 = Z11 = vMin[0]; + } + Generate = true; + } else if (!strcmp(p, "Wall facing 270...")) { + SingleBrushSelected = bSingleBrush; + Plane = PLANE_XZ1; + if (SingleBrushSelected) { + Hll = vMin[0]; + Vll = vMin[2]; + Hur = vMax[0]; + Vur = vMax[2]; + Z00 = Z01 = Z10 = Z11 = vMin[1]; + } + Generate = true; + } else if (!strcmp(p, "About...")) { + About(g_pRadiantWnd); + } + + if (Generate) { + if (SingleBrushSelected) { + UseFaceBounds(); + } + + g_pWnd.show(); + } } // ============================================================================= @@ -149,56 +147,67 @@ void QERPlug_Dispatch( const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrus #include "synapse.h" -class GenSurfSynapseClient : public CSynapseClient -{ +class GenSurfSynapseClient : public CSynapseClient { public: // CSynapseClient API -bool RequestAPI( APIDescriptor_t *pAPI ); -const char* GetInfo(); + bool RequestAPI(APIDescriptor_t *pAPI); -GenSurfSynapseClient() { } -virtual ~GenSurfSynapseClient() { } -}; + const char *GetInfo(); -CSynapseServer* g_pSynapseServer = NULL; -GenSurfSynapseClient g_SynapseClient; + GenSurfSynapseClient() + {} -extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ){ - if ( strcmp( version, SYNAPSE_VERSION ) ) { - Syn_Printf( "ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version ); - return NULL; - } - g_pSynapseServer = pServer; - g_pSynapseServer->IncRef(); - Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() ); + virtual ~GenSurfSynapseClient() + {} +}; - g_SynapseClient.AddAPI( PLUGIN_MAJOR, "gtkgensurf", sizeof( _QERPluginTable ) ); +CSynapseServer *g_pSynapseServer = NULL; +GenSurfSynapseClient g_SynapseClient; - g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( _QERFuncTable_1 ), SYN_REQUIRE, &g_FuncTable ); - g_SynapseClient.AddAPI( UIGTK_MAJOR, NULL, sizeof( _QERUIGtkTable ), SYN_REQUIRE, &g_UIGtkTable ); - g_SynapseClient.AddAPI( QGL_MAJOR, NULL, sizeof( _QERQglTable ), SYN_REQUIRE, &g_GLTable ); - g_SynapseClient.AddAPI( ENTITY_MAJOR, NULL, sizeof( _QEREntityTable ), SYN_REQUIRE, &g_EntityTable ); +extern "C" CSynapseClient *SYNAPSE_DLL_EXPORT - return &g_SynapseClient; +Synapse_EnumerateInterfaces(const char *version, CSynapseServer *pServer) +{ + if (strcmp(version, SYNAPSE_VERSION)) { + Syn_Printf("ERROR: synapse API version mismatch: should be '" + SYNAPSE_VERSION + "', got '%s'\n", version ); + return NULL; + } + g_pSynapseServer = pServer; + g_pSynapseServer->IncRef(); + Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf()); + + g_SynapseClient.AddAPI(PLUGIN_MAJOR, "gtkgensurf", sizeof(_QERPluginTable)); + + g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(_QERFuncTable_1), SYN_REQUIRE, &g_FuncTable); + g_SynapseClient.AddAPI(UIGTK_MAJOR, NULL, sizeof(_QERUIGtkTable), SYN_REQUIRE, &g_UIGtkTable); + g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(_QERQglTable), SYN_REQUIRE, &g_GLTable); + g_SynapseClient.AddAPI(ENTITY_MAJOR, NULL, sizeof(_QEREntityTable), SYN_REQUIRE, &g_EntityTable); + + return &g_SynapseClient; } -bool GenSurfSynapseClient::RequestAPI( APIDescriptor_t *pAPI ){ - if ( !strcmp( pAPI->major_name, PLUGIN_MAJOR ) ) { - _QERPluginTable* pTable = static_cast<_QERPluginTable*>( pAPI->mpTable ); - - pTable->m_pfnQERPlug_Init = QERPlug_Init; - pTable->m_pfnQERPlug_GetName = QERPlug_GetName; - pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; - pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; - return true; - } - - Syn_Printf( "ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo() ); - return false; +bool GenSurfSynapseClient::RequestAPI(APIDescriptor_t *pAPI) +{ + if (!strcmp(pAPI->major_name, PLUGIN_MAJOR)) { + _QERPluginTable *pTable = static_cast<_QERPluginTable *>( pAPI->mpTable ); + + pTable->m_pfnQERPlug_Init = QERPlug_Init; + pTable->m_pfnQERPlug_GetName = QERPlug_GetName; + pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; + pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; + return true; + } + + Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo()); + return false; } #include "version.h" -const char* GenSurfSynapseClient::GetInfo(){ - return "GtkGenSurf - built " __DATE__ " " RADIANT_VERSION; +const char *GenSurfSynapseClient::GetInfo() +{ + return "GtkGenSurf - built " __DATE__ " " + RADIANT_VERSION; } diff --git a/contrib/gtkgensurf/triangle.c b/contrib/gtkgensurf/triangle.c index 8d4e0c98..2d1ad339 100644 --- a/contrib/gtkgensurf/triangle.c +++ b/contrib/gtkgensurf/triangle.c @@ -1,4 +1,5 @@ -#define ANSI_DECLARATORS +#define +ANSI_DECLARATORS /*****************************************************************************/ /* */ /* 888888888 ,o, / 888 */ @@ -193,18 +194,23 @@ /* recommend double precision unless you want to generate a mesh for which */ /* you do not have enough memory. */ -#define SINGLE +#define +SINGLE -#ifdef SINGLE -#define REAL float +#ifdef +SINGLE +#define +REAL float #else /* not SINGLE */ -#define REAL double +#define +REAL double #endif /* not SINGLE */ /* If yours is not a Unix system, define the NO_TIMER compiler switch to */ /* remove the Unix-specific timing code. */ -#define NO_TIMER +#define +NO_TIMER /* To insert lots of self-checks for internal errors, define the SELF_CHECK */ /* symbol. This will slow down the program significantly. It is best to */ @@ -218,7 +224,8 @@ /* TRILIBRARY symbol. Read the file triangle.h for details on how to call */ /* the procedure triangulate() that results. */ -#define TRILIBRARY +#define +TRILIBRARY /* It is possible to generate a smaller version of Triangle using one or */ /* both of the following symbols. Define the REDUCED symbol to eliminate */ @@ -229,8 +236,10 @@ /* These reductions are most likely to be useful when generating an object */ /* library (triangle.o) by defining the TRILIBRARY symbol. */ -#define REDUCED -#define CDT_ONLY +#define +REDUCED +#define +CDT_ONLY /* On some machines, the exact arithmetic routines might be defeated by the */ /* use of internal extended precision floating-point registers. Sometimes */ @@ -241,76 +250,100 @@ /* To try this out, write "#define INEXACT volatile" below. Normally, */ /* however, INEXACT should be defined to be nothing. ("#define INEXACT".) */ -#define INEXACT /* Nothing */ +#define +INEXACT /* Nothing */ /* #define INEXACT volatile */ /* Maximum number of characters in a file name (including the null). */ -#define FILENAMESIZE 512 +#define +FILENAMESIZE 512 /* Maximum number of characters in a line read from a file (including the */ /* null). */ -#define INPUTLINESIZE 512 +#define +INPUTLINESIZE 512 /* For efficiency, a variety of data structures are allocated in bulk. The */ /* following constants determine how many of each structure is allocated */ /* at once. */ -#define TRIPERBLOCK 4092 /* Number of triangles allocated at once. */ -#define SHELLEPERBLOCK 508 /* Number of shell edges allocated at once. */ -#define POINTPERBLOCK 4092 /* Number of points allocated at once. */ -#define VIRUSPERBLOCK 1020 /* Number of virus triangles allocated at once. */ +#define +TRIPERBLOCK 4092 /* Number of triangles allocated at once. */ +#define +SHELLEPERBLOCK 508 /* Number of shell edges allocated at once. */ +#define +POINTPERBLOCK 4092 /* Number of points allocated at once. */ +#define +VIRUSPERBLOCK 1020 /* Number of virus triangles allocated at once. */ /* Number of encroached segments allocated at once. */ -#define BADSEGMENTPERBLOCK 252 +#define +BADSEGMENTPERBLOCK 252 /* Number of skinny triangles allocated at once. */ -#define BADTRIPERBLOCK 4092 +#define +BADTRIPERBLOCK 4092 /* Number of splay tree nodes allocated at once. */ -#define SPLAYNODEPERBLOCK 508 +#define +SPLAYNODEPERBLOCK 508 /* The point marker DEADPOINT is an arbitrary number chosen large enough to */ /* (hopefully) not conflict with user boundary markers. Make sure that it */ /* is small enough to fit into your machine's integer size. */ -#define DEADPOINT -1073741824 +#define +DEADPOINT -1073741824 /* The next line is used to outsmart some very stupid compilers. If your */ /* compiler is smarter, feel free to replace the "int" with "void". */ /* Not that it matters. */ -#define VOID int +#define +VOID int /* Two constants for algorithms based on random sampling. Both constants */ /* have been chosen empirically to optimize their respective algorithms. */ /* Used for the point location scheme of Mucke, Saias, and Zhu, to decide */ /* how large a random sample of triangles to inspect. */ -#define SAMPLEFACTOR 11 +#define +SAMPLEFACTOR 11 /* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */ /* of boundary edges should be maintained in the splay tree for point */ /* location on the front. */ -#define SAMPLERATE 10 +#define +SAMPLERATE 10 /* A number that speaks for itself, every kissable digit. */ -#define PI 3.141592653589793238462643383279502884197169399375105820974944592308 +#define +PI 3.141592653589793238462643383279502884197169399375105820974944592308 /* Another fave. */ -#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732 +#define +SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732 /* And here's one for those of you who are intimidated by math. */ -#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333 - -#include -#include -#include -#ifndef NO_TIMER -#include +#define +ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333 + +#include + +#include + +#include + +#ifndef +NO_TIMER +#include + #endif /* NO_TIMER */ -#ifdef TRILIBRARY -#include "triangle.h" +#ifdef +TRILIBRARY +#include +"triangle.h" #endif /* TRILIBRARY */ /* The following obscenity seems to be necessary to ensure that this program */ @@ -319,7 +352,8 @@ /* exit() may or may not already be defined at this point. I declare these */ /* functions explicitly because some non-ANSI C compilers lack stdlib.h. */ -#ifndef _STDLIB_H_ +#ifndef +_STDLIB_H_ extern void *malloc(); extern void free(); extern void exit(); @@ -330,7 +364,8 @@ extern long strtol(); /* A few forward declarations. */ void poolrestart(); -#ifndef TRILIBRARY +#ifndef +TRILIBRARY char *readline(); char *findfield(); #endif /* not TRILIBRARY */ @@ -338,33 +373,37 @@ char *findfield(); /* Labels that signify whether a record consists primarily of pointers or of */ /* floating-point words. Used to make decisions about data alignment. */ -enum wordtype {POINTER, FLOATINGPOINT}; +enum wordtype { +POINTER, FLOATINGPOINT +}; /* Labels that signify the result of point location. The result of a */ /* search indicates that the point falls in the interior of a triangle, on */ /* an edge, on a vertex, or outside the mesh. */ -enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE}; +enum locateresult { INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE }; /* Labels that signify the result of site insertion. The result indicates */ /* that the point was inserted with complete success, was inserted but */ /* encroaches on a segment, was not inserted because it lies on a segment, */ /* or was not inserted because another point occupies the same location. */ -enum insertsiteresult {SUCCESSFULPOINT, ENCROACHINGPOINT, VIOLATINGPOINT, - DUPLICATEPOINT}; +enum insertsiteresult { +SUCCESSFULPOINT, ENCROACHINGPOINT, VIOLATINGPOINT, +DUPLICATEPOINT +}; /* Labels that signify the result of direction finding. The result */ /* indicates that a segment connecting the two query points falls within */ /* the direction triangle, along the left edge of the direction triangle, */ /* or along the right edge of the direction triangle. */ -enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR}; +enum finddirectionresult { WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR }; /* Labels that signify the result of the circumcenter computation routine. */ /* The return value indicates which edge of the triangle is shortest. */ -enum circumcenterresult {OPPOSITEORG, OPPOSITEDEST, OPPOSITEAPEX}; +enum circumcenterresult { OPPOSITEORG, OPPOSITEDEST, OPPOSITEAPEX }; /*****************************************************************************/ /* */ @@ -488,8 +527,8 @@ typedef REAL **triangle; /* Really: typedef triangle *triangle */ /* directed to point counterclockwise about the corresponding triangle. */ struct triedge { - triangle *tri; - int orient; /* Ranges from 0 to 2. */ +triangle *tri; +int orient; /* Ranges from 0 to 2. */ }; /* The shell data structure. Each shell edge contains two pointers to */ @@ -504,8 +543,8 @@ typedef REAL **shelle; /* Really: typedef shelle *shelle */ /* directed so that the "side" denoted is the right side of the edge. */ struct edge { - shelle *sh; - int shorient; /* Ranges from 0 to 1. */ +shelle *sh; +int shorient; /* Ranges from 0 to 1. */ }; /* The point data structure. Each point is actually an array of REALs. */ @@ -519,9 +558,9 @@ typedef REAL *point; /* stored so that one can check whether a segment is still the same. */ struct badsegment { - struct edge encsegment; /* An encroached segment. */ - point segorg, segdest; /* The two vertices. */ - struct badsegment *nextsegment; /* Pointer to next encroached segment. */ +struct edge encsegment; /* An encroached segment. */ +point segorg, segdest; /* The two vertices. */ +struct badsegment *nextsegment; /* Pointer to next encroached segment. */ }; /* A queue used to store bad triangles. The key is the square of the cosine */ @@ -529,10 +568,10 @@ struct badsegment { /* stored so that one can check whether a triangle is still the same. */ struct badface { - struct triedge badfacetri; /* A bad triangle. */ - REAL key; /* cos^2 of smallest (apical) angle. */ - point faceorg, facedest, faceapex; /* The three vertices. */ - struct badface *nextface; /* Pointer to next bad triangle. */ +struct triedge badfacetri; /* A bad triangle. */ +REAL key; /* cos^2 of smallest (apical) angle. */ +point faceorg, facedest, faceapex; /* The three vertices. */ +struct badface *nextface; /* Pointer to next bad triangle. */ }; /* A node in a heap used to store events for the sweepline Delaunay */ @@ -546,9 +585,9 @@ struct badface { /* events are given an invalid (smaller than `xmin') x-coordinate `xkey'. */ struct event { - REAL xkey, ykey; /* Coordinates of the event. */ - VOID *eventptr; /* Can be a point or the location of a circle event. */ - int heapposition; /* Marks this event's position in the heap. */ +REAL xkey, ykey; /* Coordinates of the event. */ +VOID *eventptr; /* Can be a point or the location of a circle event. */ +int heapposition; /* Marks this event's position in the heap. */ }; /* A node in the splay tree. Each node holds an oriented ghost triangle */ @@ -563,9 +602,9 @@ struct event { /* boundary edge and should be deleted. */ struct splaynode { - struct triedge keyedge; /* Lprev of an edge on the front. */ - point keydest; /* Used to verify that splay node is still live. */ - struct splaynode *lchild, *rchild; /* Children in splay tree. */ +struct triedge keyedge; /* Lprev of an edge on the front. */ +point keydest; /* Used to verify that splay node is still live. */ +struct splaynode *lchild, *rchild; /* Children in splay tree. */ }; /* A type used to allocate memory. firstblock is the first block of items. */ @@ -593,18 +632,18 @@ struct splaynode { /* on deaditemstack. */ struct memorypool { - VOID **firstblock, **nowblock; - VOID *nextitem; - VOID *deaditemstack; - VOID **pathblock; - VOID *pathitem; - enum wordtype itemwordtype; - int alignbytes; - int itembytes, itemwords; - int itemsperblock; - long items, maxitems; - int unallocateditems; - int pathitemsleft; +VOID **firstblock, **nowblock; +VOID *nextitem; +VOID *deaditemstack; +VOID **pathblock; +VOID *pathitem; +enum wordtype itemwordtype; +int alignbytes; +int itembytes, itemwords; +int itemsperblock; +long items, maxitems; +int unallocateditems; +int pathitemsleft; }; /* Variables used to allocate memory for triangles, shell edges, points, */ @@ -710,7 +749,8 @@ static REAL maxarea; /* Variables for file names. */ -#ifndef TRILIBRARY +#ifndef +TRILIBRARY char innodefilename[FILENAMESIZE]; char inelefilename[FILENAMESIZE]; char inpolyfilename[FILENAMESIZE]; @@ -776,8 +816,8 @@ static struct triedge recenttri; /* Fast lookup arrays to speed some of the mesh manipulation primitives. */ -int plus1mod3[3] = {1, 2, 0}; -int minus1mod3[3] = {2, 0, 1}; +int plus1mod3[3] = { 1, 2, 0 }; +int minus1mod3[3] = { 2, 0, 1 }; /********* Primitives for triangles *********/ /* */ @@ -786,17 +826,19 @@ int minus1mod3[3] = {2, 0, 1}; /* decode() converts a pointer to an oriented triangle. The orientation is */ /* extracted from the two least significant bits of the pointer. */ -#define decode( ptr, triedge ) \ - ( triedge ).orient = (int) ( (unsigned long) ( ptr ) & (unsigned long) 3l ); \ - ( triedge ).tri = (triangle *) \ - ( (unsigned long) ( ptr ) ^ (unsigned long) ( triedge ).orient ) +#define +decode( ptr, triedge ) \ + ( triedge ).orient = (int) ((unsigned long) ( ptr ) & (unsigned long) 3l ); \ + ( triedge ).tri = (triangle *) \ + ((unsigned long) ( ptr ) ^ (unsigned long) ( triedge ).orient ) /* encode() compresses an oriented triangle into a single pointer. It */ /* relies on the assumption that all triangles are aligned to four-byte */ /* boundaries, so the two least significant bits of (triedge).tri are zero.*/ -#define encode( triedge ) \ - (triangle) ( (unsigned long) ( triedge ).tri | (unsigned long) ( triedge ).orient ) +#define +encode( triedge ) \ + (triangle) ((unsigned long) ( triedge ).tri | (unsigned long) ( triedge ).orient ) /* The following edge manipulation primitives are all described by Guibas */ /* and Stolfi. However, they use an edge-based data structure, whereas I */ @@ -806,190 +848,226 @@ int minus1mod3[3] = {2, 0, 1}; /* edge direction is necessarily reversed, because triangle/edge handles */ /* are always directed counterclockwise around the triangle. */ -#define sym( triedge1, triedge2 ) \ - ptr = ( triedge1 ).tri[( triedge1 ).orient]; \ - decode( ptr, triedge2 ); +#define +sym( triedge1, triedge2 ) \ + ptr = ( triedge1 ).tri[( triedge1 ).orient]; \ + decode( ptr, triedge2 ); -#define symself( triedge ) \ - ptr = ( triedge ).tri[( triedge ).orient]; \ - decode( ptr, triedge ); +#define +symself( triedge ) \ + ptr = ( triedge ).tri[( triedge ).orient]; \ + decode( ptr, triedge ); /* lnext() finds the next edge (counterclockwise) of a triangle. */ -#define lnext( triedge1, triedge2 ) \ - ( triedge2 ).tri = ( triedge1 ).tri; \ - ( triedge2 ).orient = plus1mod3[( triedge1 ).orient] +#define +lnext( triedge1, triedge2 ) \ + ( triedge2 ).tri = ( triedge1 ).tri; \ + ( triedge2 ).orient = plus1mod3[( triedge1 ).orient] -#define lnextself( triedge ) \ - ( triedge ).orient = plus1mod3[( triedge ).orient] +#define +lnextself( triedge ) \ + ( triedge ).orient = plus1mod3[( triedge ).orient] /* lprev() finds the previous edge (clockwise) of a triangle. */ -#define lprev( triedge1, triedge2 ) \ - ( triedge2 ).tri = ( triedge1 ).tri; \ - ( triedge2 ).orient = minus1mod3[( triedge1 ).orient] +#define +lprev( triedge1, triedge2 ) \ + ( triedge2 ).tri = ( triedge1 ).tri; \ + ( triedge2 ).orient = minus1mod3[( triedge1 ).orient] -#define lprevself( triedge ) \ - ( triedge ).orient = minus1mod3[( triedge ).orient] +#define +lprevself( triedge ) \ + ( triedge ).orient = minus1mod3[( triedge ).orient] /* onext() spins counterclockwise around a point; that is, it finds the next */ /* edge with the same origin in the counterclockwise direction. This edge */ /* will be part of a different triangle. */ -#define onext( triedge1, triedge2 ) \ - lprev( triedge1, triedge2 ); \ - symself( triedge2 ); +#define +onext( triedge1, triedge2 ) \ + lprev( triedge1, triedge2 ); \ + symself( triedge2 ); -#define onextself( triedge ) \ - lprevself( triedge ); \ - symself( triedge ); +#define +onextself( triedge ) \ + lprevself( triedge ); \ + symself( triedge ); /* oprev() spins clockwise around a point; that is, it finds the next edge */ /* with the same origin in the clockwise direction. This edge will be */ /* part of a different triangle. */ -#define oprev( triedge1, triedge2 ) \ - sym( triedge1, triedge2 ); \ - lnextself( triedge2 ); +#define +oprev( triedge1, triedge2 ) \ + sym( triedge1, triedge2 ); \ + lnextself( triedge2 ); -#define oprevself( triedge ) \ - symself( triedge ); \ - lnextself( triedge ); +#define +oprevself( triedge ) \ + symself( triedge ); \ + lnextself( triedge ); /* dnext() spins counterclockwise around a point; that is, it finds the next */ /* edge with the same destination in the counterclockwise direction. This */ /* edge will be part of a different triangle. */ -#define dnext( triedge1, triedge2 ) \ - sym( triedge1, triedge2 ); \ - lprevself( triedge2 ); +#define +dnext( triedge1, triedge2 ) \ + sym( triedge1, triedge2 ); \ + lprevself( triedge2 ); -#define dnextself( triedge ) \ - symself( triedge ); \ - lprevself( triedge ); +#define +dnextself( triedge ) \ + symself( triedge ); \ + lprevself( triedge ); /* dprev() spins clockwise around a point; that is, it finds the next edge */ /* with the same destination in the clockwise direction. This edge will */ /* be part of a different triangle. */ -#define dprev( triedge1, triedge2 ) \ - lnext( triedge1, triedge2 ); \ - symself( triedge2 ); +#define +dprev( triedge1, triedge2 ) \ + lnext( triedge1, triedge2 ); \ + symself( triedge2 ); -#define dprevself( triedge ) \ - lnextself( triedge ); \ - symself( triedge ); +#define +dprevself( triedge ) \ + lnextself( triedge ); \ + symself( triedge ); /* rnext() moves one edge counterclockwise about the adjacent triangle. */ /* (It's best understood by reading Guibas and Stolfi. It involves */ /* changing triangles twice.) */ -#define rnext( triedge1, triedge2 ) \ - sym( triedge1, triedge2 ); \ - lnextself( triedge2 ); \ - symself( triedge2 ); +#define +rnext( triedge1, triedge2 ) \ + sym( triedge1, triedge2 ); \ + lnextself( triedge2 ); \ + symself( triedge2 ); -#define rnextself( triedge ) \ - symself( triedge ); \ - lnextself( triedge ); \ - symself( triedge ); +#define +rnextself( triedge ) \ + symself( triedge ); \ + lnextself( triedge ); \ + symself( triedge ); /* rnext() moves one edge clockwise about the adjacent triangle. */ /* (It's best understood by reading Guibas and Stolfi. It involves */ /* changing triangles twice.) */ -#define rprev( triedge1, triedge2 ) \ - sym( triedge1, triedge2 ); \ - lprevself( triedge2 ); \ - symself( triedge2 ); +#define +rprev( triedge1, triedge2 ) \ + sym( triedge1, triedge2 ); \ + lprevself( triedge2 ); \ + symself( triedge2 ); -#define rprevself( triedge ) \ - symself( triedge ); \ - lprevself( triedge ); \ - symself( triedge ); +#define +rprevself( triedge ) \ + symself( triedge ); \ + lprevself( triedge ); \ + symself( triedge ); /* These primitives determine or set the origin, destination, or apex of a */ /* triangle. */ -#define org( triedge, pointptr ) \ - pointptr = (point) ( triedge ).tri[plus1mod3[( triedge ).orient] + 3] +#define +org( triedge, pointptr ) \ + pointptr = (point) ( triedge ).tri[plus1mod3[( triedge ).orient] + 3] -#define dest( triedge, pointptr ) \ - pointptr = (point) ( triedge ).tri[minus1mod3[( triedge ).orient] + 3] +#define +dest( triedge, pointptr ) \ + pointptr = (point) ( triedge ).tri[minus1mod3[( triedge ).orient] + 3] -#define apex( triedge, pointptr ) \ - pointptr = (point) ( triedge ).tri[( triedge ).orient + 3] +#define +apex( triedge, pointptr ) \ + pointptr = (point) ( triedge ).tri[( triedge ).orient + 3] -#define setorg( triedge, pointptr ) \ - ( triedge ).tri[plus1mod3[( triedge ).orient] + 3] = (triangle) pointptr +#define +setorg( triedge, pointptr ) \ + ( triedge ).tri[plus1mod3[( triedge ).orient] + 3] = (triangle) pointptr -#define setdest( triedge, pointptr ) \ - ( triedge ).tri[minus1mod3[( triedge ).orient] + 3] = (triangle) pointptr +#define +setdest( triedge, pointptr ) \ + ( triedge ).tri[minus1mod3[( triedge ).orient] + 3] = (triangle) pointptr -#define setapex( triedge, pointptr ) \ - ( triedge ).tri[( triedge ).orient + 3] = (triangle) pointptr +#define +setapex( triedge, pointptr ) \ + ( triedge ).tri[( triedge ).orient + 3] = (triangle) pointptr -#define setvertices2null( triedge ) \ - ( triedge ).tri[3] = (triangle) NULL; \ - ( triedge ).tri[4] = (triangle) NULL; \ - ( triedge ).tri[5] = (triangle) NULL; +#define +setvertices2null( triedge ) \ + ( triedge ).tri[3] = (triangle) NULL; \ + ( triedge ).tri[4] = (triangle) NULL; \ + ( triedge ).tri[5] = (triangle) NULL; /* Bond two triangles together. */ -#define bond( triedge1, triedge2 ) \ - ( triedge1 ).tri[( triedge1 ).orient] = encode( triedge2 ); \ - ( triedge2 ).tri[( triedge2 ).orient] = encode( triedge1 ) +#define +bond( triedge1, triedge2 ) \ + ( triedge1 ).tri[( triedge1 ).orient] = encode( triedge2 ); \ + ( triedge2 ).tri[( triedge2 ).orient] = encode( triedge1 ) /* Dissolve a bond (from one side). Note that the other triangle will still */ /* think it's connected to this triangle. Usually, however, the other */ /* triangle is being deleted entirely, or bonded to another triangle, so */ /* it doesn't matter. */ -#define dissolve( triedge ) \ - ( triedge ).tri[( triedge ).orient] = (triangle) dummytri +#define +dissolve( triedge ) \ + ( triedge ).tri[( triedge ).orient] = (triangle) dummytri /* Copy a triangle/edge handle. */ -#define triedgecopy( triedge1, triedge2 ) \ - ( triedge2 ).tri = ( triedge1 ).tri; \ - ( triedge2 ).orient = ( triedge1 ).orient +#define +triedgecopy( triedge1, triedge2 ) \ + ( triedge2 ).tri = ( triedge1 ).tri; \ + ( triedge2 ).orient = ( triedge1 ).orient /* Test for equality of triangle/edge handles. */ -#define triedgeequal( triedge1, triedge2 ) \ - ( ( ( triedge1 ).tri == ( triedge2 ).tri ) && \ - ( ( triedge1 ).orient == ( triedge2 ).orient ) ) +#define +triedgeequal( triedge1, triedge2 ) \ + ((( triedge1 ).tri == ( triedge2 ).tri ) && \ + (( triedge1 ).orient == ( triedge2 ).orient )) /* Primitives to infect or cure a triangle with the virus. These rely on */ /* the assumption that all shell edges are aligned to four-byte boundaries.*/ -#define infect( triedge ) \ - ( triedge ).tri[6] = (triangle) \ - ( (unsigned long) ( triedge ).tri[6] | (unsigned long) 2l ) +#define +infect( triedge ) \ + ( triedge ).tri[6] = (triangle) \ + ((unsigned long) ( triedge ).tri[6] | (unsigned long) 2l ) -#define uninfect( triedge ) \ - ( triedge ).tri[6] = (triangle) \ - ( (unsigned long) ( triedge ).tri[6] & ~(unsigned long) 2l ) +#define +uninfect( triedge ) \ + ( triedge ).tri[6] = (triangle) \ + ((unsigned long) ( triedge ).tri[6] & ~(unsigned long) 2l ) /* Test a triangle for viral infection. */ -#define infected( triedge ) \ - ( ( (unsigned long) ( triedge ).tri[6] & (unsigned long) 2l ) != 0 ) +#define +infected( triedge ) \ + (((unsigned long) ( triedge ).tri[6] & (unsigned long) 2l ) != 0 ) /* Check or set a triangle's attributes. */ -#define elemattribute( triedge, attnum ) \ - ( (REAL *) ( triedge ).tri )[elemattribindex + ( attnum )] +#define +elemattribute( triedge, attnum ) \ + ((REAL *) ( triedge ).tri )[elemattribindex + ( attnum )] -#define setelemattribute( triedge, attnum, value ) \ - ( (REAL *) ( triedge ).tri )[elemattribindex + ( attnum )] = (REAL)value +#define +setelemattribute( triedge, attnum, value ) \ + ((REAL *) ( triedge ).tri )[elemattribindex + ( attnum )] = (REAL)value /* Check or set a triangle's maximum area bound. */ -#define areabound( triedge ) ( (REAL *) ( triedge ).tri )[areaboundindex] +#define +areabound( triedge ) ((REAL *) ( triedge ).tri )[areaboundindex] -#define setareabound( triedge, value ) \ - ( (REAL *) ( triedge ).tri )[areaboundindex] = (REAL)value +#define +setareabound( triedge, value ) \ + ((REAL *) ( triedge ).tri )[areaboundindex] = (REAL)value /********* Primitives for shell edges *********/ /* */ @@ -1000,95 +1078,113 @@ int minus1mod3[3] = {2, 0, 1}; /* least significant bits (one for orientation, one for viral infection) */ /* are masked out to produce the real pointer. */ -#define sdecode( sptr, edge ) \ - ( edge ).shorient = (int) ( (unsigned long) ( sptr ) & (unsigned long) 1l ); \ - ( edge ).sh = (shelle *) \ - ( (unsigned long) ( sptr ) & ~(unsigned long) 3l ) +#define +sdecode( sptr, edge ) \ + ( edge ).shorient = (int) ((unsigned long) ( sptr ) & (unsigned long) 1l ); \ + ( edge ).sh = (shelle *) \ + ((unsigned long) ( sptr ) & ~(unsigned long) 3l ) /* sencode() compresses an oriented shell edge into a single pointer. It */ /* relies on the assumption that all shell edges are aligned to two-byte */ /* boundaries, so the least significant bit of (edge).sh is zero. */ -#define sencode( edge ) \ - (shelle) ( (unsigned long) ( edge ).sh | (unsigned long) ( edge ).shorient ) +#define +sencode( edge ) \ + (shelle) ((unsigned long) ( edge ).sh | (unsigned long) ( edge ).shorient ) /* ssym() toggles the orientation of a shell edge. */ -#define ssym( edge1, edge2 ) \ - ( edge2 ).sh = ( edge1 ).sh; \ - ( edge2 ).shorient = 1 - ( edge1 ).shorient +#define +ssym( edge1, edge2 ) \ + ( edge2 ).sh = ( edge1 ).sh; \ + ( edge2 ).shorient = 1 - ( edge1 ).shorient -#define ssymself( edge ) \ - ( edge ).shorient = 1 - ( edge ).shorient +#define +ssymself( edge ) \ + ( edge ).shorient = 1 - ( edge ).shorient /* spivot() finds the other shell edge (from the same segment) that shares */ /* the same origin. */ -#define spivot( edge1, edge2 ) \ - sptr = ( edge1 ).sh[( edge1 ).shorient]; \ - sdecode( sptr, edge2 ) +#define +spivot( edge1, edge2 ) \ + sptr = ( edge1 ).sh[( edge1 ).shorient]; \ + sdecode( sptr, edge2 ) -#define spivotself( edge ) \ - sptr = ( edge ).sh[( edge ).shorient]; \ - sdecode( sptr, edge ) +#define +spivotself( edge ) \ + sptr = ( edge ).sh[( edge ).shorient]; \ + sdecode( sptr, edge ) /* snext() finds the next shell edge (from the same segment) in sequence; */ /* one whose origin is the input shell edge's destination. */ -#define snext( edge1, edge2 ) \ - sptr = ( edge1 ).sh[1 - ( edge1 ).shorient]; \ - sdecode( sptr, edge2 ) +#define +snext( edge1, edge2 ) \ + sptr = ( edge1 ).sh[1 - ( edge1 ).shorient]; \ + sdecode( sptr, edge2 ) -#define snextself( edge ) \ - sptr = ( edge ).sh[1 - ( edge ).shorient]; \ - sdecode( sptr, edge ) +#define +snextself( edge ) \ + sptr = ( edge ).sh[1 - ( edge ).shorient]; \ + sdecode( sptr, edge ) /* These primitives determine or set the origin or destination of a shell */ /* edge. */ -#define sorg( edge, pointptr ) \ - pointptr = (point) ( edge ).sh[2 + ( edge ).shorient] +#define +sorg( edge, pointptr ) \ + pointptr = (point) ( edge ).sh[2 + ( edge ).shorient] -#define sdest( edge, pointptr ) \ - pointptr = (point) ( edge ).sh[3 - ( edge ).shorient] +#define +sdest( edge, pointptr ) \ + pointptr = (point) ( edge ).sh[3 - ( edge ).shorient] -#define setsorg( edge, pointptr ) \ - ( edge ).sh[2 + ( edge ).shorient] = (shelle) pointptr +#define +setsorg( edge, pointptr ) \ + ( edge ).sh[2 + ( edge ).shorient] = (shelle) pointptr -#define setsdest( edge, pointptr ) \ - ( edge ).sh[3 - ( edge ).shorient] = (shelle) pointptr +#define +setsdest( edge, pointptr ) \ + ( edge ).sh[3 - ( edge ).shorient] = (shelle) pointptr /* These primitives read or set a shell marker. Shell markers are used to */ /* hold user boundary information. */ -#define mark( edge ) ( *(int *) ( ( edge ).sh + 6 ) ) +#define +mark( edge ) ( *(int *) (( edge ).sh + 6 )) -#define setmark( edge, value ) \ - *(int *) ( ( edge ).sh + 6 ) = value +#define +setmark( edge, value ) \ + *(int *) (( edge ).sh + 6 ) = value /* Bond two shell edges together. */ -#define sbond( edge1, edge2 ) \ - ( edge1 ).sh[( edge1 ).shorient] = sencode( edge2 ); \ - ( edge2 ).sh[( edge2 ).shorient] = sencode( edge1 ) +#define +sbond( edge1, edge2 ) \ + ( edge1 ).sh[( edge1 ).shorient] = sencode( edge2 ); \ + ( edge2 ).sh[( edge2 ).shorient] = sencode( edge1 ) /* Dissolve a shell edge bond (from one side). Note that the other shell */ /* edge will still think it's connected to this shell edge. */ -#define sdissolve( edge ) \ - ( edge ).sh[( edge ).shorient] = (shelle) dummysh +#define +sdissolve( edge ) \ + ( edge ).sh[( edge ).shorient] = (shelle) dummysh /* Copy a shell edge. */ -#define shellecopy( edge1, edge2 ) \ - ( edge2 ).sh = ( edge1 ).sh; \ - ( edge2 ).shorient = ( edge1 ).shorient +#define +shellecopy( edge1, edge2 ) \ + ( edge2 ).sh = ( edge1 ).sh; \ + ( edge2 ).shorient = ( edge1 ).shorient /* Test for equality of shell edges. */ -#define shelleequal( edge1, edge2 ) \ - ( ( ( edge1 ).sh == ( edge2 ).sh ) && \ - ( ( edge1 ).shorient == ( edge2 ).shorient ) ) +#define +shelleequal( edge1, edge2 ) \ + ((( edge1 ).sh == ( edge2 ).sh ) && \ + (( edge1 ).shorient == ( edge2 ).shorient )) /********* Primitives for interacting triangles and shell edges *********/ /* */ @@ -1096,46 +1192,55 @@ int minus1mod3[3] = {2, 0, 1}; /* tspivot() finds a shell edge abutting a triangle. */ -#define tspivot( triedge, edge ) \ - sptr = (shelle) ( triedge ).tri[6 + ( triedge ).orient]; \ - sdecode( sptr, edge ) +#define +tspivot( triedge, edge ) \ + sptr = (shelle) ( triedge ).tri[6 + ( triedge ).orient]; \ + sdecode( sptr, edge ) /* stpivot() finds a triangle abutting a shell edge. It requires that the */ /* variable `ptr' of type `triangle' be defined. */ -#define stpivot( edge, triedge ) \ - ptr = (triangle) ( edge ).sh[4 + ( edge ).shorient]; \ - decode( ptr, triedge ) +#define +stpivot( edge, triedge ) \ + ptr = (triangle) ( edge ).sh[4 + ( edge ).shorient]; \ + decode( ptr, triedge ) /* Bond a triangle to a shell edge. */ -#define tsbond( triedge, edge ) \ - ( triedge ).tri[6 + ( triedge ).orient] = (triangle) sencode( edge ); \ - ( edge ).sh[4 + ( edge ).shorient] = (shelle) encode( triedge ) +#define +tsbond( triedge, edge ) \ + ( triedge ).tri[6 + ( triedge ).orient] = (triangle) sencode( edge ); \ + ( edge ).sh[4 + ( edge ).shorient] = (shelle) encode( triedge ) /* Dissolve a bond (from the triangle side). */ -#define tsdissolve( triedge ) \ - ( triedge ).tri[6 + ( triedge ).orient] = (triangle) dummysh +#define +tsdissolve( triedge ) \ + ( triedge ).tri[6 + ( triedge ).orient] = (triangle) dummysh /* Dissolve a bond (from the shell edge side). */ -#define stdissolve( edge ) \ - ( edge ).sh[4 + ( edge ).shorient] = (shelle) dummytri +#define +stdissolve( edge ) \ + ( edge ).sh[4 + ( edge ).shorient] = (shelle) dummytri /********* Primitives for points *********/ /* */ /* */ -#define pointmark( pt ) ( (int *) ( pt ) )[pointmarkindex] +#define +pointmark( pt ) ((int *) ( pt ))[pointmarkindex] -#define setpointmark( pt, value ) \ - ( (int *) ( pt ) )[pointmarkindex] = value +#define +setpointmark( pt, value ) \ + ((int *) ( pt ))[pointmarkindex] = value -#define point2tri( pt ) ( (triangle *) ( pt ) )[point2triindex] +#define +point2tri( pt ) ((triangle *) ( pt ))[point2triindex] -#define setpoint2tri( pt, value ) \ - ( (triangle *) ( pt ) )[point2triindex] = value +#define +setpoint2tri( pt, value ) \ + ((triangle *) ( pt ))[point2triindex] = value /** **/ /** **/ @@ -1151,66 +1256,75 @@ int minus1mod3[3] = {2, 0, 1}; /* */ /*****************************************************************************/ -#ifndef TRILIBRARY +#ifndef +TRILIBRARY void syntax(){ -#ifdef CDT_ONLY -#ifdef REDUCED - printf( "triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n" ); +#ifdef +CDT_ONLY +#ifdef +REDUCED +printf( "triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n" ); #else /* not REDUCED */ - printf( "triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n" ); +printf( "triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n" ); #endif /* not REDUCED */ #else /* not CDT_ONLY */ -#ifdef REDUCED - printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n" ); +#ifdef +REDUCED +printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n" ); #else /* not REDUCED */ - printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n" ); +printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n" ); #endif /* not REDUCED */ #endif /* not CDT_ONLY */ - printf( " -p Triangulates a Planar Straight Line Graph (.poly file).\n" ); -#ifndef CDT_ONLY - printf( " -r Refines a previously generated mesh.\n" ); - printf( - " -q Quality mesh generation. A minimum angle may be specified.\n" ); - printf( " -a Applies a maximum triangle area constraint.\n" ); +printf( " -p Triangulates a Planar Straight Line Graph (.poly file).\n" ); +#ifndef +CDT_ONLY +printf( " -r Refines a previously generated mesh.\n" ); +printf( +" -q Quality mesh generation. A minimum angle may be specified.\n" ); +printf( " -a Applies a maximum triangle area constraint.\n" ); #endif /* not CDT_ONLY */ - printf( - " -A Applies attributes to identify elements in certain regions.\n" ); - printf( " -c Encloses the convex hull with segments.\n" ); - printf( " -e Generates an edge list.\n" ); - printf( " -v Generates a Voronoi diagram.\n" ); - printf( " -n Generates a list of triangle neighbors.\n" ); - printf( " -g Generates an .off file for Geomview.\n" ); - printf( " -B Suppresses output of boundary information.\n" ); - printf( " -P Suppresses output of .poly file.\n" ); - printf( " -N Suppresses output of .node file.\n" ); - printf( " -E Suppresses output of .ele file.\n" ); - printf( " -I Suppresses mesh iteration numbers.\n" ); - printf( " -O Ignores holes in .poly file.\n" ); - printf( " -X Suppresses use of exact arithmetic.\n" ); - printf( " -z Numbers all items starting from zero (rather than one).\n" ); - printf( " -o2 Generates second-order subparametric elements.\n" ); -#ifndef CDT_ONLY - printf( " -Y Suppresses boundary segment splitting.\n" ); - printf( " -S Specifies maximum number of added Steiner points.\n" ); +printf( +" -A Applies attributes to identify elements in certain regions.\n" ); +printf( " -c Encloses the convex hull with segments.\n" ); +printf( " -e Generates an edge list.\n" ); +printf( " -v Generates a Voronoi diagram.\n" ); +printf( " -n Generates a list of triangle neighbors.\n" ); +printf( " -g Generates an .off file for Geomview.\n" ); +printf( " -B Suppresses output of boundary information.\n" ); +printf( " -P Suppresses output of .poly file.\n" ); +printf( " -N Suppresses output of .node file.\n" ); +printf( " -E Suppresses output of .ele file.\n" ); +printf( " -I Suppresses mesh iteration numbers.\n" ); +printf( " -O Ignores holes in .poly file.\n" ); +printf( " -X Suppresses use of exact arithmetic.\n" ); +printf( " -z Numbers all items starting from zero (rather than one).\n" ); +printf( " -o2 Generates second-order subparametric elements.\n" ); +#ifndef +CDT_ONLY +printf( " -Y Suppresses boundary segment splitting.\n" ); +printf( " -S Specifies maximum number of added Steiner points.\n" ); #endif /* not CDT_ONLY */ -#ifndef REDUCED - printf( " -i Uses incremental method, rather than divide-and-conquer.\n" ); - printf( " -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n" ); +#ifndef +REDUCED +printf( " -i Uses incremental method, rather than divide-and-conquer.\n" ); +printf( " -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n" ); #endif /* not REDUCED */ - printf( " -l Uses vertical cuts only, rather than alternating cuts.\n" ); -#ifndef REDUCED -#ifndef CDT_ONLY - printf( - " -s Force segments into mesh by splitting (instead of using CDT).\n" ); +printf( " -l Uses vertical cuts only, rather than alternating cuts.\n" ); +#ifndef +REDUCED +#ifndef +CDT_ONLY +printf( +" -s Force segments into mesh by splitting (instead of using CDT).\n" ); #endif /* not CDT_ONLY */ - printf( " -C Check consistency of final mesh.\n" ); +printf( " -C Check consistency of final mesh.\n" ); #endif /* not REDUCED */ - printf( " -Q Quiet: No terminal output except errors.\n" ); - printf( " -V Verbose: Detailed information on what I'm doing.\n" ); - printf( " -h Help: Detailed instructions for Triangle.\n" ); - exit( 0 ); +printf( " -Q Quiet: No terminal output except errors.\n" ); +printf( " -V Verbose: Detailed information on what I'm doing.\n" ); +printf( " -h Help: Detailed instructions for Triangle.\n" ); +exit( 0 ); } #endif /* not TRILIBRARY */ @@ -1221,1428 +1335,1433 @@ void syntax(){ /* */ /*****************************************************************************/ -#ifndef TRILIBRARY +#ifndef +TRILIBRARY void info(){ - printf( "Triangle\n" ); - printf( - "A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n" ); - printf( "Version 1.3\n\n" ); - printf( - "Copyright 1996 Jonathan Richard Shewchuk (bugs/comments to jrs@cs.cmu.edu)\n" - ); - printf( "School of Computer Science / Carnegie Mellon University\n" ); - printf( "5000 Forbes Avenue / Pittsburgh, Pennsylvania 15213-3891\n" ); - printf( - "Created as part of the Archimedes project (tools for parallel FEM).\n" ); - printf( - "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n" ); - printf( "There is no warranty whatsoever. Use at your own risk.\n" ); -#ifdef SINGLE - printf( "This executable is compiled for single precision arithmetic.\n\n\n" ); +printf( "Triangle\n" ); +printf( +"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n" ); +printf( "Version 1.3\n\n" ); +printf( +"Copyright 1996 Jonathan Richard Shewchuk (bugs/comments to jrs@cs.cmu.edu)\n" +); +printf( "School of Computer Science / Carnegie Mellon University\n" ); +printf( "5000 Forbes Avenue / Pittsburgh, Pennsylvania 15213-3891\n" ); +printf( +"Created as part of the Archimedes project (tools for parallel FEM).\n" ); +printf( +"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n" ); +printf( "There is no warranty whatsoever. Use at your own risk.\n" ); +#ifdef +SINGLE +printf( "This executable is compiled for single precision arithmetic.\n\n\n" ); #else /* not SINGLE */ - printf( "This executable is compiled for double precision arithmetic.\n\n\n" ); +printf( "This executable is compiled for double precision arithmetic.\n\n\n" ); #endif /* not SINGLE */ - printf( - "Triangle generates exact Delaunay triangulations, constrained Delaunay\n" ); - printf( - "triangulations, and quality conforming Delaunay triangulations. The latter\n" - ); - printf( - "can be generated with no small angles, and are thus suitable for finite\n" ); - printf( - "element analysis. If no command line switches are specified, your .node\n" ); - printf( - "input file will be read, and the Delaunay triangulation will be returned in\n" - ); - printf( ".node and .ele output files. The command syntax is:\n\n" ); -#ifdef CDT_ONLY -#ifdef REDUCED - printf( "triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n\n" ); +printf( +"Triangle generates exact Delaunay triangulations, constrained Delaunay\n" ); +printf( +"triangulations, and quality conforming Delaunay triangulations. The latter\n" +); +printf( +"can be generated with no small angles, and are thus suitable for finite\n" ); +printf( +"element analysis. If no command line switches are specified, your .node\n" ); +printf( +"input file will be read, and the Delaunay triangulation will be returned in\n" +); +printf( ".node and .ele output files. The command syntax is:\n\n" ); +#ifdef +CDT_ONLY +#ifdef +REDUCED +printf( "triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n\n" ); #else /* not REDUCED */ - printf( "triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n\n" ); +printf( "triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n\n" ); #endif /* not REDUCED */ #else /* not CDT_ONLY */ -#ifdef REDUCED - printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n\n" ); +#ifdef +REDUCED +printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n\n" ); #else /* not REDUCED */ - printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n" ); +printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n" ); #endif /* not REDUCED */ #endif /* not CDT_ONLY */ - printf( - "Underscores indicate that numbers may optionally follow certain switches;\n" ); - printf( - "do not leave any space between a switch and its numeric parameter.\n" ); - printf( - "input_file must be a file with extension .node, or extension .poly if the\n" ); - printf( - "-p switch is used. If -r is used, you must supply .node and .ele files,\n" ); - printf( - "and possibly a .poly file and .area file as well. The formats of these\n" ); - printf( "files are described below.\n\n" ); - printf( "Command Line Switches:\n\n" ); - printf( - " -p Reads a Planar Straight Line Graph (.poly file), which can specify\n" - ); - printf( - " points, segments, holes, and regional attributes and area\n" ); - printf( - " constraints. Will generate a constrained Delaunay triangulation\n" ); - printf( - " fitting the input; or, if -s, -q, or -a is used, a conforming\n" ); - printf( - " Delaunay triangulation. If -p is not used, Triangle reads a .node\n" - ); - printf( " file by default.\n" ); - printf( - " -r Refines a previously generated mesh. The mesh is read from a .node\n" - ); - printf( - " file and an .ele file. If -p is also used, a .poly file is read\n" ); - printf( - " and used to constrain edges in the mesh. Further details on\n" ); - printf( " refinement are given below.\n" ); - printf( - " -q Quality mesh generation by Jim Ruppert's Delaunay refinement\n" ); - printf( - " algorithm. Adds points to the mesh to ensure that no angles\n" ); - printf( - " smaller than 20 degrees occur. An alternative minimum angle may be\n" - ); - printf( - " specified after the `q'. If the minimum angle is 20.7 degrees or\n" ); - printf( - " smaller, the triangulation algorithm is theoretically guaranteed to\n" - ); - printf( - " terminate (assuming infinite precision arithmetic - Triangle may\n" ); - printf( - " fail to terminate if you run out of precision). In practice, the\n" ); - printf( - " algorithm often succeeds for minimum angles up to 33.8 degrees.\n" ); - printf( - " For highly refined meshes, however, it may be necessary to reduce\n" ); - printf( - " the minimum angle to well below 20 to avoid problems associated\n" ); - printf( - " with insufficient floating-point precision. The specified angle\n" ); - printf( " may include a decimal point.\n" ); - printf( - " -a Imposes a maximum triangle area. If a number follows the `a', no\n" ); - printf( - " triangle will be generated whose area is larger than that number.\n" ); - printf( - " If no number is specified, an .area file (if -r is used) or .poly\n" ); - printf( - " file (if -r is not used) specifies a number of maximum area\n" ); - printf( - " constraints. An .area file contains a separate area constraint for\n" - ); - printf( - " each triangle, and is useful for refining a finite element mesh\n" ); - printf( - " based on a posteriori error estimates. A .poly file can optionally\n" - ); - printf( - " contain an area constraint for each segment-bounded region, thereby\n" - ); - printf( - " enforcing triangle densities in a first triangulation. You can\n" ); - printf( - " impose both a fixed area constraint and a varying area constraint\n" ); - printf( - " by invoking the -a switch twice, once with and once without a\n" ); - printf( - " number following. Each area specified may include a decimal point.\n" - ); - printf( - " -A Assigns an additional attribute to each triangle that identifies\n" ); - printf( - " what segment-bounded region each triangle belongs to. Attributes\n" ); - printf( - " are assigned to regions by the .poly file. If a region is not\n" ); - printf( - " explicitly marked by the .poly file, triangles in that region are\n" ); - printf( - " assigned an attribute of zero. The -A switch has an effect only\n" ); - printf( " when the -p switch is used and the -r switch is not.\n" ); - printf( - " -c Creates segments on the convex hull of the triangulation. If you\n" ); - printf( - " are triangulating a point set, this switch causes a .poly file to\n" ); - printf( - " be written, containing all edges in the convex hull. (By default,\n" - ); - printf( - " a .poly file is written only if a .poly file is read.) If you are\n" - ); - printf( - " triangulating a PSLG, this switch specifies that the interior of\n" ); - printf( - " the convex hull of the PSLG should be triangulated. If you do not\n" - ); - printf( - " use this switch when triangulating a PSLG, it is assumed that you\n" ); - printf( - " have identified the region to be triangulated by surrounding it\n" ); - printf( - " with segments of the input PSLG. Beware: if you are not careful,\n" - ); - printf( - " this switch can cause the introduction of an extremely thin angle\n" ); - printf( - " between a PSLG segment and a convex hull segment, which can cause\n" ); - printf( - " overrefinement or failure if Triangle runs out of precision. If\n" ); - printf( - " you are refining a mesh, the -c switch works differently; it\n" ); - printf( - " generates the set of boundary edges of the mesh, rather than the\n" ); - printf( " convex hull.\n" ); - printf( - " -e Outputs (to an .edge file) a list of edges of the triangulation.\n" ); - printf( - " -v Outputs the Voronoi diagram associated with the triangulation.\n" ); - printf( " Does not attempt to detect degeneracies.\n" ); - printf( - " -n Outputs (to a .neigh file) a list of triangles neighboring each\n" ); - printf( " triangle.\n" ); - printf( - " -g Outputs the mesh to an Object File Format (.off) file, suitable for\n" - ); - printf( " viewing with the Geometry Center's Geomview package.\n" ); - printf( - " -B No boundary markers in the output .node, .poly, and .edge output\n" ); - printf( - " files. See the detailed discussion of boundary markers below.\n" ); - printf( - " -P No output .poly file. Saves disk space, but you lose the ability\n" ); - printf( - " to impose segment constraints on later refinements of the mesh.\n" ); - printf( " -N No output .node file.\n" ); - printf( " -E No output .ele file.\n" ); - printf( - " -I No iteration numbers. Suppresses the output of .node and .poly\n" ); - printf( - " files, so your input files won't be overwritten. (If your input is\n" - ); - printf( - " a .poly file only, a .node file will be written.) Cannot be used\n" ); - printf( - " with the -r switch, because that would overwrite your input .ele\n" ); - printf( - " file. Shouldn't be used with the -s, -q, or -a switch if you are\n" ); - printf( - " using a .node file for input, because no .node file will be\n" ); - printf( " written, so there will be no record of any added points.\n" ); - printf( " -O No holes. Ignores the holes in the .poly file.\n" ); - printf( - " -X No exact arithmetic. Normally, Triangle uses exact floating-point\n" - ); - printf( - " arithmetic for certain tests if it thinks the inexact tests are not\n" - ); - printf( - " accurate enough. Exact arithmetic ensures the robustness of the\n" ); - printf( - " triangulation algorithms, despite floating-point roundoff error.\n" ); - printf( - " Disabling exact arithmetic with the -X switch will cause a small\n" ); - printf( - " improvement in speed and create the possibility (albeit small) that\n" - ); - printf( - " Triangle will fail to produce a valid mesh. Not recommended.\n" ); - printf( - " -z Numbers all items starting from zero (rather than one). Note that\n" - ); - printf( - " this switch is normally overrided by the value used to number the\n" ); - printf( - " first point of the input .node or .poly file. However, this switch\n" - ); - printf( " is useful when calling Triangle from another program.\n" ); - printf( - " -o2 Generates second-order subparametric elements with six nodes each.\n" - ); - printf( - " -Y No new points on the boundary. This switch is useful when the mesh\n" - ); - printf( - " boundary must be preserved so that it conforms to some adjacent\n" ); - printf( - " mesh. Be forewarned that you will probably sacrifice some of the\n" ); - printf( - " quality of the mesh; Triangle will try, but the resulting mesh may\n" - ); - printf( - " contain triangles of poor aspect ratio. Works well if all the\n" ); - printf( - " boundary points are closely spaced. Specify this switch twice\n" ); - printf( - " (`-YY') to prevent all segment splitting, including internal\n" ); - printf( " boundaries.\n" ); - printf( - " -S Specifies the maximum number of Steiner points (points that are not\n" - ); - printf( - " in the input, but are added to meet the constraints of minimum\n" ); - printf( - " angle and maximum area). The default is to allow an unlimited\n" ); - printf( - " number. If you specify this switch with no number after it,\n" ); - printf( - " the limit is set to zero. Triangle always adds points at segment\n" ); - printf( - " intersections, even if it needs to use more points than the limit\n" ); - printf( - " you set. When Triangle inserts segments by splitting (-s), it\n" ); - printf( - " always adds enough points to ensure that all the segments appear in\n" - ); - printf( - " the triangulation, again ignoring the limit. Be forewarned that\n" ); - printf( - " the -S switch may result in a conforming triangulation that is not\n" - ); - printf( - " truly Delaunay, because Triangle may be forced to stop adding\n" ); - printf( - " points when the mesh is in a state where a segment is non-Delaunay\n" - ); - printf( - " and needs to be split. If so, Triangle will print a warning.\n" ); - printf( - " -i Uses an incremental rather than divide-and-conquer algorithm to\n" ); - printf( - " form a Delaunay triangulation. Try it if the divide-and-conquer\n" ); - printf( " algorithm fails.\n" ); - printf( - " -F Uses Steven Fortune's sweepline algorithm to form a Delaunay\n" ); - printf( - " triangulation. Warning: does not use exact arithmetic for all\n" ); - printf( " calculations. An exact result is not guaranteed.\n" ); - printf( - " -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n" ); - printf( - " default, Triangle uses alternating vertical and horizontal cuts,\n" ); - printf( - " which usually improve the speed except with point sets that are\n" ); - printf( - " small or short and wide. This switch is primarily of theoretical\n" ); - printf( " interest.\n" ); - printf( - " -s Specifies that segments should be forced into the triangulation by\n" - ); - printf( - " recursively splitting them at their midpoints, rather than by\n" ); - printf( - " generating a constrained Delaunay triangulation. Segment splitting\n" - ); - printf( - " is true to Ruppert's original algorithm, but can create needlessly\n" - ); - printf( " small triangles near external small features.\n" ); - printf( - " -C Check the consistency of the final mesh. Uses exact arithmetic for\n" - ); - printf( - " checking, even if the -X switch is used. Useful if you suspect\n" ); - printf( " Triangle is buggy.\n" ); - printf( - " -Q Quiet: Suppresses all explanation of what Triangle is doing, unless\n" - ); - printf( " an error occurs.\n" ); - printf( - " -V Verbose: Gives detailed information about what Triangle is doing.\n" ); - printf( - " Add more `V's for increasing amount of detail. `-V' gives\n" ); - printf( - " information on algorithmic progress and more detailed statistics.\n" ); - printf( - " `-VV' gives point-by-point details, and will print so much that\n" ); - printf( - " Triangle will run much more slowly. `-VVV' gives information only\n" - ); - printf( " a debugger could love.\n" ); - printf( " -h Help: Displays these instructions.\n" ); - printf( "\n" ); - printf( "Definitions:\n" ); - printf( "\n" ); - printf( - " A Delaunay triangulation of a point set is a triangulation whose vertices\n" - ); - printf( - " are the point set, having the property that no point in the point set\n" ); - printf( - " falls in the interior of the circumcircle (circle that passes through all\n" - ); - printf( " three vertices) of any triangle in the triangulation.\n\n" ); - printf( - " A Voronoi diagram of a point set is a subdivision of the plane into\n" ); - printf( - " polygonal regions (some of which may be infinite), where each region is\n" ); - printf( - " the set of points in the plane that are closer to some input point than\n" ); - printf( - " to any other input point. (The Voronoi diagram is the geometric dual of\n" - ); - printf( " the Delaunay triangulation.)\n\n" ); - printf( - " A Planar Straight Line Graph (PSLG) is a collection of points and\n" ); - printf( - " segments. Segments are simply edges, whose endpoints are points in the\n" ); - printf( - " PSLG. The file format for PSLGs (.poly files) is described below.\n" ); - printf( "\n" ); - printf( - " A constrained Delaunay triangulation of a PSLG is similar to a Delaunay\n" ); - printf( - " triangulation, but each PSLG segment is present as a single edge in the\n" ); - printf( - " triangulation. (A constrained Delaunay triangulation is not truly a\n" ); - printf( " Delaunay triangulation.)\n\n" ); - printf( - " A conforming Delaunay triangulation of a PSLG is a true Delaunay\n" ); - printf( - " triangulation in which each PSLG segment may have been subdivided into\n" ); - printf( - " several edges by the insertion of additional points. These inserted\n" ); - printf( - " points are necessary to allow the segments to exist in the mesh while\n" ); - printf( " maintaining the Delaunay property.\n\n" ); - printf( "File Formats:\n\n" ); - printf( - " All files may contain comments prefixed by the character '#'. Points,\n" ); - printf( - " triangles, edges, holes, and maximum area constraints must be numbered\n" ); - printf( - " consecutively, starting from either 1 or 0. Whichever you choose, all\n" ); - printf( - " input files must be consistent; if the nodes are numbered from 1, so must\n" - ); - printf( - " be all other objects. Triangle automatically detects your choice while\n" ); - printf( - " reading the .node (or .poly) file. (When calling Triangle from another\n" ); - printf( - " program, use the -z switch if you wish to number objects from zero.)\n" ); - printf( " Examples of these file formats are given below.\n\n" ); - printf( " .node files:\n" ); - printf( - " First line: <# of points> <# of attributes>\n" ); - printf( - " <# of boundary markers (0 or 1)>\n" - ); - printf( - " Remaining lines: [attributes] [boundary marker]\n" ); - printf( "\n" ); - printf( - " The attributes, which are typically floating-point values of physical\n" ); - printf( - " quantities (such as mass or conductivity) associated with the nodes of\n" - ); - printf( - " a finite element mesh, are copied unchanged to the output mesh. If -s,\n" - ); - printf( - " -q, or -a is selected, each new Steiner point added to the mesh will\n" ); - printf( " have attributes assigned to it by linear interpolation.\n\n" ); - printf( - " If the fourth entry of the first line is `1', the last column of the\n" ); - printf( - " remainder of the file is assumed to contain boundary markers. Boundary\n" - ); - printf( - " markers are used to identify boundary points and points resting on PSLG\n" - ); - printf( - " segments; a complete description appears in a section below. The .node\n" - ); - printf( - " file produced by Triangle will contain boundary markers in the last\n" ); - printf( " column unless they are suppressed by the -B switch.\n\n" ); - printf( " .ele files:\n" ); - printf( - " First line: <# of triangles> <# of attributes>\n" ); - printf( - " Remaining lines: ... [attributes]\n" - ); - printf( "\n" ); - printf( - " Points are indices into the corresponding .node file. The first three\n" - ); - printf( - " points are the corners, and are listed in counterclockwise order around\n" - ); - printf( - " each triangle. (The remaining points, if any, depend on the type of\n" ); - printf( - " finite element used.) The attributes are just like those of .node\n" ); - printf( - " files. Because there is no simple mapping from input to output\n" ); - printf( - " triangles, an attempt is made to interpolate attributes, which may\n" ); - printf( - " result in a good deal of diffusion of attributes among nearby triangles\n" - ); - printf( - " as the triangulation is refined. Diffusion does not occur across\n" ); - printf( - " segments, so attributes used to identify segment-bounded regions remain\n" - ); - printf( - " intact. In output .ele files, all triangles have three points each\n" ); - printf( - " unless the -o2 switch is used, in which case they have six, and the\n" ); - printf( - " fourth, fifth, and sixth points lie on the midpoints of the edges\n" ); - printf( " opposite the first, second, and third corners.\n\n" ); - printf( " .poly files:\n" ); - printf( - " First line: <# of points> <# of attributes>\n" ); - printf( - " <# of boundary markers (0 or 1)>\n" - ); - printf( - " Following lines: [attributes] [boundary marker]\n" ); - printf( " One line: <# of segments> <# of boundary markers (0 or 1)>\n" ); - printf( - " Following lines: [boundary marker]\n" ); - printf( " One line: <# of holes>\n" ); - printf( " Following lines: \n" ); - printf( - " Optional line: <# of regional attributes and/or area constraints>\n" ); - printf( - " Optional following lines: \n" ); - printf( "\n" ); - printf( - " A .poly file represents a PSLG, as well as some additional information.\n" - ); - printf( - " The first section lists all the points, and is identical to the format\n" - ); - printf( - " of .node files. <# of points> may be set to zero to indicate that the\n" - ); - printf( - " points are listed in a separate .node file; .poly files produced by\n" ); - printf( - " Triangle always have this format. This has the advantage that a point\n" - ); - printf( - " set may easily be triangulated with or without segments. (The same\n" ); - printf( - " effect can be achieved, albeit using more disk space, by making a copy\n" - ); - printf( - " of the .poly file with the extension .node; all sections of the file\n" ); - printf( " but the first are ignored.)\n\n" ); - printf( - " The second section lists the segments. Segments are edges whose\n" ); - printf( - " presence in the triangulation is enforced. Each segment is specified\n" ); - printf( - " by listing the indices of its two endpoints. This means that you must\n" - ); - printf( - " include its endpoints in the point list. If -s, -q, and -a are not\n" ); - printf( - " selected, Triangle will produce a constrained Delaunay triangulation,\n" ); - printf( - " in which each segment appears as a single edge in the triangulation.\n" ); - printf( - " If -q or -a is selected, Triangle will produce a conforming Delaunay\n" ); - printf( - " triangulation, in which segments may be subdivided into smaller edges.\n" - ); - printf( " Each segment, like each point, may have a boundary marker.\n\n" ); - printf( - " The third section lists holes (and concavities, if -c is selected) in\n" ); - printf( - " the triangulation. Holes are specified by identifying a point inside\n" ); - printf( - " each hole. After the triangulation is formed, Triangle creates holes\n" ); - printf( - " by eating triangles, spreading out from each hole point until its\n" ); - printf( - " progress is blocked by PSLG segments; you must be careful to enclose\n" ); - printf( - " each hole in segments, or your whole triangulation may be eaten away.\n" ); - printf( - " If the two triangles abutting a segment are eaten, the segment itself\n" ); - printf( - " is also eaten. Do not place a hole directly on a segment; if you do,\n" ); - printf( " Triangle will choose one side of the segment arbitrarily.\n\n" ); - printf( - " The optional fourth section lists regional attributes (to be assigned\n" ); - printf( - " to all triangles in a region) and regional constraints on the maximum\n" ); - printf( - " triangle area. Triangle will read this section only if the -A switch\n" ); - printf( - " is used or the -a switch is used without a number following it, and the\n" - ); - printf( - " -r switch is not used. Regional attributes and area constraints are\n" ); - printf( - " propagated in the same manner as holes; you specify a point for each\n" ); - printf( - " attribute and/or constraint, and the attribute and/or constraint will\n" ); - printf( - " affect the whole region (bounded by segments) containing the point. If\n" - ); - printf( - " two values are written on a line after the x and y coordinate, the\n" ); - printf( - " former is assumed to be a regional attribute (but will only be applied\n" - ); - printf( - " if the -A switch is selected), and the latter is assumed to be a\n" ); - printf( - " regional area constraint (but will only be applied if the -a switch is\n" - ); - printf( - " selected). You may also specify just one value after the coordinates,\n" - ); - printf( - " which can serve as both an attribute and an area constraint, depending\n" - ); - printf( - " on the choice of switches. If you are using the -A and -a switches\n" ); - printf( - " simultaneously and wish to assign an attribute to some region without\n" ); - printf( " imposing an area constraint, use a negative maximum area.\n\n" ); - printf( - " When a triangulation is created from a .poly file, you must either\n" ); - printf( - " enclose the entire region to be triangulated in PSLG segments, or\n" ); - printf( - " use the -c switch, which encloses the convex hull of the input point\n" ); - printf( - " set. If you do not use the -c switch, Triangle will eat all triangles\n" - ); - printf( - " on the outer boundary that are not protected by segments; if you are\n" ); - printf( - " not careful, your whole triangulation may be eaten away. If you do\n" ); - printf( - " use the -c switch, you can still produce concavities by appropriate\n" ); - printf( " placement of holes just inside the convex hull.\n\n" ); - printf( - " An ideal PSLG has no intersecting segments, nor any points that lie\n" ); - printf( - " upon segments (except, of course, the endpoints of each segment.) You\n" - ); - printf( - " aren't required to make your .poly files ideal, but you should be aware\n" - ); - printf( - " of what can go wrong. Segment intersections are relatively safe -\n" ); - printf( - " Triangle will calculate the intersection points for you and add them to\n" - ); - printf( - " the triangulation - as long as your machine's floating-point precision\n" - ); - printf( - " doesn't become a problem. You are tempting the fates if you have three\n" - ); - printf( - " segments that cross at the same location, and expect Triangle to figure\n" - ); - printf( - " out where the intersection point is. Thanks to floating-point roundoff\n" - ); - printf( - " error, Triangle will probably decide that the three segments intersect\n" - ); - printf( - " at three different points, and you will find a minuscule triangle in\n" ); - printf( - " your output - unless Triangle tries to refine the tiny triangle, uses\n" ); - printf( - " up the last bit of machine precision, and fails to terminate at all.\n" ); - printf( - " You're better off putting the intersection point in the input files,\n" ); - printf( - " and manually breaking up each segment into two. Similarly, if you\n" ); - printf( - " place a point at the middle of a segment, and hope that Triangle will\n" ); - printf( - " break up the segment at that point, you might get lucky. On the other\n" - ); - printf( - " hand, Triangle might decide that the point doesn't lie precisely on the\n" - ); - printf( - " line, and you'll have a needle-sharp triangle in your output - or a lot\n" - ); - printf( " of tiny triangles if you're generating a quality mesh.\n\n" ); - printf( - " When Triangle reads a .poly file, it also writes a .poly file, which\n" ); - printf( - " includes all edges that are part of input segments. If the -c switch\n" ); - printf( - " is used, the output .poly file will also include all of the edges on\n" ); - printf( - " the convex hull. Hence, the output .poly file is useful for finding\n" ); - printf( - " edges associated with input segments and setting boundary conditions in\n" - ); - printf( - " finite element simulations. More importantly, you will need it if you\n" - ); - printf( - " plan to refine the output mesh, and don't want segments to be missing\n" ); - printf( " in later triangulations.\n\n" ); - printf( " .area files:\n" ); - printf( " First line: <# of triangles>\n" ); - printf( " Following lines: \n\n" ); - printf( - " An .area file associates with each triangle a maximum area that is used\n" - ); - printf( - " for mesh refinement. As with other file formats, every triangle must\n" ); - printf( - " be represented, and they must be numbered consecutively. A triangle\n" ); - printf( - " may be left unconstrained by assigning it a negative maximum area.\n" ); - printf( "\n" ); - printf( " .edge files:\n" ); - printf( " First line: <# of edges> <# of boundary markers (0 or 1)>\n" ); - printf( - " Following lines: [boundary marker]\n" ); - printf( "\n" ); - printf( - " Endpoints are indices into the corresponding .node file. Triangle can\n" - ); - printf( - " produce .edge files (use the -e switch), but cannot read them. The\n" ); - printf( - " optional column of boundary markers is suppressed by the -B switch.\n" ); - printf( "\n" ); - printf( - " In Voronoi diagrams, one also finds a special kind of edge that is an\n" ); - printf( - " infinite ray with only one endpoint. For these edges, a different\n" ); - printf( " format is used:\n\n" ); - printf( " -1 \n\n" ); - printf( - " The `direction' is a floating-point vector that indicates the direction\n" - ); - printf( " of the infinite ray.\n\n" ); - printf( " .neigh files:\n" ); - printf( - " First line: <# of triangles> <# of neighbors per triangle (always 3)>\n" - ); - printf( - " Following lines: \n" ); - printf( "\n" ); - printf( - " Neighbors are indices into the corresponding .ele file. An index of -1\n" - ); - printf( - " indicates a mesh boundary, and therefore no neighbor. Triangle can\n" ); - printf( - " produce .neigh files (use the -n switch), but cannot read them.\n" ); - printf( "\n" ); - printf( - " The first neighbor of triangle i is opposite the first corner of\n" ); - printf( " triangle i, and so on.\n\n" ); - printf( "Boundary Markers:\n\n" ); - printf( - " Boundary markers are tags used mainly to identify which output points and\n" - ); - printf( - " edges are associated with which PSLG segment, and to identify which\n" ); - printf( - " points and edges occur on a boundary of the triangulation. A common use\n" - ); - printf( - " is to determine where boundary conditions should be applied to a finite\n" ); - printf( - " element mesh. You can prevent boundary markers from being written into\n" ); - printf( " files produced by Triangle by using the -B switch.\n\n" ); - printf( - " The boundary marker associated with each segment in an output .poly file\n" - ); - printf( " or edge in an output .edge file is chosen as follows:\n" ); - printf( - " - If an output edge is part or all of a PSLG segment with a nonzero\n" ); - printf( - " boundary marker, then the edge is assigned the same marker.\n" ); - printf( - " - Otherwise, if the edge occurs on a boundary of the triangulation\n" ); - printf( - " (including boundaries of holes), then the edge is assigned the marker\n" - ); - printf( " one (1).\n" ); - printf( " - Otherwise, the edge is assigned the marker zero (0).\n" ); - printf( - " The boundary marker associated with each point in an output .node file is\n" - ); - printf( " chosen as follows:\n" ); - printf( - " - If a point is assigned a nonzero boundary marker in the input file,\n" ); - printf( - " then it is assigned the same marker in the output .node file.\n" ); - printf( - " - Otherwise, if the point lies on a PSLG segment (including the\n" ); - printf( - " segment's endpoints) with a nonzero boundary marker, then the point\n" ); - printf( - " is assigned the same marker. If the point lies on several such\n" ); - printf( " segments, one of the markers is chosen arbitrarily.\n" ); - printf( - " - Otherwise, if the point occurs on a boundary of the triangulation,\n" ); - printf( " then the point is assigned the marker one (1).\n" ); - printf( " - Otherwise, the point is assigned the marker zero (0).\n" ); - printf( "\n" ); - printf( - " If you want Triangle to determine for you which points and edges are on\n" ); - printf( - " the boundary, assign them the boundary marker zero (or use no markers at\n" - ); - printf( - " all) in your input files. Alternatively, you can mark some of them and\n" ); - printf( " leave others marked zero, allowing Triangle to label them.\n\n" ); - printf( "Triangulation Iteration Numbers:\n\n" ); - printf( - " Because Triangle can read and refine its own triangulations, input\n" ); - printf( - " and output files have iteration numbers. For instance, Triangle might\n" ); - printf( - " read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n" ); - printf( - " triangulation, and output the files mesh.4.node, mesh.4.ele, and\n" ); - printf( " mesh.4.poly. Files with no iteration number are treated as if\n" ); - printf( - " their iteration number is zero; hence, Triangle might read the file\n" ); - printf( - " points.node, triangulate it, and produce the files points.1.node and\n" ); - printf( " points.1.ele.\n\n" ); - printf( - " Iteration numbers allow you to create a sequence of successively finer\n" ); - printf( - " meshes suitable for multigrid methods. They also allow you to produce a\n" - ); - printf( - " sequence of meshes using error estimate-driven mesh refinement.\n" ); - printf( "\n" ); - printf( - " If you're not using refinement or quality meshing, and you don't like\n" ); - printf( - " iteration numbers, use the -I switch to disable them. This switch will\n" ); - printf( - " also disable output of .node and .poly files to prevent your input files\n" - ); - printf( - " from being overwritten. (If the input is a .poly file that contains its\n" - ); - printf( " own points, a .node file will be written.)\n\n" ); - printf( "Examples of How to Use Triangle:\n\n" ); - printf( - " `triangle dots' will read points from dots.node, and write their Delaunay\n" - ); - printf( - " triangulation to dots.1.node and dots.1.ele. (dots.1.node will be\n" ); - printf( - " identical to dots.node.) `triangle -I dots' writes the triangulation to\n" - ); - printf( - " dots.ele instead. (No additional .node file is needed, so none is\n" ); - printf( " written.)\n\n" ); - printf( - " `triangle -pe object.1' will read a PSLG from object.1.poly (and possibly\n" - ); - printf( - " object.1.node, if the points are omitted from object.1.poly) and write\n" ); - printf( " their constrained Delaunay triangulation to object.2.node and\n" ); - printf( - " object.2.ele. The segments will be copied to object.2.poly, and all\n" ); - printf( " edges will be written to object.2.edge.\n\n" ); - printf( - " `triangle -pq31.5a.1 object' will read a PSLG from object.poly (and\n" ); - printf( - " possibly object.node), generate a mesh whose angles are all greater than\n" - ); - printf( - " 31.5 degrees and whose triangles all have area smaller than 0.1, and\n" ); - printf( - " write the mesh to object.1.node and object.1.ele. Each segment may have\n" - ); - printf( - " been broken up into multiple edges; the resulting constrained edges are\n" ); - printf( " written to object.1.poly.\n\n" ); - printf( - " Here is a sample file `box.poly' describing a square with a square hole:\n" - ); - printf( "\n" ); - printf( - " # A box with eight points in 2D, no attributes, one boundary marker.\n" ); - printf( " 8 2 0 1\n" ); - printf( " # Outer box has these vertices:\n" ); - printf( " 1 0 0 0\n" ); - printf( " 2 0 3 0\n" ); - printf( " 3 3 0 0\n" ); - printf( " 4 3 3 33 # A special marker for this point.\n" ); - printf( " # Inner square has these vertices:\n" ); - printf( " 5 1 1 0\n" ); - printf( " 6 1 2 0\n" ); - printf( " 7 2 1 0\n" ); - printf( " 8 2 2 0\n" ); - printf( " # Five segments with boundary markers.\n" ); - printf( " 5 1\n" ); - printf( " 1 1 2 5 # Left side of outer box.\n" ); - printf( " 2 5 7 0 # Segments 2 through 5 enclose the hole.\n" ); - printf( " 3 7 8 0\n" ); - printf( " 4 8 6 10\n" ); - printf( " 5 6 5 0\n" ); - printf( " # One hole in the middle of the inner square.\n" ); - printf( " 1\n" ); - printf( " 1 1.5 1.5\n\n" ); - printf( - " Note that some segments are missing from the outer square, so one must\n" ); - printf( - " use the `-c' switch. After `triangle -pqc box.poly', here is the output\n" - ); - printf( - " file `box.1.node', with twelve points. The last four points were added\n" ); - printf( - " to meet the angle constraint. Points 1, 2, and 9 have markers from\n" ); - printf( - " segment 1. Points 6 and 8 have markers from segment 4. All the other\n" ); - printf( - " points but 4 have been marked to indicate that they lie on a boundary.\n" ); - printf( "\n" ); - printf( " 12 2 0 1\n" ); - printf( " 1 0 0 5\n" ); - printf( " 2 0 3 5\n" ); - printf( " 3 3 0 1\n" ); - printf( " 4 3 3 33\n" ); - printf( " 5 1 1 1\n" ); - printf( " 6 1 2 10\n" ); - printf( " 7 2 1 1\n" ); - printf( " 8 2 2 10\n" ); - printf( " 9 0 1.5 5\n" ); - printf( " 10 1.5 0 1\n" ); - printf( " 11 3 1.5 1\n" ); - printf( " 12 1.5 3 1\n" ); - printf( " # Generated by triangle -pqc box.poly\n\n" ); - printf( " Here is the output file `box.1.ele', with twelve triangles.\n\n" ); - printf( " 12 3 0\n" ); - printf( " 1 5 6 9\n" ); - printf( " 2 10 3 7\n" ); - printf( " 3 6 8 12\n" ); - printf( " 4 9 1 5\n" ); - printf( " 5 6 2 9\n" ); - printf( " 6 7 3 11\n" ); - printf( " 7 11 4 8\n" ); - printf( " 8 7 5 10\n" ); - printf( " 9 12 2 6\n" ); - printf( " 10 8 7 11\n" ); - printf( " 11 5 1 10\n" ); - printf( " 12 8 4 12\n" ); - printf( " # Generated by triangle -pqc box.poly\n\n" ); - printf( - " Here is the output file `box.1.poly'. Note that segments have been added\n" - ); - printf( - " to represent the convex hull, and some segments have been split by newly\n" - ); - printf( - " added points. Note also that <# of points> is set to zero to indicate\n" ); - printf( " that the points should be read from the .node file.\n\n" ); - printf( " 0 2 0 1\n" ); - printf( " 12 1\n" ); - printf( " 1 1 9 5\n" ); - printf( " 2 5 7 1\n" ); - printf( " 3 8 7 1\n" ); - printf( " 4 6 8 10\n" ); - printf( " 5 5 6 1\n" ); - printf( " 6 3 10 1\n" ); - printf( " 7 4 11 1\n" ); - printf( " 8 2 12 1\n" ); - printf( " 9 9 2 5\n" ); - printf( " 10 10 1 1\n" ); - printf( " 11 11 3 1\n" ); - printf( " 12 12 4 1\n" ); - printf( " 1\n" ); - printf( " 1 1.5 1.5\n" ); - printf( " # Generated by triangle -pqc box.poly\n\n" ); - printf( "Refinement and Area Constraints:\n\n" ); - printf( - " The -r switch causes a mesh (.node and .ele files) to be read and\n" ); - printf( - " refined. If the -p switch is also used, a .poly file is read and used to\n" - ); - printf( - " specify edges that are constrained and cannot be eliminated (although\n" ); - printf( - " they can be divided into smaller edges) by the refinement process.\n" ); - printf( "\n" ); - printf( - " When you refine a mesh, you generally want to impose tighter quality\n" ); - printf( - " constraints. One way to accomplish this is to use -q with a larger\n" ); - printf( - " angle, or -a followed by a smaller area than you used to generate the\n" ); - printf( - " mesh you are refining. Another way to do this is to create an .area\n" ); - printf( - " file, which specifies a maximum area for each triangle, and use the -a\n" ); - printf( - " switch (without a number following). Each triangle's area constraint is\n" - ); - printf( - " applied to that triangle. Area constraints tend to diffuse as the mesh\n" ); - printf( - " is refined, so if there are large variations in area constraint between\n" ); - printf( " adjacent triangles, you may not get the results you want.\n\n" ); - printf( - " If you are refining a mesh composed of linear (three-node) elements, the\n" - ); - printf( - " output mesh will contain all the nodes present in the input mesh, in the\n" - ); - printf( - " same order, with new nodes added at the end of the .node file. However,\n" - ); - printf( - " there is no guarantee that each output element is contained in a single\n" ); - printf( - " input element. Often, output elements will overlap two input elements,\n" ); - printf( - " and input edges are not present in the output mesh. Hence, a sequence of\n" - ); - printf( - " refined meshes will form a hierarchy of nodes, but not a hierarchy of\n" ); - printf( - " elements. If you a refining a mesh of higher-order elements, the\n" ); - printf( - " hierarchical property applies only to the nodes at the corners of an\n" ); - printf( " element; other nodes may not be present in the refined mesh.\n\n" ); - printf( - " It is important to understand that maximum area constraints in .poly\n" ); - printf( - " files are handled differently from those in .area files. A maximum area\n" - ); - printf( - " in a .poly file applies to the whole (segment-bounded) region in which a\n" - ); - printf( - " point falls, whereas a maximum area in an .area file applies to only one\n" - ); - printf( - " triangle. Area constraints in .poly files are used only when a mesh is\n" ); - printf( - " first generated, whereas area constraints in .area files are used only to\n" - ); - printf( - " refine an existing mesh, and are typically based on a posteriori error\n" ); - printf( - " estimates resulting from a finite element simulation on that mesh.\n" ); - printf( "\n" ); - printf( - " `triangle -rq25 object.1' will read object.1.node and object.1.ele, then\n" - ); - printf( - " refine the triangulation to enforce a 25 degree minimum angle, and then\n" ); - printf( - " write the refined triangulation to object.2.node and object.2.ele.\n" ); - printf( "\n" ); - printf( - " `triangle -rpaa6.2 z.3' will read z.3.node, z.3.ele, z.3.poly, and\n" ); - printf( - " z.3.area. After reconstructing the mesh and its segments, Triangle will\n" - ); - printf( - " refine the mesh so that no triangle has area greater than 6.2, and\n" ); - printf( - " furthermore the triangles satisfy the maximum area constraints in\n" ); - printf( - " z.3.area. The output is written to z.4.node, z.4.ele, and z.4.poly.\n" ); - printf( "\n" ); - printf( - " The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n" ); - printf( - " x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n" ); - printf( " suitable for multigrid.\n\n" ); - printf( "Convex Hulls and Mesh Boundaries:\n\n" ); - printf( - " If the input is a point set (rather than a PSLG), Triangle produces its\n" ); - printf( - " convex hull as a by-product in the output .poly file if you use the -c\n" ); - printf( - " switch. There are faster algorithms for finding a two-dimensional convex\n" - ); - printf( - " hull than triangulation, of course, but this one comes for free. If the\n" - ); - printf( - " input is an unconstrained mesh (you are using the -r switch but not the\n" ); - printf( - " -p switch), Triangle produces a list of its boundary edges (including\n" ); - printf( " hole boundaries) as a by-product if you use the -c switch.\n\n" ); - printf( "Voronoi Diagrams:\n\n" ); - printf( - " The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n" ); - printf( - " .v.edge. For example, `triangle -v points' will read points.node,\n" ); - printf( - " produce its Delaunay triangulation in points.1.node and points.1.ele,\n" ); - printf( - " and produce its Voronoi diagram in points.1.v.node and points.1.v.edge.\n" ); - printf( - " The .v.node file contains a list of all Voronoi vertices, and the .v.edge\n" - ); - printf( - " file contains a list of all Voronoi edges, some of which may be infinite\n" - ); - printf( - " rays. (The choice of filenames makes it easy to run the set of Voronoi\n" ); - printf( " vertices through Triangle, if so desired.)\n\n" ); - printf( - " This implementation does not use exact arithmetic to compute the Voronoi\n" - ); - printf( - " vertices, and does not check whether neighboring vertices are identical.\n" - ); - printf( - " Be forewarned that if the Delaunay triangulation is degenerate or\n" ); - printf( - " near-degenerate, the Voronoi diagram may have duplicate points, crossing\n" - ); - printf( - " edges, or infinite rays whose direction vector is zero. Also, if you\n" ); - printf( - " generate a constrained (as opposed to conforming) Delaunay triangulation,\n" - ); - printf( - " or if the triangulation has holes, the corresponding Voronoi diagram is\n" ); - printf( " likely to have crossing edges and unlikely to make sense.\n\n" ); - printf( "Mesh Topology:\n\n" ); - printf( - " You may wish to know which triangles are adjacent to a certain Delaunay\n" ); - printf( - " edge in an .edge file, which Voronoi regions are adjacent to a certain\n" ); - printf( - " Voronoi edge in a .v.edge file, or which Voronoi regions are adjacent to\n" - ); - printf( - " each other. All of this information can be found by cross-referencing\n" ); - printf( - " output files with the recollection that the Delaunay triangulation and\n" ); - printf( " the Voronoi diagrams are planar duals.\n\n" ); - printf( - " Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n" ); - printf( - " the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n" ); - printf( - " wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n" ); - printf( - " vertex j of the corresponding .v.node file; and Voronoi region k is the\n" ); - printf( " dual of point k of the corresponding .node file.\n\n" ); - printf( - " Hence, to find the triangles adjacent to a Delaunay edge, look at the\n" ); - printf( - " vertices of the corresponding Voronoi edge; their dual triangles are on\n" ); - printf( - " the left and right of the Delaunay edge, respectively. To find the\n" ); - printf( - " Voronoi regions adjacent to a Voronoi edge, look at the endpoints of the\n" - ); - printf( - " corresponding Delaunay edge; their dual regions are on the right and left\n" - ); - printf( - " of the Voronoi edge, respectively. To find which Voronoi regions are\n" ); - printf( " adjacent to each other, just read the list of Delaunay edges.\n" ); - printf( "\n" ); - printf( "Statistics:\n" ); - printf( "\n" ); - printf( - " After generating a mesh, Triangle prints a count of the number of points,\n" - ); - printf( - " triangles, edges, boundary edges, and segments in the output mesh. If\n" ); - printf( - " you've forgotten the statistics for an existing mesh, the -rNEP switches\n" - ); - printf( - " (or -rpNEP if you've got a .poly file for the existing mesh) will\n" ); - printf( " regenerate these statistics without writing any output.\n\n" ); - printf( - " The -V switch produces extended statistics, including a rough estimate\n" ); - printf( - " of memory use and a histogram of triangle aspect ratios and angles in the\n" - ); - printf( " mesh.\n\n" ); - printf( "Exact Arithmetic:\n\n" ); - printf( - " Triangle uses adaptive exact arithmetic to perform what computational\n" ); - printf( - " geometers call the `orientation' and `incircle' tests. If the floating-\n" - ); - printf( - " point arithmetic of your machine conforms to the IEEE 754 standard (as\n" ); - printf( - " most workstations do), and does not use extended precision internal\n" ); - printf( - " registers, then your output is guaranteed to be an absolutely true\n" ); - printf( " Delaunay or conforming Delaunay triangulation, roundoff error\n" ); - printf( - " notwithstanding. The word `adaptive' implies that these arithmetic\n" ); - printf( - " routines compute the result only to the precision necessary to guarantee\n" - ); - printf( - " correctness, so they are usually nearly as fast as their approximate\n" ); - printf( - " counterparts. The exact tests can be disabled with the -X switch. On\n" ); - printf( - " most inputs, this switch will reduce the computation time by about eight\n" - ); - printf( - " percent - it's not worth the risk. There are rare difficult inputs\n" ); - printf( - " (having many collinear and cocircular points), however, for which the\n" ); - printf( - " difference could be a factor of two. These are precisely the inputs most\n" - ); - printf( " likely to cause errors if you use the -X switch.\n\n" ); - printf( - " Unfortunately, these routines don't solve every numerical problem. Exact\n" - ); - printf( - " arithmetic is not used to compute the positions of points, because the\n" ); - printf( - " bit complexity of point coordinates would grow without bound. Hence,\n" ); - printf( - " segment intersections aren't computed exactly; in very unusual cases,\n" ); - printf( - " roundoff error in computing an intersection point might actually lead to\n" - ); - printf( - " an inverted triangle and an invalid triangulation. (This is one reason\n" ); - printf( - " to compute your own intersection points in your .poly files.) Similarly,\n" - ); - printf( - " exact arithmetic is not used to compute the vertices of the Voronoi\n" ); - printf( " diagram.\n\n" ); - printf( - " Underflow and overflow can also cause difficulties; the exact arithmetic\n" - ); - printf( - " routines do not ameliorate out-of-bounds exponents, which can arise\n" ); - printf( - " during the orientation and incircle tests. As a rule of thumb, you\n" ); - printf( - " should ensure that your input values are within a range such that their\n" ); - printf( - " third powers can be taken without underflow or overflow. Underflow can\n" ); - printf( - " silently prevent the tests from being performed exactly, while overflow\n" ); - printf( " will typically cause a floating exception.\n\n" ); - printf( "Calling Triangle from Another Program:\n\n" ); - printf( " Read the file triangle.h for details.\n\n" ); - printf( "Troubleshooting:\n\n" ); - printf( " Please read this section before mailing me bugs.\n\n" ); - printf( " `My output mesh has no triangles!'\n\n" ); - printf( - " If you're using a PSLG, you've probably failed to specify a proper set\n" - ); - printf( - " of bounding segments, or forgotten to use the -c switch. Or you may\n" ); - printf( - " have placed a hole badly. To test these possibilities, try again with\n" - ); - printf( - " the -c and -O switches. Alternatively, all your input points may be\n" ); - printf( - " collinear, in which case you can hardly expect to triangulate them.\n" ); - printf( "\n" ); - printf( " `Triangle doesn't terminate, or just crashes.'\n" ); - printf( "\n" ); - printf( - " Bad things can happen when triangles get so small that the distance\n" ); - printf( - " between their vertices isn't much larger than the precision of your\n" ); - printf( - " machine's arithmetic. If you've compiled Triangle for single-precision\n" - ); - printf( - " arithmetic, you might do better by recompiling it for double-precision.\n" - ); - printf( - " Then again, you might just have to settle for more lenient constraints\n" - ); - printf( - " on the minimum angle and the maximum area than you had planned.\n" ); - printf( "\n" ); - printf( - " You can minimize precision problems by ensuring that the origin lies\n" ); - printf( - " inside your point set, or even inside the densest part of your\n" ); - printf( - " mesh. On the other hand, if you're triangulating an object whose x\n" ); - printf( - " coordinates all fall between 6247133 and 6247134, you're not leaving\n" ); - printf( " much floating-point precision for Triangle to work with.\n\n" ); - printf( - " Precision problems can occur covertly if the input PSLG contains two\n" ); - printf( - " segments that meet (or intersect) at a very small angle, or if such an\n" - ); - printf( - " angle is introduced by the -c switch, which may occur if a point lies\n" ); - printf( - " ever-so-slightly inside the convex hull, and is connected by a PSLG\n" ); - printf( - " segment to a point on the convex hull. If you don't realize that a\n" ); - printf( - " small angle is being formed, you might never discover why Triangle is\n" ); - printf( - " crashing. To check for this possibility, use the -S switch (with an\n" ); - printf( - " appropriate limit on the number of Steiner points, found by trial-and-\n" - ); - printf( - " error) to stop Triangle early, and view the output .poly file with\n" ); - printf( - " Show Me (described below). Look carefully for small angles between\n" ); - printf( - " segments; zoom in closely, as such segments might look like a single\n" ); - printf( " segment from a distance.\n\n" ); - printf( - " If some of the input values are too large, Triangle may suffer a\n" ); - printf( - " floating exception due to overflow when attempting to perform an\n" ); - printf( - " orientation or incircle test. (Read the section on exact arithmetic\n" ); - printf( - " above.) Again, I recommend compiling Triangle for double (rather\n" ); - printf( " than single) precision arithmetic.\n\n" ); - printf( - " `The numbering of the output points doesn't match the input points.'\n" ); - printf( "\n" ); - printf( - " You may have eaten some of your input points with a hole, or by placing\n" - ); - printf( " them outside the area enclosed by segments.\n\n" ); - printf( - " `Triangle executes without incident, but when I look at the resulting\n" ); - printf( - " mesh, it has overlapping triangles or other geometric inconsistencies.'\n" ); - printf( "\n" ); - printf( - " If you select the -X switch, Triangle's divide-and-conquer Delaunay\n" ); - printf( - " triangulation algorithm occasionally makes mistakes due to floating-\n" ); - printf( - " point roundoff error. Although these errors are rare, don't use the -X\n" - ); - printf( " switch. If you still have problems, please report the bug.\n" ); - printf( "\n" ); - printf( - " Strange things can happen if you've taken liberties with your PSLG. Do\n" ); - printf( - " you have a point lying in the middle of a segment? Triangle sometimes\n" ); - printf( - " copes poorly with that sort of thing. Do you want to lay out a collinear\n" - ); - printf( - " row of evenly spaced, segment-connected points? Have you simply defined\n" - ); - printf( - " one long segment connecting the leftmost point to the rightmost point,\n" ); - printf( - " and a bunch of points lying along it? This method occasionally works,\n" ); - printf( - " especially with horizontal and vertical lines, but often it doesn't, and\n" - ); - printf( - " you'll have to connect each adjacent pair of points with a separate\n" ); - printf( " segment. If you don't like it, tough.\n\n" ); - printf( - " Furthermore, if you have segments that intersect other than at their\n" ); - printf( - " endpoints, try not to let the intersections fall extremely close to PSLG\n" - ); - printf( " points or each other.\n\n" ); - printf( - " If you have problems refining a triangulation not produced by Triangle:\n" ); - printf( - " Are you sure the triangulation is geometrically valid? Is it formatted\n" ); - printf( - " correctly for Triangle? Are the triangles all listed so the first three\n" - ); - printf( " points are their corners in counterclockwise order?\n\n" ); - printf( "Show Me:\n\n" ); - printf( - " Triangle comes with a separate program named `Show Me', whose primary\n" ); - printf( - " purpose is to draw meshes on your screen or in PostScript. Its secondary\n" - ); - printf( - " purpose is to check the validity of your input files, and do so more\n" ); - printf( - " thoroughly than Triangle does. Show Me requires that you have the X\n" ); - printf( - " Windows system. If you didn't receive Show Me with Triangle, complain to\n" - ); - printf( " whomever you obtained Triangle from, then send me mail.\n\n" ); - printf( "Triangle on the Web:\n\n" ); - printf( - " To see an illustrated, updated version of these instructions, check out\n" ); - printf( "\n" ); - printf( " http://www.cs.cmu.edu/~quake/triangle.html\n" ); - printf( "\n" ); - printf( "A Brief Plea:\n" ); - printf( "\n" ); - printf( - " If you use Triangle, and especially if you use it to accomplish real\n" ); - printf( - " work, I would like very much to hear from you. A short letter or email\n" ); - printf( - " (to jrs@cs.cmu.edu) describing how you use Triangle will mean a lot to\n" ); - printf( - " me. The more people I know are using this program, the more easily I can\n" - ); - printf( - " justify spending time on improvements and on the three-dimensional\n" ); - printf( - " successor to Triangle, which in turn will benefit you. Also, I can put\n" ); - printf( - " you on a list to receive email whenever a new version of Triangle is\n" ); - printf( " available.\n\n" ); - printf( - " If you use a mesh generated by Triangle in a publication, please include\n" - ); - printf( " an acknowledgment as well.\n\n" ); - printf( "Research credit:\n\n" ); - printf( - " Of course, I can take credit for only a fraction of the ideas that made\n" ); - printf( - " this mesh generator possible. Triangle owes its existence to the efforts\n" - ); - printf( - " of many fine computational geometers and other researchers, including\n" ); - printf( - " Marshall Bern, L. Paul Chew, Boris Delaunay, Rex A. Dwyer, David\n" ); - printf( - " Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E. Knuth, C. L.\n" ); - printf( - " Lawson, Der-Tsai Lee, Ernst P. Mucke, Douglas M. Priest, Jim Ruppert,\n" ); - printf( - " Isaac Saias, Bruce J. Schachter, Micha Sharir, Jorge Stolfi, Christopher\n" - ); - printf( - " J. Van Wyk, David F. Watson, and Binhai Zhu. See the comments at the\n" ); - printf( " beginning of the source code for references.\n\n" ); - exit( 0 ); +printf( +"Underscores indicate that numbers may optionally follow certain switches;\n" ); +printf( +"do not leave any space between a switch and its numeric parameter.\n" ); +printf( +"input_file must be a file with extension .node, or extension .poly if the\n" ); +printf( +"-p switch is used. If -r is used, you must supply .node and .ele files,\n" ); +printf( +"and possibly a .poly file and .area file as well. The formats of these\n" ); +printf( "files are described below.\n\n" ); +printf( "Command Line Switches:\n\n" ); +printf( +" -p Reads a Planar Straight Line Graph (.poly file), which can specify\n" +); +printf( +" points, segments, holes, and regional attributes and area\n" ); +printf( +" constraints. Will generate a constrained Delaunay triangulation\n" ); +printf( +" fitting the input; or, if -s, -q, or -a is used, a conforming\n" ); +printf( +" Delaunay triangulation. If -p is not used, Triangle reads a .node\n" +); +printf( " file by default.\n" ); +printf( +" -r Refines a previously generated mesh. The mesh is read from a .node\n" +); +printf( +" file and an .ele file. If -p is also used, a .poly file is read\n" ); +printf( +" and used to constrain edges in the mesh. Further details on\n" ); +printf( " refinement are given below.\n" ); +printf( +" -q Quality mesh generation by Jim Ruppert's Delaunay refinement\n" ); +printf( +" algorithm. Adds points to the mesh to ensure that no angles\n" ); +printf( +" smaller than 20 degrees occur. An alternative minimum angle may be\n" +); +printf( +" specified after the `q'. If the minimum angle is 20.7 degrees or\n" ); +printf( +" smaller, the triangulation algorithm is theoretically guaranteed to\n" +); +printf( +" terminate (assuming infinite precision arithmetic - Triangle may\n" ); +printf( +" fail to terminate if you run out of precision). In practice, the\n" ); +printf( +" algorithm often succeeds for minimum angles up to 33.8 degrees.\n" ); +printf( +" For highly refined meshes, however, it may be necessary to reduce\n" ); +printf( +" the minimum angle to well below 20 to avoid problems associated\n" ); +printf( +" with insufficient floating-point precision. The specified angle\n" ); +printf( " may include a decimal point.\n" ); +printf( +" -a Imposes a maximum triangle area. If a number follows the `a', no\n" ); +printf( +" triangle will be generated whose area is larger than that number.\n" ); +printf( +" If no number is specified, an .area file (if -r is used) or .poly\n" ); +printf( +" file (if -r is not used) specifies a number of maximum area\n" ); +printf( +" constraints. An .area file contains a separate area constraint for\n" +); +printf( +" each triangle, and is useful for refining a finite element mesh\n" ); +printf( +" based on a posteriori error estimates. A .poly file can optionally\n" +); +printf( +" contain an area constraint for each segment-bounded region, thereby\n" +); +printf( +" enforcing triangle densities in a first triangulation. You can\n" ); +printf( +" impose both a fixed area constraint and a varying area constraint\n" ); +printf( +" by invoking the -a switch twice, once with and once without a\n" ); +printf( +" number following. Each area specified may include a decimal point.\n" +); +printf( +" -A Assigns an additional attribute to each triangle that identifies\n" ); +printf( +" what segment-bounded region each triangle belongs to. Attributes\n" ); +printf( +" are assigned to regions by the .poly file. If a region is not\n" ); +printf( +" explicitly marked by the .poly file, triangles in that region are\n" ); +printf( +" assigned an attribute of zero. The -A switch has an effect only\n" ); +printf( " when the -p switch is used and the -r switch is not.\n" ); +printf( +" -c Creates segments on the convex hull of the triangulation. If you\n" ); +printf( +" are triangulating a point set, this switch causes a .poly file to\n" ); +printf( +" be written, containing all edges in the convex hull. (By default,\n" +); +printf( +" a .poly file is written only if a .poly file is read.) If you are\n" +); +printf( +" triangulating a PSLG, this switch specifies that the interior of\n" ); +printf( +" the convex hull of the PSLG should be triangulated. If you do not\n" +); +printf( +" use this switch when triangulating a PSLG, it is assumed that you\n" ); +printf( +" have identified the region to be triangulated by surrounding it\n" ); +printf( +" with segments of the input PSLG. Beware: if you are not careful,\n" +); +printf( +" this switch can cause the introduction of an extremely thin angle\n" ); +printf( +" between a PSLG segment and a convex hull segment, which can cause\n" ); +printf( +" overrefinement or failure if Triangle runs out of precision. If\n" ); +printf( +" you are refining a mesh, the -c switch works differently; it\n" ); +printf( +" generates the set of boundary edges of the mesh, rather than the\n" ); +printf( " convex hull.\n" ); +printf( +" -e Outputs (to an .edge file) a list of edges of the triangulation.\n" ); +printf( +" -v Outputs the Voronoi diagram associated with the triangulation.\n" ); +printf( " Does not attempt to detect degeneracies.\n" ); +printf( +" -n Outputs (to a .neigh file) a list of triangles neighboring each\n" ); +printf( " triangle.\n" ); +printf( +" -g Outputs the mesh to an Object File Format (.off) file, suitable for\n" +); +printf( " viewing with the Geometry Center's Geomview package.\n" ); +printf( +" -B No boundary markers in the output .node, .poly, and .edge output\n" ); +printf( +" files. See the detailed discussion of boundary markers below.\n" ); +printf( +" -P No output .poly file. Saves disk space, but you lose the ability\n" ); +printf( +" to impose segment constraints on later refinements of the mesh.\n" ); +printf( " -N No output .node file.\n" ); +printf( " -E No output .ele file.\n" ); +printf( +" -I No iteration numbers. Suppresses the output of .node and .poly\n" ); +printf( +" files, so your input files won't be overwritten. (If your input is\n" +); +printf( +" a .poly file only, a .node file will be written.) Cannot be used\n" ); +printf( +" with the -r switch, because that would overwrite your input .ele\n" ); +printf( +" file. Shouldn't be used with the -s, -q, or -a switch if you are\n" ); +printf( +" using a .node file for input, because no .node file will be\n" ); +printf( " written, so there will be no record of any added points.\n" ); +printf( " -O No holes. Ignores the holes in the .poly file.\n" ); +printf( +" -X No exact arithmetic. Normally, Triangle uses exact floating-point\n" +); +printf( +" arithmetic for certain tests if it thinks the inexact tests are not\n" +); +printf( +" accurate enough. Exact arithmetic ensures the robustness of the\n" ); +printf( +" triangulation algorithms, despite floating-point roundoff error.\n" ); +printf( +" Disabling exact arithmetic with the -X switch will cause a small\n" ); +printf( +" improvement in speed and create the possibility (albeit small) that\n" +); +printf( +" Triangle will fail to produce a valid mesh. Not recommended.\n" ); +printf( +" -z Numbers all items starting from zero (rather than one). Note that\n" +); +printf( +" this switch is normally overrided by the value used to number the\n" ); +printf( +" first point of the input .node or .poly file. However, this switch\n" +); +printf( " is useful when calling Triangle from another program.\n" ); +printf( +" -o2 Generates second-order subparametric elements with six nodes each.\n" +); +printf( +" -Y No new points on the boundary. This switch is useful when the mesh\n" +); +printf( +" boundary must be preserved so that it conforms to some adjacent\n" ); +printf( +" mesh. Be forewarned that you will probably sacrifice some of the\n" ); +printf( +" quality of the mesh; Triangle will try, but the resulting mesh may\n" +); +printf( +" contain triangles of poor aspect ratio. Works well if all the\n" ); +printf( +" boundary points are closely spaced. Specify this switch twice\n" ); +printf( +" (`-YY') to prevent all segment splitting, including internal\n" ); +printf( " boundaries.\n" ); +printf( +" -S Specifies the maximum number of Steiner points (points that are not\n" +); +printf( +" in the input, but are added to meet the constraints of minimum\n" ); +printf( +" angle and maximum area). The default is to allow an unlimited\n" ); +printf( +" number. If you specify this switch with no number after it,\n" ); +printf( +" the limit is set to zero. Triangle always adds points at segment\n" ); +printf( +" intersections, even if it needs to use more points than the limit\n" ); +printf( +" you set. When Triangle inserts segments by splitting (-s), it\n" ); +printf( +" always adds enough points to ensure that all the segments appear in\n" +); +printf( +" the triangulation, again ignoring the limit. Be forewarned that\n" ); +printf( +" the -S switch may result in a conforming triangulation that is not\n" +); +printf( +" truly Delaunay, because Triangle may be forced to stop adding\n" ); +printf( +" points when the mesh is in a state where a segment is non-Delaunay\n" +); +printf( +" and needs to be split. If so, Triangle will print a warning.\n" ); +printf( +" -i Uses an incremental rather than divide-and-conquer algorithm to\n" ); +printf( +" form a Delaunay triangulation. Try it if the divide-and-conquer\n" ); +printf( " algorithm fails.\n" ); +printf( +" -F Uses Steven Fortune's sweepline algorithm to form a Delaunay\n" ); +printf( +" triangulation. Warning: does not use exact arithmetic for all\n" ); +printf( " calculations. An exact result is not guaranteed.\n" ); +printf( +" -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n" ); +printf( +" default, Triangle uses alternating vertical and horizontal cuts,\n" ); +printf( +" which usually improve the speed except with point sets that are\n" ); +printf( +" small or short and wide. This switch is primarily of theoretical\n" ); +printf( " interest.\n" ); +printf( +" -s Specifies that segments should be forced into the triangulation by\n" +); +printf( +" recursively splitting them at their midpoints, rather than by\n" ); +printf( +" generating a constrained Delaunay triangulation. Segment splitting\n" +); +printf( +" is true to Ruppert's original algorithm, but can create needlessly\n" +); +printf( " small triangles near external small features.\n" ); +printf( +" -C Check the consistency of the final mesh. Uses exact arithmetic for\n" +); +printf( +" checking, even if the -X switch is used. Useful if you suspect\n" ); +printf( " Triangle is buggy.\n" ); +printf( +" -Q Quiet: Suppresses all explanation of what Triangle is doing, unless\n" +); +printf( " an error occurs.\n" ); +printf( +" -V Verbose: Gives detailed information about what Triangle is doing.\n" ); +printf( +" Add more `V's for increasing amount of detail. `-V' gives\n" ); +printf( +" information on algorithmic progress and more detailed statistics.\n" ); +printf( +" `-VV' gives point-by-point details, and will print so much that\n" ); +printf( +" Triangle will run much more slowly. `-VVV' gives information only\n" +); +printf( " a debugger could love.\n" ); +printf( " -h Help: Displays these instructions.\n" ); +printf( "\n" ); +printf( "Definitions:\n" ); +printf( "\n" ); +printf( +" A Delaunay triangulation of a point set is a triangulation whose vertices\n" +); +printf( +" are the point set, having the property that no point in the point set\n" ); +printf( +" falls in the interior of the circumcircle (circle that passes through all\n" +); +printf( " three vertices) of any triangle in the triangulation.\n\n" ); +printf( +" A Voronoi diagram of a point set is a subdivision of the plane into\n" ); +printf( +" polygonal regions (some of which may be infinite), where each region is\n" ); +printf( +" the set of points in the plane that are closer to some input point than\n" ); +printf( +" to any other input point. (The Voronoi diagram is the geometric dual of\n" +); +printf( " the Delaunay triangulation.)\n\n" ); +printf( +" A Planar Straight Line Graph (PSLG) is a collection of points and\n" ); +printf( +" segments. Segments are simply edges, whose endpoints are points in the\n" ); +printf( +" PSLG. The file format for PSLGs (.poly files) is described below.\n" ); +printf( "\n" ); +printf( +" A constrained Delaunay triangulation of a PSLG is similar to a Delaunay\n" ); +printf( +" triangulation, but each PSLG segment is present as a single edge in the\n" ); +printf( +" triangulation. (A constrained Delaunay triangulation is not truly a\n" ); +printf( " Delaunay triangulation.)\n\n" ); +printf( +" A conforming Delaunay triangulation of a PSLG is a true Delaunay\n" ); +printf( +" triangulation in which each PSLG segment may have been subdivided into\n" ); +printf( +" several edges by the insertion of additional points. These inserted\n" ); +printf( +" points are necessary to allow the segments to exist in the mesh while\n" ); +printf( " maintaining the Delaunay property.\n\n" ); +printf( "File Formats:\n\n" ); +printf( +" All files may contain comments prefixed by the character '#'. Points,\n" ); +printf( +" triangles, edges, holes, and maximum area constraints must be numbered\n" ); +printf( +" consecutively, starting from either 1 or 0. Whichever you choose, all\n" ); +printf( +" input files must be consistent; if the nodes are numbered from 1, so must\n" +); +printf( +" be all other objects. Triangle automatically detects your choice while\n" ); +printf( +" reading the .node (or .poly) file. (When calling Triangle from another\n" ); +printf( +" program, use the -z switch if you wish to number objects from zero.)\n" ); +printf( " Examples of these file formats are given below.\n\n" ); +printf( " .node files:\n" ); +printf( +" First line: <# of points> <# of attributes>\n" ); +printf( +" <# of boundary markers (0 or 1)>\n" +); +printf( +" Remaining lines: [attributes] [boundary marker]\n" ); +printf( "\n" ); +printf( +" The attributes, which are typically floating-point values of physical\n" ); +printf( +" quantities (such as mass or conductivity) associated with the nodes of\n" +); +printf( +" a finite element mesh, are copied unchanged to the output mesh. If -s,\n" +); +printf( +" -q, or -a is selected, each new Steiner point added to the mesh will\n" ); +printf( " have attributes assigned to it by linear interpolation.\n\n" ); +printf( +" If the fourth entry of the first line is `1', the last column of the\n" ); +printf( +" remainder of the file is assumed to contain boundary markers. Boundary\n" +); +printf( +" markers are used to identify boundary points and points resting on PSLG\n" +); +printf( +" segments; a complete description appears in a section below. The .node\n" +); +printf( +" file produced by Triangle will contain boundary markers in the last\n" ); +printf( " column unless they are suppressed by the -B switch.\n\n" ); +printf( " .ele files:\n" ); +printf( +" First line: <# of triangles> <# of attributes>\n" ); +printf( +" Remaining lines: ... [attributes]\n" +); +printf( "\n" ); +printf( +" Points are indices into the corresponding .node file. The first three\n" +); +printf( +" points are the corners, and are listed in counterclockwise order around\n" +); +printf( +" each triangle. (The remaining points, if any, depend on the type of\n" ); +printf( +" finite element used.) The attributes are just like those of .node\n" ); +printf( +" files. Because there is no simple mapping from input to output\n" ); +printf( +" triangles, an attempt is made to interpolate attributes, which may\n" ); +printf( +" result in a good deal of diffusion of attributes among nearby triangles\n" +); +printf( +" as the triangulation is refined. Diffusion does not occur across\n" ); +printf( +" segments, so attributes used to identify segment-bounded regions remain\n" +); +printf( +" intact. In output .ele files, all triangles have three points each\n" ); +printf( +" unless the -o2 switch is used, in which case they have six, and the\n" ); +printf( +" fourth, fifth, and sixth points lie on the midpoints of the edges\n" ); +printf( " opposite the first, second, and third corners.\n\n" ); +printf( " .poly files:\n" ); +printf( +" First line: <# of points> <# of attributes>\n" ); +printf( +" <# of boundary markers (0 or 1)>\n" +); +printf( +" Following lines: [attributes] [boundary marker]\n" ); +printf( " One line: <# of segments> <# of boundary markers (0 or 1)>\n" ); +printf( +" Following lines: [boundary marker]\n" ); +printf( " One line: <# of holes>\n" ); +printf( " Following lines: \n" ); +printf( +" Optional line: <# of regional attributes and/or area constraints>\n" ); +printf( +" Optional following lines: \n" ); +printf( "\n" ); +printf( +" A .poly file represents a PSLG, as well as some additional information.\n" +); +printf( +" The first section lists all the points, and is identical to the format\n" +); +printf( +" of .node files. <# of points> may be set to zero to indicate that the\n" +); +printf( +" points are listed in a separate .node file; .poly files produced by\n" ); +printf( +" Triangle always have this format. This has the advantage that a point\n" +); +printf( +" set may easily be triangulated with or without segments. (The same\n" ); +printf( +" effect can be achieved, albeit using more disk space, by making a copy\n" +); +printf( +" of the .poly file with the extension .node; all sections of the file\n" ); +printf( " but the first are ignored.)\n\n" ); +printf( +" The second section lists the segments. Segments are edges whose\n" ); +printf( +" presence in the triangulation is enforced. Each segment is specified\n" ); +printf( +" by listing the indices of its two endpoints. This means that you must\n" +); +printf( +" include its endpoints in the point list. If -s, -q, and -a are not\n" ); +printf( +" selected, Triangle will produce a constrained Delaunay triangulation,\n" ); +printf( +" in which each segment appears as a single edge in the triangulation.\n" ); +printf( +" If -q or -a is selected, Triangle will produce a conforming Delaunay\n" ); +printf( +" triangulation, in which segments may be subdivided into smaller edges.\n" +); +printf( " Each segment, like each point, may have a boundary marker.\n\n" ); +printf( +" The third section lists holes (and concavities, if -c is selected) in\n" ); +printf( +" the triangulation. Holes are specified by identifying a point inside\n" ); +printf( +" each hole. After the triangulation is formed, Triangle creates holes\n" ); +printf( +" by eating triangles, spreading out from each hole point until its\n" ); +printf( +" progress is blocked by PSLG segments; you must be careful to enclose\n" ); +printf( +" each hole in segments, or your whole triangulation may be eaten away.\n" ); +printf( +" If the two triangles abutting a segment are eaten, the segment itself\n" ); +printf( +" is also eaten. Do not place a hole directly on a segment; if you do,\n" ); +printf( " Triangle will choose one side of the segment arbitrarily.\n\n" ); +printf( +" The optional fourth section lists regional attributes (to be assigned\n" ); +printf( +" to all triangles in a region) and regional constraints on the maximum\n" ); +printf( +" triangle area. Triangle will read this section only if the -A switch\n" ); +printf( +" is used or the -a switch is used without a number following it, and the\n" +); +printf( +" -r switch is not used. Regional attributes and area constraints are\n" ); +printf( +" propagated in the same manner as holes; you specify a point for each\n" ); +printf( +" attribute and/or constraint, and the attribute and/or constraint will\n" ); +printf( +" affect the whole region (bounded by segments) containing the point. If\n" +); +printf( +" two values are written on a line after the x and y coordinate, the\n" ); +printf( +" former is assumed to be a regional attribute (but will only be applied\n" +); +printf( +" if the -A switch is selected), and the latter is assumed to be a\n" ); +printf( +" regional area constraint (but will only be applied if the -a switch is\n" +); +printf( +" selected). You may also specify just one value after the coordinates,\n" +); +printf( +" which can serve as both an attribute and an area constraint, depending\n" +); +printf( +" on the choice of switches. If you are using the -A and -a switches\n" ); +printf( +" simultaneously and wish to assign an attribute to some region without\n" ); +printf( " imposing an area constraint, use a negative maximum area.\n\n" ); +printf( +" When a triangulation is created from a .poly file, you must either\n" ); +printf( +" enclose the entire region to be triangulated in PSLG segments, or\n" ); +printf( +" use the -c switch, which encloses the convex hull of the input point\n" ); +printf( +" set. If you do not use the -c switch, Triangle will eat all triangles\n" +); +printf( +" on the outer boundary that are not protected by segments; if you are\n" ); +printf( +" not careful, your whole triangulation may be eaten away. If you do\n" ); +printf( +" use the -c switch, you can still produce concavities by appropriate\n" ); +printf( " placement of holes just inside the convex hull.\n\n" ); +printf( +" An ideal PSLG has no intersecting segments, nor any points that lie\n" ); +printf( +" upon segments (except, of course, the endpoints of each segment.) You\n" +); +printf( +" aren't required to make your .poly files ideal, but you should be aware\n" +); +printf( +" of what can go wrong. Segment intersections are relatively safe -\n" ); +printf( +" Triangle will calculate the intersection points for you and add them to\n" +); +printf( +" the triangulation - as long as your machine's floating-point precision\n" +); +printf( +" doesn't become a problem. You are tempting the fates if you have three\n" +); +printf( +" segments that cross at the same location, and expect Triangle to figure\n" +); +printf( +" out where the intersection point is. Thanks to floating-point roundoff\n" +); +printf( +" error, Triangle will probably decide that the three segments intersect\n" +); +printf( +" at three different points, and you will find a minuscule triangle in\n" ); +printf( +" your output - unless Triangle tries to refine the tiny triangle, uses\n" ); +printf( +" up the last bit of machine precision, and fails to terminate at all.\n" ); +printf( +" You're better off putting the intersection point in the input files,\n" ); +printf( +" and manually breaking up each segment into two. Similarly, if you\n" ); +printf( +" place a point at the middle of a segment, and hope that Triangle will\n" ); +printf( +" break up the segment at that point, you might get lucky. On the other\n" +); +printf( +" hand, Triangle might decide that the point doesn't lie precisely on the\n" +); +printf( +" line, and you'll have a needle-sharp triangle in your output - or a lot\n" +); +printf( " of tiny triangles if you're generating a quality mesh.\n\n" ); +printf( +" When Triangle reads a .poly file, it also writes a .poly file, which\n" ); +printf( +" includes all edges that are part of input segments. If the -c switch\n" ); +printf( +" is used, the output .poly file will also include all of the edges on\n" ); +printf( +" the convex hull. Hence, the output .poly file is useful for finding\n" ); +printf( +" edges associated with input segments and setting boundary conditions in\n" +); +printf( +" finite element simulations. More importantly, you will need it if you\n" +); +printf( +" plan to refine the output mesh, and don't want segments to be missing\n" ); +printf( " in later triangulations.\n\n" ); +printf( " .area files:\n" ); +printf( " First line: <# of triangles>\n" ); +printf( " Following lines: \n\n" ); +printf( +" An .area file associates with each triangle a maximum area that is used\n" +); +printf( +" for mesh refinement. As with other file formats, every triangle must\n" ); +printf( +" be represented, and they must be numbered consecutively. A triangle\n" ); +printf( +" may be left unconstrained by assigning it a negative maximum area.\n" ); +printf( "\n" ); +printf( " .edge files:\n" ); +printf( " First line: <# of edges> <# of boundary markers (0 or 1)>\n" ); +printf( +" Following lines: [boundary marker]\n" ); +printf( "\n" ); +printf( +" Endpoints are indices into the corresponding .node file. Triangle can\n" +); +printf( +" produce .edge files (use the -e switch), but cannot read them. The\n" ); +printf( +" optional column of boundary markers is suppressed by the -B switch.\n" ); +printf( "\n" ); +printf( +" In Voronoi diagrams, one also finds a special kind of edge that is an\n" ); +printf( +" infinite ray with only one endpoint. For these edges, a different\n" ); +printf( " format is used:\n\n" ); +printf( " -1 \n\n" ); +printf( +" The `direction' is a floating-point vector that indicates the direction\n" +); +printf( " of the infinite ray.\n\n" ); +printf( " .neigh files:\n" ); +printf( +" First line: <# of triangles> <# of neighbors per triangle (always 3)>\n" +); +printf( +" Following lines: \n" ); +printf( "\n" ); +printf( +" Neighbors are indices into the corresponding .ele file. An index of -1\n" +); +printf( +" indicates a mesh boundary, and therefore no neighbor. Triangle can\n" ); +printf( +" produce .neigh files (use the -n switch), but cannot read them.\n" ); +printf( "\n" ); +printf( +" The first neighbor of triangle i is opposite the first corner of\n" ); +printf( " triangle i, and so on.\n\n" ); +printf( "Boundary Markers:\n\n" ); +printf( +" Boundary markers are tags used mainly to identify which output points and\n" +); +printf( +" edges are associated with which PSLG segment, and to identify which\n" ); +printf( +" points and edges occur on a boundary of the triangulation. A common use\n" +); +printf( +" is to determine where boundary conditions should be applied to a finite\n" ); +printf( +" element mesh. You can prevent boundary markers from being written into\n" ); +printf( " files produced by Triangle by using the -B switch.\n\n" ); +printf( +" The boundary marker associated with each segment in an output .poly file\n" +); +printf( " or edge in an output .edge file is chosen as follows:\n" ); +printf( +" - If an output edge is part or all of a PSLG segment with a nonzero\n" ); +printf( +" boundary marker, then the edge is assigned the same marker.\n" ); +printf( +" - Otherwise, if the edge occurs on a boundary of the triangulation\n" ); +printf( +" (including boundaries of holes), then the edge is assigned the marker\n" +); +printf( " one (1).\n" ); +printf( " - Otherwise, the edge is assigned the marker zero (0).\n" ); +printf( +" The boundary marker associated with each point in an output .node file is\n" +); +printf( " chosen as follows:\n" ); +printf( +" - If a point is assigned a nonzero boundary marker in the input file,\n" ); +printf( +" then it is assigned the same marker in the output .node file.\n" ); +printf( +" - Otherwise, if the point lies on a PSLG segment (including the\n" ); +printf( +" segment's endpoints) with a nonzero boundary marker, then the point\n" ); +printf( +" is assigned the same marker. If the point lies on several such\n" ); +printf( " segments, one of the markers is chosen arbitrarily.\n" ); +printf( +" - Otherwise, if the point occurs on a boundary of the triangulation,\n" ); +printf( " then the point is assigned the marker one (1).\n" ); +printf( " - Otherwise, the point is assigned the marker zero (0).\n" ); +printf( "\n" ); +printf( +" If you want Triangle to determine for you which points and edges are on\n" ); +printf( +" the boundary, assign them the boundary marker zero (or use no markers at\n" +); +printf( +" all) in your input files. Alternatively, you can mark some of them and\n" ); +printf( " leave others marked zero, allowing Triangle to label them.\n\n" ); +printf( "Triangulation Iteration Numbers:\n\n" ); +printf( +" Because Triangle can read and refine its own triangulations, input\n" ); +printf( +" and output files have iteration numbers. For instance, Triangle might\n" ); +printf( +" read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n" ); +printf( +" triangulation, and output the files mesh.4.node, mesh.4.ele, and\n" ); +printf( " mesh.4.poly. Files with no iteration number are treated as if\n" ); +printf( +" their iteration number is zero; hence, Triangle might read the file\n" ); +printf( +" points.node, triangulate it, and produce the files points.1.node and\n" ); +printf( " points.1.ele.\n\n" ); +printf( +" Iteration numbers allow you to create a sequence of successively finer\n" ); +printf( +" meshes suitable for multigrid methods. They also allow you to produce a\n" +); +printf( +" sequence of meshes using error estimate-driven mesh refinement.\n" ); +printf( "\n" ); +printf( +" If you're not using refinement or quality meshing, and you don't like\n" ); +printf( +" iteration numbers, use the -I switch to disable them. This switch will\n" ); +printf( +" also disable output of .node and .poly files to prevent your input files\n" +); +printf( +" from being overwritten. (If the input is a .poly file that contains its\n" +); +printf( " own points, a .node file will be written.)\n\n" ); +printf( "Examples of How to Use Triangle:\n\n" ); +printf( +" `triangle dots' will read points from dots.node, and write their Delaunay\n" +); +printf( +" triangulation to dots.1.node and dots.1.ele. (dots.1.node will be\n" ); +printf( +" identical to dots.node.) `triangle -I dots' writes the triangulation to\n" +); +printf( +" dots.ele instead. (No additional .node file is needed, so none is\n" ); +printf( " written.)\n\n" ); +printf( +" `triangle -pe object.1' will read a PSLG from object.1.poly (and possibly\n" +); +printf( +" object.1.node, if the points are omitted from object.1.poly) and write\n" ); +printf( " their constrained Delaunay triangulation to object.2.node and\n" ); +printf( +" object.2.ele. The segments will be copied to object.2.poly, and all\n" ); +printf( " edges will be written to object.2.edge.\n\n" ); +printf( +" `triangle -pq31.5a.1 object' will read a PSLG from object.poly (and\n" ); +printf( +" possibly object.node), generate a mesh whose angles are all greater than\n" +); +printf( +" 31.5 degrees and whose triangles all have area smaller than 0.1, and\n" ); +printf( +" write the mesh to object.1.node and object.1.ele. Each segment may have\n" +); +printf( +" been broken up into multiple edges; the resulting constrained edges are\n" ); +printf( " written to object.1.poly.\n\n" ); +printf( +" Here is a sample file `box.poly' describing a square with a square hole:\n" +); +printf( "\n" ); +printf( +" # A box with eight points in 2D, no attributes, one boundary marker.\n" ); +printf( " 8 2 0 1\n" ); +printf( " # Outer box has these vertices:\n" ); +printf( " 1 0 0 0\n" ); +printf( " 2 0 3 0\n" ); +printf( " 3 3 0 0\n" ); +printf( " 4 3 3 33 # A special marker for this point.\n" ); +printf( " # Inner square has these vertices:\n" ); +printf( " 5 1 1 0\n" ); +printf( " 6 1 2 0\n" ); +printf( " 7 2 1 0\n" ); +printf( " 8 2 2 0\n" ); +printf( " # Five segments with boundary markers.\n" ); +printf( " 5 1\n" ); +printf( " 1 1 2 5 # Left side of outer box.\n" ); +printf( " 2 5 7 0 # Segments 2 through 5 enclose the hole.\n" ); +printf( " 3 7 8 0\n" ); +printf( " 4 8 6 10\n" ); +printf( " 5 6 5 0\n" ); +printf( " # One hole in the middle of the inner square.\n" ); +printf( " 1\n" ); +printf( " 1 1.5 1.5\n\n" ); +printf( +" Note that some segments are missing from the outer square, so one must\n" ); +printf( +" use the `-c' switch. After `triangle -pqc box.poly', here is the output\n" +); +printf( +" file `box.1.node', with twelve points. The last four points were added\n" ); +printf( +" to meet the angle constraint. Points 1, 2, and 9 have markers from\n" ); +printf( +" segment 1. Points 6 and 8 have markers from segment 4. All the other\n" ); +printf( +" points but 4 have been marked to indicate that they lie on a boundary.\n" ); +printf( "\n" ); +printf( " 12 2 0 1\n" ); +printf( " 1 0 0 5\n" ); +printf( " 2 0 3 5\n" ); +printf( " 3 3 0 1\n" ); +printf( " 4 3 3 33\n" ); +printf( " 5 1 1 1\n" ); +printf( " 6 1 2 10\n" ); +printf( " 7 2 1 1\n" ); +printf( " 8 2 2 10\n" ); +printf( " 9 0 1.5 5\n" ); +printf( " 10 1.5 0 1\n" ); +printf( " 11 3 1.5 1\n" ); +printf( " 12 1.5 3 1\n" ); +printf( " # Generated by triangle -pqc box.poly\n\n" ); +printf( " Here is the output file `box.1.ele', with twelve triangles.\n\n" ); +printf( " 12 3 0\n" ); +printf( " 1 5 6 9\n" ); +printf( " 2 10 3 7\n" ); +printf( " 3 6 8 12\n" ); +printf( " 4 9 1 5\n" ); +printf( " 5 6 2 9\n" ); +printf( " 6 7 3 11\n" ); +printf( " 7 11 4 8\n" ); +printf( " 8 7 5 10\n" ); +printf( " 9 12 2 6\n" ); +printf( " 10 8 7 11\n" ); +printf( " 11 5 1 10\n" ); +printf( " 12 8 4 12\n" ); +printf( " # Generated by triangle -pqc box.poly\n\n" ); +printf( +" Here is the output file `box.1.poly'. Note that segments have been added\n" +); +printf( +" to represent the convex hull, and some segments have been split by newly\n" +); +printf( +" added points. Note also that <# of points> is set to zero to indicate\n" ); +printf( " that the points should be read from the .node file.\n\n" ); +printf( " 0 2 0 1\n" ); +printf( " 12 1\n" ); +printf( " 1 1 9 5\n" ); +printf( " 2 5 7 1\n" ); +printf( " 3 8 7 1\n" ); +printf( " 4 6 8 10\n" ); +printf( " 5 5 6 1\n" ); +printf( " 6 3 10 1\n" ); +printf( " 7 4 11 1\n" ); +printf( " 8 2 12 1\n" ); +printf( " 9 9 2 5\n" ); +printf( " 10 10 1 1\n" ); +printf( " 11 11 3 1\n" ); +printf( " 12 12 4 1\n" ); +printf( " 1\n" ); +printf( " 1 1.5 1.5\n" ); +printf( " # Generated by triangle -pqc box.poly\n\n" ); +printf( "Refinement and Area Constraints:\n\n" ); +printf( +" The -r switch causes a mesh (.node and .ele files) to be read and\n" ); +printf( +" refined. If the -p switch is also used, a .poly file is read and used to\n" +); +printf( +" specify edges that are constrained and cannot be eliminated (although\n" ); +printf( +" they can be divided into smaller edges) by the refinement process.\n" ); +printf( "\n" ); +printf( +" When you refine a mesh, you generally want to impose tighter quality\n" ); +printf( +" constraints. One way to accomplish this is to use -q with a larger\n" ); +printf( +" angle, or -a followed by a smaller area than you used to generate the\n" ); +printf( +" mesh you are refining. Another way to do this is to create an .area\n" ); +printf( +" file, which specifies a maximum area for each triangle, and use the -a\n" ); +printf( +" switch (without a number following). Each triangle's area constraint is\n" +); +printf( +" applied to that triangle. Area constraints tend to diffuse as the mesh\n" ); +printf( +" is refined, so if there are large variations in area constraint between\n" ); +printf( " adjacent triangles, you may not get the results you want.\n\n" ); +printf( +" If you are refining a mesh composed of linear (three-node) elements, the\n" +); +printf( +" output mesh will contain all the nodes present in the input mesh, in the\n" +); +printf( +" same order, with new nodes added at the end of the .node file. However,\n" +); +printf( +" there is no guarantee that each output element is contained in a single\n" ); +printf( +" input element. Often, output elements will overlap two input elements,\n" ); +printf( +" and input edges are not present in the output mesh. Hence, a sequence of\n" +); +printf( +" refined meshes will form a hierarchy of nodes, but not a hierarchy of\n" ); +printf( +" elements. If you a refining a mesh of higher-order elements, the\n" ); +printf( +" hierarchical property applies only to the nodes at the corners of an\n" ); +printf( " element; other nodes may not be present in the refined mesh.\n\n" ); +printf( +" It is important to understand that maximum area constraints in .poly\n" ); +printf( +" files are handled differently from those in .area files. A maximum area\n" +); +printf( +" in a .poly file applies to the whole (segment-bounded) region in which a\n" +); +printf( +" point falls, whereas a maximum area in an .area file applies to only one\n" +); +printf( +" triangle. Area constraints in .poly files are used only when a mesh is\n" ); +printf( +" first generated, whereas area constraints in .area files are used only to\n" +); +printf( +" refine an existing mesh, and are typically based on a posteriori error\n" ); +printf( +" estimates resulting from a finite element simulation on that mesh.\n" ); +printf( "\n" ); +printf( +" `triangle -rq25 object.1' will read object.1.node and object.1.ele, then\n" +); +printf( +" refine the triangulation to enforce a 25 degree minimum angle, and then\n" ); +printf( +" write the refined triangulation to object.2.node and object.2.ele.\n" ); +printf( "\n" ); +printf( +" `triangle -rpaa6.2 z.3' will read z.3.node, z.3.ele, z.3.poly, and\n" ); +printf( +" z.3.area. After reconstructing the mesh and its segments, Triangle will\n" +); +printf( +" refine the mesh so that no triangle has area greater than 6.2, and\n" ); +printf( +" furthermore the triangles satisfy the maximum area constraints in\n" ); +printf( +" z.3.area. The output is written to z.4.node, z.4.ele, and z.4.poly.\n" ); +printf( "\n" ); +printf( +" The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n" ); +printf( +" x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n" ); +printf( " suitable for multigrid.\n\n" ); +printf( "Convex Hulls and Mesh Boundaries:\n\n" ); +printf( +" If the input is a point set (rather than a PSLG), Triangle produces its\n" ); +printf( +" convex hull as a by-product in the output .poly file if you use the -c\n" ); +printf( +" switch. There are faster algorithms for finding a two-dimensional convex\n" +); +printf( +" hull than triangulation, of course, but this one comes for free. If the\n" +); +printf( +" input is an unconstrained mesh (you are using the -r switch but not the\n" ); +printf( +" -p switch), Triangle produces a list of its boundary edges (including\n" ); +printf( " hole boundaries) as a by-product if you use the -c switch.\n\n" ); +printf( "Voronoi Diagrams:\n\n" ); +printf( +" The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n" ); +printf( +" .v.edge. For example, `triangle -v points' will read points.node,\n" ); +printf( +" produce its Delaunay triangulation in points.1.node and points.1.ele,\n" ); +printf( +" and produce its Voronoi diagram in points.1.v.node and points.1.v.edge.\n" ); +printf( +" The .v.node file contains a list of all Voronoi vertices, and the .v.edge\n" +); +printf( +" file contains a list of all Voronoi edges, some of which may be infinite\n" +); +printf( +" rays. (The choice of filenames makes it easy to run the set of Voronoi\n" ); +printf( " vertices through Triangle, if so desired.)\n\n" ); +printf( +" This implementation does not use exact arithmetic to compute the Voronoi\n" +); +printf( +" vertices, and does not check whether neighboring vertices are identical.\n" +); +printf( +" Be forewarned that if the Delaunay triangulation is degenerate or\n" ); +printf( +" near-degenerate, the Voronoi diagram may have duplicate points, crossing\n" +); +printf( +" edges, or infinite rays whose direction vector is zero. Also, if you\n" ); +printf( +" generate a constrained (as opposed to conforming) Delaunay triangulation,\n" +); +printf( +" or if the triangulation has holes, the corresponding Voronoi diagram is\n" ); +printf( " likely to have crossing edges and unlikely to make sense.\n\n" ); +printf( "Mesh Topology:\n\n" ); +printf( +" You may wish to know which triangles are adjacent to a certain Delaunay\n" ); +printf( +" edge in an .edge file, which Voronoi regions are adjacent to a certain\n" ); +printf( +" Voronoi edge in a .v.edge file, or which Voronoi regions are adjacent to\n" +); +printf( +" each other. All of this information can be found by cross-referencing\n" ); +printf( +" output files with the recollection that the Delaunay triangulation and\n" ); +printf( " the Voronoi diagrams are planar duals.\n\n" ); +printf( +" Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n" ); +printf( +" the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n" ); +printf( +" wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n" ); +printf( +" vertex j of the corresponding .v.node file; and Voronoi region k is the\n" ); +printf( " dual of point k of the corresponding .node file.\n\n" ); +printf( +" Hence, to find the triangles adjacent to a Delaunay edge, look at the\n" ); +printf( +" vertices of the corresponding Voronoi edge; their dual triangles are on\n" ); +printf( +" the left and right of the Delaunay edge, respectively. To find the\n" ); +printf( +" Voronoi regions adjacent to a Voronoi edge, look at the endpoints of the\n" +); +printf( +" corresponding Delaunay edge; their dual regions are on the right and left\n" +); +printf( +" of the Voronoi edge, respectively. To find which Voronoi regions are\n" ); +printf( " adjacent to each other, just read the list of Delaunay edges.\n" ); +printf( "\n" ); +printf( "Statistics:\n" ); +printf( "\n" ); +printf( +" After generating a mesh, Triangle prints a count of the number of points,\n" +); +printf( +" triangles, edges, boundary edges, and segments in the output mesh. If\n" ); +printf( +" you've forgotten the statistics for an existing mesh, the -rNEP switches\n" +); +printf( +" (or -rpNEP if you've got a .poly file for the existing mesh) will\n" ); +printf( " regenerate these statistics without writing any output.\n\n" ); +printf( +" The -V switch produces extended statistics, including a rough estimate\n" ); +printf( +" of memory use and a histogram of triangle aspect ratios and angles in the\n" +); +printf( " mesh.\n\n" ); +printf( "Exact Arithmetic:\n\n" ); +printf( +" Triangle uses adaptive exact arithmetic to perform what computational\n" ); +printf( +" geometers call the `orientation' and `incircle' tests. If the floating-\n" +); +printf( +" point arithmetic of your machine conforms to the IEEE 754 standard (as\n" ); +printf( +" most workstations do), and does not use extended precision internal\n" ); +printf( +" registers, then your output is guaranteed to be an absolutely true\n" ); +printf( " Delaunay or conforming Delaunay triangulation, roundoff error\n" ); +printf( +" notwithstanding. The word `adaptive' implies that these arithmetic\n" ); +printf( +" routines compute the result only to the precision necessary to guarantee\n" +); +printf( +" correctness, so they are usually nearly as fast as their approximate\n" ); +printf( +" counterparts. The exact tests can be disabled with the -X switch. On\n" ); +printf( +" most inputs, this switch will reduce the computation time by about eight\n" +); +printf( +" percent - it's not worth the risk. There are rare difficult inputs\n" ); +printf( +" (having many collinear and cocircular points), however, for which the\n" ); +printf( +" difference could be a factor of two. These are precisely the inputs most\n" +); +printf( " likely to cause errors if you use the -X switch.\n\n" ); +printf( +" Unfortunately, these routines don't solve every numerical problem. Exact\n" +); +printf( +" arithmetic is not used to compute the positions of points, because the\n" ); +printf( +" bit complexity of point coordinates would grow without bound. Hence,\n" ); +printf( +" segment intersections aren't computed exactly; in very unusual cases,\n" ); +printf( +" roundoff error in computing an intersection point might actually lead to\n" +); +printf( +" an inverted triangle and an invalid triangulation. (This is one reason\n" ); +printf( +" to compute your own intersection points in your .poly files.) Similarly,\n" +); +printf( +" exact arithmetic is not used to compute the vertices of the Voronoi\n" ); +printf( " diagram.\n\n" ); +printf( +" Underflow and overflow can also cause difficulties; the exact arithmetic\n" +); +printf( +" routines do not ameliorate out-of-bounds exponents, which can arise\n" ); +printf( +" during the orientation and incircle tests. As a rule of thumb, you\n" ); +printf( +" should ensure that your input values are within a range such that their\n" ); +printf( +" third powers can be taken without underflow or overflow. Underflow can\n" ); +printf( +" silently prevent the tests from being performed exactly, while overflow\n" ); +printf( " will typically cause a floating exception.\n\n" ); +printf( "Calling Triangle from Another Program:\n\n" ); +printf( " Read the file triangle.h for details.\n\n" ); +printf( "Troubleshooting:\n\n" ); +printf( " Please read this section before mailing me bugs.\n\n" ); +printf( " `My output mesh has no triangles!'\n\n" ); +printf( +" If you're using a PSLG, you've probably failed to specify a proper set\n" +); +printf( +" of bounding segments, or forgotten to use the -c switch. Or you may\n" ); +printf( +" have placed a hole badly. To test these possibilities, try again with\n" +); +printf( +" the -c and -O switches. Alternatively, all your input points may be\n" ); +printf( +" collinear, in which case you can hardly expect to triangulate them.\n" ); +printf( "\n" ); +printf( " `Triangle doesn't terminate, or just crashes.'\n" ); +printf( "\n" ); +printf( +" Bad things can happen when triangles get so small that the distance\n" ); +printf( +" between their vertices isn't much larger than the precision of your\n" ); +printf( +" machine's arithmetic. If you've compiled Triangle for single-precision\n" +); +printf( +" arithmetic, you might do better by recompiling it for double-precision.\n" +); +printf( +" Then again, you might just have to settle for more lenient constraints\n" +); +printf( +" on the minimum angle and the maximum area than you had planned.\n" ); +printf( "\n" ); +printf( +" You can minimize precision problems by ensuring that the origin lies\n" ); +printf( +" inside your point set, or even inside the densest part of your\n" ); +printf( +" mesh. On the other hand, if you're triangulating an object whose x\n" ); +printf( +" coordinates all fall between 6247133 and 6247134, you're not leaving\n" ); +printf( " much floating-point precision for Triangle to work with.\n\n" ); +printf( +" Precision problems can occur covertly if the input PSLG contains two\n" ); +printf( +" segments that meet (or intersect) at a very small angle, or if such an\n" +); +printf( +" angle is introduced by the -c switch, which may occur if a point lies\n" ); +printf( +" ever-so-slightly inside the convex hull, and is connected by a PSLG\n" ); +printf( +" segment to a point on the convex hull. If you don't realize that a\n" ); +printf( +" small angle is being formed, you might never discover why Triangle is\n" ); +printf( +" crashing. To check for this possibility, use the -S switch (with an\n" ); +printf( +" appropriate limit on the number of Steiner points, found by trial-and-\n" +); +printf( +" error) to stop Triangle early, and view the output .poly file with\n" ); +printf( +" Show Me (described below). Look carefully for small angles between\n" ); +printf( +" segments; zoom in closely, as such segments might look like a single\n" ); +printf( " segment from a distance.\n\n" ); +printf( +" If some of the input values are too large, Triangle may suffer a\n" ); +printf( +" floating exception due to overflow when attempting to perform an\n" ); +printf( +" orientation or incircle test. (Read the section on exact arithmetic\n" ); +printf( +" above.) Again, I recommend compiling Triangle for double (rather\n" ); +printf( " than single) precision arithmetic.\n\n" ); +printf( +" `The numbering of the output points doesn't match the input points.'\n" ); +printf( "\n" ); +printf( +" You may have eaten some of your input points with a hole, or by placing\n" +); +printf( " them outside the area enclosed by segments.\n\n" ); +printf( +" `Triangle executes without incident, but when I look at the resulting\n" ); +printf( +" mesh, it has overlapping triangles or other geometric inconsistencies.'\n" ); +printf( "\n" ); +printf( +" If you select the -X switch, Triangle's divide-and-conquer Delaunay\n" ); +printf( +" triangulation algorithm occasionally makes mistakes due to floating-\n" ); +printf( +" point roundoff error. Although these errors are rare, don't use the -X\n" +); +printf( " switch. If you still have problems, please report the bug.\n" ); +printf( "\n" ); +printf( +" Strange things can happen if you've taken liberties with your PSLG. Do\n" ); +printf( +" you have a point lying in the middle of a segment? Triangle sometimes\n" ); +printf( +" copes poorly with that sort of thing. Do you want to lay out a collinear\n" +); +printf( +" row of evenly spaced, segment-connected points? Have you simply defined\n" +); +printf( +" one long segment connecting the leftmost point to the rightmost point,\n" ); +printf( +" and a bunch of points lying along it? This method occasionally works,\n" ); +printf( +" especially with horizontal and vertical lines, but often it doesn't, and\n" +); +printf( +" you'll have to connect each adjacent pair of points with a separate\n" ); +printf( " segment. If you don't like it, tough.\n\n" ); +printf( +" Furthermore, if you have segments that intersect other than at their\n" ); +printf( +" endpoints, try not to let the intersections fall extremely close to PSLG\n" +); +printf( " points or each other.\n\n" ); +printf( +" If you have problems refining a triangulation not produced by Triangle:\n" ); +printf( +" Are you sure the triangulation is geometrically valid? Is it formatted\n" ); +printf( +" correctly for Triangle? Are the triangles all listed so the first three\n" +); +printf( " points are their corners in counterclockwise order?\n\n" ); +printf( "Show Me:\n\n" ); +printf( +" Triangle comes with a separate program named `Show Me', whose primary\n" ); +printf( +" purpose is to draw meshes on your screen or in PostScript. Its secondary\n" +); +printf( +" purpose is to check the validity of your input files, and do so more\n" ); +printf( +" thoroughly than Triangle does. Show Me requires that you have the X\n" ); +printf( +" Windows system. If you didn't receive Show Me with Triangle, complain to\n" +); +printf( " whomever you obtained Triangle from, then send me mail.\n\n" ); +printf( "Triangle on the Web:\n\n" ); +printf( +" To see an illustrated, updated version of these instructions, check out\n" ); +printf( "\n" ); +printf( " http://www.cs.cmu.edu/~quake/triangle.html\n" ); +printf( "\n" ); +printf( "A Brief Plea:\n" ); +printf( "\n" ); +printf( +" If you use Triangle, and especially if you use it to accomplish real\n" ); +printf( +" work, I would like very much to hear from you. A short letter or email\n" ); +printf( +" (to jrs@cs.cmu.edu) describing how you use Triangle will mean a lot to\n" ); +printf( +" me. The more people I know are using this program, the more easily I can\n" +); +printf( +" justify spending time on improvements and on the three-dimensional\n" ); +printf( +" successor to Triangle, which in turn will benefit you. Also, I can put\n" ); +printf( +" you on a list to receive email whenever a new version of Triangle is\n" ); +printf( " available.\n\n" ); +printf( +" If you use a mesh generated by Triangle in a publication, please include\n" +); +printf( " an acknowledgment as well.\n\n" ); +printf( "Research credit:\n\n" ); +printf( +" Of course, I can take credit for only a fraction of the ideas that made\n" ); +printf( +" this mesh generator possible. Triangle owes its existence to the efforts\n" +); +printf( +" of many fine computational geometers and other researchers, including\n" ); +printf( +" Marshall Bern, L. Paul Chew, Boris Delaunay, Rex A. Dwyer, David\n" ); +printf( +" Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E. Knuth, C. L.\n" ); +printf( +" Lawson, Der-Tsai Lee, Ernst P. Mucke, Douglas M. Priest, Jim Ruppert,\n" ); +printf( +" Isaac Saias, Bruce J. Schachter, Micha Sharir, Jorge Stolfi, Christopher\n" +); +printf( +" J. Van Wyk, David F. Watson, and Binhai Zhu. See the comments at the\n" ); +printf( " beginning of the source code for references.\n\n" ); +exit( 0 ); } #endif /* not TRILIBRARY */ @@ -2654,10 +2773,10 @@ void info(){ /*****************************************************************************/ void internalerror(){ - printf( " Please report this bug to jrs@cs.cmu.edu\n" ); - printf( " Include the message above, your input data set, and the exact\n" ); - printf( " command line you used to run Triangle.\n" ); - exit( 1 ); +printf( " Please report this bug to jrs@cs.cmu.edu\n" ); +printf( " Include the message above, your input data set, and the exact\n" ); +printf( " command line you used to run Triangle.\n" ); +exit( 1 ); } /*****************************************************************************/ @@ -2673,324 +2792,341 @@ void parsecommandline( argc, argv ) int argc; char **argv; { -#ifdef TRILIBRARY -#define STARTINDEX 0 +#ifdef +TRILIBRARY +#define +STARTINDEX 0 #else /* not TRILIBRARY */ -#define STARTINDEX 1 - int increment; - int meshnumber; +#define +STARTINDEX 1 +int increment; +int meshnumber; #endif /* not TRILIBRARY */ - int i, j; -#ifndef CDT_ONLY - int k; - char workstring[FILENAMESIZE]; +int i, j; +#ifndef +CDT_ONLY +int k; +char workstring[FILENAMESIZE]; #endif - poly = refine = quality = vararea = fixedarea = regionattrib = convex = 0; - firstnumber = 1; - edgesout = voronoi = neighbors = geomview = 0; - nobound = nopolywritten = nonodewritten = noelewritten = noiterationnum = 0; - noholes = noexact = 0; - incremental = sweepline = 0; - dwyer = 1; - splitseg = 0; - docheck = 0; - nobisect = 0; - steiner = -1; - order = 1; - minangle = 0.0; - maxarea = -1.0; - quiet = verbose = 0; -#ifndef TRILIBRARY - innodefilename[0] = '\0'; +poly = refine = quality = vararea = fixedarea = regionattrib = convex = 0; +firstnumber = 1; +edgesout = voronoi = neighbors = geomview = 0; +nobound = nopolywritten = nonodewritten = noelewritten = noiterationnum = 0; +noholes = noexact = 0; +incremental = sweepline = 0; +dwyer = 1; +splitseg = 0; +docheck = 0; +nobisect = 0; +steiner = -1; +order = 1; +minangle = 0.0; +maxarea = -1.0; +quiet = verbose = 0; +#ifndef +TRILIBRARY +innodefilename[0] = '\0'; #endif /* not TRILIBRARY */ - for ( i = STARTINDEX; i < argc; i++ ) { -#ifndef TRILIBRARY - if ( argv[i][0] == '-' ) { +for ( i = STARTINDEX; i < argc; i++ ) { +#ifndef +TRILIBRARY +if ( argv[i][0] == '-' ) { #endif /* not TRILIBRARY */ - for ( j = STARTINDEX; argv[i][j] != '\0'; j++ ) { - if ( argv[i][j] == 'p' ) { - poly = 1; - } -#ifndef CDT_ONLY - if ( argv[i][j] == 'r' ) { - refine = 1; - } - if ( argv[i][j] == 'q' ) { - quality = 1; - if ( ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) || - ( argv[i][j + 1] == '.' ) ) { - k = 0; - while ( ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) || - ( argv[i][j + 1] == '.' ) ) { - j++; - workstring[k] = argv[i][j]; - k++; - } - workstring[k] = '\0'; - minangle = (REAL) strtod( workstring, (char **) NULL ); - } - else { - minangle = 20.0; - } - } - if ( argv[i][j] == 'a' ) { - quality = 1; - if ( ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) || - ( argv[i][j + 1] == '.' ) ) { - fixedarea = 1; - k = 0; - while ( ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) || - ( argv[i][j + 1] == '.' ) ) { - j++; - workstring[k] = argv[i][j]; - k++; - } - workstring[k] = '\0'; - maxarea = (REAL) strtod( workstring, (char **) NULL ); - if ( maxarea <= 0.0 ) { - printf( "Error: Maximum area must be greater than zero.\n" ); - exit( 1 ); - } - } - else { - vararea = 1; - } - } +for ( j = STARTINDEX; argv[i][j] != '\0'; j++ ) { +if ( argv[i][j] == 'p' ) { +poly = 1; +} +#ifndef +CDT_ONLY +if ( argv[i][j] == 'r' ) { +refine = 1; +} +if ( argv[i][j] == 'q' ) { +quality = 1; +if ((( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' )) || +( argv[i][j + 1] == '.' )) { +k = 0; +while ((( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' )) || +( argv[i][j + 1] == '.' )) { +j++; +workstring[k] = argv[i][j]; +k++; +} +workstring[k] = '\0'; +minangle = (REAL) strtod( workstring, (char **) NULL ); +} +else { +minangle = 20.0; +} +} +if ( argv[i][j] == 'a' ) { +quality = 1; +if ((( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' )) || +( argv[i][j + 1] == '.' )) { +fixedarea = 1; +k = 0; +while ((( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' )) || +( argv[i][j + 1] == '.' )) { +j++; +workstring[k] = argv[i][j]; +k++; +} +workstring[k] = '\0'; +maxarea = (REAL) strtod( workstring, (char **) NULL ); +if ( maxarea <= 0.0 ) { +printf( "Error: Maximum area must be greater than zero.\n" ); +exit( 1 ); +} +} +else { +vararea = 1; +} +} #endif /* not CDT_ONLY */ - if ( argv[i][j] == 'A' ) { - regionattrib = 1; - } - if ( argv[i][j] == 'c' ) { - convex = 1; - } - if ( argv[i][j] == 'z' ) { - firstnumber = 0; - } - if ( argv[i][j] == 'e' ) { - edgesout = 1; - } - if ( argv[i][j] == 'v' ) { - voronoi = 1; - } - if ( argv[i][j] == 'n' ) { - neighbors = 1; - } - if ( argv[i][j] == 'g' ) { - geomview = 1; - } - if ( argv[i][j] == 'B' ) { - nobound = 1; - } - if ( argv[i][j] == 'P' ) { - nopolywritten = 1; - } - if ( argv[i][j] == 'N' ) { - nonodewritten = 1; - } - if ( argv[i][j] == 'E' ) { - noelewritten = 1; - } -#ifndef TRILIBRARY - if ( argv[i][j] == 'I' ) { - noiterationnum = 1; - } +if ( argv[i][j] == 'A' ) { +regionattrib = 1; +} +if ( argv[i][j] == 'c' ) { +convex = 1; +} +if ( argv[i][j] == 'z' ) { +firstnumber = 0; +} +if ( argv[i][j] == 'e' ) { +edgesout = 1; +} +if ( argv[i][j] == 'v' ) { +voronoi = 1; +} +if ( argv[i][j] == 'n' ) { +neighbors = 1; +} +if ( argv[i][j] == 'g' ) { +geomview = 1; +} +if ( argv[i][j] == 'B' ) { +nobound = 1; +} +if ( argv[i][j] == 'P' ) { +nopolywritten = 1; +} +if ( argv[i][j] == 'N' ) { +nonodewritten = 1; +} +if ( argv[i][j] == 'E' ) { +noelewritten = 1; +} +#ifndef +TRILIBRARY +if ( argv[i][j] == 'I' ) { +noiterationnum = 1; +} #endif /* not TRILIBRARY */ - if ( argv[i][j] == 'O' ) { - noholes = 1; - } - if ( argv[i][j] == 'X' ) { - noexact = 1; - } - if ( argv[i][j] == 'o' ) { - if ( argv[i][j + 1] == '2' ) { - j++; - order = 2; - } - } -#ifndef CDT_ONLY - if ( argv[i][j] == 'Y' ) { - nobisect++; - } - if ( argv[i][j] == 'S' ) { - steiner = 0; - while ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) { - j++; - steiner = steiner * 10 + (int) ( argv[i][j] - '0' ); - } - } +if ( argv[i][j] == 'O' ) { +noholes = 1; +} +if ( argv[i][j] == 'X' ) { +noexact = 1; +} +if ( argv[i][j] == 'o' ) { +if ( argv[i][j + 1] == '2' ) { +j++; +order = 2; +} +} +#ifndef +CDT_ONLY +if ( argv[i][j] == 'Y' ) { +nobisect++; +} +if ( argv[i][j] == 'S' ) { +steiner = 0; +while (( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' )) { +j++; +steiner = steiner * 10 + (int) ( argv[i][j] - '0' ); +} +} #endif /* not CDT_ONLY */ -#ifndef REDUCED - if ( argv[i][j] == 'i' ) { - incremental = 1; - } - if ( argv[i][j] == 'F' ) { - sweepline = 1; - } +#ifndef +REDUCED +if ( argv[i][j] == 'i' ) { +incremental = 1; +} +if ( argv[i][j] == 'F' ) { +sweepline = 1; +} #endif /* not REDUCED */ - if ( argv[i][j] == 'l' ) { - dwyer = 0; - } -#ifndef REDUCED -#ifndef CDT_ONLY - if ( argv[i][j] == 's' ) { - splitseg = 1; - } +if ( argv[i][j] == 'l' ) { +dwyer = 0; +} +#ifndef +REDUCED +#ifndef +CDT_ONLY +if ( argv[i][j] == 's' ) { +splitseg = 1; +} #endif /* not CDT_ONLY */ - if ( argv[i][j] == 'C' ) { - docheck = 1; - } +if ( argv[i][j] == 'C' ) { +docheck = 1; +} #endif /* not REDUCED */ - if ( argv[i][j] == 'Q' ) { - quiet = 1; - } - if ( argv[i][j] == 'V' ) { - verbose++; - } -#ifndef TRILIBRARY - if ( ( argv[i][j] == 'h' ) || ( argv[i][j] == 'H' ) || - ( argv[i][j] == '?' ) ) { - info(); - } +if ( argv[i][j] == 'Q' ) { +quiet = 1; +} +if ( argv[i][j] == 'V' ) { +verbose++; +} +#ifndef +TRILIBRARY +if (( argv[i][j] == 'h' ) || ( argv[i][j] == 'H' ) || +( argv[i][j] == '?' )) { +info(); +} #endif /* not TRILIBRARY */ - } -#ifndef TRILIBRARY - } else { - strncpy( innodefilename, argv[i], FILENAMESIZE - 1 ); - innodefilename[FILENAMESIZE - 1] = '\0'; - } +} +#ifndef +TRILIBRARY +} else { +strncpy( innodefilename, argv[i], FILENAMESIZE - 1 ); +innodefilename[FILENAMESIZE - 1] = '\0'; +} #endif /* not TRILIBRARY */ - } -#ifndef TRILIBRARY - if ( innodefilename[0] == '\0' ) { - syntax(); - } - if ( !strcmp( &innodefilename[strlen( innodefilename ) - 5], ".node" ) ) { - innodefilename[strlen( innodefilename ) - 5] = '\0'; - } - if ( !strcmp( &innodefilename[strlen( innodefilename ) - 5], ".poly" ) ) { - innodefilename[strlen( innodefilename ) - 5] = '\0'; - poly = 1; - } -#ifndef CDT_ONLY - if ( !strcmp( &innodefilename[strlen( innodefilename ) - 4], ".ele" ) ) { - innodefilename[strlen( innodefilename ) - 4] = '\0'; - refine = 1; - } - if ( !strcmp( &innodefilename[strlen( innodefilename ) - 5], ".area" ) ) { - innodefilename[strlen( innodefilename ) - 5] = '\0'; - refine = 1; - quality = 1; - vararea = 1; - } +} +#ifndef +TRILIBRARY +if ( innodefilename[0] == '\0' ) { +syntax(); +} +if ( !strcmp( &innodefilename[strlen( innodefilename ) - 5], ".node" )) { +innodefilename[strlen( innodefilename ) - 5] = '\0'; +} +if ( !strcmp( &innodefilename[strlen( innodefilename ) - 5], ".poly" )) { +innodefilename[strlen( innodefilename ) - 5] = '\0'; +poly = 1; +} +#ifndef +CDT_ONLY +if ( !strcmp( &innodefilename[strlen( innodefilename ) - 4], ".ele" )) { +innodefilename[strlen( innodefilename ) - 4] = '\0'; +refine = 1; +} +if ( !strcmp( &innodefilename[strlen( innodefilename ) - 5], ".area" )) { +innodefilename[strlen( innodefilename ) - 5] = '\0'; +refine = 1; +quality = 1; +vararea = 1; +} #endif /* not CDT_ONLY */ #endif /* not TRILIBRARY */ - steinerleft = steiner; - useshelles = poly || refine || quality || convex; - goodangle = (REAL)cos( minangle * PI / 180.0 ); - goodangle *= goodangle; - if ( refine && noiterationnum ) { - printf( - "Error: You cannot use the -I switch when refining a triangulation.\n" ); - exit( 1 ); - } - /* Be careful not to allocate space for element area constraints that */ - /* will never be assigned any value (other than the default -1.0). */ - if ( !refine && !poly ) { - vararea = 0; - } - /* Be careful not to add an extra attribute to each element unless the */ - /* input supports it (PSLG in, but not refining a preexisting mesh). */ - if ( refine || !poly ) { - regionattrib = 0; - } - -#ifndef TRILIBRARY - strcpy( inpolyfilename, innodefilename ); - strcpy( inelefilename, innodefilename ); - strcpy( areafilename, innodefilename ); - increment = 0; - strcpy( workstring, innodefilename ); - j = 1; - while ( workstring[j] != '\0' ) { - if ( ( workstring[j] == '.' ) && ( workstring[j + 1] != '\0' ) ) { - increment = j + 1; - } - j++; - } - meshnumber = 0; - if ( increment > 0 ) { - j = increment; - do { - if ( ( workstring[j] >= '0' ) && ( workstring[j] <= '9' ) ) { - meshnumber = meshnumber * 10 + (int) ( workstring[j] - '0' ); - } - else { - increment = 0; - } - j++; - } while ( workstring[j] != '\0' ); - } - if ( noiterationnum ) { - strcpy( outnodefilename, innodefilename ); - strcpy( outelefilename, innodefilename ); - strcpy( edgefilename, innodefilename ); - strcpy( vnodefilename, innodefilename ); - strcpy( vedgefilename, innodefilename ); - strcpy( neighborfilename, innodefilename ); - strcpy( offfilename, innodefilename ); - strcat( outnodefilename, ".node" ); - strcat( outelefilename, ".ele" ); - strcat( edgefilename, ".edge" ); - strcat( vnodefilename, ".v.node" ); - strcat( vedgefilename, ".v.edge" ); - strcat( neighborfilename, ".neigh" ); - strcat( offfilename, ".off" ); - } - else if ( increment == 0 ) { - strcpy( outnodefilename, innodefilename ); - strcpy( outpolyfilename, innodefilename ); - strcpy( outelefilename, innodefilename ); - strcpy( edgefilename, innodefilename ); - strcpy( vnodefilename, innodefilename ); - strcpy( vedgefilename, innodefilename ); - strcpy( neighborfilename, innodefilename ); - strcpy( offfilename, innodefilename ); - strcat( outnodefilename, ".1.node" ); - strcat( outpolyfilename, ".1.poly" ); - strcat( outelefilename, ".1.ele" ); - strcat( edgefilename, ".1.edge" ); - strcat( vnodefilename, ".1.v.node" ); - strcat( vedgefilename, ".1.v.edge" ); - strcat( neighborfilename, ".1.neigh" ); - strcat( offfilename, ".1.off" ); - } - else { - workstring[increment] = '%'; - workstring[increment + 1] = 'd'; - workstring[increment + 2] = '\0'; - sprintf( outnodefilename, workstring, meshnumber + 1 ); - strcpy( outpolyfilename, outnodefilename ); - strcpy( outelefilename, outnodefilename ); - strcpy( edgefilename, outnodefilename ); - strcpy( vnodefilename, outnodefilename ); - strcpy( vedgefilename, outnodefilename ); - strcpy( neighborfilename, outnodefilename ); - strcpy( offfilename, outnodefilename ); - strcat( outnodefilename, ".node" ); - strcat( outpolyfilename, ".poly" ); - strcat( outelefilename, ".ele" ); - strcat( edgefilename, ".edge" ); - strcat( vnodefilename, ".v.node" ); - strcat( vedgefilename, ".v.edge" ); - strcat( neighborfilename, ".neigh" ); - strcat( offfilename, ".off" ); - } - strcat( innodefilename, ".node" ); - strcat( inpolyfilename, ".poly" ); - strcat( inelefilename, ".ele" ); - strcat( areafilename, ".area" ); +steinerleft = steiner; +useshelles = poly || refine || quality || convex; +goodangle = (REAL)cos( minangle * PI / 180.0 ); +goodangle *= goodangle; +if ( refine && noiterationnum ) { +printf( +"Error: You cannot use the -I switch when refining a triangulation.\n" ); +exit( 1 ); +} +/* Be careful not to allocate space for element area constraints that */ +/* will never be assigned any value (other than the default -1.0). */ +if ( !refine && !poly ) { +vararea = 0; +} +/* Be careful not to add an extra attribute to each element unless the */ +/* input supports it (PSLG in, but not refining a preexisting mesh). */ +if ( refine || !poly ) { +regionattrib = 0; +} + +#ifndef +TRILIBRARY +strcpy( inpolyfilename, innodefilename ); +strcpy( inelefilename, innodefilename ); +strcpy( areafilename, innodefilename ); +increment = 0; +strcpy( workstring, innodefilename ); +j = 1; +while ( workstring[j] != '\0' ) { +if (( workstring[j] == '.' ) && ( workstring[j + 1] != '\0' )) { +increment = j + 1; +} +j++; +} +meshnumber = 0; +if ( increment > 0 ) { +j = increment; +do { +if (( workstring[j] >= '0' ) && ( workstring[j] <= '9' )) { +meshnumber = meshnumber * 10 + (int) ( workstring[j] - '0' ); +} +else { +increment = 0; +} +j++; +} while ( workstring[j] != '\0' ); +} +if ( noiterationnum ) { +strcpy( outnodefilename, innodefilename ); +strcpy( outelefilename, innodefilename ); +strcpy( edgefilename, innodefilename ); +strcpy( vnodefilename, innodefilename ); +strcpy( vedgefilename, innodefilename ); +strcpy( neighborfilename, innodefilename ); +strcpy( offfilename, innodefilename ); +strcat( outnodefilename, ".node" ); +strcat( outelefilename, ".ele" ); +strcat( edgefilename, ".edge" ); +strcat( vnodefilename, ".v.node" ); +strcat( vedgefilename, ".v.edge" ); +strcat( neighborfilename, ".neigh" ); +strcat( offfilename, ".off" ); +} +else if ( increment == 0 ) { +strcpy( outnodefilename, innodefilename ); +strcpy( outpolyfilename, innodefilename ); +strcpy( outelefilename, innodefilename ); +strcpy( edgefilename, innodefilename ); +strcpy( vnodefilename, innodefilename ); +strcpy( vedgefilename, innodefilename ); +strcpy( neighborfilename, innodefilename ); +strcpy( offfilename, innodefilename ); +strcat( outnodefilename, ".1.node" ); +strcat( outpolyfilename, ".1.poly" ); +strcat( outelefilename, ".1.ele" ); +strcat( edgefilename, ".1.edge" ); +strcat( vnodefilename, ".1.v.node" ); +strcat( vedgefilename, ".1.v.edge" ); +strcat( neighborfilename, ".1.neigh" ); +strcat( offfilename, ".1.off" ); +} +else { +workstring[increment] = '%'; +workstring[increment + 1] = 'd'; +workstring[increment + 2] = '\0'; +sprintf( outnodefilename, workstring, meshnumber + 1 ); +strcpy( outpolyfilename, outnodefilename ); +strcpy( outelefilename, outnodefilename ); +strcpy( edgefilename, outnodefilename ); +strcpy( vnodefilename, outnodefilename ); +strcpy( vedgefilename, outnodefilename ); +strcpy( neighborfilename, outnodefilename ); +strcpy( offfilename, outnodefilename ); +strcat( outnodefilename, ".node" ); +strcat( outpolyfilename, ".poly" ); +strcat( outelefilename, ".ele" ); +strcat( edgefilename, ".edge" ); +strcat( vnodefilename, ".v.node" ); +strcat( vedgefilename, ".v.edge" ); +strcat( neighborfilename, ".neigh" ); +strcat( offfilename, ".off" ); +} +strcat( innodefilename, ".node" ); +strcat( inpolyfilename, ".poly" ); +strcat( inelefilename, ".ele" ); +strcat( areafilename, ".area" ); #endif /* not TRILIBRARY */ } @@ -3016,83 +3152,83 @@ char **argv; void printtriangle( t ) struct triedge *t; { - struct triedge printtri; - struct edge printsh; - point printpoint; - - printf( "triangle x%lx with orientation %d:\n", (unsigned long) t->tri, - t->orient ); - decode( t->tri[0], printtri ); - if ( printtri.tri == dummytri ) { - printf( " [0] = Outer space\n" ); - } - else { - printf( " [0] = x%lx %d\n", (unsigned long) printtri.tri, - printtri.orient ); - } - decode( t->tri[1], printtri ); - if ( printtri.tri == dummytri ) { - printf( " [1] = Outer space\n" ); - } - else { - printf( " [1] = x%lx %d\n", (unsigned long) printtri.tri, - printtri.orient ); - } - decode( t->tri[2], printtri ); - if ( printtri.tri == dummytri ) { - printf( " [2] = Outer space\n" ); - } - else { - printf( " [2] = x%lx %d\n", (unsigned long) printtri.tri, - printtri.orient ); - } - org( *t, printpoint ); - if ( printpoint == (point) NULL ) { - printf( " Origin[%d] = NULL\n", ( t->orient + 1 ) % 3 + 3 ); - } - else{ - printf( " Origin[%d] = x%lx (%.12g, %.12g)\n", - ( t->orient + 1 ) % 3 + 3, (unsigned long) printpoint, - printpoint[0], printpoint[1] ); - } - dest( *t, printpoint ); - if ( printpoint == (point) NULL ) { - printf( " Dest [%d] = NULL\n", ( t->orient + 2 ) % 3 + 3 ); - } - else{ - printf( " Dest [%d] = x%lx (%.12g, %.12g)\n", - ( t->orient + 2 ) % 3 + 3, (unsigned long) printpoint, - printpoint[0], printpoint[1] ); - } - apex( *t, printpoint ); - if ( printpoint == (point) NULL ) { - printf( " Apex [%d] = NULL\n", t->orient + 3 ); - } - else{ - printf( " Apex [%d] = x%lx (%.12g, %.12g)\n", - t->orient + 3, (unsigned long) printpoint, - printpoint[0], printpoint[1] ); - } - if ( useshelles ) { - sdecode( t->tri[6], printsh ); - if ( printsh.sh != dummysh ) { - printf( " [6] = x%lx %d\n", (unsigned long) printsh.sh, - printsh.shorient ); - } - sdecode( t->tri[7], printsh ); - if ( printsh.sh != dummysh ) { - printf( " [7] = x%lx %d\n", (unsigned long) printsh.sh, - printsh.shorient ); - } - sdecode( t->tri[8], printsh ); - if ( printsh.sh != dummysh ) { - printf( " [8] = x%lx %d\n", (unsigned long) printsh.sh, - printsh.shorient ); - } - } - if ( vararea ) { - printf( " Area constraint: %.4g\n", areabound( *t ) ); - } +struct triedge printtri; +struct edge printsh; +point printpoint; + +printf( "triangle x%lx with orientation %d:\n", (unsigned long) t->tri, +t->orient ); +decode( t->tri[0], printtri ); +if ( printtri.tri == dummytri ) { +printf( " [0] = Outer space\n" ); +} +else { +printf( " [0] = x%lx %d\n", (unsigned long) printtri.tri, +printtri.orient ); +} +decode( t->tri[1], printtri ); +if ( printtri.tri == dummytri ) { +printf( " [1] = Outer space\n" ); +} +else { +printf( " [1] = x%lx %d\n", (unsigned long) printtri.tri, +printtri.orient ); +} +decode( t->tri[2], printtri ); +if ( printtri.tri == dummytri ) { +printf( " [2] = Outer space\n" ); +} +else { +printf( " [2] = x%lx %d\n", (unsigned long) printtri.tri, +printtri.orient ); +} +org( *t, printpoint ); +if ( printpoint == (point) NULL ) { +printf( " Origin[%d] = NULL\n", ( t->orient + 1 ) % 3 + 3 ); +} +else{ +printf( " Origin[%d] = x%lx (%.12g, %.12g)\n", +( t->orient + 1 ) % 3 + 3, (unsigned long) printpoint, +printpoint[0], printpoint[1] ); +} +dest( *t, printpoint ); +if ( printpoint == (point) NULL ) { +printf( " Dest [%d] = NULL\n", ( t->orient + 2 ) % 3 + 3 ); +} +else{ +printf( " Dest [%d] = x%lx (%.12g, %.12g)\n", +( t->orient + 2 ) % 3 + 3, (unsigned long) printpoint, +printpoint[0], printpoint[1] ); +} +apex( *t, printpoint ); +if ( printpoint == (point) NULL ) { +printf( " Apex [%d] = NULL\n", t->orient + 3 ); +} +else{ +printf( " Apex [%d] = x%lx (%.12g, %.12g)\n", +t->orient + 3, (unsigned long) printpoint, +printpoint[0], printpoint[1] ); +} +if ( useshelles ) { +sdecode( t->tri[6], printsh ); +if ( printsh.sh != dummysh ) { +printf( " [6] = x%lx %d\n", (unsigned long) printsh.sh, +printsh.shorient ); +} +sdecode( t->tri[7], printsh ); +if ( printsh.sh != dummysh ) { +printf( " [7] = x%lx %d\n", (unsigned long) printsh.sh, +printsh.shorient ); +} +sdecode( t->tri[8], printsh ); +if ( printsh.sh != dummysh ) { +printf( " [8] = x%lx %d\n", (unsigned long) printsh.sh, +printsh.shorient ); +} +} +if ( vararea ) { +printf( " Area constraint: %.4g\n", areabound( *t )); +} } /*****************************************************************************/ @@ -3109,62 +3245,62 @@ struct triedge *t; void printshelle( s ) struct edge *s; { - struct edge printsh; - struct triedge printtri; - point printpoint; - - printf( "shell edge x%lx with orientation %d and mark %d:\n", - (unsigned long) s->sh, s->shorient, mark( *s ) ); - sdecode( s->sh[0], printsh ); - if ( printsh.sh == dummysh ) { - printf( " [0] = No shell\n" ); - } - else { - printf( " [0] = x%lx %d\n", (unsigned long) printsh.sh, - printsh.shorient ); - } - sdecode( s->sh[1], printsh ); - if ( printsh.sh == dummysh ) { - printf( " [1] = No shell\n" ); - } - else { - printf( " [1] = x%lx %d\n", (unsigned long) printsh.sh, - printsh.shorient ); - } - sorg( *s, printpoint ); - if ( printpoint == (point) NULL ) { - printf( " Origin[%d] = NULL\n", 2 + s->shorient ); - } - else{ - printf( " Origin[%d] = x%lx (%.12g, %.12g)\n", - 2 + s->shorient, (unsigned long) printpoint, - printpoint[0], printpoint[1] ); - } - sdest( *s, printpoint ); - if ( printpoint == (point) NULL ) { - printf( " Dest [%d] = NULL\n", 3 - s->shorient ); - } - else{ - printf( " Dest [%d] = x%lx (%.12g, %.12g)\n", - 3 - s->shorient, (unsigned long) printpoint, - printpoint[0], printpoint[1] ); - } - decode( s->sh[4], printtri ); - if ( printtri.tri == dummytri ) { - printf( " [4] = Outer space\n" ); - } - else { - printf( " [4] = x%lx %d\n", (unsigned long) printtri.tri, - printtri.orient ); - } - decode( s->sh[5], printtri ); - if ( printtri.tri == dummytri ) { - printf( " [5] = Outer space\n" ); - } - else { - printf( " [5] = x%lx %d\n", (unsigned long) printtri.tri, - printtri.orient ); - } +struct edge printsh; +struct triedge printtri; +point printpoint; + +printf( "shell edge x%lx with orientation %d and mark %d:\n", +(unsigned long) s->sh, s->shorient, mark( *s )); +sdecode( s->sh[0], printsh ); +if ( printsh.sh == dummysh ) { +printf( " [0] = No shell\n" ); +} +else { +printf( " [0] = x%lx %d\n", (unsigned long) printsh.sh, +printsh.shorient ); +} +sdecode( s->sh[1], printsh ); +if ( printsh.sh == dummysh ) { +printf( " [1] = No shell\n" ); +} +else { +printf( " [1] = x%lx %d\n", (unsigned long) printsh.sh, +printsh.shorient ); +} +sorg( *s, printpoint ); +if ( printpoint == (point) NULL ) { +printf( " Origin[%d] = NULL\n", 2 + s->shorient ); +} +else{ +printf( " Origin[%d] = x%lx (%.12g, %.12g)\n", +2 + s->shorient, (unsigned long) printpoint, +printpoint[0], printpoint[1] ); +} +sdest( *s, printpoint ); +if ( printpoint == (point) NULL ) { +printf( " Dest [%d] = NULL\n", 3 - s->shorient ); +} +else{ +printf( " Dest [%d] = x%lx (%.12g, %.12g)\n", +3 - s->shorient, (unsigned long) printpoint, +printpoint[0], printpoint[1] ); +} +decode( s->sh[4], printtri ); +if ( printtri.tri == dummytri ) { +printf( " [4] = Outer space\n" ); +} +else { +printf( " [4] = x%lx %d\n", (unsigned long) printtri.tri, +printtri.orient ); +} +decode( s->sh[5], printtri ); +if ( printtri.tri == dummytri ) { +printf( " [5] = Outer space\n" ); +} +else { +printf( " [5] = x%lx %d\n", (unsigned long) printtri.tri, +printtri.orient ); +} } /** **/ @@ -3201,42 +3337,42 @@ int itemcount; enum wordtype wtype; int alignment; { - int wordsize; - - /* Initialize values in the pool. */ - pool->itemwordtype = wtype; - wordsize = ( pool->itemwordtype == POINTER ) ? sizeof( VOID * ) : sizeof( REAL ); - /* Find the proper alignment, which must be at least as large as: */ - /* - The parameter `alignment'. */ - /* - The primary word type, to avoid unaligned accesses. */ - /* - sizeof(VOID *), so the stack of dead items can be maintained */ - /* without unaligned accesses. */ - if ( alignment > wordsize ) { - pool->alignbytes = alignment; - } - else { - pool->alignbytes = wordsize; - } - if ( sizeof( VOID * ) > pool->alignbytes ) { - pool->alignbytes = sizeof( VOID * ); - } - pool->itemwords = ( ( bytecount + pool->alignbytes - 1 ) / pool->alignbytes ) - * ( pool->alignbytes / wordsize ); - pool->itembytes = pool->itemwords * wordsize; - pool->itemsperblock = itemcount; - - /* Allocate a block of items. Space for `itemsperblock' items and one */ - /* pointer (to point to the next block) are allocated, as well as space */ - /* to ensure alignment of the items. */ - pool->firstblock = (VOID **) malloc( pool->itemsperblock * pool->itembytes - + sizeof( VOID * ) + pool->alignbytes ); - if ( pool->firstblock == (VOID **) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - /* Set the next block pointer to NULL. */ - *( pool->firstblock ) = (VOID *) NULL; - poolrestart( pool ); +int wordsize; + +/* Initialize values in the pool. */ +pool->itemwordtype = wtype; +wordsize = ( pool->itemwordtype == POINTER ) ? sizeof( VOID * ) : sizeof( REAL ); +/* Find the proper alignment, which must be at least as large as: */ +/* - The parameter `alignment'. */ +/* - The primary word type, to avoid unaligned accesses. */ +/* - sizeof(VOID *), so the stack of dead items can be maintained */ +/* without unaligned accesses. */ +if ( alignment > wordsize ) { +pool->alignbytes = alignment; +} +else { +pool->alignbytes = wordsize; +} +if ( sizeof( VOID * ) > pool->alignbytes ) { +pool->alignbytes = sizeof( VOID * ); +} +pool->itemwords = (( bytecount + pool->alignbytes - 1 ) / pool->alignbytes ) +* ( pool->alignbytes / wordsize ); +pool->itembytes = pool->itemwords * wordsize; +pool->itemsperblock = itemcount; + +/* Allocate a block of items. Space for `itemsperblock' items and one */ +/* pointer (to point to the next block) are allocated, as well as space */ +/* to ensure alignment of the items. */ +pool->firstblock = (VOID **) malloc( pool->itemsperblock * pool->itembytes ++ sizeof( VOID * ) + pool->alignbytes ); +if ( pool->firstblock == (VOID **) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +/* Set the next block pointer to NULL. */ +*( pool->firstblock ) = (VOID *) NULL; +poolrestart( pool ); } /*****************************************************************************/ @@ -3252,23 +3388,23 @@ int alignment; void poolrestart( pool ) struct memorypool *pool; { - unsigned long alignptr; - - pool->items = 0; - pool->maxitems = 0; - - /* Set the currently active block. */ - pool->nowblock = pool->firstblock; - /* Find the first item in the pool. Increment by the size of (VOID *). */ - alignptr = (unsigned long) ( pool->nowblock + 1 ); - /* Align the item on an `alignbytes'-byte boundary. */ - pool->nextitem = (VOID *) - ( alignptr + (unsigned long) pool->alignbytes - - ( alignptr % (unsigned long) pool->alignbytes ) ); - /* There are lots of unallocated items left in this block. */ - pool->unallocateditems = pool->itemsperblock; - /* The stack of deallocated items is empty. */ - pool->deaditemstack = (VOID *) NULL; +unsigned long alignptr; + +pool->items = 0; +pool->maxitems = 0; + +/* Set the currently active block. */ +pool->nowblock = pool->firstblock; +/* Find the first item in the pool. Increment by the size of (VOID *). */ +alignptr = (unsigned long) ( pool->nowblock + 1 ); +/* Align the item on an `alignbytes'-byte boundary. */ +pool->nextitem = (VOID *) +( alignptr + (unsigned long) pool->alignbytes +- ( alignptr % (unsigned long) pool->alignbytes )); +/* There are lots of unallocated items left in this block. */ +pool->unallocateditems = pool->itemsperblock; +/* The stack of deallocated items is empty. */ +pool->deaditemstack = (VOID *) NULL; } /*****************************************************************************/ @@ -3280,11 +3416,11 @@ struct memorypool *pool; void pooldeinit( pool ) struct memorypool *pool; { - while ( pool->firstblock != (VOID **) NULL ) { - pool->nowblock = (VOID **) *( pool->firstblock ); - free( pool->firstblock ); - pool->firstblock = pool->nowblock; - } +while ( pool->firstblock != (VOID **) NULL ) { +pool->nowblock = (VOID **) *( pool->firstblock ); +free( pool->firstblock ); +pool->firstblock = pool->nowblock; +} } /*****************************************************************************/ @@ -3296,58 +3432,58 @@ struct memorypool *pool; VOID *poolalloc( pool ) struct memorypool *pool; { - VOID *newitem; - VOID **newblock; - unsigned long alignptr; - - /* First check the linked list of dead items. If the list is not */ - /* empty, allocate an item from the list rather than a fresh one. */ - if ( pool->deaditemstack != (VOID *) NULL ) { - newitem = pool->deaditemstack; /* Take first item in list. */ - pool->deaditemstack = *(VOID **) pool->deaditemstack; - } - else { - /* Check if there are any free items left in the current block. */ - if ( pool->unallocateditems == 0 ) { - /* Check if another block must be allocated. */ - if ( *( pool->nowblock ) == (VOID *) NULL ) { - /* Allocate a new block of items, pointed to by the previous block. */ - newblock = (VOID **) malloc( pool->itemsperblock * pool->itembytes - + sizeof( VOID * ) + pool->alignbytes ); - if ( newblock == (VOID **) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - *( pool->nowblock ) = (VOID *) newblock; - /* The next block pointer is NULL. */ - *newblock = (VOID *) NULL; - } - /* Move to the new block. */ - pool->nowblock = (VOID **) *( pool->nowblock ); - /* Find the first item in the block. */ - /* Increment by the size of (VOID *). */ - alignptr = (unsigned long) ( pool->nowblock + 1 ); - /* Align the item on an `alignbytes'-byte boundary. */ - pool->nextitem = (VOID *) - ( alignptr + (unsigned long) pool->alignbytes - - ( alignptr % (unsigned long) pool->alignbytes ) ); - /* There are lots of unallocated items left in this block. */ - pool->unallocateditems = pool->itemsperblock; - } - /* Allocate a new item. */ - newitem = pool->nextitem; - /* Advance `nextitem' pointer to next free item in block. */ - if ( pool->itemwordtype == POINTER ) { - pool->nextitem = (VOID *) ( (VOID **) pool->nextitem + pool->itemwords ); - } - else { - pool->nextitem = (VOID *) ( (REAL *) pool->nextitem + pool->itemwords ); - } - pool->unallocateditems--; - pool->maxitems++; - } - pool->items++; - return newitem; +VOID *newitem; +VOID **newblock; +unsigned long alignptr; + +/* First check the linked list of dead items. If the list is not */ +/* empty, allocate an item from the list rather than a fresh one. */ +if ( pool->deaditemstack != (VOID *) NULL ) { +newitem = pool->deaditemstack; /* Take first item in list. */ +pool->deaditemstack = *(VOID **) pool->deaditemstack; +} +else { +/* Check if there are any free items left in the current block. */ +if ( pool->unallocateditems == 0 ) { +/* Check if another block must be allocated. */ +if ( *( pool->nowblock ) == (VOID *) NULL ) { +/* Allocate a new block of items, pointed to by the previous block. */ +newblock = (VOID **) malloc( pool->itemsperblock * pool->itembytes ++ sizeof( VOID * ) + pool->alignbytes ); +if ( newblock == (VOID **) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +*( pool->nowblock ) = (VOID *) newblock; +/* The next block pointer is NULL. */ +*newblock = (VOID *) NULL; +} +/* Move to the new block. */ +pool->nowblock = (VOID **) *( pool->nowblock ); +/* Find the first item in the block. */ +/* Increment by the size of (VOID *). */ +alignptr = (unsigned long) ( pool->nowblock + 1 ); +/* Align the item on an `alignbytes'-byte boundary. */ +pool->nextitem = (VOID *) +( alignptr + (unsigned long) pool->alignbytes +- ( alignptr % (unsigned long) pool->alignbytes )); +/* There are lots of unallocated items left in this block. */ +pool->unallocateditems = pool->itemsperblock; +} +/* Allocate a new item. */ +newitem = pool->nextitem; +/* Advance `nextitem' pointer to next free item in block. */ +if ( pool->itemwordtype == POINTER ) { +pool->nextitem = (VOID *) ((VOID **) pool->nextitem + pool->itemwords ); +} +else { +pool->nextitem = (VOID *) ((REAL *) pool->nextitem + pool->itemwords ); +} +pool->unallocateditems--; +pool->maxitems++; +} +pool->items++; +return newitem; } /*****************************************************************************/ @@ -3362,10 +3498,10 @@ void pooldealloc( pool, dyingitem ) struct memorypool *pool; VOID *dyingitem; { - /* Push freshly killed item onto stack. */ - *( (VOID **) dyingitem ) = pool->deaditemstack; - pool->deaditemstack = dyingitem; - pool->items--; +/* Push freshly killed item onto stack. */ +*((VOID **) dyingitem ) = pool->deaditemstack; +pool->deaditemstack = dyingitem; +pool->items--; } /*****************************************************************************/ @@ -3379,18 +3515,18 @@ VOID *dyingitem; void traversalinit( pool ) struct memorypool *pool; { - unsigned long alignptr; - - /* Begin the traversal in the first block. */ - pool->pathblock = pool->firstblock; - /* Find the first item in the block. Increment by the size of (VOID *). */ - alignptr = (unsigned long) ( pool->pathblock + 1 ); - /* Align with item on an `alignbytes'-byte boundary. */ - pool->pathitem = (VOID *) - ( alignptr + (unsigned long) pool->alignbytes - - ( alignptr % (unsigned long) pool->alignbytes ) ); - /* Set the number of items left in the current block. */ - pool->pathitemsleft = pool->itemsperblock; +unsigned long alignptr; + +/* Begin the traversal in the first block. */ +pool->pathblock = pool->firstblock; +/* Find the first item in the block. Increment by the size of (VOID *). */ +alignptr = (unsigned long) ( pool->pathblock + 1 ); +/* Align with item on an `alignbytes'-byte boundary. */ +pool->pathitem = (VOID *) +( alignptr + (unsigned long) pool->alignbytes +- ( alignptr % (unsigned long) pool->alignbytes )); +/* Set the number of items left in the current block. */ +pool->pathitemsleft = pool->itemsperblock; } /*****************************************************************************/ @@ -3410,36 +3546,36 @@ struct memorypool *pool; VOID *traverse( pool ) struct memorypool *pool; { - VOID *newitem; - unsigned long alignptr; - - /* Stop upon exhausting the list of items. */ - if ( pool->pathitem == pool->nextitem ) { - return (VOID *) NULL; - } - /* Check whether any untraversed items remain in the current block. */ - if ( pool->pathitemsleft == 0 ) { - /* Find the next block. */ - pool->pathblock = (VOID **) *( pool->pathblock ); - /* Find the first item in the block. Increment by the size of (VOID *). */ - alignptr = (unsigned long) ( pool->pathblock + 1 ); - /* Align with item on an `alignbytes'-byte boundary. */ - pool->pathitem = (VOID *) - ( alignptr + (unsigned long) pool->alignbytes - - ( alignptr % (unsigned long) pool->alignbytes ) ); - /* Set the number of items left in the current block. */ - pool->pathitemsleft = pool->itemsperblock; - } - newitem = pool->pathitem; - /* Find the next item in the block. */ - if ( pool->itemwordtype == POINTER ) { - pool->pathitem = (VOID *) ( (VOID **) pool->pathitem + pool->itemwords ); - } - else { - pool->pathitem = (VOID *) ( (REAL *) pool->pathitem + pool->itemwords ); - } - pool->pathitemsleft--; - return newitem; +VOID *newitem; +unsigned long alignptr; + +/* Stop upon exhausting the list of items. */ +if ( pool->pathitem == pool->nextitem ) { +return (VOID *) NULL; +} +/* Check whether any untraversed items remain in the current block. */ +if ( pool->pathitemsleft == 0 ) { +/* Find the next block. */ +pool->pathblock = (VOID **) *( pool->pathblock ); +/* Find the first item in the block. Increment by the size of (VOID *). */ +alignptr = (unsigned long) ( pool->pathblock + 1 ); +/* Align with item on an `alignbytes'-byte boundary. */ +pool->pathitem = (VOID *) +( alignptr + (unsigned long) pool->alignbytes +- ( alignptr % (unsigned long) pool->alignbytes )); +/* Set the number of items left in the current block. */ +pool->pathitemsleft = pool->itemsperblock; +} +newitem = pool->pathitem; +/* Find the next item in the block. */ +if ( pool->itemwordtype == POINTER ) { +pool->pathitem = (VOID *) ((VOID **) pool->pathitem + pool->itemwords ); +} +else { +pool->pathitem = (VOID *) ((REAL *) pool->pathitem + pool->itemwords ); +} +pool->pathitemsleft--; +return newitem; } /*****************************************************************************/ @@ -3463,73 +3599,73 @@ void dummyinit( trianglewords, shellewords ) int trianglewords; int shellewords; { - unsigned long alignptr; - - /* `triwords' and `shwords' are used by the mesh manipulation primitives */ - /* to extract orientations of triangles and shell edges from pointers. */ - triwords = trianglewords; /* Initialize `triwords' once and for all. */ - shwords = shellewords; /* Initialize `shwords' once and for all. */ - - /* Set up `dummytri', the `triangle' that occupies "outer space". */ - dummytribase = (triangle *) malloc( triwords * sizeof( triangle ) - + triangles.alignbytes ); - if ( dummytribase == (triangle *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */ - alignptr = (unsigned long) dummytribase; - dummytri = (triangle *) - ( alignptr + (unsigned long) triangles.alignbytes - - ( alignptr % (unsigned long) triangles.alignbytes ) ); - /* Initialize the three adjoining triangles to be "outer space". These */ - /* will eventually be changed by various bonding operations, but their */ - /* values don't really matter, as long as they can legally be */ - /* dereferenced. */ - dummytri[0] = (triangle) dummytri; - dummytri[1] = (triangle) dummytri; - dummytri[2] = (triangle) dummytri; - /* Three NULL vertex points. */ - dummytri[3] = (triangle) NULL; - dummytri[4] = (triangle) NULL; - dummytri[5] = (triangle) NULL; - - if ( useshelles ) { - /* Set up `dummysh', the omnipresent "shell edge" pointed to by any */ - /* triangle side or shell edge end that isn't attached to a real shell */ - /* edge. */ - dummyshbase = (shelle *) malloc( shwords * sizeof( shelle ) - + shelles.alignbytes ); - if ( dummyshbase == (shelle *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - /* Align `dummysh' on a `shelles.alignbytes'-byte boundary. */ - alignptr = (unsigned long) dummyshbase; - dummysh = (shelle *) - ( alignptr + (unsigned long) shelles.alignbytes - - ( alignptr % (unsigned long) shelles.alignbytes ) ); - /* Initialize the two adjoining shell edges to be the omnipresent shell */ - /* edge. These will eventually be changed by various bonding */ - /* operations, but their values don't really matter, as long as they */ - /* can legally be dereferenced. */ - dummysh[0] = (shelle) dummysh; - dummysh[1] = (shelle) dummysh; - /* Two NULL vertex points. */ - dummysh[2] = (shelle) NULL; - dummysh[3] = (shelle) NULL; - /* Initialize the two adjoining triangles to be "outer space". */ - dummysh[4] = (shelle) dummytri; - dummysh[5] = (shelle) dummytri; - /* Set the boundary marker to zero. */ - *(int *) ( dummysh + 6 ) = 0; - - /* Initialize the three adjoining shell edges of `dummytri' to be */ - /* the omnipresent shell edge. */ - dummytri[6] = (triangle) dummysh; - dummytri[7] = (triangle) dummysh; - dummytri[8] = (triangle) dummysh; - } +unsigned long alignptr; + +/* `triwords' and `shwords' are used by the mesh manipulation primitives */ +/* to extract orientations of triangles and shell edges from pointers. */ +triwords = trianglewords; /* Initialize `triwords' once and for all. */ +shwords = shellewords; /* Initialize `shwords' once and for all. */ + +/* Set up `dummytri', the `triangle' that occupies "outer space". */ +dummytribase = (triangle *) malloc( triwords * sizeof( triangle ) ++ triangles.alignbytes ); +if ( dummytribase == (triangle *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +/* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */ +alignptr = (unsigned long) dummytribase; +dummytri = (triangle *) +( alignptr + (unsigned long) triangles.alignbytes +- ( alignptr % (unsigned long) triangles.alignbytes )); +/* Initialize the three adjoining triangles to be "outer space". These */ +/* will eventually be changed by various bonding operations, but their */ +/* values don't really matter, as long as they can legally be */ +/* dereferenced. */ +dummytri[0] = (triangle) dummytri; +dummytri[1] = (triangle) dummytri; +dummytri[2] = (triangle) dummytri; +/* Three NULL vertex points. */ +dummytri[3] = (triangle) NULL; +dummytri[4] = (triangle) NULL; +dummytri[5] = (triangle) NULL; + +if ( useshelles ) { +/* Set up `dummysh', the omnipresent "shell edge" pointed to by any */ +/* triangle side or shell edge end that isn't attached to a real shell */ +/* edge. */ +dummyshbase = (shelle *) malloc( shwords * sizeof( shelle ) ++ shelles.alignbytes ); +if ( dummyshbase == (shelle *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +/* Align `dummysh' on a `shelles.alignbytes'-byte boundary. */ +alignptr = (unsigned long) dummyshbase; +dummysh = (shelle *) +( alignptr + (unsigned long) shelles.alignbytes +- ( alignptr % (unsigned long) shelles.alignbytes )); +/* Initialize the two adjoining shell edges to be the omnipresent shell */ +/* edge. These will eventually be changed by various bonding */ +/* operations, but their values don't really matter, as long as they */ +/* can legally be dereferenced. */ +dummysh[0] = (shelle) dummysh; +dummysh[1] = (shelle) dummysh; +/* Two NULL vertex points. */ +dummysh[2] = (shelle) NULL; +dummysh[3] = (shelle) NULL; +/* Initialize the two adjoining triangles to be "outer space". */ +dummysh[4] = (shelle) dummytri; +dummysh[5] = (shelle) dummytri; +/* Set the boundary marker to zero. */ +*(int *) ( dummysh + 6 ) = 0; + +/* Initialize the three adjoining shell edges of `dummytri' to be */ +/* the omnipresent shell edge. */ +dummytri[6] = (triangle) dummysh; +dummytri[7] = (triangle) dummysh; +dummytri[8] = (triangle) dummysh; +} } /*****************************************************************************/ @@ -3543,22 +3679,22 @@ int shellewords; /*****************************************************************************/ void initializepointpool(){ - int pointsize; - - /* The index within each point at which the boundary marker is found. */ - /* Ensure the point marker is aligned to a sizeof(int)-byte address. */ - pointmarkindex = ( ( mesh_dim + nextras ) * sizeof( REAL ) + sizeof( int ) - 1 ) - / sizeof( int ); - pointsize = ( pointmarkindex + 1 ) * sizeof( int ); - if ( poly ) { - /* The index within each point at which a triangle pointer is found. */ - /* Ensure the pointer is aligned to a sizeof(triangle)-byte address. */ - point2triindex = ( pointsize + sizeof( triangle ) - 1 ) / sizeof( triangle ); - pointsize = ( point2triindex + 1 ) * sizeof( triangle ); - } - /* Initialize the pool of points. */ - poolinit( &points, pointsize, POINTPERBLOCK, - ( sizeof( REAL ) >= sizeof( triangle ) ) ? FLOATINGPOINT : POINTER, 0 ); +int pointsize; + +/* The index within each point at which the boundary marker is found. */ +/* Ensure the point marker is aligned to a sizeof(int)-byte address. */ +pointmarkindex = (( mesh_dim + nextras ) * sizeof( REAL ) + sizeof( int ) - 1 ) +/ sizeof( int ); +pointsize = ( pointmarkindex + 1 ) * sizeof( int ); +if ( poly ) { +/* The index within each point at which a triangle pointer is found. */ +/* Ensure the pointer is aligned to a sizeof(triangle)-byte address. */ +point2triindex = ( pointsize + sizeof( triangle ) - 1 ) / sizeof( triangle ); +pointsize = ( point2triindex + 1 ) * sizeof( triangle ); +} +/* Initialize the pool of points. */ +poolinit( &points, pointsize, POINTPERBLOCK, +( sizeof( REAL ) >= sizeof( triangle )) ? FLOATINGPOINT : POINTER, 0 ); } /*****************************************************************************/ @@ -3573,54 +3709,54 @@ void initializepointpool(){ /*****************************************************************************/ void initializetrisegpools(){ - int trisize; - - /* The index within each triangle at which the extra nodes (above three) */ - /* associated with high order elements are found. There are three */ - /* pointers to other triangles, three pointers to corners, and possibly */ - /* three pointers to shell edges before the extra nodes. */ - highorderindex = 6 + ( useshelles * 3 ); - /* The number of bytes occupied by a triangle. */ - trisize = ( ( order + 1 ) * ( order + 2 ) / 2 + ( highorderindex - 3 ) ) * - sizeof( triangle ); - /* The index within each triangle at which its attributes are found, */ - /* where the index is measured in REALs. */ - elemattribindex = ( trisize + sizeof( REAL ) - 1 ) / sizeof( REAL ); - /* The index within each triangle at which the maximum area constraint */ - /* is found, where the index is measured in REALs. Note that if the */ - /* `regionattrib' flag is set, an additional attribute will be added. */ - areaboundindex = elemattribindex + eextras + regionattrib; - /* If triangle attributes or an area bound are needed, increase the number */ - /* of bytes occupied by a triangle. */ - if ( vararea ) { - trisize = ( areaboundindex + 1 ) * sizeof( REAL ); - } - else if ( eextras + regionattrib > 0 ) { - trisize = areaboundindex * sizeof( REAL ); - } - /* If a Voronoi diagram or triangle neighbor graph is requested, make */ - /* sure there's room to store an integer index in each triangle. This */ - /* integer index can occupy the same space as the shell edges or */ - /* attributes or area constraint or extra nodes. */ - if ( ( voronoi || neighbors ) && - ( trisize < 6 * sizeof( triangle ) + sizeof( int ) ) ) { - trisize = 6 * sizeof( triangle ) + sizeof( int ); - } - /* Having determined the memory size of a triangle, initialize the pool. */ - poolinit( &triangles, trisize, TRIPERBLOCK, POINTER, 4 ); - - if ( useshelles ) { - /* Initialize the pool of shell edges. */ - poolinit( &shelles, 6 * sizeof( triangle ) + sizeof( int ), SHELLEPERBLOCK, - POINTER, 4 ); - - /* Initialize the "outer space" triangle and omnipresent shell edge. */ - dummyinit( triangles.itemwords, shelles.itemwords ); - } - else { - /* Initialize the "outer space" triangle. */ - dummyinit( triangles.itemwords, 0 ); - } +int trisize; + +/* The index within each triangle at which the extra nodes (above three) */ +/* associated with high order elements are found. There are three */ +/* pointers to other triangles, three pointers to corners, and possibly */ +/* three pointers to shell edges before the extra nodes. */ +highorderindex = 6 + ( useshelles * 3 ); +/* The number of bytes occupied by a triangle. */ +trisize = (( order + 1 ) * ( order + 2 ) / 2 + ( highorderindex - 3 )) * +sizeof( triangle ); +/* The index within each triangle at which its attributes are found, */ +/* where the index is measured in REALs. */ +elemattribindex = ( trisize + sizeof( REAL ) - 1 ) / sizeof( REAL ); +/* The index within each triangle at which the maximum area constraint */ +/* is found, where the index is measured in REALs. Note that if the */ +/* `regionattrib' flag is set, an additional attribute will be added. */ +areaboundindex = elemattribindex + eextras + regionattrib; +/* If triangle attributes or an area bound are needed, increase the number */ +/* of bytes occupied by a triangle. */ +if ( vararea ) { +trisize = ( areaboundindex + 1 ) * sizeof( REAL ); +} +else if ( eextras + regionattrib > 0 ) { +trisize = areaboundindex * sizeof( REAL ); +} +/* If a Voronoi diagram or triangle neighbor graph is requested, make */ +/* sure there's room to store an integer index in each triangle. This */ +/* integer index can occupy the same space as the shell edges or */ +/* attributes or area constraint or extra nodes. */ +if (( voronoi || neighbors ) && +( trisize < 6 * sizeof( triangle ) + sizeof( int ))) { +trisize = 6 * sizeof( triangle ) + sizeof( int ); +} +/* Having determined the memory size of a triangle, initialize the pool. */ +poolinit( &triangles, trisize, TRIPERBLOCK, POINTER, 4 ); + +if ( useshelles ) { +/* Initialize the pool of shell edges. */ +poolinit( &shelles, 6 * sizeof( triangle ) + sizeof( int ), SHELLEPERBLOCK, +POINTER, 4 ); + +/* Initialize the "outer space" triangle and omnipresent shell edge. */ +dummyinit( triangles.itemwords, shelles.itemwords ); +} +else { +/* Initialize the "outer space" triangle. */ +dummyinit( triangles.itemwords, 0 ); +} } /*****************************************************************************/ @@ -3632,12 +3768,12 @@ void initializetrisegpools(){ void triangledealloc( dyingtriangle ) triangle * dyingtriangle; { - /* Set triangle's vertices to NULL. This makes it possible to */ - /* detect dead triangles when traversing the list of all triangles. */ - dyingtriangle[3] = (triangle) NULL; - dyingtriangle[4] = (triangle) NULL; - dyingtriangle[5] = (triangle) NULL; - pooldealloc( &triangles, (VOID *) dyingtriangle ); +/* Set triangle's vertices to NULL. This makes it possible to */ +/* detect dead triangles when traversing the list of all triangles. */ +dyingtriangle[3] = (triangle) NULL; +dyingtriangle[4] = (triangle) NULL; +dyingtriangle[5] = (triangle) NULL; +pooldealloc( &triangles, (VOID *) dyingtriangle ); } /*****************************************************************************/ @@ -3647,15 +3783,15 @@ triangle * dyingtriangle; /*****************************************************************************/ triangle *triangletraverse(){ - triangle *newtriangle; +triangle *newtriangle; - do { - newtriangle = (triangle *) traverse( &triangles ); - if ( newtriangle == (triangle *) NULL ) { - return (triangle *) NULL; - } - } while ( newtriangle[3] == (triangle) NULL ); /* Skip dead ones. */ - return newtriangle; +do { +newtriangle = (triangle *) traverse( &triangles ); +if ( newtriangle == (triangle *) NULL ) { +return (triangle *) NULL; +} +} while ( newtriangle[3] == (triangle) NULL ); /* Skip dead ones. */ +return newtriangle; } /*****************************************************************************/ @@ -3667,11 +3803,11 @@ triangle *triangletraverse(){ void shelledealloc( dyingshelle ) shelle * dyingshelle; { - /* Set shell edge's vertices to NULL. This makes it possible to */ - /* detect dead shells when traversing the list of all shells. */ - dyingshelle[2] = (shelle) NULL; - dyingshelle[3] = (shelle) NULL; - pooldealloc( &shelles, (VOID *) dyingshelle ); +/* Set shell edge's vertices to NULL. This makes it possible to */ +/* detect dead shells when traversing the list of all shells. */ +dyingshelle[2] = (shelle) NULL; +dyingshelle[3] = (shelle) NULL; +pooldealloc( &shelles, (VOID *) dyingshelle ); } /*****************************************************************************/ @@ -3681,15 +3817,15 @@ shelle * dyingshelle; /*****************************************************************************/ shelle *shelletraverse(){ - shelle *newshelle; +shelle *newshelle; - do { - newshelle = (shelle *) traverse( &shelles ); - if ( newshelle == (shelle *) NULL ) { - return (shelle *) NULL; - } - } while ( newshelle[2] == (shelle) NULL ); /* Skip dead ones. */ - return newshelle; +do { +newshelle = (shelle *) traverse( &shelles ); +if ( newshelle == (shelle *) NULL ) { +return (shelle *) NULL; +} +} while ( newshelle[2] == (shelle) NULL ); /* Skip dead ones. */ +return newshelle; } /*****************************************************************************/ @@ -3701,10 +3837,10 @@ shelle *shelletraverse(){ void pointdealloc( dyingpoint ) point dyingpoint; { - /* Mark the point as dead. This makes it possible to detect dead points */ - /* when traversing the list of all points. */ - setpointmark( dyingpoint, DEADPOINT ); - pooldealloc( &points, (VOID *) dyingpoint ); +/* Mark the point as dead. This makes it possible to detect dead points */ +/* when traversing the list of all points. */ +setpointmark( dyingpoint, DEADPOINT ); +pooldealloc( &points, (VOID *) dyingpoint ); } /*****************************************************************************/ @@ -3714,15 +3850,15 @@ point dyingpoint; /*****************************************************************************/ point pointtraverse(){ - point newpoint; +point newpoint; - do { - newpoint = (point) traverse( &points ); - if ( newpoint == (point) NULL ) { - return (point) NULL; - } - } while ( pointmark( newpoint ) == DEADPOINT ); /* Skip dead ones. */ - return newpoint; +do { +newpoint = (point) traverse( &points ); +if ( newpoint == (point) NULL ) { +return (point) NULL; +} +} while ( pointmark( newpoint ) == DEADPOINT ); /* Skip dead ones. */ +return newpoint; } /*****************************************************************************/ @@ -3732,15 +3868,16 @@ point pointtraverse(){ /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void badsegmentdealloc( dyingseg ) struct edge *dyingseg; { - /* Set segment's orientation to -1. This makes it possible to */ - /* detect dead segments when traversing the list of all segments. */ - dyingseg->shorient = -1; - pooldealloc( &badsegments, (VOID *) dyingseg ); +/* Set segment's orientation to -1. This makes it possible to */ +/* detect dead segments when traversing the list of all segments. */ +dyingseg->shorient = -1; +pooldealloc( &badsegments, (VOID *) dyingseg ); } #endif /* not CDT_ONLY */ @@ -3751,18 +3888,19 @@ struct edge *dyingseg; /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY struct edge *badsegmenttraverse(){ - struct edge *newseg; +struct edge *newseg; - do { - newseg = (struct edge *) traverse( &badsegments ); - if ( newseg == (struct edge *) NULL ) { - return (struct edge *) NULL; - } - } while ( newseg->shorient == -1 ); /* Skip dead ones. */ - return newseg; +do { +newseg = (struct edge *) traverse( &badsegments ); +if ( newseg == (struct edge *) NULL ) { +return (struct edge *) NULL; +} +} while ( newseg->shorient == -1 ); /* Skip dead ones. */ +return newseg; } #endif /* not CDT_ONLY */ @@ -3782,27 +3920,27 @@ struct edge *badsegmenttraverse(){ point getpoint( number ) int number; { - VOID **getblock; - point foundpoint; - unsigned long alignptr; - int current; - - getblock = points.firstblock; - current = firstnumber; - /* Find the right block. */ - while ( current + points.itemsperblock <= number ) { - getblock = (VOID **) *getblock; - current += points.itemsperblock; - } - /* Now find the right point. */ - alignptr = (unsigned long) ( getblock + 1 ); - foundpoint = (point) ( alignptr + (unsigned long) points.alignbytes - - ( alignptr % (unsigned long) points.alignbytes ) ); - while ( current < number ) { - foundpoint += points.itemwords; - current++; - } - return foundpoint; +VOID **getblock; +point foundpoint; +unsigned long alignptr; +int current; + +getblock = points.firstblock; +current = firstnumber; +/* Find the right block. */ +while ( current + points.itemsperblock <= number ) { +getblock = (VOID **) *getblock; +current += points.itemsperblock; +} +/* Now find the right point. */ +alignptr = (unsigned long) ( getblock + 1 ); +foundpoint = (point) ( alignptr + (unsigned long) points.alignbytes +- ( alignptr % (unsigned long) points.alignbytes )); +while ( current < number ) { +foundpoint += points.itemwords; +current++; +} +return foundpoint; } /*****************************************************************************/ @@ -3812,20 +3950,21 @@ int number; /*****************************************************************************/ void triangledeinit(){ - pooldeinit( &triangles ); - free( dummytribase ); - if ( useshelles ) { - pooldeinit( &shelles ); - free( dummyshbase ); - } - pooldeinit( &points ); -#ifndef CDT_ONLY - if ( quality ) { - pooldeinit( &badsegments ); - if ( ( minangle > 0.0 ) || vararea || fixedarea ) { - pooldeinit( &badtriangles ); - } - } +pooldeinit( &triangles ); +free( dummytribase ); +if ( useshelles ) { +pooldeinit( &shelles ); +free( dummyshbase ); +} +pooldeinit( &points ); +#ifndef +CDT_ONLY +if ( quality ) { +pooldeinit( &badsegments ); +if (( minangle > 0.0 ) || vararea || fixedarea ) { +pooldeinit( &badtriangles ); +} +} #endif /* not CDT_ONLY */ } @@ -3846,32 +3985,32 @@ void triangledeinit(){ void maketriangle( newtriedge ) struct triedge *newtriedge; { - int i; - - newtriedge->tri = (triangle *) poolalloc( &triangles ); - /* Initialize the three adjoining triangles to be "outer space". */ - newtriedge->tri[0] = (triangle) dummytri; - newtriedge->tri[1] = (triangle) dummytri; - newtriedge->tri[2] = (triangle) dummytri; - /* Three NULL vertex points. */ - newtriedge->tri[3] = (triangle) NULL; - newtriedge->tri[4] = (triangle) NULL; - newtriedge->tri[5] = (triangle) NULL; - /* Initialize the three adjoining shell edges to be the omnipresent */ - /* shell edge. */ - if ( useshelles ) { - newtriedge->tri[6] = (triangle) dummysh; - newtriedge->tri[7] = (triangle) dummysh; - newtriedge->tri[8] = (triangle) dummysh; - } - for ( i = 0; i < eextras; i++ ) { - setelemattribute( *newtriedge, i, 0.0 ); - } - if ( vararea ) { - setareabound( *newtriedge, -1.0 ); - } - - newtriedge->orient = 0; +int i; + +newtriedge->tri = (triangle *) poolalloc( &triangles ); +/* Initialize the three adjoining triangles to be "outer space". */ +newtriedge->tri[0] = (triangle) dummytri; +newtriedge->tri[1] = (triangle) dummytri; +newtriedge->tri[2] = (triangle) dummytri; +/* Three NULL vertex points. */ +newtriedge->tri[3] = (triangle) NULL; +newtriedge->tri[4] = (triangle) NULL; +newtriedge->tri[5] = (triangle) NULL; +/* Initialize the three adjoining shell edges to be the omnipresent */ +/* shell edge. */ +if ( useshelles ) { +newtriedge->tri[6] = (triangle) dummysh; +newtriedge->tri[7] = (triangle) dummysh; +newtriedge->tri[8] = (triangle) dummysh; +} +for ( i = 0; i < eextras; i++ ) { +setelemattribute( *newtriedge, i, 0.0 ); +} +if ( vararea ) { +setareabound( *newtriedge, -1.0 ); +} + +newtriedge->orient = 0; } /*****************************************************************************/ @@ -3883,21 +4022,21 @@ struct triedge *newtriedge; void makeshelle( newedge ) struct edge *newedge; { - newedge->sh = (shelle *) poolalloc( &shelles ); - /* Initialize the two adjoining shell edges to be the omnipresent */ - /* shell edge. */ - newedge->sh[0] = (shelle) dummysh; - newedge->sh[1] = (shelle) dummysh; - /* Two NULL vertex points. */ - newedge->sh[2] = (shelle) NULL; - newedge->sh[3] = (shelle) NULL; - /* Initialize the two adjoining triangles to be "outer space". */ - newedge->sh[4] = (shelle) dummytri; - newedge->sh[5] = (shelle) dummytri; - /* Set the boundary marker to zero. */ - setmark( *newedge, 0 ); - - newedge->shorient = 0; +newedge->sh = (shelle *) poolalloc( &shelles ); +/* Initialize the two adjoining shell edges to be the omnipresent */ +/* shell edge. */ +newedge->sh[0] = (shelle) dummysh; +newedge->sh[1] = (shelle) dummysh; +/* Two NULL vertex points. */ +newedge->sh[2] = (shelle) NULL; +newedge->sh[3] = (shelle) NULL; +/* Initialize the two adjoining triangles to be "outer space". */ +newedge->sh[4] = (shelle) dummytri; +newedge->sh[5] = (shelle) dummytri; +/* Set the boundary marker to zero. */ +setmark( *newedge, 0 ); + +newedge->shorient = 0; } /** **/ @@ -3918,7 +4057,8 @@ struct edge *newedge; /* which is disastrously slow. A faster way on IEEE machines might be to */ /* mask the appropriate bit, but that's difficult to do in C. */ -#define Absolute( a ) ( ( a ) >= 0.0 ? ( a ) : -( a ) ) +#define +Absolute( a ) (( a ) >= 0.0 ? ( a ) : -( a )) /* #define Absolute(a) fabs(a) */ /* Many of the operations are broken up into two pieces, a main part that */ @@ -3934,95 +4074,111 @@ struct edge *newedge; /* The input parameter `x' (or the highest numbered `x_' parameter) must */ /* also be declared `INEXACT'. */ -#define Fast_Two_Sum_Tail( a, b, x, y ) \ - bvirt = x - a; \ - y = b - bvirt - -#define Fast_Two_Sum( a, b, x, y ) \ - x = (REAL) ( a + b ); \ - Fast_Two_Sum_Tail( a, b, x, y ) - -#define Two_Sum_Tail( a, b, x, y ) \ - bvirt = (REAL) ( x - a ); \ - avirt = x - bvirt; \ - bround = b - bvirt; \ - around = a - avirt; \ - y = around + bround - -#define Two_Sum( a, b, x, y ) \ - x = (REAL) ( a + b ); \ - Two_Sum_Tail( a, b, x, y ) - -#define Two_Diff_Tail( a, b, x, y ) \ - bvirt = (REAL) ( a - x ); \ - avirt = x + bvirt; \ - bround = bvirt - b; \ - around = a - avirt; \ - y = around + bround - -#define Two_Diff( a, b, x, y ) \ - x = (REAL) ( a - b ); \ - Two_Diff_Tail( a, b, x, y ) - -#define Split( a, ahi, alo ) \ - c = (REAL) ( splitter * a ); \ - abig = (REAL) ( c - a ); \ - ahi = (REAL)( c - abig ); \ - alo = (REAL)( a - ahi ) - -#define Two_Product_Tail( a, b, x, y ) \ - Split( a, ahi, alo ); \ - Split( b, bhi, blo ); \ - err1 = x - ( ahi * bhi ); \ - err2 = err1 - ( alo * bhi ); \ - err3 = err2 - ( ahi * blo ); \ - y = ( alo * blo ) - err3 - -#define Two_Product( a, b, x, y ) \ - x = (REAL) ( a * b ); \ - Two_Product_Tail( a, b, x, y ) +#define +Fast_Two_Sum_Tail( a, b, x, y ) \ + bvirt = x - a; \ + y = b - bvirt + +#define +Fast_Two_Sum( a, b, x, y ) \ + x = (REAL) ( a + b ); \ + Fast_Two_Sum_Tail( a, b, x, y ) + +#define +Two_Sum_Tail( a, b, x, y ) \ + bvirt = (REAL) ( x - a ); \ + avirt = x - bvirt; \ + bround = b - bvirt; \ + around = a - avirt; \ + y = around + bround + +#define +Two_Sum( a, b, x, y ) \ + x = (REAL) ( a + b ); \ + Two_Sum_Tail( a, b, x, y ) + +#define +Two_Diff_Tail( a, b, x, y ) \ + bvirt = (REAL) ( a - x ); \ + avirt = x + bvirt; \ + bround = bvirt - b; \ + around = a - avirt; \ + y = around + bround + +#define +Two_Diff( a, b, x, y ) \ + x = (REAL) ( a - b ); \ + Two_Diff_Tail( a, b, x, y ) + +#define +Split( a, ahi, alo ) \ + c = (REAL) ( splitter * a ); \ + abig = (REAL) ( c - a ); \ + ahi = (REAL)( c - abig ); \ + alo = (REAL)( a - ahi ) + +#define +Two_Product_Tail( a, b, x, y ) \ + Split( a, ahi, alo ); \ + Split( b, bhi, blo ); \ + err1 = x - ( ahi * bhi ); \ + err2 = err1 - ( alo * bhi ); \ + err3 = err2 - ( ahi * blo ); \ + y = ( alo * blo ) - err3 + +#define +Two_Product( a, b, x, y ) \ + x = (REAL) ( a * b ); \ + Two_Product_Tail( a, b, x, y ) /* Two_Product_Presplit() is Two_Product() where one of the inputs has */ /* already been split. Avoids redundant splitting. */ -#define Two_Product_Presplit( a, b, bhi, blo, x, y ) \ - x = (REAL) ( a * b ); \ - Split( a, ahi, alo ); \ - err1 = x - ( ahi * bhi ); \ - err2 = err1 - ( alo * bhi ); \ - err3 = err2 - ( ahi * blo ); \ - y = ( alo * blo ) - err3 +#define +Two_Product_Presplit( a, b, bhi, blo, x, y ) \ + x = (REAL) ( a * b ); \ + Split( a, ahi, alo ); \ + err1 = x - ( ahi * bhi ); \ + err2 = err1 - ( alo * bhi ); \ + err3 = err2 - ( ahi * blo ); \ + y = ( alo * blo ) - err3 /* Square() can be done more quickly than Two_Product(). */ -#define Square_Tail( a, x, y ) \ - Split( a, ahi, alo ); \ - err1 = x - ( ahi * ahi ); \ - err3 = err1 - ( ( ahi + ahi ) * alo ); \ - y = ( alo * alo ) - err3 +#define +Square_Tail( a, x, y ) \ + Split( a, ahi, alo ); \ + err1 = x - ( ahi * ahi ); \ + err3 = err1 - (( ahi + ahi ) * alo ); \ + y = ( alo * alo ) - err3 -#define Square( a, x, y ) \ - x = (REAL) ( a * a ); \ - Square_Tail( a, x, y ) +#define +Square( a, x, y ) \ + x = (REAL) ( a * a ); \ + Square_Tail( a, x, y ) /* Macros for summing expansions of various fixed lengths. These are all */ /* unrolled versions of Expansion_Sum(). */ -#define Two_One_Sum( a1, a0, b, x2, x1, x0 ) \ - Two_Sum( a0, b, _i, x0 ); \ - Two_Sum( a1, _i, x2, x1 ) +#define +Two_One_Sum( a1, a0, b, x2, x1, x0 ) \ + Two_Sum( a0, b, _i, x0 ); \ + Two_Sum( a1, _i, x2, x1 ) -#define Two_One_Diff( a1, a0, b, x2, x1, x0 ) \ - Two_Diff( a0, b, _i, x0 ); \ - Two_Sum( a1, _i, x2, x1 ) +#define +Two_One_Diff( a1, a0, b, x2, x1, x0 ) \ + Two_Diff( a0, b, _i, x0 ); \ + Two_Sum( a1, _i, x2, x1 ) -#define Two_Two_Sum( a1, a0, b1, b0, x3, x2, x1, x0 ) \ - Two_One_Sum( a1, a0, b0, _j, _0, x0 ); \ - Two_One_Sum( _j, _0, b1, x3, x2, x1 ) +#define +Two_Two_Sum( a1, a0, b1, b0, x3, x2, x1, x0 ) \ + Two_One_Sum( a1, a0, b0, _j, _0, x0 ); \ + Two_One_Sum( _j, _0, b1, x3, x2, x1 ) -#define Two_Two_Diff( a1, a0, b1, b0, x3, x2, x1, x0 ) \ - Two_One_Diff( a1, a0, b0, _j, _0, x0 ); \ - Two_One_Diff( _j, _0, b1, x3, x2, x1 ) +#define +Two_Two_Diff( a1, a0, b1, b0, x3, x2, x1, x0 ) \ + Two_One_Diff( a1, a0, b0, _j, _0, x0 ); \ + Two_One_Diff( _j, _0, b1, x3, x2, x1 ) /*****************************************************************************/ /* */ @@ -4044,41 +4200,41 @@ struct edge *newedge; /*****************************************************************************/ void exactinit(){ - REAL half; - REAL check, lastcheck; - int every_other; - - every_other = 1; - half = 0.5; - epsilon = 1.0; - splitter = 1.0; - check = 1.0; - /* Repeatedly divide `epsilon' by two until it is too small to add to */ - /* one without causing roundoff. (Also check if the sum is equal to */ - /* the previous sum, for machines that round up instead of using exact */ - /* rounding. Not that these routines will work on such machines anyway. */ - do { - lastcheck = check; - epsilon *= half; - if ( every_other ) { - splitter *= 2.0; - } - every_other = !every_other; - check = (REAL)( 1.0 + epsilon ); - } while ( ( check != 1.0 ) && ( check != lastcheck ) ); - splitter += 1.0; - if ( verbose > 1 ) { - printf( "Floating point roundoff is of magnitude %.17g\n", epsilon ); - printf( "Floating point splitter is %.17g\n", splitter ); - } - /* Error bounds for orientation and incircle tests. */ - resulterrbound = (REAL)( ( 3.0 + 8.0 * epsilon ) * epsilon ); - ccwerrboundA = (REAL)( ( 3.0 + 16.0 * epsilon ) * epsilon ); - ccwerrboundB = (REAL)( ( 2.0 + 12.0 * epsilon ) * epsilon ); - ccwerrboundC = (REAL)( ( 9.0 + 64.0 * epsilon ) * epsilon * epsilon ); - iccerrboundA = (REAL)( ( 10.0 + 96.0 * epsilon ) * epsilon ); - iccerrboundB = (REAL)( ( 4.0 + 48.0 * epsilon ) * epsilon ); - iccerrboundC = (REAL)( ( 44.0 + 576.0 * epsilon ) * epsilon * epsilon ); +REAL half; +REAL check, lastcheck; +int every_other; + +every_other = 1; +half = 0.5; +epsilon = 1.0; +splitter = 1.0; +check = 1.0; +/* Repeatedly divide `epsilon' by two until it is too small to add to */ +/* one without causing roundoff. (Also check if the sum is equal to */ +/* the previous sum, for machines that round up instead of using exact */ +/* rounding. Not that these routines will work on such machines anyway. */ +do { +lastcheck = check; +epsilon *= half; +if ( every_other ) { +splitter *= 2.0; +} +every_other = !every_other; +check = (REAL)( 1.0 + epsilon ); +} while (( check != 1.0 ) && ( check != lastcheck )); +splitter += 1.0; +if ( verbose > 1 ) { +printf( "Floating point roundoff is of magnitude %.17g\n", epsilon ); +printf( "Floating point splitter is %.17g\n", splitter ); +} +/* Error bounds for orientation and incircle tests. */ +resulterrbound = (REAL)(( 3.0 + 8.0 * epsilon ) * epsilon ); +ccwerrboundA = (REAL)(( 3.0 + 16.0 * epsilon ) * epsilon ); +ccwerrboundB = (REAL)(( 2.0 + 12.0 * epsilon ) * epsilon ); +ccwerrboundC = (REAL)(( 9.0 + 64.0 * epsilon ) * epsilon * epsilon ); +iccerrboundA = (REAL)(( 10.0 + 96.0 * epsilon ) * epsilon ); +iccerrboundB = (REAL)(( 4.0 + 48.0 * epsilon ) * epsilon ); +iccerrboundC = (REAL)(( 44.0 + 576.0 * epsilon ) * epsilon * epsilon ); } /*****************************************************************************/ @@ -4102,74 +4258,74 @@ int flen; REAL *f; REAL *h; { - REAL Q; - INEXACT REAL Qnew; - INEXACT REAL hh; - INEXACT REAL bvirt; - REAL avirt, bround, around; - int eindex, findex, hindex; - REAL enow, fnow; - - enow = e[0]; - fnow = f[0]; - eindex = findex = 0; - if ( ( fnow > enow ) == ( fnow > -enow ) ) { - Q = enow; - enow = e[++eindex]; - } - else { - Q = fnow; - fnow = f[++findex]; - } - hindex = 0; - if ( ( eindex < elen ) && ( findex < flen ) ) { - if ( ( fnow > enow ) == ( fnow > -enow ) ) { - Fast_Two_Sum( enow, Q, Qnew, hh ); - enow = e[++eindex]; - } - else { - Fast_Two_Sum( fnow, Q, Qnew, hh ); - fnow = f[++findex]; - } - Q = Qnew; - if ( hh != 0.0 ) { - h[hindex++] = hh; - } - while ( ( eindex < elen ) && ( findex < flen ) ) { - if ( ( fnow > enow ) == ( fnow > -enow ) ) { - Two_Sum( Q, enow, Qnew, hh ); - enow = e[++eindex]; - } - else { - Two_Sum( Q, fnow, Qnew, hh ); - fnow = f[++findex]; - } - Q = Qnew; - if ( hh != 0.0 ) { - h[hindex++] = hh; - } - } - } - while ( eindex < elen ) { - Two_Sum( Q, enow, Qnew, hh ); - enow = e[++eindex]; - Q = Qnew; - if ( hh != 0.0 ) { - h[hindex++] = hh; - } - } - while ( findex < flen ) { - Two_Sum( Q, fnow, Qnew, hh ); - fnow = f[++findex]; - Q = Qnew; - if ( hh != 0.0 ) { - h[hindex++] = hh; - } - } - if ( ( Q != 0.0 ) || ( hindex == 0 ) ) { - h[hindex++] = Q; - } - return hindex; +REAL Q; +INEXACT REAL Qnew; +INEXACT REAL hh; +INEXACT REAL bvirt; +REAL avirt, bround, around; +int eindex, findex, hindex; +REAL enow, fnow; + +enow = e[0]; +fnow = f[0]; +eindex = findex = 0; +if (( fnow > enow ) == ( fnow > -enow )) { +Q = enow; +enow = e[++eindex]; +} +else { +Q = fnow; +fnow = f[++findex]; +} +hindex = 0; +if (( eindex < elen ) && ( findex < flen )) { +if (( fnow > enow ) == ( fnow > -enow )) { +Fast_Two_Sum( enow, Q, Qnew, hh ); +enow = e[++eindex]; +} +else { +Fast_Two_Sum( fnow, Q, Qnew, hh ); +fnow = f[++findex]; +} +Q = Qnew; +if ( hh != 0.0 ) { +h[hindex++] = hh; +} +while (( eindex < elen ) && ( findex < flen )) { +if (( fnow > enow ) == ( fnow > -enow )) { +Two_Sum( Q, enow, Qnew, hh ); +enow = e[++eindex]; +} +else { +Two_Sum( Q, fnow, Qnew, hh ); +fnow = f[++findex]; +} +Q = Qnew; +if ( hh != 0.0 ) { +h[hindex++] = hh; +} +} +} +while ( eindex < elen ) { +Two_Sum( Q, enow, Qnew, hh ); +enow = e[++eindex]; +Q = Qnew; +if ( hh != 0.0 ) { +h[hindex++] = hh; +} +} +while ( findex < flen ) { +Two_Sum( Q, fnow, Qnew, hh ); +fnow = f[++findex]; +Q = Qnew; +if ( hh != 0.0 ) { +h[hindex++] = hh; +} +} +if (( Q != 0.0 ) || ( hindex == 0 )) { +h[hindex++] = Q; +} +return hindex; } /*****************************************************************************/ @@ -4193,41 +4349,41 @@ REAL *e; REAL b; REAL *h; { - INEXACT REAL Q, sum; - REAL hh; - INEXACT REAL product1; - REAL product0; - int eindex, hindex; - REAL enow; - INEXACT REAL bvirt; - REAL avirt, bround, around; - INEXACT REAL c; - INEXACT REAL abig; - REAL ahi, alo, bhi, blo; - REAL err1, err2, err3; - - Split( b, bhi, blo ); - Two_Product_Presplit( e[0], b, bhi, blo, Q, hh ); - hindex = 0; - if ( hh != 0 ) { - h[hindex++] = hh; - } - for ( eindex = 1; eindex < elen; eindex++ ) { - enow = e[eindex]; - Two_Product_Presplit( enow, b, bhi, blo, product1, product0 ); - Two_Sum( Q, product0, sum, hh ); - if ( hh != 0 ) { - h[hindex++] = hh; - } - Fast_Two_Sum( product1, sum, Q, hh ); - if ( hh != 0 ) { - h[hindex++] = hh; - } - } - if ( ( Q != 0.0 ) || ( hindex == 0 ) ) { - h[hindex++] = Q; - } - return hindex; +INEXACT REAL Q, sum; +REAL hh; +INEXACT REAL product1; +REAL product0; +int eindex, hindex; +REAL enow; +INEXACT REAL bvirt; +REAL avirt, bround, around; +INEXACT REAL c; +INEXACT REAL abig; +REAL ahi, alo, bhi, blo; +REAL err1, err2, err3; + +Split( b, bhi, blo ); +Two_Product_Presplit( e[0], b, bhi, blo, Q, hh ); +hindex = 0; +if ( hh != 0 ) { +h[hindex++] = hh; +} +for ( eindex = 1; eindex < elen; eindex++ ) { +enow = e[eindex]; +Two_Product_Presplit( enow, b, bhi, blo, product1, product0 ); +Two_Sum( Q, product0, sum, hh ); +if ( hh != 0 ) { +h[hindex++] = hh; +} +Fast_Two_Sum( product1, sum, Q, hh ); +if ( hh != 0 ) { +h[hindex++] = hh; +} +} +if (( Q != 0.0 ) || ( hindex == 0 )) { +h[hindex++] = Q; +} +return hindex; } /*****************************************************************************/ @@ -4242,14 +4398,14 @@ REAL estimate( elen, e ) int elen; REAL *e; { - REAL Q; - int eindex; +REAL Q; +int eindex; - Q = e[0]; - for ( eindex = 1; eindex < elen; eindex++ ) { - Q += e[eindex]; - } - return Q; +Q = e[0]; +for ( eindex = 1; eindex < elen; eindex++ ) { +Q += e[eindex]; +} +return Q; } /*****************************************************************************/ @@ -4278,82 +4434,82 @@ point pb; point pc; REAL detsum; { - INEXACT REAL acx, acy, bcx, bcy; - REAL acxtail, acytail, bcxtail, bcytail; - INEXACT REAL detleft, detright; - REAL detlefttail, detrighttail; - REAL det, errbound; - REAL B[4], C1[8], C2[12], D[16]; - INEXACT REAL B3; - int C1length, C2length, Dlength; - REAL u[4]; - INEXACT REAL u3; - INEXACT REAL s1, t1; - REAL s0, t0; - - INEXACT REAL bvirt; - REAL avirt, bround, around; - INEXACT REAL c; - INEXACT REAL abig; - REAL ahi, alo, bhi, blo; - REAL err1, err2, err3; - INEXACT REAL _i, _j; - REAL _0; - - acx = (REAL) ( pa[0] - pc[0] ); - bcx = (REAL) ( pb[0] - pc[0] ); - acy = (REAL) ( pa[1] - pc[1] ); - bcy = (REAL) ( pb[1] - pc[1] ); - - Two_Product( acx, bcy, detleft, detlefttail ); - Two_Product( acy, bcx, detright, detrighttail ); - - Two_Two_Diff( detleft, detlefttail, detright, detrighttail, - B3, B[2], B[1], B[0] ); - B[3] = B3; - - det = estimate( 4, B ); - errbound = (REAL)( ccwerrboundB * detsum ); - if ( ( det >= errbound ) || ( -det >= errbound ) ) { - return det; - } - - Two_Diff_Tail( pa[0], pc[0], acx, acxtail ); - Two_Diff_Tail( pb[0], pc[0], bcx, bcxtail ); - Two_Diff_Tail( pa[1], pc[1], acy, acytail ); - Two_Diff_Tail( pb[1], pc[1], bcy, bcytail ); - - if ( ( acxtail == 0.0 ) && ( acytail == 0.0 ) - && ( bcxtail == 0.0 ) && ( bcytail == 0.0 ) ) { - return det; - } - - errbound = (REAL)( ccwerrboundC * detsum + resulterrbound * Absolute( det ) ); - det += ( acx * bcytail + bcy * acxtail ) - - ( acy * bcxtail + bcx * acytail ); - if ( ( det >= errbound ) || ( -det >= errbound ) ) { - return det; - } - - Two_Product( acxtail, bcy, s1, s0 ); - Two_Product( acytail, bcx, t1, t0 ); - Two_Two_Diff( s1, s0, t1, t0, u3, u[2], u[1], u[0] ); - u[3] = u3; - C1length = fast_expansion_sum_zeroelim( 4, B, 4, u, C1 ); - - Two_Product( acx, bcytail, s1, s0 ); - Two_Product( acy, bcxtail, t1, t0 ); - Two_Two_Diff( s1, s0, t1, t0, u3, u[2], u[1], u[0] ); - u[3] = u3; - C2length = fast_expansion_sum_zeroelim( C1length, C1, 4, u, C2 ); - - Two_Product( acxtail, bcytail, s1, s0 ); - Two_Product( acytail, bcxtail, t1, t0 ); - Two_Two_Diff( s1, s0, t1, t0, u3, u[2], u[1], u[0] ); - u[3] = u3; - Dlength = fast_expansion_sum_zeroelim( C2length, C2, 4, u, D ); - - return( D[Dlength - 1] ); +INEXACT REAL acx, acy, bcx, bcy; +REAL acxtail, acytail, bcxtail, bcytail; +INEXACT REAL detleft, detright; +REAL detlefttail, detrighttail; +REAL det, errbound; +REAL B[4], C1[8], C2[12], D[16]; +INEXACT REAL B3; +int C1length, C2length, Dlength; +REAL u[4]; +INEXACT REAL u3; +INEXACT REAL s1, t1; +REAL s0, t0; + +INEXACT REAL bvirt; +REAL avirt, bround, around; +INEXACT REAL c; +INEXACT REAL abig; +REAL ahi, alo, bhi, blo; +REAL err1, err2, err3; +INEXACT REAL _i, _j; +REAL _0; + +acx = (REAL) ( pa[0] - pc[0] ); +bcx = (REAL) ( pb[0] - pc[0] ); +acy = (REAL) ( pa[1] - pc[1] ); +bcy = (REAL) ( pb[1] - pc[1] ); + +Two_Product( acx, bcy, detleft, detlefttail ); +Two_Product( acy, bcx, detright, detrighttail ); + +Two_Two_Diff( detleft, detlefttail, detright, detrighttail, +B3, B[2], B[1], B[0] ); +B[3] = B3; + +det = estimate( 4, B ); +errbound = (REAL)( ccwerrboundB * detsum ); +if (( det >= errbound ) || ( -det >= errbound )) { +return det; +} + +Two_Diff_Tail( pa[0], pc[0], acx, acxtail ); +Two_Diff_Tail( pb[0], pc[0], bcx, bcxtail ); +Two_Diff_Tail( pa[1], pc[1], acy, acytail ); +Two_Diff_Tail( pb[1], pc[1], bcy, bcytail ); + +if (( acxtail == 0.0 ) && ( acytail == 0.0 ) +&& ( bcxtail == 0.0 ) && ( bcytail == 0.0 )) { +return det; +} + +errbound = (REAL)( ccwerrboundC * detsum + resulterrbound * Absolute( det )); +det += ( acx * bcytail + bcy * acxtail ) +- ( acy * bcxtail + bcx * acytail ); +if (( det >= errbound ) || ( -det >= errbound )) { +return det; +} + +Two_Product( acxtail, bcy, s1, s0 ); +Two_Product( acytail, bcx, t1, t0 ); +Two_Two_Diff( s1, s0, t1, t0, u3, u[2], u[1], u[0] ); +u[3] = u3; +C1length = fast_expansion_sum_zeroelim( 4, B, 4, u, C1 ); + +Two_Product( acx, bcytail, s1, s0 ); +Two_Product( acy, bcxtail, t1, t0 ); +Two_Two_Diff( s1, s0, t1, t0, u3, u[2], u[1], u[0] ); +u[3] = u3; +C2length = fast_expansion_sum_zeroelim( C1length, C1, 4, u, C2 ); + +Two_Product( acxtail, bcytail, s1, s0 ); +Two_Product( acytail, bcxtail, t1, t0 ); +Two_Two_Diff( s1, s0, t1, t0, u3, u[2], u[1], u[0] ); +u[3] = u3; +Dlength = fast_expansion_sum_zeroelim( C2length, C2, 4, u, D ); + +return( D[Dlength - 1] ); } REAL counterclockwise( pa, pb, pc ) @@ -4361,45 +4517,45 @@ point pa; point pb; point pc; { - REAL detleft, detright, det; - REAL detsum, errbound; +REAL detleft, detright, det; +REAL detsum, errbound; - counterclockcount++; +counterclockcount++; - detleft = ( pa[0] - pc[0] ) * ( pb[1] - pc[1] ); - detright = ( pa[1] - pc[1] ) * ( pb[0] - pc[0] ); - det = detleft - detright; +detleft = ( pa[0] - pc[0] ) * ( pb[1] - pc[1] ); +detright = ( pa[1] - pc[1] ) * ( pb[0] - pc[0] ); +det = detleft - detright; - if ( noexact ) { - return det; - } +if ( noexact ) { +return det; +} - if ( detleft > 0.0 ) { - if ( detright <= 0.0 ) { - return det; - } - else { - detsum = detleft + detright; - } - } - else if ( detleft < 0.0 ) { - if ( detright >= 0.0 ) { - return det; - } - else { - detsum = -detleft - detright; - } - } - else { - return det; - } +if ( detleft > 0.0 ) { +if ( detright <= 0.0 ) { +return det; +} +else { +detsum = detleft + detright; +} +} +else if ( detleft < 0.0 ) { +if ( detright >= 0.0 ) { +return det; +} +else { +detsum = -detleft - detright; +} +} +else { +return det; +} - errbound = ccwerrboundA * detsum; - if ( ( det >= errbound ) || ( -det >= errbound ) ) { - return det; - } +errbound = ccwerrboundA * detsum; +if (( det >= errbound ) || ( -det >= errbound )) { +return det; +} - return counterclockwiseadapt( pa, pb, pc, detsum ); +return counterclockwiseadapt( pa, pb, pc, detsum ); } /*****************************************************************************/ @@ -4428,626 +4584,626 @@ point pc; point pd; REAL permanent; { - INEXACT REAL adx, bdx, cdx, ady, bdy, cdy; - REAL det, errbound; - - INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1; - REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0; - REAL bc[4], ca[4], ab[4]; - INEXACT REAL bc3, ca3, ab3; - REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32]; - int axbclen, axxbclen, aybclen, ayybclen, alen; - REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32]; - int bxcalen, bxxcalen, bycalen, byycalen, blen; - REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32]; - int cxablen, cxxablen, cyablen, cyyablen, clen; - REAL abdet[64]; - int ablen; - REAL fin1[1152], fin2[1152]; - REAL *finnow, *finother, *finswap; - int finlength; - - REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail; - INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1; - REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0; - REAL aa[4], bb[4], cc[4]; - INEXACT REAL aa3, bb3, cc3; - INEXACT REAL ti1, tj1; - REAL ti0, tj0; - REAL u[4], v[4]; - INEXACT REAL u3, v3; - REAL temp8[8], temp16a[16], temp16b[16], temp16c[16]; - REAL temp32a[32], temp32b[32], temp48[48], temp64[64]; - int temp8len, temp16alen, temp16blen, temp16clen; - int temp32alen, temp32blen, temp48len, temp64len; - REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8]; - int axtbblen, axtcclen, aytbblen, aytcclen; - REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8]; - int bxtaalen, bxtcclen, bytaalen, bytcclen; - REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8]; - int cxtaalen, cxtbblen, cytaalen, cytbblen; - REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8]; - int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen; - REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16]; - int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen; - REAL axtbctt[8], aytbctt[8], bxtcatt[8]; - REAL bytcatt[8], cxtabtt[8], cytabtt[8]; - int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen; - REAL abt[8], bct[8], cat[8]; - int abtlen, bctlen, catlen; - REAL abtt[4], bctt[4], catt[4]; - int abttlen, bcttlen, cattlen; - INEXACT REAL abtt3, bctt3, catt3; - REAL negate; - - INEXACT REAL bvirt; - REAL avirt, bround, around; - INEXACT REAL c; - INEXACT REAL abig; - REAL ahi, alo, bhi, blo; - REAL err1, err2, err3; - INEXACT REAL _i, _j; - REAL _0; - - adx = (REAL) ( pa[0] - pd[0] ); - bdx = (REAL) ( pb[0] - pd[0] ); - cdx = (REAL) ( pc[0] - pd[0] ); - ady = (REAL) ( pa[1] - pd[1] ); - bdy = (REAL) ( pb[1] - pd[1] ); - cdy = (REAL) ( pc[1] - pd[1] ); - - Two_Product( bdx, cdy, bdxcdy1, bdxcdy0 ); - Two_Product( cdx, bdy, cdxbdy1, cdxbdy0 ); - Two_Two_Diff( bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0] ); - bc[3] = bc3; - axbclen = scale_expansion_zeroelim( 4, bc, adx, axbc ); - axxbclen = scale_expansion_zeroelim( axbclen, axbc, adx, axxbc ); - aybclen = scale_expansion_zeroelim( 4, bc, ady, aybc ); - ayybclen = scale_expansion_zeroelim( aybclen, aybc, ady, ayybc ); - alen = fast_expansion_sum_zeroelim( axxbclen, axxbc, ayybclen, ayybc, adet ); - - Two_Product( cdx, ady, cdxady1, cdxady0 ); - Two_Product( adx, cdy, adxcdy1, adxcdy0 ); - Two_Two_Diff( cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0] ); - ca[3] = ca3; - bxcalen = scale_expansion_zeroelim( 4, ca, bdx, bxca ); - bxxcalen = scale_expansion_zeroelim( bxcalen, bxca, bdx, bxxca ); - bycalen = scale_expansion_zeroelim( 4, ca, bdy, byca ); - byycalen = scale_expansion_zeroelim( bycalen, byca, bdy, byyca ); - blen = fast_expansion_sum_zeroelim( bxxcalen, bxxca, byycalen, byyca, bdet ); - - Two_Product( adx, bdy, adxbdy1, adxbdy0 ); - Two_Product( bdx, ady, bdxady1, bdxady0 ); - Two_Two_Diff( adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0] ); - ab[3] = ab3; - cxablen = scale_expansion_zeroelim( 4, ab, cdx, cxab ); - cxxablen = scale_expansion_zeroelim( cxablen, cxab, cdx, cxxab ); - cyablen = scale_expansion_zeroelim( 4, ab, cdy, cyab ); - cyyablen = scale_expansion_zeroelim( cyablen, cyab, cdy, cyyab ); - clen = fast_expansion_sum_zeroelim( cxxablen, cxxab, cyyablen, cyyab, cdet ); - - ablen = fast_expansion_sum_zeroelim( alen, adet, blen, bdet, abdet ); - finlength = fast_expansion_sum_zeroelim( ablen, abdet, clen, cdet, fin1 ); - - det = estimate( finlength, fin1 ); - errbound = (REAL)( iccerrboundB * permanent ); - if ( ( det >= errbound ) || ( -det >= errbound ) ) { - return det; - } - - Two_Diff_Tail( pa[0], pd[0], adx, adxtail ); - Two_Diff_Tail( pa[1], pd[1], ady, adytail ); - Two_Diff_Tail( pb[0], pd[0], bdx, bdxtail ); - Two_Diff_Tail( pb[1], pd[1], bdy, bdytail ); - Two_Diff_Tail( pc[0], pd[0], cdx, cdxtail ); - Two_Diff_Tail( pc[1], pd[1], cdy, cdytail ); - if ( ( adxtail == 0.0 ) && ( bdxtail == 0.0 ) && ( cdxtail == 0.0 ) - && ( adytail == 0.0 ) && ( bdytail == 0.0 ) && ( cdytail == 0.0 ) ) { - return det; - } - - errbound = (REAL)( iccerrboundC * permanent + resulterrbound * Absolute( det ) ); - det += (REAL)( ( ( adx * adx + ady * ady ) * ( ( bdx * cdytail + cdy * bdxtail ) - - ( bdy * cdxtail + cdx * bdytail ) ) - + 2.0 * ( adx * adxtail + ady * adytail ) * ( bdx * cdy - bdy * cdx ) ) - + ( ( bdx * bdx + bdy * bdy ) * ( ( cdx * adytail + ady * cdxtail ) - - ( cdy * adxtail + adx * cdytail ) ) - + 2.0 * ( bdx * bdxtail + bdy * bdytail ) * ( cdx * ady - cdy * adx ) ) - + ( ( cdx * cdx + cdy * cdy ) * ( ( adx * bdytail + bdy * adxtail ) - - ( ady * bdxtail + bdx * adytail ) ) - + 2.0 * ( cdx * cdxtail + cdy * cdytail ) * ( adx * bdy - ady * bdx ) ) ); - if ( ( det >= errbound ) || ( -det >= errbound ) ) { - return det; - } - - finnow = fin1; - finother = fin2; - - if ( ( bdxtail != 0.0 ) || ( bdytail != 0.0 ) - || ( cdxtail != 0.0 ) || ( cdytail != 0.0 ) ) { - Square( adx, adxadx1, adxadx0 ); - Square( ady, adyady1, adyady0 ); - Two_Two_Sum( adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0] ); - aa[3] = aa3; - } - if ( ( cdxtail != 0.0 ) || ( cdytail != 0.0 ) - || ( adxtail != 0.0 ) || ( adytail != 0.0 ) ) { - Square( bdx, bdxbdx1, bdxbdx0 ); - Square( bdy, bdybdy1, bdybdy0 ); - Two_Two_Sum( bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0] ); - bb[3] = bb3; - } - if ( ( adxtail != 0.0 ) || ( adytail != 0.0 ) - || ( bdxtail != 0.0 ) || ( bdytail != 0.0 ) ) { - Square( cdx, cdxcdx1, cdxcdx0 ); - Square( cdy, cdycdy1, cdycdy0 ); - Two_Two_Sum( cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0] ); - cc[3] = cc3; - } - - if ( adxtail != 0.0 ) { - axtbclen = scale_expansion_zeroelim( 4, bc, adxtail, axtbc ); - temp16alen = scale_expansion_zeroelim( axtbclen, axtbc, 2.0 * adx, - temp16a ); - - axtcclen = scale_expansion_zeroelim( 4, cc, adxtail, axtcc ); - temp16blen = scale_expansion_zeroelim( axtcclen, axtcc, bdy, temp16b ); - - axtbblen = scale_expansion_zeroelim( 4, bb, adxtail, axtbb ); - temp16clen = scale_expansion_zeroelim( axtbblen, axtbb, -cdy, temp16c ); - - temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( adytail != 0.0 ) { - aytbclen = scale_expansion_zeroelim( 4, bc, adytail, aytbc ); - temp16alen = scale_expansion_zeroelim( aytbclen, aytbc, 2.0 * ady, - temp16a ); - - aytbblen = scale_expansion_zeroelim( 4, bb, adytail, aytbb ); - temp16blen = scale_expansion_zeroelim( aytbblen, aytbb, cdx, temp16b ); - - aytcclen = scale_expansion_zeroelim( 4, cc, adytail, aytcc ); - temp16clen = scale_expansion_zeroelim( aytcclen, aytcc, -bdx, temp16c ); - - temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( bdxtail != 0.0 ) { - bxtcalen = scale_expansion_zeroelim( 4, ca, bdxtail, bxtca ); - temp16alen = scale_expansion_zeroelim( bxtcalen, bxtca, 2.0 * bdx, - temp16a ); - - bxtaalen = scale_expansion_zeroelim( 4, aa, bdxtail, bxtaa ); - temp16blen = scale_expansion_zeroelim( bxtaalen, bxtaa, cdy, temp16b ); - - bxtcclen = scale_expansion_zeroelim( 4, cc, bdxtail, bxtcc ); - temp16clen = scale_expansion_zeroelim( bxtcclen, bxtcc, -ady, temp16c ); - - temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( bdytail != 0.0 ) { - bytcalen = scale_expansion_zeroelim( 4, ca, bdytail, bytca ); - temp16alen = scale_expansion_zeroelim( bytcalen, bytca, 2.0 * bdy, - temp16a ); - - bytcclen = scale_expansion_zeroelim( 4, cc, bdytail, bytcc ); - temp16blen = scale_expansion_zeroelim( bytcclen, bytcc, adx, temp16b ); - - bytaalen = scale_expansion_zeroelim( 4, aa, bdytail, bytaa ); - temp16clen = scale_expansion_zeroelim( bytaalen, bytaa, -cdx, temp16c ); - - temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( cdxtail != 0.0 ) { - cxtablen = scale_expansion_zeroelim( 4, ab, cdxtail, cxtab ); - temp16alen = scale_expansion_zeroelim( cxtablen, cxtab, 2.0 * cdx, - temp16a ); - - cxtbblen = scale_expansion_zeroelim( 4, bb, cdxtail, cxtbb ); - temp16blen = scale_expansion_zeroelim( cxtbblen, cxtbb, ady, temp16b ); - - cxtaalen = scale_expansion_zeroelim( 4, aa, cdxtail, cxtaa ); - temp16clen = scale_expansion_zeroelim( cxtaalen, cxtaa, -bdy, temp16c ); - - temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( cdytail != 0.0 ) { - cytablen = scale_expansion_zeroelim( 4, ab, cdytail, cytab ); - temp16alen = scale_expansion_zeroelim( cytablen, cytab, 2.0 * cdy, - temp16a ); - - cytaalen = scale_expansion_zeroelim( 4, aa, cdytail, cytaa ); - temp16blen = scale_expansion_zeroelim( cytaalen, cytaa, bdx, temp16b ); - - cytbblen = scale_expansion_zeroelim( 4, bb, cdytail, cytbb ); - temp16clen = scale_expansion_zeroelim( cytbblen, cytbb, -adx, temp16c ); - - temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - - if ( ( adxtail != 0.0 ) || ( adytail != 0.0 ) ) { - if ( ( bdxtail != 0.0 ) || ( bdytail != 0.0 ) - || ( cdxtail != 0.0 ) || ( cdytail != 0.0 ) ) { - Two_Product( bdxtail, cdy, ti1, ti0 ); - Two_Product( bdx, cdytail, tj1, tj0 ); - Two_Two_Sum( ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0] ); - u[3] = u3; - negate = -bdy; - Two_Product( cdxtail, negate, ti1, ti0 ); - negate = -bdytail; - Two_Product( cdx, negate, tj1, tj0 ); - Two_Two_Sum( ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0] ); - v[3] = v3; - bctlen = fast_expansion_sum_zeroelim( 4, u, 4, v, bct ); - - Two_Product( bdxtail, cdytail, ti1, ti0 ); - Two_Product( cdxtail, bdytail, tj1, tj0 ); - Two_Two_Diff( ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0] ); - bctt[3] = bctt3; - bcttlen = 4; - } - else { - bct[0] = 0.0; - bctlen = 1; - bctt[0] = 0.0; - bcttlen = 1; - } - - if ( adxtail != 0.0 ) { - temp16alen = scale_expansion_zeroelim( axtbclen, axtbc, adxtail, temp16a ); - axtbctlen = scale_expansion_zeroelim( bctlen, bct, adxtail, axtbct ); - temp32alen = scale_expansion_zeroelim( axtbctlen, axtbct, 2.0 * adx, - temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - if ( bdytail != 0.0 ) { - temp8len = scale_expansion_zeroelim( 4, cc, adxtail, temp8 ); - temp16alen = scale_expansion_zeroelim( temp8len, temp8, bdytail, - temp16a ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, - temp16a, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( cdytail != 0.0 ) { - temp8len = scale_expansion_zeroelim( 4, bb, -adxtail, temp8 ); - temp16alen = scale_expansion_zeroelim( temp8len, temp8, cdytail, - temp16a ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, - temp16a, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - - temp32alen = scale_expansion_zeroelim( axtbctlen, axtbct, adxtail, - temp32a ); - axtbcttlen = scale_expansion_zeroelim( bcttlen, bctt, adxtail, axtbctt ); - temp16alen = scale_expansion_zeroelim( axtbcttlen, axtbctt, 2.0 * adx, - temp16a ); - temp16blen = scale_expansion_zeroelim( axtbcttlen, axtbctt, adxtail, - temp16b ); - temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32b ); - temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, - temp32blen, temp32b, temp64 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, - temp64, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( adytail != 0.0 ) { - temp16alen = scale_expansion_zeroelim( aytbclen, aytbc, adytail, temp16a ); - aytbctlen = scale_expansion_zeroelim( bctlen, bct, adytail, aytbct ); - temp32alen = scale_expansion_zeroelim( aytbctlen, aytbct, 2.0 * ady, - temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - - - temp32alen = scale_expansion_zeroelim( aytbctlen, aytbct, adytail, - temp32a ); - aytbcttlen = scale_expansion_zeroelim( bcttlen, bctt, adytail, aytbctt ); - temp16alen = scale_expansion_zeroelim( aytbcttlen, aytbctt, 2.0 * ady, - temp16a ); - temp16blen = scale_expansion_zeroelim( aytbcttlen, aytbctt, adytail, - temp16b ); - temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32b ); - temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, - temp32blen, temp32b, temp64 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, - temp64, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - } - if ( ( bdxtail != 0.0 ) || ( bdytail != 0.0 ) ) { - if ( ( cdxtail != 0.0 ) || ( cdytail != 0.0 ) - || ( adxtail != 0.0 ) || ( adytail != 0.0 ) ) { - Two_Product( cdxtail, ady, ti1, ti0 ); - Two_Product( cdx, adytail, tj1, tj0 ); - Two_Two_Sum( ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0] ); - u[3] = u3; - negate = -cdy; - Two_Product( adxtail, negate, ti1, ti0 ); - negate = -cdytail; - Two_Product( adx, negate, tj1, tj0 ); - Two_Two_Sum( ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0] ); - v[3] = v3; - catlen = fast_expansion_sum_zeroelim( 4, u, 4, v, cat ); - - Two_Product( cdxtail, adytail, ti1, ti0 ); - Two_Product( adxtail, cdytail, tj1, tj0 ); - Two_Two_Diff( ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0] ); - catt[3] = catt3; - cattlen = 4; - } - else { - cat[0] = 0.0; - catlen = 1; - catt[0] = 0.0; - cattlen = 1; - } - - if ( bdxtail != 0.0 ) { - temp16alen = scale_expansion_zeroelim( bxtcalen, bxtca, bdxtail, temp16a ); - bxtcatlen = scale_expansion_zeroelim( catlen, cat, bdxtail, bxtcat ); - temp32alen = scale_expansion_zeroelim( bxtcatlen, bxtcat, 2.0 * bdx, - temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - if ( cdytail != 0.0 ) { - temp8len = scale_expansion_zeroelim( 4, aa, bdxtail, temp8 ); - temp16alen = scale_expansion_zeroelim( temp8len, temp8, cdytail, - temp16a ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, - temp16a, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( adytail != 0.0 ) { - temp8len = scale_expansion_zeroelim( 4, cc, -bdxtail, temp8 ); - temp16alen = scale_expansion_zeroelim( temp8len, temp8, adytail, - temp16a ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, - temp16a, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - - temp32alen = scale_expansion_zeroelim( bxtcatlen, bxtcat, bdxtail, - temp32a ); - bxtcattlen = scale_expansion_zeroelim( cattlen, catt, bdxtail, bxtcatt ); - temp16alen = scale_expansion_zeroelim( bxtcattlen, bxtcatt, 2.0 * bdx, - temp16a ); - temp16blen = scale_expansion_zeroelim( bxtcattlen, bxtcatt, bdxtail, - temp16b ); - temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32b ); - temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, - temp32blen, temp32b, temp64 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, - temp64, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( bdytail != 0.0 ) { - temp16alen = scale_expansion_zeroelim( bytcalen, bytca, bdytail, temp16a ); - bytcatlen = scale_expansion_zeroelim( catlen, cat, bdytail, bytcat ); - temp32alen = scale_expansion_zeroelim( bytcatlen, bytcat, 2.0 * bdy, - temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - - - temp32alen = scale_expansion_zeroelim( bytcatlen, bytcat, bdytail, - temp32a ); - bytcattlen = scale_expansion_zeroelim( cattlen, catt, bdytail, bytcatt ); - temp16alen = scale_expansion_zeroelim( bytcattlen, bytcatt, 2.0 * bdy, - temp16a ); - temp16blen = scale_expansion_zeroelim( bytcattlen, bytcatt, bdytail, - temp16b ); - temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32b ); - temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, - temp32blen, temp32b, temp64 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, - temp64, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - } - if ( ( cdxtail != 0.0 ) || ( cdytail != 0.0 ) ) { - if ( ( adxtail != 0.0 ) || ( adytail != 0.0 ) - || ( bdxtail != 0.0 ) || ( bdytail != 0.0 ) ) { - Two_Product( adxtail, bdy, ti1, ti0 ); - Two_Product( adx, bdytail, tj1, tj0 ); - Two_Two_Sum( ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0] ); - u[3] = u3; - negate = -ady; - Two_Product( bdxtail, negate, ti1, ti0 ); - negate = -adytail; - Two_Product( bdx, negate, tj1, tj0 ); - Two_Two_Sum( ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0] ); - v[3] = v3; - abtlen = fast_expansion_sum_zeroelim( 4, u, 4, v, abt ); - - Two_Product( adxtail, bdytail, ti1, ti0 ); - Two_Product( bdxtail, adytail, tj1, tj0 ); - Two_Two_Diff( ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0] ); - abtt[3] = abtt3; - abttlen = 4; - } - else { - abt[0] = 0.0; - abtlen = 1; - abtt[0] = 0.0; - abttlen = 1; - } - - if ( cdxtail != 0.0 ) { - temp16alen = scale_expansion_zeroelim( cxtablen, cxtab, cdxtail, temp16a ); - cxtabtlen = scale_expansion_zeroelim( abtlen, abt, cdxtail, cxtabt ); - temp32alen = scale_expansion_zeroelim( cxtabtlen, cxtabt, 2.0 * cdx, - temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - if ( adytail != 0.0 ) { - temp8len = scale_expansion_zeroelim( 4, bb, cdxtail, temp8 ); - temp16alen = scale_expansion_zeroelim( temp8len, temp8, adytail, - temp16a ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, - temp16a, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( bdytail != 0.0 ) { - temp8len = scale_expansion_zeroelim( 4, aa, -cdxtail, temp8 ); - temp16alen = scale_expansion_zeroelim( temp8len, temp8, bdytail, - temp16a ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, - temp16a, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - - temp32alen = scale_expansion_zeroelim( cxtabtlen, cxtabt, cdxtail, - temp32a ); - cxtabttlen = scale_expansion_zeroelim( abttlen, abtt, cdxtail, cxtabtt ); - temp16alen = scale_expansion_zeroelim( cxtabttlen, cxtabtt, 2.0 * cdx, - temp16a ); - temp16blen = scale_expansion_zeroelim( cxtabttlen, cxtabtt, cdxtail, - temp16b ); - temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32b ); - temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, - temp32blen, temp32b, temp64 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, - temp64, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - if ( cdytail != 0.0 ) { - temp16alen = scale_expansion_zeroelim( cytablen, cytab, cdytail, temp16a ); - cytabtlen = scale_expansion_zeroelim( abtlen, abt, cdytail, cytabt ); - temp32alen = scale_expansion_zeroelim( cytabtlen, cytabt, 2.0 * cdy, - temp32a ); - temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp32alen, temp32a, temp48 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, - temp48, finother ); - finswap = finnow; finnow = finother; finother = finswap; - - - temp32alen = scale_expansion_zeroelim( cytabtlen, cytabt, cdytail, - temp32a ); - cytabttlen = scale_expansion_zeroelim( abttlen, abtt, cdytail, cytabtt ); - temp16alen = scale_expansion_zeroelim( cytabttlen, cytabtt, 2.0 * cdy, - temp16a ); - temp16blen = scale_expansion_zeroelim( cytabttlen, cytabtt, cdytail, - temp16b ); - temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, - temp16blen, temp16b, temp32b ); - temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, - temp32blen, temp32b, temp64 ); - finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, - temp64, finother ); - finswap = finnow; finnow = finother; finother = finswap; - } - } - - return finnow[finlength - 1]; +INEXACT REAL adx, bdx, cdx, ady, bdy, cdy; +REAL det, errbound; + +INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1; +REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0; +REAL bc[4], ca[4], ab[4]; +INEXACT REAL bc3, ca3, ab3; +REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32]; +int axbclen, axxbclen, aybclen, ayybclen, alen; +REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32]; +int bxcalen, bxxcalen, bycalen, byycalen, blen; +REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32]; +int cxablen, cxxablen, cyablen, cyyablen, clen; +REAL abdet[64]; +int ablen; +REAL fin1[1152], fin2[1152]; +REAL *finnow, *finother, *finswap; +int finlength; + +REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail; +INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1; +REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0; +REAL aa[4], bb[4], cc[4]; +INEXACT REAL aa3, bb3, cc3; +INEXACT REAL ti1, tj1; +REAL ti0, tj0; +REAL u[4], v[4]; +INEXACT REAL u3, v3; +REAL temp8[8], temp16a[16], temp16b[16], temp16c[16]; +REAL temp32a[32], temp32b[32], temp48[48], temp64[64]; +int temp8len, temp16alen, temp16blen, temp16clen; +int temp32alen, temp32blen, temp48len, temp64len; +REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8]; +int axtbblen, axtcclen, aytbblen, aytcclen; +REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8]; +int bxtaalen, bxtcclen, bytaalen, bytcclen; +REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8]; +int cxtaalen, cxtbblen, cytaalen, cytbblen; +REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8]; +int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen; +REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16]; +int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen; +REAL axtbctt[8], aytbctt[8], bxtcatt[8]; +REAL bytcatt[8], cxtabtt[8], cytabtt[8]; +int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen; +REAL abt[8], bct[8], cat[8]; +int abtlen, bctlen, catlen; +REAL abtt[4], bctt[4], catt[4]; +int abttlen, bcttlen, cattlen; +INEXACT REAL abtt3, bctt3, catt3; +REAL negate; + +INEXACT REAL bvirt; +REAL avirt, bround, around; +INEXACT REAL c; +INEXACT REAL abig; +REAL ahi, alo, bhi, blo; +REAL err1, err2, err3; +INEXACT REAL _i, _j; +REAL _0; + +adx = (REAL) ( pa[0] - pd[0] ); +bdx = (REAL) ( pb[0] - pd[0] ); +cdx = (REAL) ( pc[0] - pd[0] ); +ady = (REAL) ( pa[1] - pd[1] ); +bdy = (REAL) ( pb[1] - pd[1] ); +cdy = (REAL) ( pc[1] - pd[1] ); + +Two_Product( bdx, cdy, bdxcdy1, bdxcdy0 ); +Two_Product( cdx, bdy, cdxbdy1, cdxbdy0 ); +Two_Two_Diff( bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0] ); +bc[3] = bc3; +axbclen = scale_expansion_zeroelim( 4, bc, adx, axbc ); +axxbclen = scale_expansion_zeroelim( axbclen, axbc, adx, axxbc ); +aybclen = scale_expansion_zeroelim( 4, bc, ady, aybc ); +ayybclen = scale_expansion_zeroelim( aybclen, aybc, ady, ayybc ); +alen = fast_expansion_sum_zeroelim( axxbclen, axxbc, ayybclen, ayybc, adet ); + +Two_Product( cdx, ady, cdxady1, cdxady0 ); +Two_Product( adx, cdy, adxcdy1, adxcdy0 ); +Two_Two_Diff( cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0] ); +ca[3] = ca3; +bxcalen = scale_expansion_zeroelim( 4, ca, bdx, bxca ); +bxxcalen = scale_expansion_zeroelim( bxcalen, bxca, bdx, bxxca ); +bycalen = scale_expansion_zeroelim( 4, ca, bdy, byca ); +byycalen = scale_expansion_zeroelim( bycalen, byca, bdy, byyca ); +blen = fast_expansion_sum_zeroelim( bxxcalen, bxxca, byycalen, byyca, bdet ); + +Two_Product( adx, bdy, adxbdy1, adxbdy0 ); +Two_Product( bdx, ady, bdxady1, bdxady0 ); +Two_Two_Diff( adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0] ); +ab[3] = ab3; +cxablen = scale_expansion_zeroelim( 4, ab, cdx, cxab ); +cxxablen = scale_expansion_zeroelim( cxablen, cxab, cdx, cxxab ); +cyablen = scale_expansion_zeroelim( 4, ab, cdy, cyab ); +cyyablen = scale_expansion_zeroelim( cyablen, cyab, cdy, cyyab ); +clen = fast_expansion_sum_zeroelim( cxxablen, cxxab, cyyablen, cyyab, cdet ); + +ablen = fast_expansion_sum_zeroelim( alen, adet, blen, bdet, abdet ); +finlength = fast_expansion_sum_zeroelim( ablen, abdet, clen, cdet, fin1 ); + +det = estimate( finlength, fin1 ); +errbound = (REAL)( iccerrboundB * permanent ); +if (( det >= errbound ) || ( -det >= errbound )) { +return det; } -REAL incircle( pa, pb, pc, pd ) -point pa; -point pb; -point pc; -point pd; -{ - REAL adx, bdx, cdx, ady, bdy, cdy; - REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady; - REAL alift, blift, clift; - REAL det; - REAL permanent, errbound; +Two_Diff_Tail( pa[0], pd[0], adx, adxtail ); +Two_Diff_Tail( pa[1], pd[1], ady, adytail ); +Two_Diff_Tail( pb[0], pd[0], bdx, bdxtail ); +Two_Diff_Tail( pb[1], pd[1], bdy, bdytail ); +Two_Diff_Tail( pc[0], pd[0], cdx, cdxtail ); +Two_Diff_Tail( pc[1], pd[1], cdy, cdytail ); +if (( adxtail == 0.0 ) && ( bdxtail == 0.0 ) && ( cdxtail == 0.0 ) +&& ( adytail == 0.0 ) && ( bdytail == 0.0 ) && ( cdytail == 0.0 )) { +return det; +} + +errbound = (REAL)( iccerrboundC * permanent + resulterrbound * Absolute( det )); +det += (REAL)((( adx * adx + ady * ady ) * (( bdx * cdytail + cdy * bdxtail ) +- ( bdy * cdxtail + cdx * bdytail )) ++ 2.0 * ( adx * adxtail + ady * adytail ) * ( bdx * cdy - bdy * cdx )) ++ (( bdx * bdx + bdy * bdy ) * (( cdx * adytail + ady * cdxtail ) +- ( cdy * adxtail + adx * cdytail )) ++ 2.0 * ( bdx * bdxtail + bdy * bdytail ) * ( cdx * ady - cdy * adx )) ++ (( cdx * cdx + cdy * cdy ) * (( adx * bdytail + bdy * adxtail ) +- ( ady * bdxtail + bdx * adytail )) ++ 2.0 * ( cdx * cdxtail + cdy * cdytail ) * ( adx * bdy - ady * bdx ))); +if (( det >= errbound ) || ( -det >= errbound )) { +return det; +} + +finnow = fin1; +finother = fin2; + +if (( bdxtail != 0.0 ) || ( bdytail != 0.0 ) +|| ( cdxtail != 0.0 ) || ( cdytail != 0.0 )) { +Square( adx, adxadx1, adxadx0 ); +Square( ady, adyady1, adyady0 ); +Two_Two_Sum( adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0] ); +aa[3] = aa3; +} +if (( cdxtail != 0.0 ) || ( cdytail != 0.0 ) +|| ( adxtail != 0.0 ) || ( adytail != 0.0 )) { +Square( bdx, bdxbdx1, bdxbdx0 ); +Square( bdy, bdybdy1, bdybdy0 ); +Two_Two_Sum( bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0] ); +bb[3] = bb3; +} +if (( adxtail != 0.0 ) || ( adytail != 0.0 ) +|| ( bdxtail != 0.0 ) || ( bdytail != 0.0 )) { +Square( cdx, cdxcdx1, cdxcdx0 ); +Square( cdy, cdycdy1, cdycdy0 ); +Two_Two_Sum( cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0] ); +cc[3] = cc3; +} + +if ( adxtail != 0.0 ) { +axtbclen = scale_expansion_zeroelim( 4, bc, adxtail, axtbc ); +temp16alen = scale_expansion_zeroelim( axtbclen, axtbc, 2.0 * adx, +temp16a ); + +axtcclen = scale_expansion_zeroelim( 4, cc, adxtail, axtcc ); +temp16blen = scale_expansion_zeroelim( axtcclen, axtcc, bdy, temp16b ); + +axtbblen = scale_expansion_zeroelim( 4, bb, adxtail, axtbb ); +temp16clen = scale_expansion_zeroelim( axtbblen, axtbb, -cdy, temp16c ); + +temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( adytail != 0.0 ) { +aytbclen = scale_expansion_zeroelim( 4, bc, adytail, aytbc ); +temp16alen = scale_expansion_zeroelim( aytbclen, aytbc, 2.0 * ady, +temp16a ); + +aytbblen = scale_expansion_zeroelim( 4, bb, adytail, aytbb ); +temp16blen = scale_expansion_zeroelim( aytbblen, aytbb, cdx, temp16b ); + +aytcclen = scale_expansion_zeroelim( 4, cc, adytail, aytcc ); +temp16clen = scale_expansion_zeroelim( aytcclen, aytcc, -bdx, temp16c ); + +temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( bdxtail != 0.0 ) { +bxtcalen = scale_expansion_zeroelim( 4, ca, bdxtail, bxtca ); +temp16alen = scale_expansion_zeroelim( bxtcalen, bxtca, 2.0 * bdx, +temp16a ); + +bxtaalen = scale_expansion_zeroelim( 4, aa, bdxtail, bxtaa ); +temp16blen = scale_expansion_zeroelim( bxtaalen, bxtaa, cdy, temp16b ); + +bxtcclen = scale_expansion_zeroelim( 4, cc, bdxtail, bxtcc ); +temp16clen = scale_expansion_zeroelim( bxtcclen, bxtcc, -ady, temp16c ); + +temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( bdytail != 0.0 ) { +bytcalen = scale_expansion_zeroelim( 4, ca, bdytail, bytca ); +temp16alen = scale_expansion_zeroelim( bytcalen, bytca, 2.0 * bdy, +temp16a ); + +bytcclen = scale_expansion_zeroelim( 4, cc, bdytail, bytcc ); +temp16blen = scale_expansion_zeroelim( bytcclen, bytcc, adx, temp16b ); + +bytaalen = scale_expansion_zeroelim( 4, aa, bdytail, bytaa ); +temp16clen = scale_expansion_zeroelim( bytaalen, bytaa, -cdx, temp16c ); + +temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( cdxtail != 0.0 ) { +cxtablen = scale_expansion_zeroelim( 4, ab, cdxtail, cxtab ); +temp16alen = scale_expansion_zeroelim( cxtablen, cxtab, 2.0 * cdx, +temp16a ); + +cxtbblen = scale_expansion_zeroelim( 4, bb, cdxtail, cxtbb ); +temp16blen = scale_expansion_zeroelim( cxtbblen, cxtbb, ady, temp16b ); + +cxtaalen = scale_expansion_zeroelim( 4, aa, cdxtail, cxtaa ); +temp16clen = scale_expansion_zeroelim( cxtaalen, cxtaa, -bdy, temp16c ); + +temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( cdytail != 0.0 ) { +cytablen = scale_expansion_zeroelim( 4, ab, cdytail, cytab ); +temp16alen = scale_expansion_zeroelim( cytablen, cytab, 2.0 * cdy, +temp16a ); + +cytaalen = scale_expansion_zeroelim( 4, aa, cdytail, cytaa ); +temp16blen = scale_expansion_zeroelim( cytaalen, cytaa, bdx, temp16b ); + +cytbblen = scale_expansion_zeroelim( 4, bb, cdytail, cytbb ); +temp16clen = scale_expansion_zeroelim( cytbblen, cytbb, -adx, temp16c ); + +temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} + +if (( adxtail != 0.0 ) || ( adytail != 0.0 )) { +if (( bdxtail != 0.0 ) || ( bdytail != 0.0 ) +|| ( cdxtail != 0.0 ) || ( cdytail != 0.0 )) { +Two_Product( bdxtail, cdy, ti1, ti0 ); +Two_Product( bdx, cdytail, tj1, tj0 ); +Two_Two_Sum( ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0] ); +u[3] = u3; +negate = -bdy; +Two_Product( cdxtail, negate, ti1, ti0 ); +negate = -bdytail; +Two_Product( cdx, negate, tj1, tj0 ); +Two_Two_Sum( ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0] ); +v[3] = v3; +bctlen = fast_expansion_sum_zeroelim( 4, u, 4, v, bct ); + +Two_Product( bdxtail, cdytail, ti1, ti0 ); +Two_Product( cdxtail, bdytail, tj1, tj0 ); +Two_Two_Diff( ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0] ); +bctt[3] = bctt3; +bcttlen = 4; +} +else { +bct[0] = 0.0; +bctlen = 1; +bctt[0] = 0.0; +bcttlen = 1; +} + +if ( adxtail != 0.0 ) { +temp16alen = scale_expansion_zeroelim( axtbclen, axtbc, adxtail, temp16a ); +axtbctlen = scale_expansion_zeroelim( bctlen, bct, adxtail, axtbct ); +temp32alen = scale_expansion_zeroelim( axtbctlen, axtbct, 2.0 * adx, +temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; +if ( bdytail != 0.0 ) { +temp8len = scale_expansion_zeroelim( 4, cc, adxtail, temp8 ); +temp16alen = scale_expansion_zeroelim( temp8len, temp8, bdytail, +temp16a ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, +temp16a, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( cdytail != 0.0 ) { +temp8len = scale_expansion_zeroelim( 4, bb, -adxtail, temp8 ); +temp16alen = scale_expansion_zeroelim( temp8len, temp8, cdytail, +temp16a ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, +temp16a, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} - incirclecount++; +temp32alen = scale_expansion_zeroelim( axtbctlen, axtbct, adxtail, +temp32a ); +axtbcttlen = scale_expansion_zeroelim( bcttlen, bctt, adxtail, axtbctt ); +temp16alen = scale_expansion_zeroelim( axtbcttlen, axtbctt, 2.0 * adx, +temp16a ); +temp16blen = scale_expansion_zeroelim( axtbcttlen, axtbctt, adxtail, +temp16b ); +temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32b ); +temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, +temp32blen, temp32b, temp64 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, +temp64, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( adytail != 0.0 ) { +temp16alen = scale_expansion_zeroelim( aytbclen, aytbc, adytail, temp16a ); +aytbctlen = scale_expansion_zeroelim( bctlen, bct, adytail, aytbct ); +temp32alen = scale_expansion_zeroelim( aytbctlen, aytbct, 2.0 * ady, +temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; + + +temp32alen = scale_expansion_zeroelim( aytbctlen, aytbct, adytail, +temp32a ); +aytbcttlen = scale_expansion_zeroelim( bcttlen, bctt, adytail, aytbctt ); +temp16alen = scale_expansion_zeroelim( aytbcttlen, aytbctt, 2.0 * ady, +temp16a ); +temp16blen = scale_expansion_zeroelim( aytbcttlen, aytbctt, adytail, +temp16b ); +temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32b ); +temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, +temp32blen, temp32b, temp64 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, +temp64, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +} +if (( bdxtail != 0.0 ) || ( bdytail != 0.0 )) { +if (( cdxtail != 0.0 ) || ( cdytail != 0.0 ) +|| ( adxtail != 0.0 ) || ( adytail != 0.0 )) { +Two_Product( cdxtail, ady, ti1, ti0 ); +Two_Product( cdx, adytail, tj1, tj0 ); +Two_Two_Sum( ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0] ); +u[3] = u3; +negate = -cdy; +Two_Product( adxtail, negate, ti1, ti0 ); +negate = -cdytail; +Two_Product( adx, negate, tj1, tj0 ); +Two_Two_Sum( ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0] ); +v[3] = v3; +catlen = fast_expansion_sum_zeroelim( 4, u, 4, v, cat ); + +Two_Product( cdxtail, adytail, ti1, ti0 ); +Two_Product( adxtail, cdytail, tj1, tj0 ); +Two_Two_Diff( ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0] ); +catt[3] = catt3; +cattlen = 4; +} +else { +cat[0] = 0.0; +catlen = 1; +catt[0] = 0.0; +cattlen = 1; +} - adx = pa[0] - pd[0]; - bdx = pb[0] - pd[0]; - cdx = pc[0] - pd[0]; - ady = pa[1] - pd[1]; - bdy = pb[1] - pd[1]; - cdy = pc[1] - pd[1]; +if ( bdxtail != 0.0 ) { +temp16alen = scale_expansion_zeroelim( bxtcalen, bxtca, bdxtail, temp16a ); +bxtcatlen = scale_expansion_zeroelim( catlen, cat, bdxtail, bxtcat ); +temp32alen = scale_expansion_zeroelim( bxtcatlen, bxtcat, 2.0 * bdx, +temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; +if ( cdytail != 0.0 ) { +temp8len = scale_expansion_zeroelim( 4, aa, bdxtail, temp8 ); +temp16alen = scale_expansion_zeroelim( temp8len, temp8, cdytail, +temp16a ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, +temp16a, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( adytail != 0.0 ) { +temp8len = scale_expansion_zeroelim( 4, cc, -bdxtail, temp8 ); +temp16alen = scale_expansion_zeroelim( temp8len, temp8, adytail, +temp16a ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, +temp16a, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} - bdxcdy = bdx * cdy; - cdxbdy = cdx * bdy; - alift = adx * adx + ady * ady; +temp32alen = scale_expansion_zeroelim( bxtcatlen, bxtcat, bdxtail, +temp32a ); +bxtcattlen = scale_expansion_zeroelim( cattlen, catt, bdxtail, bxtcatt ); +temp16alen = scale_expansion_zeroelim( bxtcattlen, bxtcatt, 2.0 * bdx, +temp16a ); +temp16blen = scale_expansion_zeroelim( bxtcattlen, bxtcatt, bdxtail, +temp16b ); +temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32b ); +temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, +temp32blen, temp32b, temp64 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, +temp64, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( bdytail != 0.0 ) { +temp16alen = scale_expansion_zeroelim( bytcalen, bytca, bdytail, temp16a ); +bytcatlen = scale_expansion_zeroelim( catlen, cat, bdytail, bytcat ); +temp32alen = scale_expansion_zeroelim( bytcatlen, bytcat, 2.0 * bdy, +temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; + + +temp32alen = scale_expansion_zeroelim( bytcatlen, bytcat, bdytail, +temp32a ); +bytcattlen = scale_expansion_zeroelim( cattlen, catt, bdytail, bytcatt ); +temp16alen = scale_expansion_zeroelim( bytcattlen, bytcatt, 2.0 * bdy, +temp16a ); +temp16blen = scale_expansion_zeroelim( bytcattlen, bytcatt, bdytail, +temp16b ); +temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32b ); +temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, +temp32blen, temp32b, temp64 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, +temp64, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +} +if (( cdxtail != 0.0 ) || ( cdytail != 0.0 )) { +if (( adxtail != 0.0 ) || ( adytail != 0.0 ) +|| ( bdxtail != 0.0 ) || ( bdytail != 0.0 )) { +Two_Product( adxtail, bdy, ti1, ti0 ); +Two_Product( adx, bdytail, tj1, tj0 ); +Two_Two_Sum( ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0] ); +u[3] = u3; +negate = -ady; +Two_Product( bdxtail, negate, ti1, ti0 ); +negate = -adytail; +Two_Product( bdx, negate, tj1, tj0 ); +Two_Two_Sum( ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0] ); +v[3] = v3; +abtlen = fast_expansion_sum_zeroelim( 4, u, 4, v, abt ); + +Two_Product( adxtail, bdytail, ti1, ti0 ); +Two_Product( bdxtail, adytail, tj1, tj0 ); +Two_Two_Diff( ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0] ); +abtt[3] = abtt3; +abttlen = 4; +} +else { +abt[0] = 0.0; +abtlen = 1; +abtt[0] = 0.0; +abttlen = 1; +} - cdxady = cdx * ady; - adxcdy = adx * cdy; - blift = bdx * bdx + bdy * bdy; +if ( cdxtail != 0.0 ) { +temp16alen = scale_expansion_zeroelim( cxtablen, cxtab, cdxtail, temp16a ); +cxtabtlen = scale_expansion_zeroelim( abtlen, abt, cdxtail, cxtabt ); +temp32alen = scale_expansion_zeroelim( cxtabtlen, cxtabt, 2.0 * cdx, +temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; +if ( adytail != 0.0 ) { +temp8len = scale_expansion_zeroelim( 4, bb, cdxtail, temp8 ); +temp16alen = scale_expansion_zeroelim( temp8len, temp8, adytail, +temp16a ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, +temp16a, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( bdytail != 0.0 ) { +temp8len = scale_expansion_zeroelim( 4, aa, -cdxtail, temp8 ); +temp16alen = scale_expansion_zeroelim( temp8len, temp8, bdytail, +temp16a ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen, +temp16a, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} - adxbdy = adx * bdy; - bdxady = bdx * ady; - clift = cdx * cdx + cdy * cdy; +temp32alen = scale_expansion_zeroelim( cxtabtlen, cxtabt, cdxtail, +temp32a ); +cxtabttlen = scale_expansion_zeroelim( abttlen, abtt, cdxtail, cxtabtt ); +temp16alen = scale_expansion_zeroelim( cxtabttlen, cxtabtt, 2.0 * cdx, +temp16a ); +temp16blen = scale_expansion_zeroelim( cxtabttlen, cxtabtt, cdxtail, +temp16b ); +temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32b ); +temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, +temp32blen, temp32b, temp64 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, +temp64, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +if ( cdytail != 0.0 ) { +temp16alen = scale_expansion_zeroelim( cytablen, cytab, cdytail, temp16a ); +cytabtlen = scale_expansion_zeroelim( abtlen, abt, cdytail, cytabt ); +temp32alen = scale_expansion_zeroelim( cytabtlen, cytabt, 2.0 * cdy, +temp32a ); +temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp32alen, temp32a, temp48 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len, +temp48, finother ); +finswap = finnow; finnow = finother; finother = finswap; + + +temp32alen = scale_expansion_zeroelim( cytabtlen, cytabt, cdytail, +temp32a ); +cytabttlen = scale_expansion_zeroelim( abttlen, abtt, cdytail, cytabtt ); +temp16alen = scale_expansion_zeroelim( cytabttlen, cytabtt, 2.0 * cdy, +temp16a ); +temp16blen = scale_expansion_zeroelim( cytabttlen, cytabtt, cdytail, +temp16b ); +temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a, +temp16blen, temp16b, temp32b ); +temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a, +temp32blen, temp32b, temp64 ); +finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len, +temp64, finother ); +finswap = finnow; finnow = finother; finother = finswap; +} +} - det = alift * ( bdxcdy - cdxbdy ) - + blift * ( cdxady - adxcdy ) - + clift * ( adxbdy - bdxady ); +return finnow[finlength - 1]; +} - if ( noexact ) { - return det; - } +REAL incircle( pa, pb, pc, pd ) +point pa; +point pb; +point pc; +point pd; +{ +REAL adx, bdx, cdx, ady, bdy, cdy; +REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady; +REAL alift, blift, clift; +REAL det; +REAL permanent, errbound; + +incirclecount++; + +adx = pa[0] - pd[0]; +bdx = pb[0] - pd[0]; +cdx = pc[0] - pd[0]; +ady = pa[1] - pd[1]; +bdy = pb[1] - pd[1]; +cdy = pc[1] - pd[1]; + +bdxcdy = bdx * cdy; +cdxbdy = cdx * bdy; +alift = adx * adx + ady * ady; + +cdxady = cdx * ady; +adxcdy = adx * cdy; +blift = bdx * bdx + bdy * bdy; + +adxbdy = adx * bdy; +bdxady = bdx * ady; +clift = cdx * cdx + cdy * cdy; + +det = alift * ( bdxcdy - cdxbdy ) ++ blift * ( cdxady - adxcdy ) ++ clift * ( adxbdy - bdxady ); + +if ( noexact ) { +return det; +} - permanent = ( Absolute( bdxcdy ) + Absolute( cdxbdy ) ) * alift - + ( Absolute( cdxady ) + Absolute( adxcdy ) ) * blift - + ( Absolute( adxbdy ) + Absolute( bdxady ) ) * clift; - errbound = iccerrboundA * permanent; - if ( ( det > errbound ) || ( -det > errbound ) ) { - return det; - } +permanent = ( Absolute( bdxcdy ) + Absolute( cdxbdy )) * alift ++ ( Absolute( cdxady ) + Absolute( adxcdy )) * blift ++ ( Absolute( adxbdy ) + Absolute( bdxady )) * clift; +errbound = iccerrboundA * permanent; +if (( det > errbound ) || ( -det > errbound )) { +return det; +} - return incircleadapt( pa, pb, pc, pd, permanent ); +return incircleadapt( pa, pb, pc, pd, permanent ); } /** **/ @@ -5061,18 +5217,18 @@ point pd; /*****************************************************************************/ void triangleinit(){ - points.maxitems = triangles.maxitems = shelles.maxitems = viri.maxitems = - badsegments.maxitems = badtriangles.maxitems = splaynodes.maxitems = 0l; - points.itembytes = triangles.itembytes = shelles.itembytes = viri.itembytes = - badsegments.itembytes = badtriangles.itembytes = splaynodes.itembytes = 0; - recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */ - samples = 1; /* Point location should take at least one sample. */ - checksegments = 0; /* There are no segments in the triangulation yet. */ - incirclecount = counterclockcount = hyperbolacount = 0; - circumcentercount = circletopcount = 0; - randomseed = 1; - - exactinit(); /* Initialize exact arithmetic constants. */ +points.maxitems = triangles.maxitems = shelles.maxitems = viri.maxitems = +badsegments.maxitems = badtriangles.maxitems = splaynodes.maxitems = 0l; +points.itembytes = triangles.itembytes = shelles.itembytes = viri.itembytes = +badsegments.itembytes = badtriangles.itembytes = splaynodes.itembytes = 0; +recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */ +samples = 1; /* Point location should take at least one sample. */ +checksegments = 0; /* There are no segments in the triangulation yet. */ +incirclecount = counterclockcount = hyperbolacount = 0; +circumcentercount = circletopcount = 0; +randomseed = 1; + +exactinit(); /* Initialize exact arithmetic constants. */ } /*****************************************************************************/ @@ -5088,8 +5244,8 @@ void triangleinit(){ unsigned long randomnation( choices ) unsigned int choices; { - randomseed = ( randomseed * 1366l + 150889l ) % 714025l; - return randomseed / ( 714025l / choices + 1 ); +randomseed = ( randomseed * 1366l + 150889l ) % 714025l; +return randomseed / ( 714025l / choices + 1 ); } /********* Mesh quality testing routines begin here *********/ @@ -5102,89 +5258,90 @@ unsigned int choices; /* */ /*****************************************************************************/ -#ifndef REDUCED +#ifndef +REDUCED void checkmesh(){ - struct triedge triangleloop; - struct triedge oppotri, oppooppotri; - point triorg, tridest, triapex; - point oppoorg, oppodest; - int horrors; - int saveexact; - triangle ptr; /* Temporary variable used by sym(). */ - - /* Temporarily turn on exact arithmetic if it's off. */ - saveexact = noexact; - noexact = 0; - if ( !quiet ) { - printf( " Checking consistency of mesh...\n" ); - } - horrors = 0; - /* Run through the list of triangles, checking each one. */ - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - while ( triangleloop.tri != (triangle *) NULL ) { - /* Check all three edges of the triangle. */ - for ( triangleloop.orient = 0; triangleloop.orient < 3; - triangleloop.orient++ ) { - org( triangleloop, triorg ); - dest( triangleloop, tridest ); - if ( triangleloop.orient == 0 ) { /* Only test for inversion once. */ - /* Test if the triangle is flat or inverted. */ - apex( triangleloop, triapex ); - if ( counterclockwise( triorg, tridest, triapex ) <= 0.0 ) { - printf( " !! !! Inverted " ); - printtriangle( &triangleloop ); - horrors++; - } - } - /* Find the neighboring triangle on this edge. */ - sym( triangleloop, oppotri ); - if ( oppotri.tri != dummytri ) { - /* Check that the triangle's neighbor knows it's a neighbor. */ - sym( oppotri, oppooppotri ); - if ( ( triangleloop.tri != oppooppotri.tri ) - || ( triangleloop.orient != oppooppotri.orient ) ) { - printf( " !! !! Asymmetric triangle-triangle bond:\n" ); - if ( triangleloop.tri == oppooppotri.tri ) { - printf( " (Right triangle, wrong orientation)\n" ); - } - printf( " First " ); - printtriangle( &triangleloop ); - printf( " Second (nonreciprocating) " ); - printtriangle( &oppotri ); - horrors++; - } - /* Check that both triangles agree on the identities */ - /* of their shared vertices. */ - org( oppotri, oppoorg ); - dest( oppotri, oppodest ); - if ( ( triorg != oppodest ) || ( tridest != oppoorg ) ) { - printf( " !! !! Mismatched edge coordinates between two triangles:\n" - ); - printf( " First mismatched " ); - printtriangle( &triangleloop ); - printf( " Second mismatched " ); - printtriangle( &oppotri ); - horrors++; - } - } - } - triangleloop.tri = triangletraverse(); - } - if ( horrors == 0 ) { - if ( !quiet ) { - printf( " In my studied opinion, the mesh appears to be consistent.\n" ); - } - } - else if ( horrors == 1 ) { - printf( " !! !! !! !! Precisely one festering wound discovered.\n" ); - } - else { - printf( " !! !! !! !! %d abominations witnessed.\n", horrors ); - } - /* Restore the status of exact arithmetic. */ - noexact = saveexact; +struct triedge triangleloop; +struct triedge oppotri, oppooppotri; +point triorg, tridest, triapex; +point oppoorg, oppodest; +int horrors; +int saveexact; +triangle ptr; /* Temporary variable used by sym(). */ + +/* Temporarily turn on exact arithmetic if it's off. */ +saveexact = noexact; +noexact = 0; +if ( !quiet ) { +printf( " Checking consistency of mesh...\n" ); +} +horrors = 0; +/* Run through the list of triangles, checking each one. */ +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +while ( triangleloop.tri != (triangle *) NULL ) { +/* Check all three edges of the triangle. */ +for ( triangleloop.orient = 0; triangleloop.orient < 3; +triangleloop.orient++ ) { +org( triangleloop, triorg ); +dest( triangleloop, tridest ); +if ( triangleloop.orient == 0 ) { /* Only test for inversion once. */ +/* Test if the triangle is flat or inverted. */ +apex( triangleloop, triapex ); +if ( counterclockwise( triorg, tridest, triapex ) <= 0.0 ) { +printf( " !! !! Inverted " ); +printtriangle( &triangleloop ); +horrors++; +} +} +/* Find the neighboring triangle on this edge. */ +sym( triangleloop, oppotri ); +if ( oppotri.tri != dummytri ) { +/* Check that the triangle's neighbor knows it's a neighbor. */ +sym( oppotri, oppooppotri ); +if (( triangleloop.tri != oppooppotri.tri ) +|| ( triangleloop.orient != oppooppotri.orient )) { +printf( " !! !! Asymmetric triangle-triangle bond:\n" ); +if ( triangleloop.tri == oppooppotri.tri ) { +printf( " (Right triangle, wrong orientation)\n" ); +} +printf( " First " ); +printtriangle( &triangleloop ); +printf( " Second (nonreciprocating) " ); +printtriangle( &oppotri ); +horrors++; +} +/* Check that both triangles agree on the identities */ +/* of their shared vertices. */ +org( oppotri, oppoorg ); +dest( oppotri, oppodest ); +if (( triorg != oppodest ) || ( tridest != oppoorg )) { +printf( " !! !! Mismatched edge coordinates between two triangles:\n" +); +printf( " First mismatched " ); +printtriangle( &triangleloop ); +printf( " Second mismatched " ); +printtriangle( &oppotri ); +horrors++; +} +} +} +triangleloop.tri = triangletraverse(); +} +if ( horrors == 0 ) { +if ( !quiet ) { +printf( " In my studied opinion, the mesh appears to be consistent.\n" ); +} +} +else if ( horrors == 1 ) { +printf( " !! !! !! !! Precisely one festering wound discovered.\n" ); +} +else { +printf( " !! !! !! !! %d abominations witnessed.\n", horrors ); +} +/* Restore the status of exact arithmetic. */ +noexact = saveexact; } #endif /* not REDUCED */ @@ -5195,81 +5352,82 @@ void checkmesh(){ /* */ /*****************************************************************************/ -#ifndef REDUCED +#ifndef +REDUCED void checkdelaunay(){ - struct triedge triangleloop; - struct triedge oppotri; - struct edge opposhelle; - point triorg, tridest, triapex; - point oppoapex; - int shouldbedelaunay; - int horrors; - int saveexact; - triangle ptr; /* Temporary variable used by sym(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - /* Temporarily turn on exact arithmetic if it's off. */ - saveexact = noexact; - noexact = 0; - if ( !quiet ) { - printf( " Checking Delaunay property of mesh...\n" ); - } - horrors = 0; - /* Run through the list of triangles, checking each one. */ - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - while ( triangleloop.tri != (triangle *) NULL ) { - /* Check all three edges of the triangle. */ - for ( triangleloop.orient = 0; triangleloop.orient < 3; - triangleloop.orient++ ) { - org( triangleloop, triorg ); - dest( triangleloop, tridest ); - apex( triangleloop, triapex ); - sym( triangleloop, oppotri ); - apex( oppotri, oppoapex ); - /* Only test that the edge is locally Delaunay if there is an */ - /* adjoining triangle whose pointer is larger (to ensure that */ - /* each pair isn't tested twice). */ - shouldbedelaunay = ( oppotri.tri != dummytri ) - && ( triapex != (point) NULL ) && ( oppoapex != (point) NULL ) - && ( triangleloop.tri < oppotri.tri ); - if ( checksegments && shouldbedelaunay ) { - /* If a shell edge separates the triangles, then the edge is */ - /* constrained, so no local Delaunay test should be done. */ - tspivot( triangleloop, opposhelle ); - if ( opposhelle.sh != dummysh ) { - shouldbedelaunay = 0; - } - } - if ( shouldbedelaunay ) { - if ( incircle( triorg, tridest, triapex, oppoapex ) > 0.0 ) { - printf( " !! !! Non-Delaunay pair of triangles:\n" ); - printf( " First non-Delaunay " ); - printtriangle( &triangleloop ); - printf( " Second non-Delaunay " ); - printtriangle( &oppotri ); - horrors++; - } - } - } - triangleloop.tri = triangletraverse(); - } - if ( horrors == 0 ) { - if ( !quiet ) { - printf( - " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n" ); - } - } - else if ( horrors == 1 ) { - printf( - " !! !! !! !! Precisely one terrifying transgression identified.\n" ); - } - else { - printf( " !! !! !! !! %d obscenities viewed with horror.\n", horrors ); - } - /* Restore the status of exact arithmetic. */ - noexact = saveexact; +struct triedge triangleloop; +struct triedge oppotri; +struct edge opposhelle; +point triorg, tridest, triapex; +point oppoapex; +int shouldbedelaunay; +int horrors; +int saveexact; +triangle ptr; /* Temporary variable used by sym(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +/* Temporarily turn on exact arithmetic if it's off. */ +saveexact = noexact; +noexact = 0; +if ( !quiet ) { +printf( " Checking Delaunay property of mesh...\n" ); +} +horrors = 0; +/* Run through the list of triangles, checking each one. */ +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +while ( triangleloop.tri != (triangle *) NULL ) { +/* Check all three edges of the triangle. */ +for ( triangleloop.orient = 0; triangleloop.orient < 3; +triangleloop.orient++ ) { +org( triangleloop, triorg ); +dest( triangleloop, tridest ); +apex( triangleloop, triapex ); +sym( triangleloop, oppotri ); +apex( oppotri, oppoapex ); +/* Only test that the edge is locally Delaunay if there is an */ +/* adjoining triangle whose pointer is larger (to ensure that */ +/* each pair isn't tested twice). */ +shouldbedelaunay = ( oppotri.tri != dummytri ) +&& ( triapex != (point) NULL ) && ( oppoapex != (point) NULL ) +&& ( triangleloop.tri < oppotri.tri ); +if ( checksegments && shouldbedelaunay ) { +/* If a shell edge separates the triangles, then the edge is */ +/* constrained, so no local Delaunay test should be done. */ +tspivot( triangleloop, opposhelle ); +if ( opposhelle.sh != dummysh ) { +shouldbedelaunay = 0; +} +} +if ( shouldbedelaunay ) { +if ( incircle( triorg, tridest, triapex, oppoapex ) > 0.0 ) { +printf( " !! !! Non-Delaunay pair of triangles:\n" ); +printf( " First non-Delaunay " ); +printtriangle( &triangleloop ); +printf( " Second non-Delaunay " ); +printtriangle( &oppotri ); +horrors++; +} +} +} +triangleloop.tri = triangletraverse(); +} +if ( horrors == 0 ) { +if ( !quiet ) { +printf( +" By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n" ); +} +} +else if ( horrors == 1 ) { +printf( +" !! !! !! !! Precisely one terrifying transgression identified.\n" ); +} +else { +printf( " !! !! !! !! %d obscenities viewed with horror.\n", horrors ); +} +/* Restore the status of exact arithmetic. */ +noexact = saveexact; } #endif /* not REDUCED */ @@ -5284,7 +5442,8 @@ void checkdelaunay(){ /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void enqueuebadtri( instri, angle, insapex, insorg, insdest ) struct triedge *instri; @@ -5293,38 +5452,38 @@ point insapex; point insorg; point insdest; { - struct badface *newface; - int queuenumber; - - if ( verbose > 2 ) { - printf( " Queueing bad triangle:\n" ); - printf( " (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", insorg[0], - insorg[1], insdest[0], insdest[1], insapex[0], insapex[1] ); - } - /* Allocate space for the bad triangle. */ - newface = (struct badface *) poolalloc( &badtriangles ); - triedgecopy( *instri, newface->badfacetri ); - newface->key = angle; - newface->faceapex = insapex; - newface->faceorg = insorg; - newface->facedest = insdest; - newface->nextface = (struct badface *) NULL; - /* Determine the appropriate queue to put the bad triangle into. */ - if ( angle > 0.6 ) { - queuenumber = (int) ( 160.0 * ( angle - 0.6 ) ); - if ( queuenumber > 63 ) { - queuenumber = 63; - } - } - else { - /* It's not a bad angle; put the triangle in the lowest-priority queue. */ - queuenumber = 0; - } - /* Add the triangle to the end of a queue. */ - *queuetail[queuenumber] = newface; - /* Maintain a pointer to the NULL pointer at the end of the queue. */ - queuetail[queuenumber] = &newface->nextface; -} +struct badface *newface; +int queuenumber; + +if ( verbose > 2 ) { +printf( " Queueing bad triangle:\n" ); +printf( " (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", insorg[0], +insorg[1], insdest[0], insdest[1], insapex[0], insapex[1] ); +} +/* Allocate space for the bad triangle. */ +newface = (struct badface *) poolalloc( &badtriangles ); +triedgecopy( *instri, newface->badfacetri ); +newface->key = angle; +newface->faceapex = insapex; +newface->faceorg = insorg; +newface->facedest = insdest; +newface->nextface = (struct badface *) NULL; +/* Determine the appropriate queue to put the bad triangle into. */ +if ( angle > 0.6 ) { +queuenumber = (int) ( 160.0 * ( angle - 0.6 )); +if ( queuenumber > 63 ) { +queuenumber = 63; +} +} +else { +/* It's not a bad angle; put the triangle in the lowest-priority queue. */ +queuenumber = 0; +} +/* Add the triangle to the end of a queue. */ +*queuetail[queuenumber] = newface; +/* Maintain a pointer to the NULL pointer at the end of the queue. */ +queuetail[queuenumber] = &newface->nextface; +} #endif /* not CDT_ONLY */ @@ -5334,26 +5493,27 @@ point insdest; /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY struct badface *dequeuebadtri(){ - struct badface *result; - int queuenumber; - - /* Look for a nonempty queue. */ - for ( queuenumber = 63; queuenumber >= 0; queuenumber-- ) { - result = queuefront[queuenumber]; - if ( result != (struct badface *) NULL ) { - /* Remove the triangle from the queue. */ - queuefront[queuenumber] = result->nextface; - /* Maintain a pointer to the NULL pointer at the end of the queue. */ - if ( queuefront[queuenumber] == (struct badface *) NULL ) { - queuetail[queuenumber] = &queuefront[queuenumber]; - } - return result; - } - } - return (struct badface *) NULL; +struct badface *result; +int queuenumber; + +/* Look for a nonempty queue. */ +for ( queuenumber = 63; queuenumber >= 0; queuenumber-- ) { +result = queuefront[queuenumber]; +if ( result != (struct badface *) NULL ) { +/* Remove the triangle from the queue. */ +queuefront[queuenumber] = result->nextface; +/* Maintain a pointer to the NULL pointer at the end of the queue. */ +if ( queuefront[queuenumber] == (struct badface *) NULL ) { +queuetail[queuenumber] = &queuefront[queuenumber]; +} +return result; +} +} +return (struct badface *) NULL; } #endif /* not CDT_ONLY */ @@ -5371,75 +5531,76 @@ struct badface *dequeuebadtri(){ /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY int checkedge4encroach( testedge ) struct edge *testedge; { - struct triedge neighbortri; - struct edge testsym; - struct edge *badedge; - int addtolist; - int sides; - point eorg, edest, eapex; - triangle ptr; /* Temporary variable used by stpivot(). */ - - addtolist = 0; - sides = 0; - - sorg( *testedge, eorg ); - sdest( *testedge, edest ); - /* Check one neighbor of the shell edge. */ - stpivot( *testedge, neighbortri ); - /* Does the neighbor exist, or is this a boundary edge? */ - if ( neighbortri.tri != dummytri ) { - sides++; - /* Find a vertex opposite this edge. */ - apex( neighbortri, eapex ); - /* Check whether the vertex is inside the diametral circle of the */ - /* shell edge. Pythagoras' Theorem is used to check whether the */ - /* angle at the vertex is greater than 90 degrees. */ - if ( eapex[0] * ( eorg[0] + edest[0] ) + eapex[1] * ( eorg[1] + edest[1] ) > - eapex[0] * eapex[0] + eorg[0] * edest[0] + - eapex[1] * eapex[1] + eorg[1] * edest[1] ) { - addtolist = 1; - } - } - /* Check the other neighbor of the shell edge. */ - ssym( *testedge, testsym ); - stpivot( testsym, neighbortri ); - /* Does the neighbor exist, or is this a boundary edge? */ - if ( neighbortri.tri != dummytri ) { - sides++; - /* Find the other vertex opposite this edge. */ - apex( neighbortri, eapex ); - /* Check whether the vertex is inside the diametral circle of the */ - /* shell edge. Pythagoras' Theorem is used to check whether the */ - /* angle at the vertex is greater than 90 degrees. */ - if ( eapex[0] * ( eorg[0] + edest[0] ) + - eapex[1] * ( eorg[1] + edest[1] ) > - eapex[0] * eapex[0] + eorg[0] * edest[0] + - eapex[1] * eapex[1] + eorg[1] * edest[1] ) { - addtolist += 2; - } - } - - if ( addtolist && ( !nobisect || ( ( nobisect == 1 ) && ( sides == 2 ) ) ) ) { - if ( verbose > 2 ) { - printf( " Queueing encroached segment (%.12g, %.12g) (%.12g, %.12g).\n", - eorg[0], eorg[1], edest[0], edest[1] ); - } - /* Add the shell edge to the list of encroached segments. */ - /* Be sure to get the orientation right. */ - badedge = (struct edge *) poolalloc( &badsegments ); - if ( addtolist == 1 ) { - shellecopy( *testedge, *badedge ); - } - else { - shellecopy( testsym, *badedge ); - } - } - return addtolist; +struct triedge neighbortri; +struct edge testsym; +struct edge *badedge; +int addtolist; +int sides; +point eorg, edest, eapex; +triangle ptr; /* Temporary variable used by stpivot(). */ + +addtolist = 0; +sides = 0; + +sorg( *testedge, eorg ); +sdest( *testedge, edest ); +/* Check one neighbor of the shell edge. */ +stpivot( *testedge, neighbortri ); +/* Does the neighbor exist, or is this a boundary edge? */ +if ( neighbortri.tri != dummytri ) { +sides++; +/* Find a vertex opposite this edge. */ +apex( neighbortri, eapex ); +/* Check whether the vertex is inside the diametral circle of the */ +/* shell edge. Pythagoras' Theorem is used to check whether the */ +/* angle at the vertex is greater than 90 degrees. */ +if ( eapex[0] * ( eorg[0] + edest[0] ) + eapex[1] * ( eorg[1] + edest[1] ) > +eapex[0] * eapex[0] + eorg[0] * edest[0] + +eapex[1] * eapex[1] + eorg[1] * edest[1] ) { +addtolist = 1; +} +} +/* Check the other neighbor of the shell edge. */ +ssym( *testedge, testsym ); +stpivot( testsym, neighbortri ); +/* Does the neighbor exist, or is this a boundary edge? */ +if ( neighbortri.tri != dummytri ) { +sides++; +/* Find the other vertex opposite this edge. */ +apex( neighbortri, eapex ); +/* Check whether the vertex is inside the diametral circle of the */ +/* shell edge. Pythagoras' Theorem is used to check whether the */ +/* angle at the vertex is greater than 90 degrees. */ +if ( eapex[0] * ( eorg[0] + edest[0] ) + +eapex[1] * ( eorg[1] + edest[1] ) > +eapex[0] * eapex[0] + eorg[0] * edest[0] + +eapex[1] * eapex[1] + eorg[1] * edest[1] ) { +addtolist += 2; +} +} + +if ( addtolist && ( !nobisect || (( nobisect == 1 ) && ( sides == 2 )))) { +if ( verbose > 2 ) { +printf( " Queueing encroached segment (%.12g, %.12g) (%.12g, %.12g).\n", +eorg[0], eorg[1], edest[0], edest[1] ); +} +/* Add the shell edge to the list of encroached segments. */ +/* Be sure to get the orientation right. */ +badedge = (struct edge *) poolalloc( &badsegments ); +if ( addtolist == 1 ) { +shellecopy( *testedge, *badedge ); +} +else { +shellecopy( testsym, *badedge ); +} +} +return addtolist; } #endif /* not CDT_ONLY */ @@ -5454,112 +5615,113 @@ struct edge *testedge; /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void testtriangle( testtri ) struct triedge *testtri; { - struct triedge sametesttri; - struct edge edge1, edge2; - point torg, tdest, tapex; - point anglevertex; - REAL dxod, dyod, dxda, dyda, dxao, dyao; - REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2; - REAL apexlen, orglen, destlen; - REAL angle; - REAL area; - shelle sptr; /* Temporary variable used by tspivot(). */ - - org( *testtri, torg ); - dest( *testtri, tdest ); - apex( *testtri, tapex ); - dxod = torg[0] - tdest[0]; - dyod = torg[1] - tdest[1]; - dxda = tdest[0] - tapex[0]; - dyda = tdest[1] - tapex[1]; - dxao = tapex[0] - torg[0]; - dyao = tapex[1] - torg[1]; - dxod2 = dxod * dxod; - dyod2 = dyod * dyod; - dxda2 = dxda * dxda; - dyda2 = dyda * dyda; - dxao2 = dxao * dxao; - dyao2 = dyao * dyao; - /* Find the lengths of the triangle's three edges. */ - apexlen = dxod2 + dyod2; - orglen = dxda2 + dyda2; - destlen = dxao2 + dyao2; - if ( ( apexlen < orglen ) && ( apexlen < destlen ) ) { - /* The edge opposite the apex is shortest. */ - /* Find the square of the cosine of the angle at the apex. */ - angle = dxda * dxao + dyda * dyao; - angle = angle * angle / ( orglen * destlen ); - anglevertex = tapex; - lnext( *testtri, sametesttri ); - tspivot( sametesttri, edge1 ); - lnextself( sametesttri ); - tspivot( sametesttri, edge2 ); - } - else if ( orglen < destlen ) { - /* The edge opposite the origin is shortest. */ - /* Find the square of the cosine of the angle at the origin. */ - angle = dxod * dxao + dyod * dyao; - angle = angle * angle / ( apexlen * destlen ); - anglevertex = torg; - tspivot( *testtri, edge1 ); - lprev( *testtri, sametesttri ); - tspivot( sametesttri, edge2 ); - } - else { - /* The edge opposite the destination is shortest. */ - /* Find the square of the cosine of the angle at the destination. */ - angle = dxod * dxda + dyod * dyda; - angle = angle * angle / ( apexlen * orglen ); - anglevertex = tdest; - tspivot( *testtri, edge1 ); - lnext( *testtri, sametesttri ); - tspivot( sametesttri, edge2 ); - } - /* Check if both edges that form the angle are segments. */ - if ( ( edge1.sh != dummysh ) && ( edge2.sh != dummysh ) ) { - /* The angle is a segment intersection. */ - if ( ( angle > 0.9924 ) && !quiet ) { /* Roughly 5 degrees. */ - if ( angle > 1.0 ) { - /* Beware of a floating exception in acos(). */ - angle = 1.0; - } - /* Find the actual angle in degrees, for printing. */ - angle = acos( sqrt( angle ) ) * ( 180.0 / PI ); - printf( - "Warning: Small angle (%.4g degrees) between segments at point\n", - angle ); - printf( " (%.12g, %.12g)\n", anglevertex[0], anglevertex[1] ); - } - /* Don't add this bad triangle to the list; there's nothing that */ - /* can be done about a small angle between two segments. */ - angle = 0.0; - } - /* Check whether the angle is smaller than permitted. */ - if ( angle > goodangle ) { - /* Add this triangle to the list of bad triangles. */ - enqueuebadtri( testtri, angle, tapex, torg, tdest ); - return; - } - if ( vararea || fixedarea ) { - /* Check whether the area is larger than permitted. */ - area = 0.5 * ( dxod * dyda - dyod * dxda ); - if ( fixedarea && ( area > maxarea ) ) { - /* Add this triangle to the list of bad triangles. */ - enqueuebadtri( testtri, angle, tapex, torg, tdest ); - } - else if ( vararea ) { - /* Nonpositive area constraints are treated as unconstrained. */ - if ( ( area > areabound( *testtri ) ) && ( areabound( *testtri ) > 0.0 ) ) { - /* Add this triangle to the list of bad triangles. */ - enqueuebadtri( testtri, angle, tapex, torg, tdest ); - } - } - } +struct triedge sametesttri; +struct edge edge1, edge2; +point torg, tdest, tapex; +point anglevertex; +REAL dxod, dyod, dxda, dyda, dxao, dyao; +REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2; +REAL apexlen, orglen, destlen; +REAL angle; +REAL area; +shelle sptr; /* Temporary variable used by tspivot(). */ + +org( *testtri, torg ); +dest( *testtri, tdest ); +apex( *testtri, tapex ); +dxod = torg[0] - tdest[0]; +dyod = torg[1] - tdest[1]; +dxda = tdest[0] - tapex[0]; +dyda = tdest[1] - tapex[1]; +dxao = tapex[0] - torg[0]; +dyao = tapex[1] - torg[1]; +dxod2 = dxod * dxod; +dyod2 = dyod * dyod; +dxda2 = dxda * dxda; +dyda2 = dyda * dyda; +dxao2 = dxao * dxao; +dyao2 = dyao * dyao; +/* Find the lengths of the triangle's three edges. */ +apexlen = dxod2 + dyod2; +orglen = dxda2 + dyda2; +destlen = dxao2 + dyao2; +if (( apexlen < orglen ) && ( apexlen < destlen )) { +/* The edge opposite the apex is shortest. */ +/* Find the square of the cosine of the angle at the apex. */ +angle = dxda * dxao + dyda * dyao; +angle = angle * angle / ( orglen * destlen ); +anglevertex = tapex; +lnext( *testtri, sametesttri ); +tspivot( sametesttri, edge1 ); +lnextself( sametesttri ); +tspivot( sametesttri, edge2 ); +} +else if ( orglen < destlen ) { +/* The edge opposite the origin is shortest. */ +/* Find the square of the cosine of the angle at the origin. */ +angle = dxod * dxao + dyod * dyao; +angle = angle * angle / ( apexlen * destlen ); +anglevertex = torg; +tspivot( *testtri, edge1 ); +lprev( *testtri, sametesttri ); +tspivot( sametesttri, edge2 ); +} +else { +/* The edge opposite the destination is shortest. */ +/* Find the square of the cosine of the angle at the destination. */ +angle = dxod * dxda + dyod * dyda; +angle = angle * angle / ( apexlen * orglen ); +anglevertex = tdest; +tspivot( *testtri, edge1 ); +lnext( *testtri, sametesttri ); +tspivot( sametesttri, edge2 ); +} +/* Check if both edges that form the angle are segments. */ +if (( edge1.sh != dummysh ) && ( edge2.sh != dummysh )) { +/* The angle is a segment intersection. */ +if (( angle > 0.9924 ) && !quiet ) { /* Roughly 5 degrees. */ +if ( angle > 1.0 ) { +/* Beware of a floating exception in acos(). */ +angle = 1.0; +} +/* Find the actual angle in degrees, for printing. */ +angle = acos( sqrt( angle )) * ( 180.0 / PI ); +printf( +"Warning: Small angle (%.4g degrees) between segments at point\n", +angle ); +printf( " (%.12g, %.12g)\n", anglevertex[0], anglevertex[1] ); +} +/* Don't add this bad triangle to the list; there's nothing that */ +/* can be done about a small angle between two segments. */ +angle = 0.0; +} +/* Check whether the angle is smaller than permitted. */ +if ( angle > goodangle ) { +/* Add this triangle to the list of bad triangles. */ +enqueuebadtri( testtri, angle, tapex, torg, tdest ); +return; +} +if ( vararea || fixedarea ) { +/* Check whether the area is larger than permitted. */ +area = 0.5 * ( dxod * dyda - dyod * dxda ); +if ( fixedarea && ( area > maxarea )) { +/* Add this triangle to the list of bad triangles. */ +enqueuebadtri( testtri, angle, tapex, torg, tdest ); +} +else if ( vararea ) { +/* Nonpositive area constraints are treated as unconstrained. */ +if (( area > areabound( *testtri )) && ( areabound( *testtri ) > 0.0 )) { +/* Add this triangle to the list of bad triangles. */ +enqueuebadtri( testtri, angle, tapex, torg, tdest ); +} +} +} } #endif /* not CDT_ONLY */ @@ -5586,23 +5748,23 @@ struct triedge *testtri; /*****************************************************************************/ void makepointmap(){ - struct triedge triangleloop; - point triorg; +struct triedge triangleloop; +point triorg; - if ( verbose ) { - printf( " Constructing mapping from points to triangles.\n" ); - } - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - while ( triangleloop.tri != (triangle *) NULL ) { - /* Check all three points of the triangle. */ - for ( triangleloop.orient = 0; triangleloop.orient < 3; - triangleloop.orient++ ) { - org( triangleloop, triorg ); - setpoint2tri( triorg, encode( triangleloop ) ); - } - triangleloop.tri = triangletraverse(); - } +if ( verbose ) { +printf( " Constructing mapping from points to triangles.\n" ); +} +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +while ( triangleloop.tri != (triangle *) NULL ) { +/* Check all three points of the triangle. */ +for ( triangleloop.orient = 0; triangleloop.orient < 3; +triangleloop.orient++ ) { +org( triangleloop, triorg ); +setpoint2tri( triorg, encode( triangleloop )); +} +triangleloop.tri = triangletraverse(); +} } /*****************************************************************************/ @@ -5673,103 +5835,103 @@ enum locateresult preciselocate( searchpoint, searchtri ) point searchpoint; struct triedge *searchtri; { - struct triedge backtracktri; - point forg, fdest, fapex; - point swappoint; - REAL orgorient, destorient; - int moveleft; - triangle ptr; /* Temporary variable used by sym(). */ - - if ( verbose > 2 ) { - printf( " Searching for point (%.12g, %.12g).\n", - searchpoint[0], searchpoint[1] ); - } - /* Where are we? */ - org( *searchtri, forg ); - dest( *searchtri, fdest ); - apex( *searchtri, fapex ); - while ( 1 ) { - if ( verbose > 2 ) { - printf( " At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", - forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1] ); - } - /* Check whether the apex is the point we seek. */ - if ( ( fapex[0] == searchpoint[0] ) && ( fapex[1] == searchpoint[1] ) ) { - lprevself( *searchtri ); - return ONVERTEX; - } - /* Does the point lie on the other side of the line defined by the */ - /* triangle edge opposite the triangle's destination? */ - destorient = counterclockwise( forg, fapex, searchpoint ); - /* Does the point lie on the other side of the line defined by the */ - /* triangle edge opposite the triangle's origin? */ - orgorient = counterclockwise( fapex, fdest, searchpoint ); - if ( destorient > 0.0 ) { - if ( orgorient > 0.0 ) { - /* Move left if the inner product of (fapex - searchpoint) and */ - /* (fdest - forg) is positive. This is equivalent to drawing */ - /* a line perpendicular to the line (forg, fdest) passing */ - /* through `fapex', and determining which side of this line */ - /* `searchpoint' falls on. */ - moveleft = ( fapex[0] - searchpoint[0] ) * ( fdest[0] - forg[0] ) + - ( fapex[1] - searchpoint[1] ) * ( fdest[1] - forg[1] ) > 0.0; - } - else { - moveleft = 1; - } - } - else { - if ( orgorient > 0.0 ) { - moveleft = 0; - } - else { - /* The point we seek must be on the boundary of or inside this */ - /* triangle. */ - if ( destorient == 0.0 ) { - lprevself( *searchtri ); - return ONEDGE; - } - if ( orgorient == 0.0 ) { - lnextself( *searchtri ); - return ONEDGE; - } - return INTRIANGLE; - } - } - - /* Move to another triangle. Leave a trace `backtracktri' in case */ - /* floating-point roundoff or some such bogey causes us to walk */ - /* off a boundary of the triangulation. We can just bounce off */ - /* the boundary as if it were an elastic band. */ - if ( moveleft ) { - lprev( *searchtri, backtracktri ); - fdest = fapex; - } - else { - lnext( *searchtri, backtracktri ); - forg = fapex; - } - sym( backtracktri, *searchtri ); - - /* Check for walking off the edge. */ - if ( searchtri->tri == dummytri ) { - /* Turn around. */ - triedgecopy( backtracktri, *searchtri ); - swappoint = forg; - forg = fdest; - fdest = swappoint; - apex( *searchtri, fapex ); - /* Check if the point really is beyond the triangulation boundary. */ - destorient = counterclockwise( forg, fapex, searchpoint ); - orgorient = counterclockwise( fapex, fdest, searchpoint ); - if ( ( orgorient < 0.0 ) && ( destorient < 0.0 ) ) { - return OUTSIDE; - } - } - else { - apex( *searchtri, fapex ); - } - } +struct triedge backtracktri; +point forg, fdest, fapex; +point swappoint; +REAL orgorient, destorient; +int moveleft; +triangle ptr; /* Temporary variable used by sym(). */ + +if ( verbose > 2 ) { +printf( " Searching for point (%.12g, %.12g).\n", +searchpoint[0], searchpoint[1] ); +} +/* Where are we? */ +org( *searchtri, forg ); +dest( *searchtri, fdest ); +apex( *searchtri, fapex ); +while ( 1 ) { +if ( verbose > 2 ) { +printf( " At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", +forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1] ); +} +/* Check whether the apex is the point we seek. */ +if (( fapex[0] == searchpoint[0] ) && ( fapex[1] == searchpoint[1] )) { +lprevself( *searchtri ); +return ONVERTEX; +} +/* Does the point lie on the other side of the line defined by the */ +/* triangle edge opposite the triangle's destination? */ +destorient = counterclockwise( forg, fapex, searchpoint ); +/* Does the point lie on the other side of the line defined by the */ +/* triangle edge opposite the triangle's origin? */ +orgorient = counterclockwise( fapex, fdest, searchpoint ); +if ( destorient > 0.0 ) { +if ( orgorient > 0.0 ) { +/* Move left if the inner product of (fapex - searchpoint) and */ +/* (fdest - forg) is positive. This is equivalent to drawing */ +/* a line perpendicular to the line (forg, fdest) passing */ +/* through `fapex', and determining which side of this line */ +/* `searchpoint' falls on. */ +moveleft = ( fapex[0] - searchpoint[0] ) * ( fdest[0] - forg[0] ) + +( fapex[1] - searchpoint[1] ) * ( fdest[1] - forg[1] ) > 0.0; +} +else { +moveleft = 1; +} +} +else { +if ( orgorient > 0.0 ) { +moveleft = 0; +} +else { +/* The point we seek must be on the boundary of or inside this */ +/* triangle. */ +if ( destorient == 0.0 ) { +lprevself( *searchtri ); +return ONEDGE; +} +if ( orgorient == 0.0 ) { +lnextself( *searchtri ); +return ONEDGE; +} +return INTRIANGLE; +} +} + +/* Move to another triangle. Leave a trace `backtracktri' in case */ +/* floating-point roundoff or some such bogey causes us to walk */ +/* off a boundary of the triangulation. We can just bounce off */ +/* the boundary as if it were an elastic band. */ +if ( moveleft ) { +lprev( *searchtri, backtracktri ); +fdest = fapex; +} +else { +lnext( *searchtri, backtracktri ); +forg = fapex; +} +sym( backtracktri, *searchtri ); + +/* Check for walking off the edge. */ +if ( searchtri->tri == dummytri ) { +/* Turn around. */ +triedgecopy( backtracktri, *searchtri ); +swappoint = forg; +forg = fdest; +fdest = swappoint; +apex( *searchtri, fapex ); +/* Check if the point really is beyond the triangulation boundary. */ +destorient = counterclockwise( forg, fapex, searchpoint ); +orgorient = counterclockwise( fapex, fdest, searchpoint ); +if (( orgorient < 0.0 ) && ( destorient < 0.0 )) { +return OUTSIDE; +} +} +else { +apex( *searchtri, fapex ); +} +} } /*****************************************************************************/ @@ -5812,121 +5974,121 @@ enum locateresult locate( searchpoint, searchtri ) point searchpoint; struct triedge *searchtri; { - VOID **sampleblock; - triangle *firsttri; - struct triedge sampletri; - point torg, tdest; - unsigned long alignptr; - REAL searchdist, dist; - REAL ahead; - long sampleblocks, samplesperblock, samplenum; - long triblocks; - long i, j; - triangle ptr; /* Temporary variable used by sym(). */ - - if ( verbose > 2 ) { - printf( " Randomly sampling for a triangle near point (%.12g, %.12g).\n", - searchpoint[0], searchpoint[1] ); - } - /* Record the distance from the suggested starting triangle to the */ - /* point we seek. */ - org( *searchtri, torg ); - searchdist = ( searchpoint[0] - torg[0] ) * ( searchpoint[0] - torg[0] ) - + ( searchpoint[1] - torg[1] ) * ( searchpoint[1] - torg[1] ); - if ( verbose > 2 ) { - printf( " Boundary triangle has origin (%.12g, %.12g).\n", - torg[0], torg[1] ); - } - - /* If a recently encountered triangle has been recorded and has not been */ - /* deallocated, test it as a good starting point. */ - if ( recenttri.tri != (triangle *) NULL ) { - if ( recenttri.tri[3] != (triangle) NULL ) { - org( recenttri, torg ); - if ( ( torg[0] == searchpoint[0] ) && ( torg[1] == searchpoint[1] ) ) { - triedgecopy( recenttri, *searchtri ); - return ONVERTEX; - } - dist = ( searchpoint[0] - torg[0] ) * ( searchpoint[0] - torg[0] ) - + ( searchpoint[1] - torg[1] ) * ( searchpoint[1] - torg[1] ); - if ( dist < searchdist ) { - triedgecopy( recenttri, *searchtri ); - searchdist = dist; - if ( verbose > 2 ) { - printf( " Choosing recent triangle with origin (%.12g, %.12g).\n", - torg[0], torg[1] ); - } - } - } - } - - /* The number of random samples taken is proportional to the cube root of */ - /* the number of triangles in the mesh. The next bit of code assumes */ - /* that the number of triangles increases monotonically. */ - while ( SAMPLEFACTOR * samples * samples * samples < triangles.items ) { - samples++; - } - triblocks = ( triangles.maxitems + TRIPERBLOCK - 1 ) / TRIPERBLOCK; - samplesperblock = 1 + ( samples / triblocks ); - sampleblocks = samples / samplesperblock; - sampleblock = triangles.firstblock; - sampletri.orient = 0; - for ( i = 0; i < sampleblocks; i++ ) { - alignptr = (unsigned long) ( sampleblock + 1 ); - firsttri = (triangle *) ( alignptr + (unsigned long) triangles.alignbytes - - ( alignptr % (unsigned long) triangles.alignbytes ) ); - for ( j = 0; j < samplesperblock; j++ ) { - if ( i == triblocks - 1 ) { - samplenum = randomnation( (int) - ( triangles.maxitems - ( i * TRIPERBLOCK ) ) ); - } - else { - samplenum = randomnation( TRIPERBLOCK ); - } - sampletri.tri = (triangle *) - ( firsttri + ( samplenum * triangles.itemwords ) ); - if ( sampletri.tri[3] != (triangle) NULL ) { - org( sampletri, torg ); - dist = ( searchpoint[0] - torg[0] ) * ( searchpoint[0] - torg[0] ) - + ( searchpoint[1] - torg[1] ) * ( searchpoint[1] - torg[1] ); - if ( dist < searchdist ) { - triedgecopy( sampletri, *searchtri ); - searchdist = dist; - if ( verbose > 2 ) { - printf( " Choosing triangle with origin (%.12g, %.12g).\n", - torg[0], torg[1] ); - } - } - } - } - sampleblock = (VOID **) *sampleblock; - } - /* Where are we? */ - org( *searchtri, torg ); - dest( *searchtri, tdest ); - /* Check the starting triangle's vertices. */ - if ( ( torg[0] == searchpoint[0] ) && ( torg[1] == searchpoint[1] ) ) { - return ONVERTEX; - } - if ( ( tdest[0] == searchpoint[0] ) && ( tdest[1] == searchpoint[1] ) ) { - lnextself( *searchtri ); - return ONVERTEX; - } - /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */ - ahead = counterclockwise( torg, tdest, searchpoint ); - if ( ahead < 0.0 ) { - /* Turn around so that `searchpoint' is to the left of the */ - /* edge specified by `searchtri'. */ - symself( *searchtri ); - } - else if ( ahead == 0.0 ) { - /* Check if `searchpoint' is between `torg' and `tdest'. */ - if ( ( ( torg[0] < searchpoint[0] ) == ( searchpoint[0] < tdest[0] ) ) - && ( ( torg[1] < searchpoint[1] ) == ( searchpoint[1] < tdest[1] ) ) ) { - return ONEDGE; - } - } - return preciselocate( searchpoint, searchtri ); +VOID **sampleblock; +triangle *firsttri; +struct triedge sampletri; +point torg, tdest; +unsigned long alignptr; +REAL searchdist, dist; +REAL ahead; +long sampleblocks, samplesperblock, samplenum; +long triblocks; +long i, j; +triangle ptr; /* Temporary variable used by sym(). */ + +if ( verbose > 2 ) { +printf( " Randomly sampling for a triangle near point (%.12g, %.12g).\n", +searchpoint[0], searchpoint[1] ); +} +/* Record the distance from the suggested starting triangle to the */ +/* point we seek. */ +org( *searchtri, torg ); +searchdist = ( searchpoint[0] - torg[0] ) * ( searchpoint[0] - torg[0] ) ++ ( searchpoint[1] - torg[1] ) * ( searchpoint[1] - torg[1] ); +if ( verbose > 2 ) { +printf( " Boundary triangle has origin (%.12g, %.12g).\n", +torg[0], torg[1] ); +} + +/* If a recently encountered triangle has been recorded and has not been */ +/* deallocated, test it as a good starting point. */ +if ( recenttri.tri != (triangle *) NULL ) { +if ( recenttri.tri[3] != (triangle) NULL ) { +org( recenttri, torg ); +if (( torg[0] == searchpoint[0] ) && ( torg[1] == searchpoint[1] )) { +triedgecopy( recenttri, *searchtri ); +return ONVERTEX; +} +dist = ( searchpoint[0] - torg[0] ) * ( searchpoint[0] - torg[0] ) ++ ( searchpoint[1] - torg[1] ) * ( searchpoint[1] - torg[1] ); +if ( dist < searchdist ) { +triedgecopy( recenttri, *searchtri ); +searchdist = dist; +if ( verbose > 2 ) { +printf( " Choosing recent triangle with origin (%.12g, %.12g).\n", +torg[0], torg[1] ); +} +} +} +} + +/* The number of random samples taken is proportional to the cube root of */ +/* the number of triangles in the mesh. The next bit of code assumes */ +/* that the number of triangles increases monotonically. */ +while ( SAMPLEFACTOR * samples * samples * samples < triangles.items ) { +samples++; +} +triblocks = ( triangles.maxitems + TRIPERBLOCK - 1 ) / TRIPERBLOCK; +samplesperblock = 1 + ( samples / triblocks ); +sampleblocks = samples / samplesperblock; +sampleblock = triangles.firstblock; +sampletri.orient = 0; +for ( i = 0; i < sampleblocks; i++ ) { +alignptr = (unsigned long) ( sampleblock + 1 ); +firsttri = (triangle *) ( alignptr + (unsigned long) triangles.alignbytes +- ( alignptr % (unsigned long) triangles.alignbytes )); +for ( j = 0; j < samplesperblock; j++ ) { +if ( i == triblocks - 1 ) { +samplenum = randomnation((int) +( triangles.maxitems - ( i * TRIPERBLOCK ))); +} +else { +samplenum = randomnation( TRIPERBLOCK ); +} +sampletri.tri = (triangle *) +( firsttri + ( samplenum * triangles.itemwords )); +if ( sampletri.tri[3] != (triangle) NULL ) { +org( sampletri, torg ); +dist = ( searchpoint[0] - torg[0] ) * ( searchpoint[0] - torg[0] ) ++ ( searchpoint[1] - torg[1] ) * ( searchpoint[1] - torg[1] ); +if ( dist < searchdist ) { +triedgecopy( sampletri, *searchtri ); +searchdist = dist; +if ( verbose > 2 ) { +printf( " Choosing triangle with origin (%.12g, %.12g).\n", +torg[0], torg[1] ); +} +} +} +} +sampleblock = (VOID **) *sampleblock; +} +/* Where are we? */ +org( *searchtri, torg ); +dest( *searchtri, tdest ); +/* Check the starting triangle's vertices. */ +if (( torg[0] == searchpoint[0] ) && ( torg[1] == searchpoint[1] )) { +return ONVERTEX; +} +if (( tdest[0] == searchpoint[0] ) && ( tdest[1] == searchpoint[1] )) { +lnextself( *searchtri ); +return ONVERTEX; +} +/* Orient `searchtri' to fit the preconditions of calling preciselocate(). */ +ahead = counterclockwise( torg, tdest, searchpoint ); +if ( ahead < 0.0 ) { +/* Turn around so that `searchpoint' is to the left of the */ +/* edge specified by `searchtri'. */ +symself( *searchtri ); +} +else if ( ahead == 0.0 ) { +/* Check if `searchpoint' is between `torg' and `tdest'. */ +if ((( torg[0] < searchpoint[0] ) == ( searchpoint[0] < tdest[0] )) +&& (( torg[1] < searchpoint[1] ) == ( searchpoint[1] < tdest[1] ))) { +return ONEDGE; +} +} +return preciselocate( searchpoint, searchtri ); } /** **/ @@ -5952,47 +6114,47 @@ void insertshelle( tri, shellemark ) struct triedge *tri; /* Edge at which to insert the new shell edge. */ int shellemark; /* Marker for the new shell edge. */ { - struct triedge oppotri; - struct edge newshelle; - point triorg, tridest; - triangle ptr; /* Temporary variable used by sym(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - /* Mark points if possible. */ - org( *tri, triorg ); - dest( *tri, tridest ); - if ( pointmark( triorg ) == 0 ) { - setpointmark( triorg, shellemark ); - } - if ( pointmark( tridest ) == 0 ) { - setpointmark( tridest, shellemark ); - } - /* Check if there's already a shell edge here. */ - tspivot( *tri, newshelle ); - if ( newshelle.sh == dummysh ) { - /* Make new shell edge and initialize its vertices. */ - makeshelle( &newshelle ); - setsorg( newshelle, tridest ); - setsdest( newshelle, triorg ); - /* Bond new shell edge to the two triangles it is sandwiched between. */ - /* Note that the facing triangle `oppotri' might be equal to */ - /* `dummytri' (outer space), but the new shell edge is bonded to it */ - /* all the same. */ - tsbond( *tri, newshelle ); - sym( *tri, oppotri ); - ssymself( newshelle ); - tsbond( oppotri, newshelle ); - setmark( newshelle, shellemark ); - if ( verbose > 2 ) { - printf( " Inserting new " ); - printshelle( &newshelle ); - } - } - else { - if ( mark( newshelle ) == 0 ) { - setmark( newshelle, shellemark ); - } - } +struct triedge oppotri; +struct edge newshelle; +point triorg, tridest; +triangle ptr; /* Temporary variable used by sym(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +/* Mark points if possible. */ +org( *tri, triorg ); +dest( *tri, tridest ); +if ( pointmark( triorg ) == 0 ) { +setpointmark( triorg, shellemark ); +} +if ( pointmark( tridest ) == 0 ) { +setpointmark( tridest, shellemark ); +} +/* Check if there's already a shell edge here. */ +tspivot( *tri, newshelle ); +if ( newshelle.sh == dummysh ) { +/* Make new shell edge and initialize its vertices. */ +makeshelle( &newshelle ); +setsorg( newshelle, tridest ); +setsdest( newshelle, triorg ); +/* Bond new shell edge to the two triangles it is sandwiched between. */ +/* Note that the facing triangle `oppotri' might be equal to */ +/* `dummytri' (outer space), but the new shell edge is bonded to it */ +/* all the same. */ +tsbond( *tri, newshelle ); +sym( *tri, oppotri ); +ssymself( newshelle ); +tsbond( oppotri, newshelle ); +setmark( newshelle, shellemark ); +if ( verbose > 2 ) { +printf( " Inserting new " ); +printshelle( &newshelle ); +} +} +else { +if ( mark( newshelle ) == 0 ) { +setmark( newshelle, shellemark ); +} +} } /*****************************************************************************/ @@ -6051,101 +6213,102 @@ int shellemark; /* Marker for the new shell edge. */ void flip( flipedge ) struct triedge *flipedge; /* Handle for the triangle abc. */ { - struct triedge botleft, botright; - struct triedge topleft, topright; - struct triedge top; - struct triedge botlcasing, botrcasing; - struct triedge toplcasing, toprcasing; - struct edge botlshelle, botrshelle; - struct edge toplshelle, toprshelle; - point leftpoint, rightpoint, botpoint; - point farpoint; - triangle ptr; /* Temporary variable used by sym(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - /* Identify the vertices of the quadrilateral. */ - org( *flipedge, rightpoint ); - dest( *flipedge, leftpoint ); - apex( *flipedge, botpoint ); - sym( *flipedge, top ); -#ifdef SELF_CHECK - if ( top.tri == dummytri ) { - printf( "Internal error in flip(): Attempt to flip on boundary.\n" ); - lnextself( *flipedge ); - return; - } - if ( checksegments ) { - tspivot( *flipedge, toplshelle ); - if ( toplshelle.sh != dummysh ) { - printf( "Internal error in flip(): Attempt to flip a segment.\n" ); - lnextself( *flipedge ); - return; - } - } +struct triedge botleft, botright; +struct triedge topleft, topright; +struct triedge top; +struct triedge botlcasing, botrcasing; +struct triedge toplcasing, toprcasing; +struct edge botlshelle, botrshelle; +struct edge toplshelle, toprshelle; +point leftpoint, rightpoint, botpoint; +point farpoint; +triangle ptr; /* Temporary variable used by sym(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +/* Identify the vertices of the quadrilateral. */ +org( *flipedge, rightpoint ); +dest( *flipedge, leftpoint ); +apex( *flipedge, botpoint ); +sym( *flipedge, top ); +#ifdef +SELF_CHECK +if ( top.tri == dummytri ) { +printf( "Internal error in flip(): Attempt to flip on boundary.\n" ); +lnextself( *flipedge ); +return; +} +if ( checksegments ) { +tspivot( *flipedge, toplshelle ); +if ( toplshelle.sh != dummysh ) { +printf( "Internal error in flip(): Attempt to flip a segment.\n" ); +lnextself( *flipedge ); +return; +} +} #endif /* SELF_CHECK */ - apex( top, farpoint ); - - /* Identify the casing of the quadrilateral. */ - lprev( top, topleft ); - sym( topleft, toplcasing ); - lnext( top, topright ); - sym( topright, toprcasing ); - lnext( *flipedge, botleft ); - sym( botleft, botlcasing ); - lprev( *flipedge, botright ); - sym( botright, botrcasing ); - /* Rotate the quadrilateral one-quarter turn counterclockwise. */ - bond( topleft, botlcasing ); - bond( botleft, botrcasing ); - bond( botright, toprcasing ); - bond( topright, toplcasing ); - - if ( checksegments ) { - /* Check for shell edges and rebond them to the quadrilateral. */ - tspivot( topleft, toplshelle ); - tspivot( botleft, botlshelle ); - tspivot( botright, botrshelle ); - tspivot( topright, toprshelle ); - if ( toplshelle.sh == dummysh ) { - tsdissolve( topright ); - } - else { - tsbond( topright, toplshelle ); - } - if ( botlshelle.sh == dummysh ) { - tsdissolve( topleft ); - } - else { - tsbond( topleft, botlshelle ); - } - if ( botrshelle.sh == dummysh ) { - tsdissolve( botleft ); - } - else { - tsbond( botleft, botrshelle ); - } - if ( toprshelle.sh == dummysh ) { - tsdissolve( botright ); - } - else { - tsbond( botright, toprshelle ); - } - } - - /* New point assignments for the rotated quadrilateral. */ - setorg( *flipedge, farpoint ); - setdest( *flipedge, botpoint ); - setapex( *flipedge, rightpoint ); - setorg( top, botpoint ); - setdest( top, farpoint ); - setapex( top, leftpoint ); - if ( verbose > 2 ) { - printf( " Edge flip results in left " ); - lnextself( topleft ); - printtriangle( &topleft ); - printf( " and right " ); - printtriangle( flipedge ); - } +apex( top, farpoint ); + +/* Identify the casing of the quadrilateral. */ +lprev( top, topleft ); +sym( topleft, toplcasing ); +lnext( top, topright ); +sym( topright, toprcasing ); +lnext( *flipedge, botleft ); +sym( botleft, botlcasing ); +lprev( *flipedge, botright ); +sym( botright, botrcasing ); +/* Rotate the quadrilateral one-quarter turn counterclockwise. */ +bond( topleft, botlcasing ); +bond( botleft, botrcasing ); +bond( botright, toprcasing ); +bond( topright, toplcasing ); + +if ( checksegments ) { +/* Check for shell edges and rebond them to the quadrilateral. */ +tspivot( topleft, toplshelle ); +tspivot( botleft, botlshelle ); +tspivot( botright, botrshelle ); +tspivot( topright, toprshelle ); +if ( toplshelle.sh == dummysh ) { +tsdissolve( topright ); +} +else { +tsbond( topright, toplshelle ); +} +if ( botlshelle.sh == dummysh ) { +tsdissolve( topleft ); +} +else { +tsbond( topleft, botlshelle ); +} +if ( botrshelle.sh == dummysh ) { +tsdissolve( botleft ); +} +else { +tsbond( botleft, botrshelle ); +} +if ( toprshelle.sh == dummysh ) { +tsdissolve( botright ); +} +else { +tsbond( botright, toprshelle ); +} +} + +/* New point assignments for the rotated quadrilateral. */ +setorg( *flipedge, farpoint ); +setdest( *flipedge, botpoint ); +setapex( *flipedge, rightpoint ); +setorg( top, botpoint ); +setdest( top, farpoint ); +setapex( top, leftpoint ); +if ( verbose > 2 ) { +printf( " Edge flip results in left " ); +lnextself( topleft ); +printtriangle( &topleft ); +printf( " and right " ); +printtriangle( flipedge ); +} } /*****************************************************************************/ @@ -6196,544 +6359,549 @@ struct triedge *flipedge; /* Handle for the triangle abc. */ /*****************************************************************************/ enum insertsiteresult insertsite( insertpoint, searchtri, splitedge, - segmentflaws, triflaws ) +segmentflaws, triflaws ) point insertpoint; struct triedge *searchtri; struct edge *splitedge; int segmentflaws; int triflaws; { - struct triedge horiz; - struct triedge top; - struct triedge botleft, botright; - struct triedge topleft, topright; - struct triedge newbotleft, newbotright; - struct triedge newtopright; - struct triedge botlcasing, botrcasing; - struct triedge toplcasing, toprcasing; - struct triedge testtri; - struct edge botlshelle, botrshelle; - struct edge toplshelle, toprshelle; - struct edge brokenshelle; - struct edge checkshelle; - struct edge rightedge; - struct edge newedge; - struct edge *encroached; - point first; - point leftpoint, rightpoint, botpoint, toppoint, farpoint; - REAL attrib; - REAL area; - enum insertsiteresult success; - enum locateresult intersect; - int doflip; - int mirrorflag; - int i; - triangle ptr; /* Temporary variable used by sym(). */ - shelle sptr; /* Temporary variable used by spivot() and tspivot(). */ - - if ( verbose > 1 ) { - printf( " Inserting (%.12g, %.12g).\n", insertpoint[0], insertpoint[1] ); - } - if ( splitedge == (struct edge *) NULL ) { - /* Find the location of the point to be inserted. Check if a good */ - /* starting triangle has already been provided by the caller. */ - if ( searchtri->tri == (triangle *) NULL ) { - /* Find a boundary triangle. */ - horiz.tri = dummytri; - horiz.orient = 0; - symself( horiz ); - /* Search for a triangle containing `insertpoint'. */ - intersect = locate( insertpoint, &horiz ); - } - else { - /* Start searching from the triangle provided by the caller. */ - triedgecopy( *searchtri, horiz ); - intersect = preciselocate( insertpoint, &horiz ); - } - } - else { - /* The calling routine provides the edge in which the point is inserted. */ - triedgecopy( *searchtri, horiz ); - intersect = ONEDGE; - } - if ( intersect == ONVERTEX ) { - /* There's already a vertex there. Return in `searchtri' a triangle */ - /* whose origin is the existing vertex. */ - triedgecopy( horiz, *searchtri ); - triedgecopy( horiz, recenttri ); - return DUPLICATEPOINT; - } - if ( ( intersect == ONEDGE ) || ( intersect == OUTSIDE ) ) { - /* The vertex falls on an edge or boundary. */ - if ( checksegments && ( splitedge == (struct edge *) NULL ) ) { - /* Check whether the vertex falls on a shell edge. */ - tspivot( horiz, brokenshelle ); - if ( brokenshelle.sh != dummysh ) { - /* The vertex falls on a shell edge. */ - if ( segmentflaws ) { - if ( nobisect == 0 ) { - /* Add the shell edge to the list of encroached segments. */ - encroached = (struct edge *) poolalloc( &badsegments ); - shellecopy( brokenshelle, *encroached ); - } - else if ( ( nobisect == 1 ) && ( intersect == ONEDGE ) ) { - /* This segment may be split only if it is an internal boundary. */ - sym( horiz, testtri ); - if ( testtri.tri != dummytri ) { - /* Add the shell edge to the list of encroached segments. */ - encroached = (struct edge *) poolalloc( &badsegments ); - shellecopy( brokenshelle, *encroached ); - } - } - } - /* Return a handle whose primary edge contains the point, */ - /* which has not been inserted. */ - triedgecopy( horiz, *searchtri ); - triedgecopy( horiz, recenttri ); - return VIOLATINGPOINT; - } - } - /* Insert the point on an edge, dividing one triangle into two (if */ - /* the edge lies on a boundary) or two triangles into four. */ - lprev( horiz, botright ); - sym( botright, botrcasing ); - sym( horiz, topright ); - /* Is there a second triangle? (Or does this edge lie on a boundary?) */ - mirrorflag = topright.tri != dummytri; - if ( mirrorflag ) { - lnextself( topright ); - sym( topright, toprcasing ); - maketriangle( &newtopright ); - } - else { - /* Splitting the boundary edge increases the number of boundary edges. */ - hullsize++; - } - maketriangle( &newbotright ); - - /* Set the vertices of changed and new triangles. */ - org( horiz, rightpoint ); - dest( horiz, leftpoint ); - apex( horiz, botpoint ); - setorg( newbotright, botpoint ); - setdest( newbotright, rightpoint ); - setapex( newbotright, insertpoint ); - setorg( horiz, insertpoint ); - for ( i = 0; i < eextras; i++ ) { - /* Set the element attributes of a new triangle. */ - setelemattribute( newbotright, i, elemattribute( botright, i ) ); - } - if ( vararea ) { - /* Set the area constraint of a new triangle. */ - setareabound( newbotright, areabound( botright ) ); - } - if ( mirrorflag ) { - dest( topright, toppoint ); - setorg( newtopright, rightpoint ); - setdest( newtopright, toppoint ); - setapex( newtopright, insertpoint ); - setorg( topright, insertpoint ); - for ( i = 0; i < eextras; i++ ) { - /* Set the element attributes of another new triangle. */ - setelemattribute( newtopright, i, elemattribute( topright, i ) ); - } - if ( vararea ) { - /* Set the area constraint of another new triangle. */ - setareabound( newtopright, areabound( topright ) ); - } - } - - /* There may be shell edges that need to be bonded */ - /* to the new triangle(s). */ - if ( checksegments ) { - tspivot( botright, botrshelle ); - if ( botrshelle.sh != dummysh ) { - tsdissolve( botright ); - tsbond( newbotright, botrshelle ); - } - if ( mirrorflag ) { - tspivot( topright, toprshelle ); - if ( toprshelle.sh != dummysh ) { - tsdissolve( topright ); - tsbond( newtopright, toprshelle ); - } - } - } - - /* Bond the new triangle(s) to the surrounding triangles. */ - bond( newbotright, botrcasing ); - lprevself( newbotright ); - bond( newbotright, botright ); - lprevself( newbotright ); - if ( mirrorflag ) { - bond( newtopright, toprcasing ); - lnextself( newtopright ); - bond( newtopright, topright ); - lnextself( newtopright ); - bond( newtopright, newbotright ); - } - - if ( splitedge != (struct edge *) NULL ) { - /* Split the shell edge into two. */ - setsdest( *splitedge, insertpoint ); - ssymself( *splitedge ); - spivot( *splitedge, rightedge ); - insertshelle( &newbotright, mark( *splitedge ) ); - tspivot( newbotright, newedge ); - sbond( *splitedge, newedge ); - ssymself( newedge ); - sbond( newedge, rightedge ); - ssymself( *splitedge ); - } - -#ifdef SELF_CHECK - if ( counterclockwise( rightpoint, leftpoint, botpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle prior to edge point insertion (bottom).\n" ); - } - if ( mirrorflag ) { - if ( counterclockwise( leftpoint, rightpoint, toppoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle prior to edge point insertion (top).\n" ); - } - if ( counterclockwise( rightpoint, toppoint, insertpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle after edge point insertion (top right).\n" - ); - } - if ( counterclockwise( toppoint, leftpoint, insertpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle after edge point insertion (top left).\n" - ); - } - } - if ( counterclockwise( leftpoint, botpoint, insertpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle after edge point insertion (bottom left).\n" - ); - } - if ( counterclockwise( botpoint, rightpoint, insertpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( - " Clockwise triangle after edge point insertion (bottom right).\n" ); - } +struct triedge horiz; +struct triedge top; +struct triedge botleft, botright; +struct triedge topleft, topright; +struct triedge newbotleft, newbotright; +struct triedge newtopright; +struct triedge botlcasing, botrcasing; +struct triedge toplcasing, toprcasing; +struct triedge testtri; +struct edge botlshelle, botrshelle; +struct edge toplshelle, toprshelle; +struct edge brokenshelle; +struct edge checkshelle; +struct edge rightedge; +struct edge newedge; +struct edge *encroached; +point first; +point leftpoint, rightpoint, botpoint, toppoint, farpoint; +REAL attrib; +REAL area; +enum insertsiteresult success; +enum locateresult intersect; +int doflip; +int mirrorflag; +int i; +triangle ptr; /* Temporary variable used by sym(). */ +shelle sptr; /* Temporary variable used by spivot() and tspivot(). */ + +if ( verbose > 1 ) { +printf( " Inserting (%.12g, %.12g).\n", insertpoint[0], insertpoint[1] ); +} +if ( splitedge == (struct edge *) NULL ) { +/* Find the location of the point to be inserted. Check if a good */ +/* starting triangle has already been provided by the caller. */ +if ( searchtri->tri == (triangle *) NULL ) { +/* Find a boundary triangle. */ +horiz.tri = dummytri; +horiz.orient = 0; +symself( horiz ); +/* Search for a triangle containing `insertpoint'. */ +intersect = locate( insertpoint, &horiz ); +} +else { +/* Start searching from the triangle provided by the caller. */ +triedgecopy( *searchtri, horiz ); +intersect = preciselocate( insertpoint, &horiz ); +} +} +else { +/* The calling routine provides the edge in which the point is inserted. */ +triedgecopy( *searchtri, horiz ); +intersect = ONEDGE; +} +if ( intersect == ONVERTEX ) { +/* There's already a vertex there. Return in `searchtri' a triangle */ +/* whose origin is the existing vertex. */ +triedgecopy( horiz, *searchtri ); +triedgecopy( horiz, recenttri ); +return DUPLICATEPOINT; +} +if (( intersect == ONEDGE ) || ( intersect == OUTSIDE )) { +/* The vertex falls on an edge or boundary. */ +if ( checksegments && ( splitedge == (struct edge *) NULL )) { +/* Check whether the vertex falls on a shell edge. */ +tspivot( horiz, brokenshelle ); +if ( brokenshelle.sh != dummysh ) { +/* The vertex falls on a shell edge. */ +if ( segmentflaws ) { +if ( nobisect == 0 ) { +/* Add the shell edge to the list of encroached segments. */ +encroached = (struct edge *) poolalloc( &badsegments ); +shellecopy( brokenshelle, *encroached ); +} +else if (( nobisect == 1 ) && ( intersect == ONEDGE )) { +/* This segment may be split only if it is an internal boundary. */ +sym( horiz, testtri ); +if ( testtri.tri != dummytri ) { +/* Add the shell edge to the list of encroached segments. */ +encroached = (struct edge *) poolalloc( &badsegments ); +shellecopy( brokenshelle, *encroached ); +} +} +} +/* Return a handle whose primary edge contains the point, */ +/* which has not been inserted. */ +triedgecopy( horiz, *searchtri ); +triedgecopy( horiz, recenttri ); +return VIOLATINGPOINT; +} +} +/* Insert the point on an edge, dividing one triangle into two (if */ +/* the edge lies on a boundary) or two triangles into four. */ +lprev( horiz, botright ); +sym( botright, botrcasing ); +sym( horiz, topright ); +/* Is there a second triangle? (Or does this edge lie on a boundary?) */ +mirrorflag = topright.tri != dummytri; +if ( mirrorflag ) { +lnextself( topright ); +sym( topright, toprcasing ); +maketriangle( &newtopright ); +} +else { +/* Splitting the boundary edge increases the number of boundary edges. */ +hullsize++; +} +maketriangle( &newbotright ); + +/* Set the vertices of changed and new triangles. */ +org( horiz, rightpoint ); +dest( horiz, leftpoint ); +apex( horiz, botpoint ); +setorg( newbotright, botpoint ); +setdest( newbotright, rightpoint ); +setapex( newbotright, insertpoint ); +setorg( horiz, insertpoint ); +for ( i = 0; i < eextras; i++ ) { +/* Set the element attributes of a new triangle. */ +setelemattribute( newbotright, i, elemattribute( botright, i )); +} +if ( vararea ) { +/* Set the area constraint of a new triangle. */ +setareabound( newbotright, areabound( botright )); +} +if ( mirrorflag ) { +dest( topright, toppoint ); +setorg( newtopright, rightpoint ); +setdest( newtopright, toppoint ); +setapex( newtopright, insertpoint ); +setorg( topright, insertpoint ); +for ( i = 0; i < eextras; i++ ) { +/* Set the element attributes of another new triangle. */ +setelemattribute( newtopright, i, elemattribute( topright, i )); +} +if ( vararea ) { +/* Set the area constraint of another new triangle. */ +setareabound( newtopright, areabound( topright )); +} +} + +/* There may be shell edges that need to be bonded */ +/* to the new triangle(s). */ +if ( checksegments ) { +tspivot( botright, botrshelle ); +if ( botrshelle.sh != dummysh ) { +tsdissolve( botright ); +tsbond( newbotright, botrshelle ); +} +if ( mirrorflag ) { +tspivot( topright, toprshelle ); +if ( toprshelle.sh != dummysh ) { +tsdissolve( topright ); +tsbond( newtopright, toprshelle ); +} +} +} + +/* Bond the new triangle(s) to the surrounding triangles. */ +bond( newbotright, botrcasing ); +lprevself( newbotright ); +bond( newbotright, botright ); +lprevself( newbotright ); +if ( mirrorflag ) { +bond( newtopright, toprcasing ); +lnextself( newtopright ); +bond( newtopright, topright ); +lnextself( newtopright ); +bond( newtopright, newbotright ); +} + +if ( splitedge != (struct edge *) NULL ) { +/* Split the shell edge into two. */ +setsdest( *splitedge, insertpoint ); +ssymself( *splitedge ); +spivot( *splitedge, rightedge ); +insertshelle( &newbotright, mark( *splitedge )); +tspivot( newbotright, newedge ); +sbond( *splitedge, newedge ); +ssymself( newedge ); +sbond( newedge, rightedge ); +ssymself( *splitedge ); +} + +#ifdef +SELF_CHECK +if ( counterclockwise( rightpoint, leftpoint, botpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle prior to edge point insertion (bottom).\n" ); +} +if ( mirrorflag ) { +if ( counterclockwise( leftpoint, rightpoint, toppoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle prior to edge point insertion (top).\n" ); +} +if ( counterclockwise( rightpoint, toppoint, insertpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle after edge point insertion (top right).\n" +); +} +if ( counterclockwise( toppoint, leftpoint, insertpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle after edge point insertion (top left).\n" +); +} +} +if ( counterclockwise( leftpoint, botpoint, insertpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle after edge point insertion (bottom left).\n" +); +} +if ( counterclockwise( botpoint, rightpoint, insertpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( +" Clockwise triangle after edge point insertion (bottom right).\n" ); +} #endif /* SELF_CHECK */ - if ( verbose > 2 ) { - printf( " Updating bottom left " ); - printtriangle( &botright ); - if ( mirrorflag ) { - printf( " Updating top left " ); - printtriangle( &topright ); - printf( " Creating top right " ); - printtriangle( &newtopright ); - } - printf( " Creating bottom right " ); - printtriangle( &newbotright ); - } - - /* Position `horiz' on the first edge to check for */ - /* the Delaunay property. */ - lnextself( horiz ); - } - else { - /* Insert the point in a triangle, splitting it into three. */ - lnext( horiz, botleft ); - lprev( horiz, botright ); - sym( botleft, botlcasing ); - sym( botright, botrcasing ); - maketriangle( &newbotleft ); - maketriangle( &newbotright ); - - /* Set the vertices of changed and new triangles. */ - org( horiz, rightpoint ); - dest( horiz, leftpoint ); - apex( horiz, botpoint ); - setorg( newbotleft, leftpoint ); - setdest( newbotleft, botpoint ); - setapex( newbotleft, insertpoint ); - setorg( newbotright, botpoint ); - setdest( newbotright, rightpoint ); - setapex( newbotright, insertpoint ); - setapex( horiz, insertpoint ); - for ( i = 0; i < eextras; i++ ) { - /* Set the element attributes of the new triangles. */ - attrib = elemattribute( horiz, i ); - setelemattribute( newbotleft, i, attrib ); - setelemattribute( newbotright, i, attrib ); - } - if ( vararea ) { - /* Set the area constraint of the new triangles. */ - area = areabound( horiz ); - setareabound( newbotleft, area ); - setareabound( newbotright, area ); - } - - /* There may be shell edges that need to be bonded */ - /* to the new triangles. */ - if ( checksegments ) { - tspivot( botleft, botlshelle ); - if ( botlshelle.sh != dummysh ) { - tsdissolve( botleft ); - tsbond( newbotleft, botlshelle ); - } - tspivot( botright, botrshelle ); - if ( botrshelle.sh != dummysh ) { - tsdissolve( botright ); - tsbond( newbotright, botrshelle ); - } - } - - /* Bond the new triangles to the surrounding triangles. */ - bond( newbotleft, botlcasing ); - bond( newbotright, botrcasing ); - lnextself( newbotleft ); - lprevself( newbotright ); - bond( newbotleft, newbotright ); - lnextself( newbotleft ); - bond( botleft, newbotleft ); - lprevself( newbotright ); - bond( botright, newbotright ); - -#ifdef SELF_CHECK - if ( counterclockwise( rightpoint, leftpoint, botpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle prior to point insertion.\n" ); - } - if ( counterclockwise( rightpoint, leftpoint, insertpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle after point insertion (top).\n" ); - } - if ( counterclockwise( leftpoint, botpoint, insertpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle after point insertion (left).\n" ); - } - if ( counterclockwise( botpoint, rightpoint, insertpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle after point insertion (right).\n" ); - } +if ( verbose > 2 ) { +printf( " Updating bottom left " ); +printtriangle( &botright ); +if ( mirrorflag ) { +printf( " Updating top left " ); +printtriangle( &topright ); +printf( " Creating top right " ); +printtriangle( &newtopright ); +} +printf( " Creating bottom right " ); +printtriangle( &newbotright ); +} + +/* Position `horiz' on the first edge to check for */ +/* the Delaunay property. */ +lnextself( horiz ); +} +else { +/* Insert the point in a triangle, splitting it into three. */ +lnext( horiz, botleft ); +lprev( horiz, botright ); +sym( botleft, botlcasing ); +sym( botright, botrcasing ); +maketriangle( &newbotleft ); +maketriangle( &newbotright ); + +/* Set the vertices of changed and new triangles. */ +org( horiz, rightpoint ); +dest( horiz, leftpoint ); +apex( horiz, botpoint ); +setorg( newbotleft, leftpoint ); +setdest( newbotleft, botpoint ); +setapex( newbotleft, insertpoint ); +setorg( newbotright, botpoint ); +setdest( newbotright, rightpoint ); +setapex( newbotright, insertpoint ); +setapex( horiz, insertpoint ); +for ( i = 0; i < eextras; i++ ) { +/* Set the element attributes of the new triangles. */ +attrib = elemattribute( horiz, i ); +setelemattribute( newbotleft, i, attrib ); +setelemattribute( newbotright, i, attrib ); +} +if ( vararea ) { +/* Set the area constraint of the new triangles. */ +area = areabound( horiz ); +setareabound( newbotleft, area ); +setareabound( newbotright, area ); +} + +/* There may be shell edges that need to be bonded */ +/* to the new triangles. */ +if ( checksegments ) { +tspivot( botleft, botlshelle ); +if ( botlshelle.sh != dummysh ) { +tsdissolve( botleft ); +tsbond( newbotleft, botlshelle ); +} +tspivot( botright, botrshelle ); +if ( botrshelle.sh != dummysh ) { +tsdissolve( botright ); +tsbond( newbotright, botrshelle ); +} +} + +/* Bond the new triangles to the surrounding triangles. */ +bond( newbotleft, botlcasing ); +bond( newbotright, botrcasing ); +lnextself( newbotleft ); +lprevself( newbotright ); +bond( newbotleft, newbotright ); +lnextself( newbotleft ); +bond( botleft, newbotleft ); +lprevself( newbotright ); +bond( botright, newbotright ); + +#ifdef +SELF_CHECK +if ( counterclockwise( rightpoint, leftpoint, botpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle prior to point insertion.\n" ); +} +if ( counterclockwise( rightpoint, leftpoint, insertpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle after point insertion (top).\n" ); +} +if ( counterclockwise( leftpoint, botpoint, insertpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle after point insertion (left).\n" ); +} +if ( counterclockwise( botpoint, rightpoint, insertpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle after point insertion (right).\n" ); +} #endif /* SELF_CHECK */ - if ( verbose > 2 ) { - printf( " Updating top " ); - printtriangle( &horiz ); - printf( " Creating left " ); - printtriangle( &newbotleft ); - printf( " Creating right " ); - printtriangle( &newbotright ); - } - } - - /* The insertion is successful by default, unless an encroached */ - /* edge is found. */ - success = SUCCESSFULPOINT; - /* Circle around the newly inserted vertex, checking each edge opposite */ - /* it for the Delaunay property. Non-Delaunay edges are flipped. */ - /* `horiz' is always the edge being checked. `first' marks where to */ - /* stop circling. */ - org( horiz, first ); - rightpoint = first; - dest( horiz, leftpoint ); - /* Circle until finished. */ - while ( 1 ) { - /* By default, the edge will be flipped. */ - doflip = 1; - if ( checksegments ) { - /* Check for a segment, which cannot be flipped. */ - tspivot( horiz, checkshelle ); - if ( checkshelle.sh != dummysh ) { - /* The edge is a segment and cannot be flipped. */ - doflip = 0; -#ifndef CDT_ONLY - if ( segmentflaws ) { - /* Does the new point encroach upon this segment? */ - if ( checkedge4encroach( &checkshelle ) ) { - success = ENCROACHINGPOINT; - } - } +if ( verbose > 2 ) { +printf( " Updating top " ); +printtriangle( &horiz ); +printf( " Creating left " ); +printtriangle( &newbotleft ); +printf( " Creating right " ); +printtriangle( &newbotright ); +} +} + +/* The insertion is successful by default, unless an encroached */ +/* edge is found. */ +success = SUCCESSFULPOINT; +/* Circle around the newly inserted vertex, checking each edge opposite */ +/* it for the Delaunay property. Non-Delaunay edges are flipped. */ +/* `horiz' is always the edge being checked. `first' marks where to */ +/* stop circling. */ +org( horiz, first ); +rightpoint = first; +dest( horiz, leftpoint ); +/* Circle until finished. */ +while ( 1 ) { +/* By default, the edge will be flipped. */ +doflip = 1; +if ( checksegments ) { +/* Check for a segment, which cannot be flipped. */ +tspivot( horiz, checkshelle ); +if ( checkshelle.sh != dummysh ) { +/* The edge is a segment and cannot be flipped. */ +doflip = 0; +#ifndef +CDT_ONLY +if ( segmentflaws ) { +/* Does the new point encroach upon this segment? */ +if ( checkedge4encroach( &checkshelle )) { +success = ENCROACHINGPOINT; +} +} #endif /* not CDT_ONLY */ - } - } - if ( doflip ) { - /* Check if the edge is a boundary edge. */ - sym( horiz, top ); - if ( top.tri == dummytri ) { - /* The edge is a boundary edge and cannot be flipped. */ - doflip = 0; - } - else { - /* Find the point on the other side of the edge. */ - apex( top, farpoint ); - /* In the incremental Delaunay triangulation algorithm, any of */ - /* `leftpoint', `rightpoint', and `farpoint' could be vertices */ - /* of the triangular bounding box. These vertices must be */ - /* treated as if they are infinitely distant, even though their */ - /* "coordinates" are not. */ - if ( ( leftpoint == infpoint1 ) || ( leftpoint == infpoint2 ) - || ( leftpoint == infpoint3 ) ) { - /* `leftpoint' is infinitely distant. Check the convexity of */ - /* the boundary of the triangulation. 'farpoint' might be */ - /* infinite as well, but trust me, this same condition */ - /* should be applied. */ - doflip = counterclockwise( insertpoint, rightpoint, farpoint ) > 0.0; - } - else if ( ( rightpoint == infpoint1 ) || ( rightpoint == infpoint2 ) - || ( rightpoint == infpoint3 ) ) { - /* `rightpoint' is infinitely distant. Check the convexity of */ - /* the boundary of the triangulation. 'farpoint' might be */ - /* infinite as well, but trust me, this same condition */ - /* should be applied. */ - doflip = counterclockwise( farpoint, leftpoint, insertpoint ) > 0.0; - } - else if ( ( farpoint == infpoint1 ) || ( farpoint == infpoint2 ) - || ( farpoint == infpoint3 ) ) { - /* `farpoint' is infinitely distant and cannot be inside */ - /* the circumcircle of the triangle `horiz'. */ - doflip = 0; - } - else { - /* Test whether the edge is locally Delaunay. */ - doflip = incircle( leftpoint, insertpoint, rightpoint, farpoint ) - > 0.0; - } - if ( doflip ) { - /* We made it! Flip the edge `horiz' by rotating its containing */ - /* quadrilateral (the two triangles adjacent to `horiz'). */ - /* Identify the casing of the quadrilateral. */ - lprev( top, topleft ); - sym( topleft, toplcasing ); - lnext( top, topright ); - sym( topright, toprcasing ); - lnext( horiz, botleft ); - sym( botleft, botlcasing ); - lprev( horiz, botright ); - sym( botright, botrcasing ); - /* Rotate the quadrilateral one-quarter turn counterclockwise. */ - bond( topleft, botlcasing ); - bond( botleft, botrcasing ); - bond( botright, toprcasing ); - bond( topright, toplcasing ); - if ( checksegments ) { - /* Check for shell edges and rebond them to the quadrilateral. */ - tspivot( topleft, toplshelle ); - tspivot( botleft, botlshelle ); - tspivot( botright, botrshelle ); - tspivot( topright, toprshelle ); - if ( toplshelle.sh == dummysh ) { - tsdissolve( topright ); - } - else { - tsbond( topright, toplshelle ); - } - if ( botlshelle.sh == dummysh ) { - tsdissolve( topleft ); - } - else { - tsbond( topleft, botlshelle ); - } - if ( botrshelle.sh == dummysh ) { - tsdissolve( botleft ); - } - else { - tsbond( botleft, botrshelle ); - } - if ( toprshelle.sh == dummysh ) { - tsdissolve( botright ); - } - else { - tsbond( botright, toprshelle ); - } - } - /* New point assignments for the rotated quadrilateral. */ - setorg( horiz, farpoint ); - setdest( horiz, insertpoint ); - setapex( horiz, rightpoint ); - setorg( top, insertpoint ); - setdest( top, farpoint ); - setapex( top, leftpoint ); - for ( i = 0; i < eextras; i++ ) { - /* Take the average of the two triangles' attributes. */ - attrib = (REAL)( 0.5 * ( elemattribute( top, i ) + elemattribute( horiz, i ) ) ); - setelemattribute( top, i, attrib ); - setelemattribute( horiz, i, attrib ); - } - if ( vararea ) { - if ( ( areabound( top ) <= 0.0 ) || ( areabound( horiz ) <= 0.0 ) ) { - area = -1.0; - } - else { - /* Take the average of the two triangles' area constraints. */ - /* This prevents small area constraints from migrating a */ - /* long, long way from their original location due to flips. */ - area = (REAL)( 0.5 * ( areabound( top ) + areabound( horiz ) ) ); - } - setareabound( top, area ); - setareabound( horiz, area ); - } -#ifdef SELF_CHECK - if ( insertpoint != (point) NULL ) { - if ( counterclockwise( leftpoint, insertpoint, rightpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle prior to edge flip (bottom).\n" ); - } - /* The following test has been removed because constrainededge() */ - /* sometimes generates inverted triangles that insertsite() */ - /* removes. */ +} +} +if ( doflip ) { +/* Check if the edge is a boundary edge. */ +sym( horiz, top ); +if ( top.tri == dummytri ) { +/* The edge is a boundary edge and cannot be flipped. */ +doflip = 0; +} +else { +/* Find the point on the other side of the edge. */ +apex( top, farpoint ); +/* In the incremental Delaunay triangulation algorithm, any of */ +/* `leftpoint', `rightpoint', and `farpoint' could be vertices */ +/* of the triangular bounding box. These vertices must be */ +/* treated as if they are infinitely distant, even though their */ +/* "coordinates" are not. */ +if (( leftpoint == infpoint1 ) || ( leftpoint == infpoint2 ) +|| ( leftpoint == infpoint3 )) { +/* `leftpoint' is infinitely distant. Check the convexity of */ +/* the boundary of the triangulation. 'farpoint' might be */ +/* infinite as well, but trust me, this same condition */ +/* should be applied. */ +doflip = counterclockwise( insertpoint, rightpoint, farpoint ) > 0.0; +} +else if (( rightpoint == infpoint1 ) || ( rightpoint == infpoint2 ) +|| ( rightpoint == infpoint3 )) { +/* `rightpoint' is infinitely distant. Check the convexity of */ +/* the boundary of the triangulation. 'farpoint' might be */ +/* infinite as well, but trust me, this same condition */ +/* should be applied. */ +doflip = counterclockwise( farpoint, leftpoint, insertpoint ) > 0.0; +} +else if (( farpoint == infpoint1 ) || ( farpoint == infpoint2 ) +|| ( farpoint == infpoint3 )) { +/* `farpoint' is infinitely distant and cannot be inside */ +/* the circumcircle of the triangle `horiz'. */ +doflip = 0; +} +else { +/* Test whether the edge is locally Delaunay. */ +doflip = incircle( leftpoint, insertpoint, rightpoint, farpoint ) +> 0.0; +} +if ( doflip ) { +/* We made it! Flip the edge `horiz' by rotating its containing */ +/* quadrilateral (the two triangles adjacent to `horiz'). */ +/* Identify the casing of the quadrilateral. */ +lprev( top, topleft ); +sym( topleft, toplcasing ); +lnext( top, topright ); +sym( topright, toprcasing ); +lnext( horiz, botleft ); +sym( botleft, botlcasing ); +lprev( horiz, botright ); +sym( botright, botrcasing ); +/* Rotate the quadrilateral one-quarter turn counterclockwise. */ +bond( topleft, botlcasing ); +bond( botleft, botrcasing ); +bond( botright, toprcasing ); +bond( topright, toplcasing ); +if ( checksegments ) { +/* Check for shell edges and rebond them to the quadrilateral. */ +tspivot( topleft, toplshelle ); +tspivot( botleft, botlshelle ); +tspivot( botright, botrshelle ); +tspivot( topright, toprshelle ); +if ( toplshelle.sh == dummysh ) { +tsdissolve( topright ); +} +else { +tsbond( topright, toplshelle ); +} +if ( botlshelle.sh == dummysh ) { +tsdissolve( topleft ); +} +else { +tsbond( topleft, botlshelle ); +} +if ( botrshelle.sh == dummysh ) { +tsdissolve( botleft ); +} +else { +tsbond( botleft, botrshelle ); +} +if ( toprshelle.sh == dummysh ) { +tsdissolve( botright ); +} +else { +tsbond( botright, toprshelle ); +} +} +/* New point assignments for the rotated quadrilateral. */ +setorg( horiz, farpoint ); +setdest( horiz, insertpoint ); +setapex( horiz, rightpoint ); +setorg( top, insertpoint ); +setdest( top, farpoint ); +setapex( top, leftpoint ); +for ( i = 0; i < eextras; i++ ) { +/* Take the average of the two triangles' attributes. */ +attrib = (REAL)( 0.5 * ( elemattribute( top, i ) + elemattribute( horiz, i ))); +setelemattribute( top, i, attrib ); +setelemattribute( horiz, i, attrib ); +} +if ( vararea ) { +if (( areabound( top ) <= 0.0 ) || ( areabound( horiz ) <= 0.0 )) { +area = -1.0; +} +else { +/* Take the average of the two triangles' area constraints. */ +/* This prevents small area constraints from migrating a */ +/* long, long way from their original location due to flips. */ +area = (REAL)( 0.5 * ( areabound( top ) + areabound( horiz ))); +} +setareabound( top, area ); +setareabound( horiz, area ); +} +#ifdef +SELF_CHECK +if ( insertpoint != (point) NULL ) { +if ( counterclockwise( leftpoint, insertpoint, rightpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle prior to edge flip (bottom).\n" ); +} +/* The following test has been removed because constrainededge() */ +/* sometimes generates inverted triangles that insertsite() */ +/* removes. */ /* if (counterclockwise(rightpoint, farpoint, leftpoint) < 0.0) { printf("Internal error in insertsite():\n"); printf(" Clockwise triangle prior to edge flip (top).\n"); } */ - if ( counterclockwise( farpoint, leftpoint, insertpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle after edge flip (left).\n" ); - } - if ( counterclockwise( insertpoint, rightpoint, farpoint ) < 0.0 ) { - printf( "Internal error in insertsite():\n" ); - printf( " Clockwise triangle after edge flip (right).\n" ); - } - } +if ( counterclockwise( farpoint, leftpoint, insertpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle after edge flip (left).\n" ); +} +if ( counterclockwise( insertpoint, rightpoint, farpoint ) < 0.0 ) { +printf( "Internal error in insertsite():\n" ); +printf( " Clockwise triangle after edge flip (right).\n" ); +} +} #endif /* SELF_CHECK */ - if ( verbose > 2 ) { - printf( " Edge flip results in left " ); - lnextself( topleft ); - printtriangle( &topleft ); - printf( " and right " ); - printtriangle( &horiz ); - } - /* On the next iterations, consider the two edges that were */ - /* exposed (this is, are now visible to the newly inserted */ - /* point) by the edge flip. */ - lprevself( horiz ); - leftpoint = farpoint; - } - } - } - if ( !doflip ) { - /* The handle `horiz' is accepted as locally Delaunay. */ -#ifndef CDT_ONLY - if ( triflaws ) { - /* Check the triangle `horiz' for quality. */ - testtriangle( &horiz ); - } +if ( verbose > 2 ) { +printf( " Edge flip results in left " ); +lnextself( topleft ); +printtriangle( &topleft ); +printf( " and right " ); +printtriangle( &horiz ); +} +/* On the next iterations, consider the two edges that were */ +/* exposed (this is, are now visible to the newly inserted */ +/* point) by the edge flip. */ +lprevself( horiz ); +leftpoint = farpoint; +} +} +} +if ( !doflip ) { +/* The handle `horiz' is accepted as locally Delaunay. */ +#ifndef +CDT_ONLY +if ( triflaws ) { +/* Check the triangle `horiz' for quality. */ +testtriangle( &horiz ); +} #endif /* not CDT_ONLY */ - /* Look for the next edge around the newly inserted point. */ - lnextself( horiz ); - sym( horiz, testtri ); - /* Check for finishing a complete revolution about the new point, or */ - /* falling off the edge of the triangulation. The latter will */ - /* happen when a point is inserted at a boundary. */ - if ( ( leftpoint == first ) || ( testtri.tri == dummytri ) ) { - /* We're done. Return a triangle whose origin is the new point. */ - lnext( horiz, *searchtri ); - lnext( horiz, recenttri ); - return success; - } - /* Finish finding the next edge around the newly inserted point. */ - lnext( testtri, horiz ); - rightpoint = leftpoint; - dest( horiz, leftpoint ); - } - } +/* Look for the next edge around the newly inserted point. */ +lnextself( horiz ); +sym( horiz, testtri ); +/* Check for finishing a complete revolution about the new point, or */ +/* falling off the edge of the triangulation. The latter will */ +/* happen when a point is inserted at a boundary. */ +if (( leftpoint == first ) || ( testtri.tri == dummytri )) { +/* We're done. Return a triangle whose origin is the new point. */ +lnext( horiz, *searchtri ); +lnext( horiz, recenttri ); +return success; +} +/* Finish finding the next edge around the newly inserted point. */ +lnext( testtri, horiz ); +rightpoint = leftpoint; +dest( horiz, leftpoint ); +} +} } /*****************************************************************************/ @@ -6807,69 +6975,70 @@ int edgecount; int doflip; int triflaws; { - struct triedge testtri; - struct triedge besttri; - struct triedge tempedge; - point leftbasepoint, rightbasepoint; - point testpoint; - point bestpoint; - int bestnumber; - int i; - triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ - - /* Identify the base vertices. */ - apex( *lastedge, leftbasepoint ); - dest( *firstedge, rightbasepoint ); - if ( verbose > 2 ) { - printf( " Triangulating interior polygon at edge\n" ); - printf( " (%.12g, %.12g) (%.12g, %.12g)\n", leftbasepoint[0], - leftbasepoint[1], rightbasepoint[0], rightbasepoint[1] ); - } - /* Find the best vertex to connect the base to. */ - onext( *firstedge, besttri ); - dest( besttri, bestpoint ); - triedgecopy( besttri, testtri ); - bestnumber = 1; - for ( i = 2; i <= edgecount - 2; i++ ) { - onextself( testtri ); - dest( testtri, testpoint ); - /* Is this a better vertex? */ - if ( incircle( leftbasepoint, rightbasepoint, bestpoint, testpoint ) > 0.0 ) { - triedgecopy( testtri, besttri ); - bestpoint = testpoint; - bestnumber = i; - } - } - if ( verbose > 2 ) { - printf( " Connecting edge to (%.12g, %.12g)\n", bestpoint[0], - bestpoint[1] ); - } - if ( bestnumber > 1 ) { - /* Recursively triangulate the smaller polygon on the right. */ - oprev( besttri, tempedge ); - triangulatepolygon( firstedge, &tempedge, bestnumber + 1, 1, triflaws ); - } - if ( bestnumber < edgecount - 2 ) { - /* Recursively triangulate the smaller polygon on the left. */ - sym( besttri, tempedge ); - triangulatepolygon( &besttri, lastedge, edgecount - bestnumber, 1, - triflaws ); - /* Find `besttri' again; it may have been lost to edge flips. */ - sym( tempedge, besttri ); - } - if ( doflip ) { - /* Do one final edge flip. */ - flip( &besttri ); -#ifndef CDT_ONLY - if ( triflaws ) { - /* Check the quality of the newly committed triangle. */ - sym( besttri, testtri ); - testtriangle( &testtri ); - } +struct triedge testtri; +struct triedge besttri; +struct triedge tempedge; +point leftbasepoint, rightbasepoint; +point testpoint; +point bestpoint; +int bestnumber; +int i; +triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ + +/* Identify the base vertices. */ +apex( *lastedge, leftbasepoint ); +dest( *firstedge, rightbasepoint ); +if ( verbose > 2 ) { +printf( " Triangulating interior polygon at edge\n" ); +printf( " (%.12g, %.12g) (%.12g, %.12g)\n", leftbasepoint[0], +leftbasepoint[1], rightbasepoint[0], rightbasepoint[1] ); +} +/* Find the best vertex to connect the base to. */ +onext( *firstedge, besttri ); +dest( besttri, bestpoint ); +triedgecopy( besttri, testtri ); +bestnumber = 1; +for ( i = 2; i <= edgecount - 2; i++ ) { +onextself( testtri ); +dest( testtri, testpoint ); +/* Is this a better vertex? */ +if ( incircle( leftbasepoint, rightbasepoint, bestpoint, testpoint ) > 0.0 ) { +triedgecopy( testtri, besttri ); +bestpoint = testpoint; +bestnumber = i; +} +} +if ( verbose > 2 ) { +printf( " Connecting edge to (%.12g, %.12g)\n", bestpoint[0], +bestpoint[1] ); +} +if ( bestnumber > 1 ) { +/* Recursively triangulate the smaller polygon on the right. */ +oprev( besttri, tempedge ); +triangulatepolygon( firstedge, &tempedge, bestnumber + 1, 1, triflaws ); +} +if ( bestnumber < edgecount - 2 ) { +/* Recursively triangulate the smaller polygon on the left. */ +sym( besttri, tempedge ); +triangulatepolygon( &besttri, lastedge, edgecount - bestnumber, 1, +triflaws ); +/* Find `besttri' again; it may have been lost to edge flips. */ +sym( tempedge, besttri ); +} +if ( doflip ) { +/* Do one final edge flip. */ +flip( &besttri ); +#ifndef +CDT_ONLY +if ( triflaws ) { +/* Check the quality of the newly committed triangle. */ +sym( besttri, testtri ); +testtriangle( &testtri ); +} #endif /* not CDT_ONLY */ - } - /* Return the base triangle. */ - triedgecopy( besttri, *lastedge ); +} +/* Return the base triangle. */ +triedgecopy( besttri, *lastedge ); } /*****************************************************************************/ @@ -6886,86 +7055,89 @@ int triflaws; /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void deletesite( deltri ) struct triedge *deltri; { - struct triedge countingtri; - struct triedge firstedge, lastedge; - struct triedge deltriright; - struct triedge lefttri, righttri; - struct triedge leftcasing, rightcasing; - struct edge leftshelle, rightshelle; - point delpoint; - point neworg; - int edgecount; - triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - org( *deltri, delpoint ); - if ( verbose > 1 ) { - printf( " Deleting (%.12g, %.12g).\n", delpoint[0], delpoint[1] ); - } - pointdealloc( delpoint ); - - /* Count the degree of the point being deleted. */ - onext( *deltri, countingtri ); - edgecount = 1; - while ( !triedgeequal( *deltri, countingtri ) ) { -#ifdef SELF_CHECK - if ( countingtri.tri == dummytri ) { - printf( "Internal error in deletesite():\n" ); - printf( " Attempt to delete boundary point.\n" ); - internalerror(); - } +struct triedge countingtri; +struct triedge firstedge, lastedge; +struct triedge deltriright; +struct triedge lefttri, righttri; +struct triedge leftcasing, rightcasing; +struct edge leftshelle, rightshelle; +point delpoint; +point neworg; +int edgecount; +triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +org( *deltri, delpoint ); +if ( verbose > 1 ) { +printf( " Deleting (%.12g, %.12g).\n", delpoint[0], delpoint[1] ); +} +pointdealloc( delpoint ); + +/* Count the degree of the point being deleted. */ +onext( *deltri, countingtri ); +edgecount = 1; +while ( !triedgeequal( *deltri, countingtri )) { +#ifdef +SELF_CHECK +if ( countingtri.tri == dummytri ) { +printf( "Internal error in deletesite():\n" ); +printf( " Attempt to delete boundary point.\n" ); +internalerror(); +} #endif /* SELF_CHECK */ - edgecount++; - onextself( countingtri ); - } - -#ifdef SELF_CHECK - if ( edgecount < 3 ) { - printf( "Internal error in deletesite():\n Point has degree %d.\n", - edgecount ); - internalerror(); - } +edgecount++; +onextself( countingtri ); +} + +#ifdef +SELF_CHECK +if ( edgecount < 3 ) { +printf( "Internal error in deletesite():\n Point has degree %d.\n", +edgecount ); +internalerror(); +} #endif /* SELF_CHECK */ - if ( edgecount > 3 ) { - /* Triangulate the polygon defined by the union of all triangles */ - /* adjacent to the point being deleted. Check the quality of */ - /* the resulting triangles. */ - onext( *deltri, firstedge ); - oprev( *deltri, lastedge ); - triangulatepolygon( &firstedge, &lastedge, edgecount, 0, !nobisect ); - } - /* Splice out two triangles. */ - lprev( *deltri, deltriright ); - dnext( *deltri, lefttri ); - sym( lefttri, leftcasing ); - oprev( deltriright, righttri ); - sym( righttri, rightcasing ); - bond( *deltri, leftcasing ); - bond( deltriright, rightcasing ); - tspivot( lefttri, leftshelle ); - if ( leftshelle.sh != dummysh ) { - tsbond( *deltri, leftshelle ); - } - tspivot( righttri, rightshelle ); - if ( rightshelle.sh != dummysh ) { - tsbond( deltriright, rightshelle ); - } - - /* Set the new origin of `deltri' and check its quality. */ - org( lefttri, neworg ); - setorg( *deltri, neworg ); - if ( !nobisect ) { - testtriangle( deltri ); - } - - /* Delete the two spliced-out triangles. */ - triangledealloc( lefttri.tri ); - triangledealloc( righttri.tri ); +if ( edgecount > 3 ) { +/* Triangulate the polygon defined by the union of all triangles */ +/* adjacent to the point being deleted. Check the quality of */ +/* the resulting triangles. */ +onext( *deltri, firstedge ); +oprev( *deltri, lastedge ); +triangulatepolygon( &firstedge, &lastedge, edgecount, 0, !nobisect ); +} +/* Splice out two triangles. */ +lprev( *deltri, deltriright ); +dnext( *deltri, lefttri ); +sym( lefttri, leftcasing ); +oprev( deltriright, righttri ); +sym( righttri, rightcasing ); +bond( *deltri, leftcasing ); +bond( deltriright, rightcasing ); +tspivot( lefttri, leftshelle ); +if ( leftshelle.sh != dummysh ) { +tsbond( *deltri, leftshelle ); +} +tspivot( righttri, rightshelle ); +if ( rightshelle.sh != dummysh ) { +tsbond( deltriright, rightshelle ); +} + +/* Set the new origin of `deltri' and check its quality. */ +org( lefttri, neworg ); +setorg( *deltri, neworg ); +if ( !nobisect ) { +testtriangle( deltri ); +} + +/* Delete the two spliced-out triangles. */ +triangledealloc( lefttri.tri ); +triangledealloc( righttri.tri ); } #endif /* not CDT_ONLY */ @@ -7023,57 +7195,57 @@ void pointsort( sortarray, arraysize ) point * sortarray; int arraysize; { - int left, right; - int pivot; - REAL pivotx, pivoty; - point temp; - - if ( arraysize == 2 ) { - /* Recursive base case. */ - if ( ( sortarray[0][0] > sortarray[1][0] ) || - ( ( sortarray[0][0] == sortarray[1][0] ) && - ( sortarray[0][1] > sortarray[1][1] ) ) ) { - temp = sortarray[1]; - sortarray[1] = sortarray[0]; - sortarray[0] = temp; - } - return; - } - /* Choose a random pivot to split the array. */ - pivot = (int) randomnation( arraysize ); - pivotx = sortarray[pivot][0]; - pivoty = sortarray[pivot][1]; - /* Split the array. */ - left = -1; - right = arraysize; - while ( left < right ) { - /* Search for a point whose x-coordinate is too large for the left. */ - do { - left++; - } while ( ( left <= right ) && ( ( sortarray[left][0] < pivotx ) || - ( ( sortarray[left][0] == pivotx ) && - ( sortarray[left][1] < pivoty ) ) ) ); - /* Search for a point whose x-coordinate is too small for the right. */ - do { - right--; - } while ( ( left <= right ) && ( ( sortarray[right][0] > pivotx ) || - ( ( sortarray[right][0] == pivotx ) && - ( sortarray[right][1] > pivoty ) ) ) ); - if ( left < right ) { - /* Swap the left and right points. */ - temp = sortarray[left]; - sortarray[left] = sortarray[right]; - sortarray[right] = temp; - } - } - if ( left > 1 ) { - /* Recursively sort the left subset. */ - pointsort( sortarray, left ); - } - if ( right < arraysize - 2 ) { - /* Recursively sort the right subset. */ - pointsort( &sortarray[right + 1], arraysize - right - 1 ); - } +int left, right; +int pivot; +REAL pivotx, pivoty; +point temp; + +if ( arraysize == 2 ) { +/* Recursive base case. */ +if (( sortarray[0][0] > sortarray[1][0] ) || +(( sortarray[0][0] == sortarray[1][0] ) && +( sortarray[0][1] > sortarray[1][1] ))) { +temp = sortarray[1]; +sortarray[1] = sortarray[0]; +sortarray[0] = temp; +} +return; +} +/* Choose a random pivot to split the array. */ +pivot = (int) randomnation( arraysize ); +pivotx = sortarray[pivot][0]; +pivoty = sortarray[pivot][1]; +/* Split the array. */ +left = -1; +right = arraysize; +while ( left < right ) { +/* Search for a point whose x-coordinate is too large for the left. */ +do { +left++; +} while (( left <= right ) && (( sortarray[left][0] < pivotx ) || +(( sortarray[left][0] == pivotx ) && +( sortarray[left][1] < pivoty )))); +/* Search for a point whose x-coordinate is too small for the right. */ +do { +right--; +} while (( left <= right ) && (( sortarray[right][0] > pivotx ) || +(( sortarray[right][0] == pivotx ) && +( sortarray[right][1] > pivoty )))); +if ( left < right ) { +/* Swap the left and right points. */ +temp = sortarray[left]; +sortarray[left] = sortarray[right]; +sortarray[right] = temp; +} +} +if ( left > 1 ) { +/* Recursively sort the left subset. */ +pointsort( sortarray, left ); +} +if ( right < arraysize - 2 ) { +/* Recursively sort the right subset. */ +pointsort( &sortarray[right + 1], arraysize - right - 1 ); +} } /*****************************************************************************/ @@ -7094,60 +7266,60 @@ int arraysize; int median; int axis; { - int left, right; - int pivot; - REAL pivot1, pivot2; - point temp; - - if ( arraysize == 2 ) { - /* Recursive base case. */ - if ( ( sortarray[0][axis] > sortarray[1][axis] ) || - ( ( sortarray[0][axis] == sortarray[1][axis] ) && - ( sortarray[0][1 - axis] > sortarray[1][1 - axis] ) ) ) { - temp = sortarray[1]; - sortarray[1] = sortarray[0]; - sortarray[0] = temp; - } - return; - } - /* Choose a random pivot to split the array. */ - pivot = (int) randomnation( arraysize ); - pivot1 = sortarray[pivot][axis]; - pivot2 = sortarray[pivot][1 - axis]; - /* Split the array. */ - left = -1; - right = arraysize; - while ( left < right ) { - /* Search for a point whose x-coordinate is too large for the left. */ - do { - left++; - } while ( ( left <= right ) && ( ( sortarray[left][axis] < pivot1 ) || - ( ( sortarray[left][axis] == pivot1 ) && - ( sortarray[left][1 - axis] < pivot2 ) ) ) ); - /* Search for a point whose x-coordinate is too small for the right. */ - do { - right--; - } while ( ( left <= right ) && ( ( sortarray[right][axis] > pivot1 ) || - ( ( sortarray[right][axis] == pivot1 ) && - ( sortarray[right][1 - axis] > pivot2 ) ) ) ); - if ( left < right ) { - /* Swap the left and right points. */ - temp = sortarray[left]; - sortarray[left] = sortarray[right]; - sortarray[right] = temp; - } - } - /* Unlike in pointsort(), at most one of the following */ - /* conditionals is true. */ - if ( left > median ) { - /* Recursively shuffle the left subset. */ - pointmedian( sortarray, left, median, axis ); - } - if ( right < median - 1 ) { - /* Recursively shuffle the right subset. */ - pointmedian( &sortarray[right + 1], arraysize - right - 1, - median - right - 1, axis ); - } +int left, right; +int pivot; +REAL pivot1, pivot2; +point temp; + +if ( arraysize == 2 ) { +/* Recursive base case. */ +if (( sortarray[0][axis] > sortarray[1][axis] ) || +(( sortarray[0][axis] == sortarray[1][axis] ) && +( sortarray[0][1 - axis] > sortarray[1][1 - axis] ))) { +temp = sortarray[1]; +sortarray[1] = sortarray[0]; +sortarray[0] = temp; +} +return; +} +/* Choose a random pivot to split the array. */ +pivot = (int) randomnation( arraysize ); +pivot1 = sortarray[pivot][axis]; +pivot2 = sortarray[pivot][1 - axis]; +/* Split the array. */ +left = -1; +right = arraysize; +while ( left < right ) { +/* Search for a point whose x-coordinate is too large for the left. */ +do { +left++; +} while (( left <= right ) && (( sortarray[left][axis] < pivot1 ) || +(( sortarray[left][axis] == pivot1 ) && +( sortarray[left][1 - axis] < pivot2 )))); +/* Search for a point whose x-coordinate is too small for the right. */ +do { +right--; +} while (( left <= right ) && (( sortarray[right][axis] > pivot1 ) || +(( sortarray[right][axis] == pivot1 ) && +( sortarray[right][1 - axis] > pivot2 )))); +if ( left < right ) { +/* Swap the left and right points. */ +temp = sortarray[left]; +sortarray[left] = sortarray[right]; +sortarray[right] = temp; +} +} +/* Unlike in pointsort(), at most one of the following */ +/* conditionals is true. */ +if ( left > median ) { +/* Recursively shuffle the left subset. */ +pointmedian( sortarray, left, median, axis ); +} +if ( right < median - 1 ) { +/* Recursively shuffle the right subset. */ +pointmedian( &sortarray[right + 1], arraysize - right - 1, +median - right - 1, axis ); +} } /*****************************************************************************/ @@ -7166,23 +7338,23 @@ point * sortarray; int arraysize; int axis; { - int divider; +int divider; - divider = arraysize >> 1; - if ( arraysize <= 3 ) { - /* Recursive base case: subsets of two or three points will be */ - /* handled specially, and should always be sorted by x-coordinate. */ - axis = 0; - } - /* Partition with a horizontal or vertical cut. */ - pointmedian( sortarray, arraysize, divider, axis ); - /* Recursively partition the subsets with a cross cut. */ - if ( arraysize - divider >= 2 ) { - if ( divider >= 2 ) { - alternateaxes( sortarray, divider, 1 - axis ); - } - alternateaxes( &sortarray[divider], arraysize - divider, 1 - axis ); - } +divider = arraysize >> 1; +if ( arraysize <= 3 ) { +/* Recursive base case: subsets of two or three points will be */ +/* handled specially, and should always be sorted by x-coordinate. */ +axis = 0; +} +/* Partition with a horizontal or vertical cut. */ +pointmedian( sortarray, arraysize, divider, axis ); +/* Recursively partition the subsets with a cross cut. */ +if ( arraysize - divider >= 2 ) { +if ( divider >= 2 ) { +alternateaxes( sortarray, divider, 1 - axis ); +} +alternateaxes( &sortarray[divider], arraysize - divider, 1 - axis ); +} } /*****************************************************************************/ @@ -7227,293 +7399,293 @@ struct triedge *innerright; struct triedge *farright; int axis; { - struct triedge leftcand, rightcand; - struct triedge baseedge; - struct triedge nextedge; - struct triedge sidecasing, topcasing, outercasing; - struct triedge checkedge; - point innerleftdest; - point innerrightorg; - point innerleftapex, innerrightapex; - point farleftpt, farrightpt; - point farleftapex, farrightapex; - point lowerleft, lowerright; - point upperleft, upperright; - point nextapex; - point checkvertex; - int changemade; - int badedge; - int leftfinished, rightfinished; - triangle ptr; /* Temporary variable used by sym(). */ - - dest( *innerleft, innerleftdest ); - apex( *innerleft, innerleftapex ); - org( *innerright, innerrightorg ); - apex( *innerright, innerrightapex ); - /* Special treatment for horizontal cuts. */ - if ( dwyer && ( axis == 1 ) ) { - org( *farleft, farleftpt ); - apex( *farleft, farleftapex ); - dest( *farright, farrightpt ); - apex( *farright, farrightapex ); - /* The pointers to the extremal points are shifted to point to the */ - /* topmost and bottommost point of each hull, rather than the */ - /* leftmost and rightmost points. */ - while ( farleftapex[1] < farleftpt[1] ) { - lnextself( *farleft ); - symself( *farleft ); - farleftpt = farleftapex; - apex( *farleft, farleftapex ); - } - sym( *innerleft, checkedge ); - apex( checkedge, checkvertex ); - while ( checkvertex[1] > innerleftdest[1] ) { - lnext( checkedge, *innerleft ); - innerleftapex = innerleftdest; - innerleftdest = checkvertex; - sym( *innerleft, checkedge ); - apex( checkedge, checkvertex ); - } - while ( innerrightapex[1] < innerrightorg[1] ) { - lnextself( *innerright ); - symself( *innerright ); - innerrightorg = innerrightapex; - apex( *innerright, innerrightapex ); - } - sym( *farright, checkedge ); - apex( checkedge, checkvertex ); - while ( checkvertex[1] > farrightpt[1] ) { - lnext( checkedge, *farright ); - farrightapex = farrightpt; - farrightpt = checkvertex; - sym( *farright, checkedge ); - apex( checkedge, checkvertex ); - } - } - /* Find a line tangent to and below both hulls. */ - do { - changemade = 0; - /* Make innerleftdest the "bottommost" point of the left hull. */ - if ( counterclockwise( innerleftdest, innerleftapex, innerrightorg ) > 0.0 ) { - lprevself( *innerleft ); - symself( *innerleft ); - innerleftdest = innerleftapex; - apex( *innerleft, innerleftapex ); - changemade = 1; - } - /* Make innerrightorg the "bottommost" point of the right hull. */ - if ( counterclockwise( innerrightapex, innerrightorg, innerleftdest ) > 0.0 ) { - lnextself( *innerright ); - symself( *innerright ); - innerrightorg = innerrightapex; - apex( *innerright, innerrightapex ); - changemade = 1; - } - } while ( changemade ); - /* Find the two candidates to be the next "gear tooth". */ - sym( *innerleft, leftcand ); - sym( *innerright, rightcand ); - /* Create the bottom new bounding triangle. */ - maketriangle( &baseedge ); - /* Connect it to the bounding boxes of the left and right triangulations. */ - bond( baseedge, *innerleft ); - lnextself( baseedge ); - bond( baseedge, *innerright ); - lnextself( baseedge ); - setorg( baseedge, innerrightorg ); - setdest( baseedge, innerleftdest ); - /* Apex is intentionally left NULL. */ - if ( verbose > 2 ) { - printf( " Creating base bounding " ); - printtriangle( &baseedge ); - } - /* Fix the extreme triangles if necessary. */ - org( *farleft, farleftpt ); - if ( innerleftdest == farleftpt ) { - lnext( baseedge, *farleft ); - } - dest( *farright, farrightpt ); - if ( innerrightorg == farrightpt ) { - lprev( baseedge, *farright ); - } - /* The vertices of the current knitting edge. */ - lowerleft = innerleftdest; - lowerright = innerrightorg; - /* The candidate vertices for knitting. */ - apex( leftcand, upperleft ); - apex( rightcand, upperright ); - /* Walk up the gap between the two triangulations, knitting them together. */ - while ( 1 ) { - /* Have we reached the top? (This isn't quite the right question, */ - /* because even though the left triangulation might seem finished now, */ - /* moving up on the right triangulation might reveal a new point of */ - /* the left triangulation. And vice-versa.) */ - leftfinished = counterclockwise( upperleft, lowerleft, lowerright ) <= 0.0; - rightfinished = counterclockwise( upperright, lowerleft, lowerright ) <= 0.0; - if ( leftfinished && rightfinished ) { - /* Create the top new bounding triangle. */ - maketriangle( &nextedge ); - setorg( nextedge, lowerleft ); - setdest( nextedge, lowerright ); - /* Apex is intentionally left NULL. */ - /* Connect it to the bounding boxes of the two triangulations. */ - bond( nextedge, baseedge ); - lnextself( nextedge ); - bond( nextedge, rightcand ); - lnextself( nextedge ); - bond( nextedge, leftcand ); - if ( verbose > 2 ) { - printf( " Creating top bounding " ); - printtriangle( &baseedge ); - } - /* Special treatment for horizontal cuts. */ - if ( dwyer && ( axis == 1 ) ) { - org( *farleft, farleftpt ); - apex( *farleft, farleftapex ); - dest( *farright, farrightpt ); - apex( *farright, farrightapex ); - sym( *farleft, checkedge ); - apex( checkedge, checkvertex ); - /* The pointers to the extremal points are restored to the leftmost */ - /* and rightmost points (rather than topmost and bottommost). */ - while ( checkvertex[0] < farleftpt[0] ) { - lprev( checkedge, *farleft ); - farleftapex = farleftpt; - farleftpt = checkvertex; - sym( *farleft, checkedge ); - apex( checkedge, checkvertex ); - } - while ( farrightapex[0] > farrightpt[0] ) { - lprevself( *farright ); - symself( *farright ); - farrightpt = farrightapex; - apex( *farright, farrightapex ); - } - } - return; - } - /* Consider eliminating edges from the left triangulation. */ - if ( !leftfinished ) { - /* What vertex would be exposed if an edge were deleted? */ - lprev( leftcand, nextedge ); - symself( nextedge ); - apex( nextedge, nextapex ); - /* If nextapex is NULL, then no vertex would be exposed; the */ - /* triangulation would have been eaten right through. */ - if ( nextapex != (point) NULL ) { - /* Check whether the edge is Delaunay. */ - badedge = incircle( lowerleft, lowerright, upperleft, nextapex ) > 0.0; - while ( badedge ) { - /* Eliminate the edge with an edge flip. As a result, the */ - /* left triangulation will have one more boundary triangle. */ - lnextself( nextedge ); - sym( nextedge, topcasing ); - lnextself( nextedge ); - sym( nextedge, sidecasing ); - bond( nextedge, topcasing ); - bond( leftcand, sidecasing ); - lnextself( leftcand ); - sym( leftcand, outercasing ); - lprevself( nextedge ); - bond( nextedge, outercasing ); - /* Correct the vertices to reflect the edge flip. */ - setorg( leftcand, lowerleft ); - setdest( leftcand, NULL ); - setapex( leftcand, nextapex ); - setorg( nextedge, NULL ); - setdest( nextedge, upperleft ); - setapex( nextedge, nextapex ); - /* Consider the newly exposed vertex. */ - upperleft = nextapex; - /* What vertex would be exposed if another edge were deleted? */ - triedgecopy( sidecasing, nextedge ); - apex( nextedge, nextapex ); - if ( nextapex != (point) NULL ) { - /* Check whether the edge is Delaunay. */ - badedge = incircle( lowerleft, lowerright, upperleft, nextapex ) - > 0.0; - } - else { - /* Avoid eating right through the triangulation. */ - badedge = 0; - } - } - } - } - /* Consider eliminating edges from the right triangulation. */ - if ( !rightfinished ) { - /* What vertex would be exposed if an edge were deleted? */ - lnext( rightcand, nextedge ); - symself( nextedge ); - apex( nextedge, nextapex ); - /* If nextapex is NULL, then no vertex would be exposed; the */ - /* triangulation would have been eaten right through. */ - if ( nextapex != (point) NULL ) { - /* Check whether the edge is Delaunay. */ - badedge = incircle( lowerleft, lowerright, upperright, nextapex ) > 0.0; - while ( badedge ) { - /* Eliminate the edge with an edge flip. As a result, the */ - /* right triangulation will have one more boundary triangle. */ - lprevself( nextedge ); - sym( nextedge, topcasing ); - lprevself( nextedge ); - sym( nextedge, sidecasing ); - bond( nextedge, topcasing ); - bond( rightcand, sidecasing ); - lprevself( rightcand ); - sym( rightcand, outercasing ); - lnextself( nextedge ); - bond( nextedge, outercasing ); - /* Correct the vertices to reflect the edge flip. */ - setorg( rightcand, NULL ); - setdest( rightcand, lowerright ); - setapex( rightcand, nextapex ); - setorg( nextedge, upperright ); - setdest( nextedge, NULL ); - setapex( nextedge, nextapex ); - /* Consider the newly exposed vertex. */ - upperright = nextapex; - /* What vertex would be exposed if another edge were deleted? */ - triedgecopy( sidecasing, nextedge ); - apex( nextedge, nextapex ); - if ( nextapex != (point) NULL ) { - /* Check whether the edge is Delaunay. */ - badedge = incircle( lowerleft, lowerright, upperright, nextapex ) - > 0.0; - } - else { - /* Avoid eating right through the triangulation. */ - badedge = 0; - } - } - } - } - if ( leftfinished || ( !rightfinished && - ( incircle( upperleft, lowerleft, lowerright, upperright ) > 0.0 ) ) ) { - /* Knit the triangulations, adding an edge from `lowerleft' */ - /* to `upperright'. */ - bond( baseedge, rightcand ); - lprev( rightcand, baseedge ); - setdest( baseedge, lowerleft ); - lowerright = upperright; - sym( baseedge, rightcand ); - apex( rightcand, upperright ); - } - else { - /* Knit the triangulations, adding an edge from `upperleft' */ - /* to `lowerright'. */ - bond( baseedge, leftcand ); - lnext( leftcand, baseedge ); - setorg( baseedge, lowerright ); - lowerleft = upperleft; - sym( baseedge, leftcand ); - apex( leftcand, upperleft ); - } - if ( verbose > 2 ) { - printf( " Connecting " ); - printtriangle( &baseedge ); - } - } +struct triedge leftcand, rightcand; +struct triedge baseedge; +struct triedge nextedge; +struct triedge sidecasing, topcasing, outercasing; +struct triedge checkedge; +point innerleftdest; +point innerrightorg; +point innerleftapex, innerrightapex; +point farleftpt, farrightpt; +point farleftapex, farrightapex; +point lowerleft, lowerright; +point upperleft, upperright; +point nextapex; +point checkvertex; +int changemade; +int badedge; +int leftfinished, rightfinished; +triangle ptr; /* Temporary variable used by sym(). */ + +dest( *innerleft, innerleftdest ); +apex( *innerleft, innerleftapex ); +org( *innerright, innerrightorg ); +apex( *innerright, innerrightapex ); +/* Special treatment for horizontal cuts. */ +if ( dwyer && ( axis == 1 )) { +org( *farleft, farleftpt ); +apex( *farleft, farleftapex ); +dest( *farright, farrightpt ); +apex( *farright, farrightapex ); +/* The pointers to the extremal points are shifted to point to the */ +/* topmost and bottommost point of each hull, rather than the */ +/* leftmost and rightmost points. */ +while ( farleftapex[1] < farleftpt[1] ) { +lnextself( *farleft ); +symself( *farleft ); +farleftpt = farleftapex; +apex( *farleft, farleftapex ); +} +sym( *innerleft, checkedge ); +apex( checkedge, checkvertex ); +while ( checkvertex[1] > innerleftdest[1] ) { +lnext( checkedge, *innerleft ); +innerleftapex = innerleftdest; +innerleftdest = checkvertex; +sym( *innerleft, checkedge ); +apex( checkedge, checkvertex ); +} +while ( innerrightapex[1] < innerrightorg[1] ) { +lnextself( *innerright ); +symself( *innerright ); +innerrightorg = innerrightapex; +apex( *innerright, innerrightapex ); +} +sym( *farright, checkedge ); +apex( checkedge, checkvertex ); +while ( checkvertex[1] > farrightpt[1] ) { +lnext( checkedge, *farright ); +farrightapex = farrightpt; +farrightpt = checkvertex; +sym( *farright, checkedge ); +apex( checkedge, checkvertex ); +} +} +/* Find a line tangent to and below both hulls. */ +do { +changemade = 0; +/* Make innerleftdest the "bottommost" point of the left hull. */ +if ( counterclockwise( innerleftdest, innerleftapex, innerrightorg ) > 0.0 ) { +lprevself( *innerleft ); +symself( *innerleft ); +innerleftdest = innerleftapex; +apex( *innerleft, innerleftapex ); +changemade = 1; +} +/* Make innerrightorg the "bottommost" point of the right hull. */ +if ( counterclockwise( innerrightapex, innerrightorg, innerleftdest ) > 0.0 ) { +lnextself( *innerright ); +symself( *innerright ); +innerrightorg = innerrightapex; +apex( *innerright, innerrightapex ); +changemade = 1; +} +} while ( changemade ); +/* Find the two candidates to be the next "gear tooth". */ +sym( *innerleft, leftcand ); +sym( *innerright, rightcand ); +/* Create the bottom new bounding triangle. */ +maketriangle( &baseedge ); +/* Connect it to the bounding boxes of the left and right triangulations. */ +bond( baseedge, *innerleft ); +lnextself( baseedge ); +bond( baseedge, *innerright ); +lnextself( baseedge ); +setorg( baseedge, innerrightorg ); +setdest( baseedge, innerleftdest ); +/* Apex is intentionally left NULL. */ +if ( verbose > 2 ) { +printf( " Creating base bounding " ); +printtriangle( &baseedge ); +} +/* Fix the extreme triangles if necessary. */ +org( *farleft, farleftpt ); +if ( innerleftdest == farleftpt ) { +lnext( baseedge, *farleft ); +} +dest( *farright, farrightpt ); +if ( innerrightorg == farrightpt ) { +lprev( baseedge, *farright ); +} +/* The vertices of the current knitting edge. */ +lowerleft = innerleftdest; +lowerright = innerrightorg; +/* The candidate vertices for knitting. */ +apex( leftcand, upperleft ); +apex( rightcand, upperright ); +/* Walk up the gap between the two triangulations, knitting them together. */ +while ( 1 ) { +/* Have we reached the top? (This isn't quite the right question, */ +/* because even though the left triangulation might seem finished now, */ +/* moving up on the right triangulation might reveal a new point of */ +/* the left triangulation. And vice-versa.) */ +leftfinished = counterclockwise( upperleft, lowerleft, lowerright ) <= 0.0; +rightfinished = counterclockwise( upperright, lowerleft, lowerright ) <= 0.0; +if ( leftfinished && rightfinished ) { +/* Create the top new bounding triangle. */ +maketriangle( &nextedge ); +setorg( nextedge, lowerleft ); +setdest( nextedge, lowerright ); +/* Apex is intentionally left NULL. */ +/* Connect it to the bounding boxes of the two triangulations. */ +bond( nextedge, baseedge ); +lnextself( nextedge ); +bond( nextedge, rightcand ); +lnextself( nextedge ); +bond( nextedge, leftcand ); +if ( verbose > 2 ) { +printf( " Creating top bounding " ); +printtriangle( &baseedge ); +} +/* Special treatment for horizontal cuts. */ +if ( dwyer && ( axis == 1 )) { +org( *farleft, farleftpt ); +apex( *farleft, farleftapex ); +dest( *farright, farrightpt ); +apex( *farright, farrightapex ); +sym( *farleft, checkedge ); +apex( checkedge, checkvertex ); +/* The pointers to the extremal points are restored to the leftmost */ +/* and rightmost points (rather than topmost and bottommost). */ +while ( checkvertex[0] < farleftpt[0] ) { +lprev( checkedge, *farleft ); +farleftapex = farleftpt; +farleftpt = checkvertex; +sym( *farleft, checkedge ); +apex( checkedge, checkvertex ); +} +while ( farrightapex[0] > farrightpt[0] ) { +lprevself( *farright ); +symself( *farright ); +farrightpt = farrightapex; +apex( *farright, farrightapex ); +} +} +return; +} +/* Consider eliminating edges from the left triangulation. */ +if ( !leftfinished ) { +/* What vertex would be exposed if an edge were deleted? */ +lprev( leftcand, nextedge ); +symself( nextedge ); +apex( nextedge, nextapex ); +/* If nextapex is NULL, then no vertex would be exposed; the */ +/* triangulation would have been eaten right through. */ +if ( nextapex != (point) NULL ) { +/* Check whether the edge is Delaunay. */ +badedge = incircle( lowerleft, lowerright, upperleft, nextapex ) > 0.0; +while ( badedge ) { +/* Eliminate the edge with an edge flip. As a result, the */ +/* left triangulation will have one more boundary triangle. */ +lnextself( nextedge ); +sym( nextedge, topcasing ); +lnextself( nextedge ); +sym( nextedge, sidecasing ); +bond( nextedge, topcasing ); +bond( leftcand, sidecasing ); +lnextself( leftcand ); +sym( leftcand, outercasing ); +lprevself( nextedge ); +bond( nextedge, outercasing ); +/* Correct the vertices to reflect the edge flip. */ +setorg( leftcand, lowerleft ); +setdest( leftcand, NULL ); +setapex( leftcand, nextapex ); +setorg( nextedge, NULL ); +setdest( nextedge, upperleft ); +setapex( nextedge, nextapex ); +/* Consider the newly exposed vertex. */ +upperleft = nextapex; +/* What vertex would be exposed if another edge were deleted? */ +triedgecopy( sidecasing, nextedge ); +apex( nextedge, nextapex ); +if ( nextapex != (point) NULL ) { +/* Check whether the edge is Delaunay. */ +badedge = incircle( lowerleft, lowerright, upperleft, nextapex ) +> 0.0; +} +else { +/* Avoid eating right through the triangulation. */ +badedge = 0; +} +} +} +} +/* Consider eliminating edges from the right triangulation. */ +if ( !rightfinished ) { +/* What vertex would be exposed if an edge were deleted? */ +lnext( rightcand, nextedge ); +symself( nextedge ); +apex( nextedge, nextapex ); +/* If nextapex is NULL, then no vertex would be exposed; the */ +/* triangulation would have been eaten right through. */ +if ( nextapex != (point) NULL ) { +/* Check whether the edge is Delaunay. */ +badedge = incircle( lowerleft, lowerright, upperright, nextapex ) > 0.0; +while ( badedge ) { +/* Eliminate the edge with an edge flip. As a result, the */ +/* right triangulation will have one more boundary triangle. */ +lprevself( nextedge ); +sym( nextedge, topcasing ); +lprevself( nextedge ); +sym( nextedge, sidecasing ); +bond( nextedge, topcasing ); +bond( rightcand, sidecasing ); +lprevself( rightcand ); +sym( rightcand, outercasing ); +lnextself( nextedge ); +bond( nextedge, outercasing ); +/* Correct the vertices to reflect the edge flip. */ +setorg( rightcand, NULL ); +setdest( rightcand, lowerright ); +setapex( rightcand, nextapex ); +setorg( nextedge, upperright ); +setdest( nextedge, NULL ); +setapex( nextedge, nextapex ); +/* Consider the newly exposed vertex. */ +upperright = nextapex; +/* What vertex would be exposed if another edge were deleted? */ +triedgecopy( sidecasing, nextedge ); +apex( nextedge, nextapex ); +if ( nextapex != (point) NULL ) { +/* Check whether the edge is Delaunay. */ +badedge = incircle( lowerleft, lowerright, upperright, nextapex ) +> 0.0; +} +else { +/* Avoid eating right through the triangulation. */ +badedge = 0; +} +} +} +} +if ( leftfinished || ( !rightfinished && +( incircle( upperleft, lowerleft, lowerright, upperright ) > 0.0 ))) { +/* Knit the triangulations, adding an edge from `lowerleft' */ +/* to `upperright'. */ +bond( baseedge, rightcand ); +lprev( rightcand, baseedge ); +setdest( baseedge, lowerleft ); +lowerright = upperright; +sym( baseedge, rightcand ); +apex( rightcand, upperright ); +} +else { +/* Knit the triangulations, adding an edge from `upperleft' */ +/* to `lowerright'. */ +bond( baseedge, leftcand ); +lnext( leftcand, baseedge ); +setorg( baseedge, lowerright ); +lowerleft = upperleft; +sym( baseedge, leftcand ); +apex( leftcand, upperleft ); +} +if ( verbose > 2 ) { +printf( " Connecting " ); +printtriangle( &baseedge ); +} +} } /*****************************************************************************/ @@ -7540,205 +7712,205 @@ int axis; struct triedge *farleft; struct triedge *farright; { - struct triedge midtri, tri1, tri2, tri3; - struct triedge innerleft, innerright; - REAL area; - int divider; - - if ( verbose > 2 ) { - printf( " Triangulating %d points.\n", vertices ); - } - if ( vertices == 2 ) { - /* The triangulation of two vertices is an edge. An edge is */ - /* represented by two bounding triangles. */ - maketriangle( farleft ); - setorg( *farleft, sortarray[0] ); - setdest( *farleft, sortarray[1] ); - /* The apex is intentionally left NULL. */ - maketriangle( farright ); - setorg( *farright, sortarray[1] ); - setdest( *farright, sortarray[0] ); - /* The apex is intentionally left NULL. */ - bond( *farleft, *farright ); - lprevself( *farleft ); - lnextself( *farright ); - bond( *farleft, *farright ); - lprevself( *farleft ); - lnextself( *farright ); - bond( *farleft, *farright ); - if ( verbose > 2 ) { - printf( " Creating " ); - printtriangle( farleft ); - printf( " Creating " ); - printtriangle( farright ); - } - /* Ensure that the origin of `farleft' is sortarray[0]. */ - lprev( *farright, *farleft ); - return; - } - else if ( vertices == 3 ) { - /* The triangulation of three vertices is either a triangle (with */ - /* three bounding triangles) or two edges (with four bounding */ - /* triangles). In either case, four triangles are created. */ - maketriangle( &midtri ); - maketriangle( &tri1 ); - maketriangle( &tri2 ); - maketriangle( &tri3 ); - area = counterclockwise( sortarray[0], sortarray[1], sortarray[2] ); - if ( area == 0.0 ) { - /* Three collinear points; the triangulation is two edges. */ - setorg( midtri, sortarray[0] ); - setdest( midtri, sortarray[1] ); - setorg( tri1, sortarray[1] ); - setdest( tri1, sortarray[0] ); - setorg( tri2, sortarray[2] ); - setdest( tri2, sortarray[1] ); - setorg( tri3, sortarray[1] ); - setdest( tri3, sortarray[2] ); - /* All apices are intentionally left NULL. */ - bond( midtri, tri1 ); - bond( tri2, tri3 ); - lnextself( midtri ); - lprevself( tri1 ); - lnextself( tri2 ); - lprevself( tri3 ); - bond( midtri, tri3 ); - bond( tri1, tri2 ); - lnextself( midtri ); - lprevself( tri1 ); - lnextself( tri2 ); - lprevself( tri3 ); - bond( midtri, tri1 ); - bond( tri2, tri3 ); - /* Ensure that the origin of `farleft' is sortarray[0]. */ - triedgecopy( tri1, *farleft ); - /* Ensure that the destination of `farright' is sortarray[2]. */ - triedgecopy( tri2, *farright ); - } - else { - /* The three points are not collinear; the triangulation is one */ - /* triangle, namely `midtri'. */ - setorg( midtri, sortarray[0] ); - setdest( tri1, sortarray[0] ); - setorg( tri3, sortarray[0] ); - /* Apices of tri1, tri2, and tri3 are left NULL. */ - if ( area > 0.0 ) { - /* The vertices are in counterclockwise order. */ - setdest( midtri, sortarray[1] ); - setorg( tri1, sortarray[1] ); - setdest( tri2, sortarray[1] ); - setapex( midtri, sortarray[2] ); - setorg( tri2, sortarray[2] ); - setdest( tri3, sortarray[2] ); - } - else { - /* The vertices are in clockwise order. */ - setdest( midtri, sortarray[2] ); - setorg( tri1, sortarray[2] ); - setdest( tri2, sortarray[2] ); - setapex( midtri, sortarray[1] ); - setorg( tri2, sortarray[1] ); - setdest( tri3, sortarray[1] ); - } - /* The topology does not depend on how the vertices are ordered. */ - bond( midtri, tri1 ); - lnextself( midtri ); - bond( midtri, tri2 ); - lnextself( midtri ); - bond( midtri, tri3 ); - lprevself( tri1 ); - lnextself( tri2 ); - bond( tri1, tri2 ); - lprevself( tri1 ); - lprevself( tri3 ); - bond( tri1, tri3 ); - lnextself( tri2 ); - lprevself( tri3 ); - bond( tri2, tri3 ); - /* Ensure that the origin of `farleft' is sortarray[0]. */ - triedgecopy( tri1, *farleft ); - /* Ensure that the destination of `farright' is sortarray[2]. */ - if ( area > 0.0 ) { - triedgecopy( tri2, *farright ); - } - else { - lnext( *farleft, *farright ); - } - } - if ( verbose > 2 ) { - printf( " Creating " ); - printtriangle( &midtri ); - printf( " Creating " ); - printtriangle( &tri1 ); - printf( " Creating " ); - printtriangle( &tri2 ); - printf( " Creating " ); - printtriangle( &tri3 ); - } - return; - } - else { - /* Split the vertices in half. */ - divider = vertices >> 1; - /* Recursively triangulate each half. */ - divconqrecurse( sortarray, divider, 1 - axis, farleft, &innerleft ); - divconqrecurse( &sortarray[divider], vertices - divider, 1 - axis, - &innerright, farright ); - if ( verbose > 1 ) { - printf( " Joining triangulations with %d and %d vertices.\n", divider, - vertices - divider ); - } - /* Merge the two triangulations into one. */ - mergehulls( farleft, &innerleft, &innerright, farright, axis ); - } -} +struct triedge midtri, tri1, tri2, tri3; +struct triedge innerleft, innerright; +REAL area; +int divider; -long removeghosts( startghost ) -struct triedge *startghost; -{ - struct triedge searchedge; - struct triedge dissolveedge; - struct triedge deadtri; - point markorg; - long hullsize; - triangle ptr; /* Temporary variable used by sym(). */ - - if ( verbose ) { - printf( " Removing ghost triangles.\n" ); - } - /* Find an edge on the convex hull to start point location from. */ - lprev( *startghost, searchedge ); - symself( searchedge ); - dummytri[0] = encode( searchedge ); - /* Remove the bounding box and count the convex hull edges. */ - triedgecopy( *startghost, dissolveedge ); - hullsize = 0; - do { - hullsize++; - lnext( dissolveedge, deadtri ); - lprevself( dissolveedge ); - symself( dissolveedge ); - /* If no PSLG is involved, set the boundary markers of all the points */ - /* on the convex hull. If a PSLG is used, this step is done later. */ - if ( !poly ) { - /* Watch out for the case where all the input points are collinear. */ - if ( dissolveedge.tri != dummytri ) { - org( dissolveedge, markorg ); - if ( pointmark( markorg ) == 0 ) { - setpointmark( markorg, 1 ); - } - } - } - /* Remove a bounding triangle from a convex hull triangle. */ - dissolve( dissolveedge ); - /* Find the next bounding triangle. */ - sym( deadtri, dissolveedge ); - /* Delete the bounding triangle. */ - triangledealloc( deadtri.tri ); - } while ( !triedgeequal( dissolveedge, *startghost ) ); - return hullsize; +if ( verbose > 2 ) { +printf( " Triangulating %d points.\n", vertices ); } - +if ( vertices == 2 ) { +/* The triangulation of two vertices is an edge. An edge is */ +/* represented by two bounding triangles. */ +maketriangle( farleft ); +setorg( *farleft, sortarray[0] ); +setdest( *farleft, sortarray[1] ); +/* The apex is intentionally left NULL. */ +maketriangle( farright ); +setorg( *farright, sortarray[1] ); +setdest( *farright, sortarray[0] ); +/* The apex is intentionally left NULL. */ +bond( *farleft, *farright ); +lprevself( *farleft ); +lnextself( *farright ); +bond( *farleft, *farright ); +lprevself( *farleft ); +lnextself( *farright ); +bond( *farleft, *farright ); +if ( verbose > 2 ) { +printf( " Creating " ); +printtriangle( farleft ); +printf( " Creating " ); +printtriangle( farright ); +} +/* Ensure that the origin of `farleft' is sortarray[0]. */ +lprev( *farright, *farleft ); +return; +} +else if ( vertices == 3 ) { +/* The triangulation of three vertices is either a triangle (with */ +/* three bounding triangles) or two edges (with four bounding */ +/* triangles). In either case, four triangles are created. */ +maketriangle( &midtri ); +maketriangle( &tri1 ); +maketriangle( &tri2 ); +maketriangle( &tri3 ); +area = counterclockwise( sortarray[0], sortarray[1], sortarray[2] ); +if ( area == 0.0 ) { +/* Three collinear points; the triangulation is two edges. */ +setorg( midtri, sortarray[0] ); +setdest( midtri, sortarray[1] ); +setorg( tri1, sortarray[1] ); +setdest( tri1, sortarray[0] ); +setorg( tri2, sortarray[2] ); +setdest( tri2, sortarray[1] ); +setorg( tri3, sortarray[1] ); +setdest( tri3, sortarray[2] ); +/* All apices are intentionally left NULL. */ +bond( midtri, tri1 ); +bond( tri2, tri3 ); +lnextself( midtri ); +lprevself( tri1 ); +lnextself( tri2 ); +lprevself( tri3 ); +bond( midtri, tri3 ); +bond( tri1, tri2 ); +lnextself( midtri ); +lprevself( tri1 ); +lnextself( tri2 ); +lprevself( tri3 ); +bond( midtri, tri1 ); +bond( tri2, tri3 ); +/* Ensure that the origin of `farleft' is sortarray[0]. */ +triedgecopy( tri1, *farleft ); +/* Ensure that the destination of `farright' is sortarray[2]. */ +triedgecopy( tri2, *farright ); +} +else { +/* The three points are not collinear; the triangulation is one */ +/* triangle, namely `midtri'. */ +setorg( midtri, sortarray[0] ); +setdest( tri1, sortarray[0] ); +setorg( tri3, sortarray[0] ); +/* Apices of tri1, tri2, and tri3 are left NULL. */ +if ( area > 0.0 ) { +/* The vertices are in counterclockwise order. */ +setdest( midtri, sortarray[1] ); +setorg( tri1, sortarray[1] ); +setdest( tri2, sortarray[1] ); +setapex( midtri, sortarray[2] ); +setorg( tri2, sortarray[2] ); +setdest( tri3, sortarray[2] ); +} +else { +/* The vertices are in clockwise order. */ +setdest( midtri, sortarray[2] ); +setorg( tri1, sortarray[2] ); +setdest( tri2, sortarray[2] ); +setapex( midtri, sortarray[1] ); +setorg( tri2, sortarray[1] ); +setdest( tri3, sortarray[1] ); +} +/* The topology does not depend on how the vertices are ordered. */ +bond( midtri, tri1 ); +lnextself( midtri ); +bond( midtri, tri2 ); +lnextself( midtri ); +bond( midtri, tri3 ); +lprevself( tri1 ); +lnextself( tri2 ); +bond( tri1, tri2 ); +lprevself( tri1 ); +lprevself( tri3 ); +bond( tri1, tri3 ); +lnextself( tri2 ); +lprevself( tri3 ); +bond( tri2, tri3 ); +/* Ensure that the origin of `farleft' is sortarray[0]. */ +triedgecopy( tri1, *farleft ); +/* Ensure that the destination of `farright' is sortarray[2]. */ +if ( area > 0.0 ) { +triedgecopy( tri2, *farright ); +} +else { +lnext( *farleft, *farright ); +} +} +if ( verbose > 2 ) { +printf( " Creating " ); +printtriangle( &midtri ); +printf( " Creating " ); +printtriangle( &tri1 ); +printf( " Creating " ); +printtriangle( &tri2 ); +printf( " Creating " ); +printtriangle( &tri3 ); +} +return; +} +else { +/* Split the vertices in half. */ +divider = vertices >> 1; +/* Recursively triangulate each half. */ +divconqrecurse( sortarray, divider, 1 - axis, farleft, &innerleft ); +divconqrecurse( &sortarray[divider], vertices - divider, 1 - axis, +&innerright, farright ); +if ( verbose > 1 ) { +printf( " Joining triangulations with %d and %d vertices.\n", divider, +vertices - divider ); +} +/* Merge the two triangulations into one. */ +mergehulls( farleft, &innerleft, &innerright, farright, axis ); +} +} + +long removeghosts( startghost ) +struct triedge *startghost; +{ +struct triedge searchedge; +struct triedge dissolveedge; +struct triedge deadtri; +point markorg; +long hullsize; +triangle ptr; /* Temporary variable used by sym(). */ + +if ( verbose ) { +printf( " Removing ghost triangles.\n" ); +} +/* Find an edge on the convex hull to start point location from. */ +lprev( *startghost, searchedge ); +symself( searchedge ); +dummytri[0] = encode( searchedge ); +/* Remove the bounding box and count the convex hull edges. */ +triedgecopy( *startghost, dissolveedge ); +hullsize = 0; +do { +hullsize++; +lnext( dissolveedge, deadtri ); +lprevself( dissolveedge ); +symself( dissolveedge ); +/* If no PSLG is involved, set the boundary markers of all the points */ +/* on the convex hull. If a PSLG is used, this step is done later. */ +if ( !poly ) { +/* Watch out for the case where all the input points are collinear. */ +if ( dissolveedge.tri != dummytri ) { +org( dissolveedge, markorg ); +if ( pointmark( markorg ) == 0 ) { +setpointmark( markorg, 1 ); +} +} +} +/* Remove a bounding triangle from a convex hull triangle. */ +dissolve( dissolveedge ); +/* Find the next bounding triangle. */ +sym( deadtri, dissolveedge ); +/* Delete the bounding triangle. */ +triangledealloc( deadtri.tri ); +} while ( !triedgeequal( dissolveedge, *startghost )); +return hullsize; +} + /*****************************************************************************/ /* */ /* divconqdelaunay() Form a Delaunay triangulation by the divide-and- */ @@ -7750,65 +7922,65 @@ struct triedge *startghost; /*****************************************************************************/ long divconqdelaunay(){ - point *sortarray; - struct triedge hullleft, hullright; - int divider; - int i, j; - - /* Allocate an array of pointers to points for sorting. */ - sortarray = (point *) malloc( inpoints * sizeof( point ) ); - if ( sortarray == (point *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - traversalinit( &points ); - for ( i = 0; i < inpoints; i++ ) { - sortarray[i] = pointtraverse(); - } - if ( verbose ) { - printf( " Sorting points.\n" ); - } - /* Sort the points. */ - pointsort( sortarray, inpoints ); - /* Discard duplicate points, which can really mess up the algorithm. */ - i = 0; - for ( j = 1; j < inpoints; j++ ) { - if ( ( sortarray[i][0] == sortarray[j][0] ) - && ( sortarray[i][1] == sortarray[j][1] ) ) { - if ( !quiet ) { - printf( - "Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n", - sortarray[j][0], sortarray[j][1] ); - } +point *sortarray; +struct triedge hullleft, hullright; +int divider; +int i, j; + +/* Allocate an array of pointers to points for sorting. */ +sortarray = (point *) malloc( inpoints * sizeof( point )); +if ( sortarray == (point *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +traversalinit( &points ); +for ( i = 0; i < inpoints; i++ ) { +sortarray[i] = pointtraverse(); +} +if ( verbose ) { +printf( " Sorting points.\n" ); +} +/* Sort the points. */ +pointsort( sortarray, inpoints ); +/* Discard duplicate points, which can really mess up the algorithm. */ +i = 0; +for ( j = 1; j < inpoints; j++ ) { +if (( sortarray[i][0] == sortarray[j][0] ) +&& ( sortarray[i][1] == sortarray[j][1] )) { +if ( !quiet ) { +printf( +"Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n", +sortarray[j][0], sortarray[j][1] ); +} /* Commented out - would eliminate point from output .node file, but causes a failure if some segment has this point as an endpoint. setpointmark(sortarray[j], DEADPOINT); */ - } - else { - i++; - sortarray[i] = sortarray[j]; - } - } - i++; - if ( dwyer ) { - /* Re-sort the array of points to accommodate alternating cuts. */ - divider = i >> 1; - if ( i - divider >= 2 ) { - if ( divider >= 2 ) { - alternateaxes( sortarray, divider, 1 ); - } - alternateaxes( &sortarray[divider], i - divider, 1 ); - } - } - if ( verbose ) { - printf( " Forming triangulation.\n" ); - } - /* Form the Delaunay triangulation. */ - divconqrecurse( sortarray, i, 0, &hullleft, &hullright ); - free( sortarray ); - - return removeghosts( &hullleft ); +} +else { +i++; +sortarray[i] = sortarray[j]; +} +} +i++; +if ( dwyer ) { +/* Re-sort the array of points to accommodate alternating cuts. */ +divider = i >> 1; +if ( i - divider >= 2 ) { +if ( divider >= 2 ) { +alternateaxes( sortarray, divider, 1 ); +} +alternateaxes( &sortarray[divider], i - divider, 1 ); +} +} +if ( verbose ) { +printf( " Forming triangulation.\n" ); +} +/* Form the Delaunay triangulation. */ +divconqrecurse( sortarray, i, 0, &hullleft, &hullright ); +free( sortarray ); + +return removeghosts( &hullleft ); } /** **/ @@ -7830,51 +8002,52 @@ long divconqdelaunay(){ /* */ /*****************************************************************************/ -#ifndef REDUCED +#ifndef +REDUCED void boundingbox(){ - struct triedge inftri; /* Handle for the triangular bounding box. */ - REAL width; - - if ( verbose ) { - printf( " Creating triangular bounding box.\n" ); - } - /* Find the width (or height, whichever is larger) of the triangulation. */ - width = xmax - xmin; - if ( ymax - ymin > width ) { - width = ymax - ymin; - } - if ( width == 0.0 ) { - width = 1.0; - } - /* Create the vertices of the bounding box. */ - infpoint1 = (point) malloc( points.itembytes ); - infpoint2 = (point) malloc( points.itembytes ); - infpoint3 = (point) malloc( points.itembytes ); - if ( ( infpoint1 == (point) NULL ) || ( infpoint2 == (point) NULL ) - || ( infpoint3 == (point) NULL ) ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - infpoint1[0] = xmin - 50.0 * width; - infpoint1[1] = ymin - 40.0 * width; - infpoint2[0] = xmax + 50.0 * width; - infpoint2[1] = ymin - 40.0 * width; - infpoint3[0] = 0.5 * ( xmin + xmax ); - infpoint3[1] = ymax + 60.0 * width; - - /* Create the bounding box. */ - maketriangle( &inftri ); - setorg( inftri, infpoint1 ); - setdest( inftri, infpoint2 ); - setapex( inftri, infpoint3 ); - /* Link dummytri to the bounding box so we can always find an */ - /* edge to begin searching (point location) from. */ - dummytri[0] = (triangle) inftri.tri; - if ( verbose > 2 ) { - printf( " Creating " ); - printtriangle( &inftri ); - } +struct triedge inftri; /* Handle for the triangular bounding box. */ +REAL width; + +if ( verbose ) { +printf( " Creating triangular bounding box.\n" ); +} +/* Find the width (or height, whichever is larger) of the triangulation. */ +width = xmax - xmin; +if ( ymax - ymin > width ) { +width = ymax - ymin; +} +if ( width == 0.0 ) { +width = 1.0; +} +/* Create the vertices of the bounding box. */ +infpoint1 = (point) malloc( points.itembytes ); +infpoint2 = (point) malloc( points.itembytes ); +infpoint3 = (point) malloc( points.itembytes ); +if (( infpoint1 == (point) NULL ) || ( infpoint2 == (point) NULL ) +|| ( infpoint3 == (point) NULL )) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +infpoint1[0] = xmin - 50.0 * width; +infpoint1[1] = ymin - 40.0 * width; +infpoint2[0] = xmax + 50.0 * width; +infpoint2[1] = ymin - 40.0 * width; +infpoint3[0] = 0.5 * ( xmin + xmax ); +infpoint3[1] = ymax + 60.0 * width; + +/* Create the bounding box. */ +maketriangle( &inftri ); +setorg( inftri, infpoint1 ); +setdest( inftri, infpoint2 ); +setapex( inftri, infpoint3 ); +/* Link dummytri to the bounding box so we can always find an */ +/* edge to begin searching (point location) from. */ +dummytri[0] = (triangle) inftri.tri; +if ( verbose > 2 ) { +printf( " Creating " ); +printtriangle( &inftri ); +} } #endif /* not REDUCED */ @@ -7891,84 +8064,85 @@ void boundingbox(){ /* */ /*****************************************************************************/ -#ifndef REDUCED +#ifndef +REDUCED long removebox(){ - struct triedge deadtri; - struct triedge searchedge; - struct triedge checkedge; - struct triedge nextedge, finaledge, dissolveedge; - point markorg; - long hullsize; - triangle ptr; /* Temporary variable used by sym(). */ - - if ( verbose ) { - printf( " Removing triangular bounding box.\n" ); - } - /* Find a boundary triangle. */ - nextedge.tri = dummytri; - nextedge.orient = 0; - symself( nextedge ); - /* Mark a place to stop. */ - lprev( nextedge, finaledge ); - lnextself( nextedge ); - symself( nextedge ); - /* Find a triangle (on the boundary of the point set) that isn't */ - /* a bounding box triangle. */ - lprev( nextedge, searchedge ); - symself( searchedge ); - /* Check whether nextedge is another boundary triangle */ - /* adjacent to the first one. */ - lnext( nextedge, checkedge ); - symself( checkedge ); - if ( checkedge.tri == dummytri ) { - /* Go on to the next triangle. There are only three boundary */ - /* triangles, and this next triangle cannot be the third one, */ - /* so it's safe to stop here. */ - lprevself( searchedge ); - symself( searchedge ); - } - /* Find a new boundary edge to search from, as the current search */ - /* edge lies on a bounding box triangle and will be deleted. */ - dummytri[0] = encode( searchedge ); - hullsize = -2l; - while ( !triedgeequal( nextedge, finaledge ) ) { - hullsize++; - lprev( nextedge, dissolveedge ); - symself( dissolveedge ); - /* If not using a PSLG, the vertices should be marked now. */ - /* (If using a PSLG, markhull() will do the job.) */ - if ( !poly ) { - /* Be careful! One must check for the case where all the input */ - /* points are collinear, and thus all the triangles are part of */ - /* the bounding box. Otherwise, the setpointmark() call below */ - /* will cause a bad pointer reference. */ - if ( dissolveedge.tri != dummytri ) { - org( dissolveedge, markorg ); - if ( pointmark( markorg ) == 0 ) { - setpointmark( markorg, 1 ); - } - } - } - /* Disconnect the bounding box triangle from the mesh triangle. */ - dissolve( dissolveedge ); - lnext( nextedge, deadtri ); - sym( deadtri, nextedge ); - /* Get rid of the bounding box triangle. */ - triangledealloc( deadtri.tri ); - /* Do we need to turn the corner? */ - if ( nextedge.tri == dummytri ) { - /* Turn the corner. */ - triedgecopy( dissolveedge, nextedge ); - } - } - triangledealloc( finaledge.tri ); - - free( infpoint1 ); /* Deallocate the bounding box vertices. */ - free( infpoint2 ); - free( infpoint3 ); - - return hullsize; +struct triedge deadtri; +struct triedge searchedge; +struct triedge checkedge; +struct triedge nextedge, finaledge, dissolveedge; +point markorg; +long hullsize; +triangle ptr; /* Temporary variable used by sym(). */ + +if ( verbose ) { +printf( " Removing triangular bounding box.\n" ); +} +/* Find a boundary triangle. */ +nextedge.tri = dummytri; +nextedge.orient = 0; +symself( nextedge ); +/* Mark a place to stop. */ +lprev( nextedge, finaledge ); +lnextself( nextedge ); +symself( nextedge ); +/* Find a triangle (on the boundary of the point set) that isn't */ +/* a bounding box triangle. */ +lprev( nextedge, searchedge ); +symself( searchedge ); +/* Check whether nextedge is another boundary triangle */ +/* adjacent to the first one. */ +lnext( nextedge, checkedge ); +symself( checkedge ); +if ( checkedge.tri == dummytri ) { +/* Go on to the next triangle. There are only three boundary */ +/* triangles, and this next triangle cannot be the third one, */ +/* so it's safe to stop here. */ +lprevself( searchedge ); +symself( searchedge ); +} +/* Find a new boundary edge to search from, as the current search */ +/* edge lies on a bounding box triangle and will be deleted. */ +dummytri[0] = encode( searchedge ); +hullsize = -2l; +while ( !triedgeequal( nextedge, finaledge )) { +hullsize++; +lprev( nextedge, dissolveedge ); +symself( dissolveedge ); +/* If not using a PSLG, the vertices should be marked now. */ +/* (If using a PSLG, markhull() will do the job.) */ +if ( !poly ) { +/* Be careful! One must check for the case where all the input */ +/* points are collinear, and thus all the triangles are part of */ +/* the bounding box. Otherwise, the setpointmark() call below */ +/* will cause a bad pointer reference. */ +if ( dissolveedge.tri != dummytri ) { +org( dissolveedge, markorg ); +if ( pointmark( markorg ) == 0 ) { +setpointmark( markorg, 1 ); +} +} +} +/* Disconnect the bounding box triangle from the mesh triangle. */ +dissolve( dissolveedge ); +lnext( nextedge, deadtri ); +sym( deadtri, nextedge ); +/* Get rid of the bounding box triangle. */ +triangledealloc( deadtri.tri ); +/* Do we need to turn the corner? */ +if ( nextedge.tri == dummytri ) { +/* Turn the corner. */ +triedgecopy( dissolveedge, nextedge ); +} +} +triangledealloc( finaledge.tri ); + +free( infpoint1 ); /* Deallocate the bounding box vertices. */ +free( infpoint2 ); +free( infpoint3 ); + +return hullsize; } #endif /* not REDUCED */ @@ -7980,40 +8154,41 @@ long removebox(){ /* */ /*****************************************************************************/ -#ifndef REDUCED +#ifndef +REDUCED long incrementaldelaunay(){ - struct triedge starttri; - point pointloop; - int i; - - /* Create a triangular bounding box. */ - boundingbox(); - if ( verbose ) { - printf( " Incrementally inserting points.\n" ); - } - traversalinit( &points ); - pointloop = pointtraverse(); - i = 1; - while ( pointloop != (point) NULL ) { - /* Find a boundary triangle to search from. */ - starttri.tri = (triangle *) NULL; - if ( insertsite( pointloop, &starttri, (struct edge *) NULL, 0, 0 ) == - DUPLICATEPOINT ) { - if ( !quiet ) { - printf( - "Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n", - pointloop[0], pointloop[1] ); - } +struct triedge starttri; +point pointloop; +int i; + +/* Create a triangular bounding box. */ +boundingbox(); +if ( verbose ) { +printf( " Incrementally inserting points.\n" ); +} +traversalinit( &points ); +pointloop = pointtraverse(); +i = 1; +while ( pointloop != (point) NULL ) { +/* Find a boundary triangle to search from. */ +starttri.tri = (triangle *) NULL; +if ( insertsite( pointloop, &starttri, (struct edge *) NULL, 0, 0 ) == +DUPLICATEPOINT ) { +if ( !quiet ) { +printf( +"Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n", +pointloop[0], pointloop[1] ); +} /* Commented out - would eliminate point from output .node file. setpointmark(pointloop, DEADPOINT); */ - } - pointloop = pointtraverse(); - i++; - } - /* Remove the bounding box. */ - return removebox(); +} +pointloop = pointtraverse(); +i++; +} +/* Remove the bounding box. */ +return removebox(); } #endif /* not REDUCED */ @@ -8026,208 +8201,214 @@ long incrementaldelaunay(){ /** **/ /** **/ -#ifndef REDUCED +#ifndef +REDUCED void eventheapinsert( heap, heapsize, newevent ) struct event **heap; int heapsize; struct event *newevent; { - REAL eventx, eventy; - int eventnum; - int parent; - int notdone; - - eventx = newevent->xkey; - eventy = newevent->ykey; - eventnum = heapsize; - notdone = eventnum > 0; - while ( notdone ) { - parent = ( eventnum - 1 ) >> 1; - if ( ( heap[parent]->ykey < eventy ) || - ( ( heap[parent]->ykey == eventy ) - && ( heap[parent]->xkey <= eventx ) ) ) { - notdone = 0; - } - else { - heap[eventnum] = heap[parent]; - heap[eventnum]->heapposition = eventnum; - - eventnum = parent; - notdone = eventnum > 0; - } - } - heap[eventnum] = newevent; - newevent->heapposition = eventnum; +REAL eventx, eventy; +int eventnum; +int parent; +int notdone; + +eventx = newevent->xkey; +eventy = newevent->ykey; +eventnum = heapsize; +notdone = eventnum > 0; +while ( notdone ) { +parent = ( eventnum - 1 ) >> 1; +if (( heap[parent]->ykey < eventy ) || +(( heap[parent]->ykey == eventy ) +&& ( heap[parent]->xkey <= eventx ))) { +notdone = 0; +} +else { +heap[eventnum] = heap[parent]; +heap[eventnum]->heapposition = eventnum; + +eventnum = parent; +notdone = eventnum > 0; +} +} +heap[eventnum] = newevent; +newevent->heapposition = eventnum; } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED void eventheapify( heap, heapsize, eventnum ) struct event **heap; int heapsize; int eventnum; { - struct event *thisevent; - REAL eventx, eventy; - int leftchild, rightchild; - int smallest; - int notdone; - - thisevent = heap[eventnum]; - eventx = thisevent->xkey; - eventy = thisevent->ykey; - leftchild = 2 * eventnum + 1; - notdone = leftchild < heapsize; - while ( notdone ) { - if ( ( heap[leftchild]->ykey < eventy ) || - ( ( heap[leftchild]->ykey == eventy ) - && ( heap[leftchild]->xkey < eventx ) ) ) { - smallest = leftchild; - } - else { - smallest = eventnum; - } - rightchild = leftchild + 1; - if ( rightchild < heapsize ) { - if ( ( heap[rightchild]->ykey < heap[smallest]->ykey ) || - ( ( heap[rightchild]->ykey == heap[smallest]->ykey ) - && ( heap[rightchild]->xkey < heap[smallest]->xkey ) ) ) { - smallest = rightchild; - } - } - if ( smallest == eventnum ) { - notdone = 0; - } - else { - heap[eventnum] = heap[smallest]; - heap[eventnum]->heapposition = eventnum; - heap[smallest] = thisevent; - thisevent->heapposition = smallest; - - eventnum = smallest; - leftchild = 2 * eventnum + 1; - notdone = leftchild < heapsize; - } - } +struct event *thisevent; +REAL eventx, eventy; +int leftchild, rightchild; +int smallest; +int notdone; + +thisevent = heap[eventnum]; +eventx = thisevent->xkey; +eventy = thisevent->ykey; +leftchild = 2 * eventnum + 1; +notdone = leftchild < heapsize; +while ( notdone ) { +if (( heap[leftchild]->ykey < eventy ) || +(( heap[leftchild]->ykey == eventy ) +&& ( heap[leftchild]->xkey < eventx ))) { +smallest = leftchild; +} +else { +smallest = eventnum; +} +rightchild = leftchild + 1; +if ( rightchild < heapsize ) { +if (( heap[rightchild]->ykey < heap[smallest]->ykey ) || +(( heap[rightchild]->ykey == heap[smallest]->ykey ) +&& ( heap[rightchild]->xkey < heap[smallest]->xkey ))) { +smallest = rightchild; +} +} +if ( smallest == eventnum ) { +notdone = 0; +} +else { +heap[eventnum] = heap[smallest]; +heap[eventnum]->heapposition = eventnum; +heap[smallest] = thisevent; +thisevent->heapposition = smallest; + +eventnum = smallest; +leftchild = 2 * eventnum + 1; +notdone = leftchild < heapsize; +} +} } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED void eventheapdelete( heap, heapsize, eventnum ) struct event **heap; int heapsize; int eventnum; { - struct event *moveevent; - REAL eventx, eventy; - int parent; - int notdone; - - moveevent = heap[heapsize - 1]; - if ( eventnum > 0 ) { - eventx = moveevent->xkey; - eventy = moveevent->ykey; - do { - parent = ( eventnum - 1 ) >> 1; - if ( ( heap[parent]->ykey < eventy ) || - ( ( heap[parent]->ykey == eventy ) - && ( heap[parent]->xkey <= eventx ) ) ) { - notdone = 0; - } - else { - heap[eventnum] = heap[parent]; - heap[eventnum]->heapposition = eventnum; - - eventnum = parent; - notdone = eventnum > 0; - } - } while ( notdone ); - } - heap[eventnum] = moveevent; - moveevent->heapposition = eventnum; - eventheapify( heap, heapsize - 1, eventnum ); +struct event *moveevent; +REAL eventx, eventy; +int parent; +int notdone; + +moveevent = heap[heapsize - 1]; +if ( eventnum > 0 ) { +eventx = moveevent->xkey; +eventy = moveevent->ykey; +do { +parent = ( eventnum - 1 ) >> 1; +if (( heap[parent]->ykey < eventy ) || +(( heap[parent]->ykey == eventy ) +&& ( heap[parent]->xkey <= eventx ))) { +notdone = 0; +} +else { +heap[eventnum] = heap[parent]; +heap[eventnum]->heapposition = eventnum; + +eventnum = parent; +notdone = eventnum > 0; +} +} while ( notdone ); +} +heap[eventnum] = moveevent; +moveevent->heapposition = eventnum; +eventheapify( heap, heapsize - 1, eventnum ); } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED void createeventheap( eventheap, events, freeevents ) struct event ***eventheap; struct event **events; struct event **freeevents; { - point thispoint; - int maxevents; - int i; - - maxevents = ( 3 * inpoints ) / 2; - *eventheap = (struct event **) malloc( maxevents * sizeof( struct event * ) ); - if ( *eventheap == (struct event **) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - *events = (struct event *) malloc( maxevents * sizeof( struct event ) ); - if ( *events == (struct event *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - traversalinit( &points ); - for ( i = 0; i < inpoints; i++ ) { - thispoint = pointtraverse(); - ( *events )[i].eventptr = (VOID *) thispoint; - ( *events )[i].xkey = thispoint[0]; - ( *events )[i].ykey = thispoint[1]; - eventheapinsert( *eventheap, i, *events + i ); - } - *freeevents = (struct event *) NULL; - for ( i = maxevents - 1; i >= inpoints; i-- ) { - ( *events )[i].eventptr = (VOID *) *freeevents; - *freeevents = *events + i; - } +point thispoint; +int maxevents; +int i; + +maxevents = ( 3 * inpoints ) / 2; +*eventheap = (struct event **) malloc( maxevents * sizeof( struct event * )); +if ( *eventheap == (struct event **) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +*events = (struct event *) malloc( maxevents * sizeof( struct event )); +if ( *events == (struct event *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +traversalinit( &points ); +for ( i = 0; i < inpoints; i++ ) { +thispoint = pointtraverse(); +( *events )[i].eventptr = (VOID *) thispoint; +( *events )[i].xkey = thispoint[0]; +( *events )[i].ykey = thispoint[1]; +eventheapinsert( *eventheap, i, *events + i ); +} +*freeevents = (struct event *) NULL; +for ( i = maxevents - 1; i >= inpoints; i-- ) { +( *events )[i].eventptr = (VOID *) *freeevents; +*freeevents = *events + i; +} } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED int rightofhyperbola( fronttri, newsite ) struct triedge *fronttri; point newsite; { - point leftpoint, rightpoint; - REAL dxa, dya, dxb, dyb; - - hyperbolacount++; - - dest( *fronttri, leftpoint ); - apex( *fronttri, rightpoint ); - if ( ( leftpoint[1] < rightpoint[1] ) - || ( ( leftpoint[1] == rightpoint[1] ) && ( leftpoint[0] < rightpoint[0] ) ) ) { - if ( newsite[0] >= rightpoint[0] ) { - return 1; - } - } - else { - if ( newsite[0] <= leftpoint[0] ) { - return 0; - } - } - dxa = leftpoint[0] - newsite[0]; - dya = leftpoint[1] - newsite[1]; - dxb = rightpoint[0] - newsite[0]; - dyb = rightpoint[1] - newsite[1]; - return dya * ( dxb * dxb + dyb * dyb ) > dyb * ( dxa * dxa + dya * dya ); +point leftpoint, rightpoint; +REAL dxa, dya, dxb, dyb; + +hyperbolacount++; + +dest( *fronttri, leftpoint ); +apex( *fronttri, rightpoint ); +if (( leftpoint[1] < rightpoint[1] ) +|| (( leftpoint[1] == rightpoint[1] ) && ( leftpoint[0] < rightpoint[0] ))) { +if ( newsite[0] >= rightpoint[0] ) { +return 1; +} +} +else { +if ( newsite[0] <= leftpoint[0] ) { +return 0; +} +} +dxa = leftpoint[0] - newsite[0]; +dya = leftpoint[1] - newsite[1]; +dxb = rightpoint[0] - newsite[0]; +dyb = rightpoint[1] - newsite[1]; +return dya * ( dxb * dxb + dyb * dyb ) > dyb * ( dxa * dxa + dya * dya ); } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED REAL circletop( pa, pb, pc, ccwabc ) point pa; @@ -8235,27 +8416,28 @@ point pb; point pc; REAL ccwabc; { - REAL xac, yac, xbc, ybc, xab, yab; - REAL aclen2, bclen2, ablen2; - - circletopcount++; - - xac = pa[0] - pc[0]; - yac = pa[1] - pc[1]; - xbc = pb[0] - pc[0]; - ybc = pb[1] - pc[1]; - xab = pa[0] - pb[0]; - yab = pa[1] - pb[1]; - aclen2 = xac * xac + yac * yac; - bclen2 = xbc * xbc + ybc * ybc; - ablen2 = xab * xab + yab * yab; - return pc[1] + ( xac * bclen2 - xbc * aclen2 + sqrt( aclen2 * bclen2 * ablen2 ) ) - / ( 2.0 * ccwabc ); +REAL xac, yac, xbc, ybc, xab, yab; +REAL aclen2, bclen2, ablen2; + +circletopcount++; + +xac = pa[0] - pc[0]; +yac = pa[1] - pc[1]; +xbc = pb[0] - pc[0]; +ybc = pb[1] - pc[1]; +xab = pa[0] - pb[0]; +yab = pa[1] - pb[1]; +aclen2 = xac * xac + yac * yac; +bclen2 = xbc * xbc + ybc * ybc; +ablen2 = xab * xab + yab * yab; +return pc[1] + ( xac * bclen2 - xbc * aclen2 + sqrt( aclen2 * bclen2 * ablen2 )) +/ ( 2.0 * ccwabc ); } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED void check4deadevent( checktri, freeevents, eventheap, heapsize ) struct triedge *checktri; @@ -8263,180 +8445,183 @@ struct event **freeevents; struct event **eventheap; int *heapsize; { - struct event *deadevent; - point eventpoint; - int eventnum; - - org( *checktri, eventpoint ); - if ( eventpoint != (point) NULL ) { - deadevent = (struct event *) eventpoint; - eventnum = deadevent->heapposition; - deadevent->eventptr = (VOID *) *freeevents; - *freeevents = deadevent; - eventheapdelete( eventheap, *heapsize, eventnum ); - ( *heapsize )--; - setorg( *checktri, NULL ); - } +struct event *deadevent; +point eventpoint; +int eventnum; + +org( *checktri, eventpoint ); +if ( eventpoint != (point) NULL ) { +deadevent = (struct event *) eventpoint; +eventnum = deadevent->heapposition; +deadevent->eventptr = (VOID *) *freeevents; +*freeevents = deadevent; +eventheapdelete( eventheap, *heapsize, eventnum ); +( *heapsize )--; +setorg( *checktri, NULL ); +} } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED struct splaynode *splay( splaytree, searchpoint, searchtri ) struct splaynode *splaytree; point searchpoint; struct triedge *searchtri; { - struct splaynode *child, *grandchild; - struct splaynode *lefttree, *righttree; - struct splaynode *leftright; - point checkpoint; - int rightofroot, rightofchild; - - if ( splaytree == (struct splaynode *) NULL ) { - return (struct splaynode *) NULL; - } - dest( splaytree->keyedge, checkpoint ); - if ( checkpoint == splaytree->keydest ) { - rightofroot = rightofhyperbola( &splaytree->keyedge, searchpoint ); - if ( rightofroot ) { - triedgecopy( splaytree->keyedge, *searchtri ); - child = splaytree->rchild; - } - else { - child = splaytree->lchild; - } - if ( child == (struct splaynode *) NULL ) { - return splaytree; - } - dest( child->keyedge, checkpoint ); - if ( checkpoint != child->keydest ) { - child = splay( child, searchpoint, searchtri ); - if ( child == (struct splaynode *) NULL ) { - if ( rightofroot ) { - splaytree->rchild = (struct splaynode *) NULL; - } - else { - splaytree->lchild = (struct splaynode *) NULL; - } - return splaytree; - } - } - rightofchild = rightofhyperbola( &child->keyedge, searchpoint ); - if ( rightofchild ) { - triedgecopy( child->keyedge, *searchtri ); - grandchild = splay( child->rchild, searchpoint, searchtri ); - child->rchild = grandchild; - } - else { - grandchild = splay( child->lchild, searchpoint, searchtri ); - child->lchild = grandchild; - } - if ( grandchild == (struct splaynode *) NULL ) { - if ( rightofroot ) { - splaytree->rchild = child->lchild; - child->lchild = splaytree; - } - else { - splaytree->lchild = child->rchild; - child->rchild = splaytree; - } - return child; - } - if ( rightofchild ) { - if ( rightofroot ) { - splaytree->rchild = child->lchild; - child->lchild = splaytree; - } - else { - splaytree->lchild = grandchild->rchild; - grandchild->rchild = splaytree; - } - child->rchild = grandchild->lchild; - grandchild->lchild = child; - } - else { - if ( rightofroot ) { - splaytree->rchild = grandchild->lchild; - grandchild->lchild = splaytree; - } - else { - splaytree->lchild = child->rchild; - child->rchild = splaytree; - } - child->lchild = grandchild->rchild; - grandchild->rchild = child; - } - return grandchild; - } - else { - lefttree = splay( splaytree->lchild, searchpoint, searchtri ); - righttree = splay( splaytree->rchild, searchpoint, searchtri ); - - pooldealloc( &splaynodes, (VOID *) splaytree ); - if ( lefttree == (struct splaynode *) NULL ) { - return righttree; - } - else if ( righttree == (struct splaynode *) NULL ) { - return lefttree; - } - else if ( lefttree->rchild == (struct splaynode *) NULL ) { - lefttree->rchild = righttree->lchild; - righttree->lchild = lefttree; - return righttree; - } - else if ( righttree->lchild == (struct splaynode *) NULL ) { - righttree->lchild = lefttree->rchild; - lefttree->rchild = righttree; - return lefttree; - } - else { +struct splaynode *child, *grandchild; +struct splaynode *lefttree, *righttree; +struct splaynode *leftright; +point checkpoint; +int rightofroot, rightofchild; + +if ( splaytree == (struct splaynode *) NULL ) { +return (struct splaynode *) NULL; +} +dest( splaytree->keyedge, checkpoint ); +if ( checkpoint == splaytree->keydest ) { +rightofroot = rightofhyperbola( &splaytree->keyedge, searchpoint ); +if ( rightofroot ) { +triedgecopy( splaytree->keyedge, *searchtri ); +child = splaytree->rchild; +} +else { +child = splaytree->lchild; +} +if ( child == (struct splaynode *) NULL ) { +return splaytree; +} +dest( child->keyedge, checkpoint ); +if ( checkpoint != child->keydest ) { +child = splay( child, searchpoint, searchtri ); +if ( child == (struct splaynode *) NULL ) { +if ( rightofroot ) { +splaytree->rchild = (struct splaynode *) NULL; +} +else { +splaytree->lchild = (struct splaynode *) NULL; +} +return splaytree; +} +} +rightofchild = rightofhyperbola( &child->keyedge, searchpoint ); +if ( rightofchild ) { +triedgecopy( child->keyedge, *searchtri ); +grandchild = splay( child->rchild, searchpoint, searchtri ); +child->rchild = grandchild; +} +else { +grandchild = splay( child->lchild, searchpoint, searchtri ); +child->lchild = grandchild; +} +if ( grandchild == (struct splaynode *) NULL ) { +if ( rightofroot ) { +splaytree->rchild = child->lchild; +child->lchild = splaytree; +} +else { +splaytree->lchild = child->rchild; +child->rchild = splaytree; +} +return child; +} +if ( rightofchild ) { +if ( rightofroot ) { +splaytree->rchild = child->lchild; +child->lchild = splaytree; +} +else { +splaytree->lchild = grandchild->rchild; +grandchild->rchild = splaytree; +} +child->rchild = grandchild->lchild; +grandchild->lchild = child; +} +else { +if ( rightofroot ) { +splaytree->rchild = grandchild->lchild; +grandchild->lchild = splaytree; +} +else { +splaytree->lchild = child->rchild; +child->rchild = splaytree; +} +child->lchild = grandchild->rchild; +grandchild->rchild = child; +} +return grandchild; +} +else { +lefttree = splay( splaytree->lchild, searchpoint, searchtri ); +righttree = splay( splaytree->rchild, searchpoint, searchtri ); + +pooldealloc( &splaynodes, (VOID *) splaytree ); +if ( lefttree == (struct splaynode *) NULL ) { +return righttree; +} +else if ( righttree == (struct splaynode *) NULL ) { +return lefttree; +} +else if ( lefttree->rchild == (struct splaynode *) NULL ) { +lefttree->rchild = righttree->lchild; +righttree->lchild = lefttree; +return righttree; +} +else if ( righttree->lchild == (struct splaynode *) NULL ) { +righttree->lchild = lefttree->rchild; +lefttree->rchild = righttree; +return lefttree; +} +else { /* printf("Holy Toledo!!!\n"); */ - leftright = lefttree->rchild; - while ( leftright->rchild != (struct splaynode *) NULL ) { - leftright = leftright->rchild; - } - leftright->rchild = righttree; - return lefttree; - } - } +leftright = lefttree->rchild; +while ( leftright->rchild != (struct splaynode *) NULL ) { +leftright = leftright->rchild; +} +leftright->rchild = righttree; +return lefttree; +} +} } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED struct splaynode *splayinsert( splayroot, newkey, searchpoint ) struct splaynode *splayroot; struct triedge *newkey; point searchpoint; { - struct splaynode *newsplaynode; - - newsplaynode = (struct splaynode *) poolalloc( &splaynodes ); - triedgecopy( *newkey, newsplaynode->keyedge ); - dest( *newkey, newsplaynode->keydest ); - if ( splayroot == (struct splaynode *) NULL ) { - newsplaynode->lchild = (struct splaynode *) NULL; - newsplaynode->rchild = (struct splaynode *) NULL; - } - else if ( rightofhyperbola( &splayroot->keyedge, searchpoint ) ) { - newsplaynode->lchild = splayroot; - newsplaynode->rchild = splayroot->rchild; - splayroot->rchild = (struct splaynode *) NULL; - } - else { - newsplaynode->lchild = splayroot->lchild; - newsplaynode->rchild = splayroot; - splayroot->lchild = (struct splaynode *) NULL; - } - return newsplaynode; +struct splaynode *newsplaynode; + +newsplaynode = (struct splaynode *) poolalloc( &splaynodes ); +triedgecopy( *newkey, newsplaynode->keyedge ); +dest( *newkey, newsplaynode->keydest ); +if ( splayroot == (struct splaynode *) NULL ) { +newsplaynode->lchild = (struct splaynode *) NULL; +newsplaynode->rchild = (struct splaynode *) NULL; +} +else if ( rightofhyperbola( &splayroot->keyedge, searchpoint )) { +newsplaynode->lchild = splayroot; +newsplaynode->rchild = splayroot->rchild; +splayroot->rchild = (struct splaynode *) NULL; +} +else { +newsplaynode->lchild = splayroot->lchild; +newsplaynode->rchild = splayroot; +splayroot->lchild = (struct splaynode *) NULL; +} +return newsplaynode; } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED struct splaynode *circletopinsert( splayroot, newkey, pa, pb, pc, topy ) struct splaynode *splayroot; @@ -8446,177 +8631,179 @@ point pb; point pc; REAL topy; { - REAL ccwabc; - REAL xac, yac, xbc, ybc; - REAL aclen2, bclen2; - REAL searchpoint[2]; - struct triedge dummytri; - - ccwabc = counterclockwise( pa, pb, pc ); - xac = pa[0] - pc[0]; - yac = pa[1] - pc[1]; - xbc = pb[0] - pc[0]; - ybc = pb[1] - pc[1]; - aclen2 = xac * xac + yac * yac; - bclen2 = xbc * xbc + ybc * ybc; - searchpoint[0] = pc[0] - ( yac * bclen2 - ybc * aclen2 ) / ( 2.0 * ccwabc ); - searchpoint[1] = topy; - return splayinsert( splay( splayroot, (point) searchpoint, &dummytri ), newkey, - (point) searchpoint ); +REAL ccwabc; +REAL xac, yac, xbc, ybc; +REAL aclen2, bclen2; +REAL searchpoint[2]; +struct triedge dummytri; + +ccwabc = counterclockwise( pa, pb, pc ); +xac = pa[0] - pc[0]; +yac = pa[1] - pc[1]; +xbc = pb[0] - pc[0]; +ybc = pb[1] - pc[1]; +aclen2 = xac * xac + yac * yac; +bclen2 = xbc * xbc + ybc * ybc; +searchpoint[0] = pc[0] - ( yac * bclen2 - ybc * aclen2 ) / ( 2.0 * ccwabc ); +searchpoint[1] = topy; +return splayinsert( splay( splayroot, (point) searchpoint, &dummytri ), newkey, +(point) searchpoint ); } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED struct splaynode *frontlocate( splayroot, bottommost, searchpoint, searchtri, - farright ) +farright ) struct splaynode *splayroot; struct triedge *bottommost; point searchpoint; struct triedge *searchtri; int *farright; { - int farrightflag; - triangle ptr; /* Temporary variable used by onext(). */ +int farrightflag; +triangle ptr; /* Temporary variable used by onext(). */ - triedgecopy( *bottommost, *searchtri ); - splayroot = splay( splayroot, searchpoint, searchtri ); +triedgecopy( *bottommost, *searchtri ); +splayroot = splay( splayroot, searchpoint, searchtri ); - farrightflag = 0; - while ( !farrightflag && rightofhyperbola( searchtri, searchpoint ) ) { - onextself( *searchtri ); - farrightflag = triedgeequal( *searchtri, *bottommost ); - } - *farright = farrightflag; - return splayroot; +farrightflag = 0; +while ( !farrightflag && rightofhyperbola( searchtri, searchpoint )) { +onextself( *searchtri ); +farrightflag = triedgeequal( *searchtri, *bottommost ); +} +*farright = farrightflag; +return splayroot; } #endif /* not REDUCED */ -#ifndef REDUCED +#ifndef +REDUCED long sweeplinedelaunay(){ - struct event **eventheap; - struct event *events; - struct event *freeevents; - struct event *nextevent; - struct event *newevent; - struct splaynode *splayroot; - struct triedge bottommost; - struct triedge searchtri; - struct triedge fliptri; - struct triedge lefttri, righttri, farlefttri, farrighttri; - struct triedge inserttri; - point firstpoint, secondpoint; - point nextpoint, lastpoint; - point connectpoint; - point leftpoint, midpoint, rightpoint; - REAL lefttest, righttest; - int heapsize; - int check4events, farrightflag; - triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ - - poolinit( &splaynodes, sizeof( struct splaynode ), SPLAYNODEPERBLOCK, POINTER, - 0 ); - splayroot = (struct splaynode *) NULL; - - if ( verbose ) { - printf( " Placing points in event heap.\n" ); - } - createeventheap( &eventheap, &events, &freeevents ); - heapsize = inpoints; - - if ( verbose ) { - printf( " Forming triangulation.\n" ); - } - maketriangle( &lefttri ); - maketriangle( &righttri ); - bond( lefttri, righttri ); - lnextself( lefttri ); - lprevself( righttri ); - bond( lefttri, righttri ); - lnextself( lefttri ); - lprevself( righttri ); - bond( lefttri, righttri ); - firstpoint = (point) eventheap[0]->eventptr; - eventheap[0]->eventptr = (VOID *) freeevents; - freeevents = eventheap[0]; - eventheapdelete( eventheap, heapsize, 0 ); - heapsize--; - do { - if ( heapsize == 0 ) { - printf( "Error: Input points are all identical.\n" ); - exit( 1 ); - } - secondpoint = (point) eventheap[0]->eventptr; - eventheap[0]->eventptr = (VOID *) freeevents; - freeevents = eventheap[0]; - eventheapdelete( eventheap, heapsize, 0 ); - heapsize--; - if ( ( firstpoint[0] == secondpoint[0] ) - && ( firstpoint[1] == secondpoint[1] ) ) { - printf( - "Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n", - secondpoint[0], secondpoint[1] ); +struct event **eventheap; +struct event *events; +struct event *freeevents; +struct event *nextevent; +struct event *newevent; +struct splaynode *splayroot; +struct triedge bottommost; +struct triedge searchtri; +struct triedge fliptri; +struct triedge lefttri, righttri, farlefttri, farrighttri; +struct triedge inserttri; +point firstpoint, secondpoint; +point nextpoint, lastpoint; +point connectpoint; +point leftpoint, midpoint, rightpoint; +REAL lefttest, righttest; +int heapsize; +int check4events, farrightflag; +triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ + +poolinit( &splaynodes, sizeof( struct splaynode ), SPLAYNODEPERBLOCK, POINTER, +0 ); +splayroot = (struct splaynode *) NULL; + +if ( verbose ) { +printf( " Placing points in event heap.\n" ); +} +createeventheap( &eventheap, &events, &freeevents ); +heapsize = inpoints; + +if ( verbose ) { +printf( " Forming triangulation.\n" ); +} +maketriangle( &lefttri ); +maketriangle( &righttri ); +bond( lefttri, righttri ); +lnextself( lefttri ); +lprevself( righttri ); +bond( lefttri, righttri ); +lnextself( lefttri ); +lprevself( righttri ); +bond( lefttri, righttri ); +firstpoint = (point) eventheap[0]->eventptr; +eventheap[0]->eventptr = (VOID *) freeevents; +freeevents = eventheap[0]; +eventheapdelete( eventheap, heapsize, 0 ); +heapsize--; +do { +if ( heapsize == 0 ) { +printf( "Error: Input points are all identical.\n" ); +exit( 1 ); +} +secondpoint = (point) eventheap[0]->eventptr; +eventheap[0]->eventptr = (VOID *) freeevents; +freeevents = eventheap[0]; +eventheapdelete( eventheap, heapsize, 0 ); +heapsize--; +if (( firstpoint[0] == secondpoint[0] ) +&& ( firstpoint[1] == secondpoint[1] )) { +printf( +"Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n", +secondpoint[0], secondpoint[1] ); /* Commented out - would eliminate point from output .node file. setpointmark(secondpoint, DEADPOINT); */ - } - } while ( ( firstpoint[0] == secondpoint[0] ) - && ( firstpoint[1] == secondpoint[1] ) ); - setorg( lefttri, firstpoint ); - setdest( lefttri, secondpoint ); - setorg( righttri, secondpoint ); - setdest( righttri, firstpoint ); - lprev( lefttri, bottommost ); - lastpoint = secondpoint; - while ( heapsize > 0 ) { - nextevent = eventheap[0]; - eventheapdelete( eventheap, heapsize, 0 ); - heapsize--; - check4events = 1; - if ( nextevent->xkey < xmin ) { - decode( nextevent->eventptr, fliptri ); - oprev( fliptri, farlefttri ); - check4deadevent( &farlefttri, &freeevents, eventheap, &heapsize ); - onext( fliptri, farrighttri ); - check4deadevent( &farrighttri, &freeevents, eventheap, &heapsize ); - - if ( triedgeequal( farlefttri, bottommost ) ) { - lprev( fliptri, bottommost ); - } - flip( &fliptri ); - setapex( fliptri, NULL ); - lprev( fliptri, lefttri ); - lnext( fliptri, righttri ); - sym( lefttri, farlefttri ); - - if ( randomnation( SAMPLERATE ) == 0 ) { - symself( fliptri ); - dest( fliptri, leftpoint ); - apex( fliptri, midpoint ); - org( fliptri, rightpoint ); - splayroot = circletopinsert( splayroot, &lefttri, leftpoint, midpoint, - rightpoint, nextevent->ykey ); - } - } - else { - nextpoint = (point) nextevent->eventptr; - if ( ( nextpoint[0] == lastpoint[0] ) && ( nextpoint[1] == lastpoint[1] ) ) { - printf( - "Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n", - nextpoint[0], nextpoint[1] ); +} +} while (( firstpoint[0] == secondpoint[0] ) +&& ( firstpoint[1] == secondpoint[1] )); +setorg( lefttri, firstpoint ); +setdest( lefttri, secondpoint ); +setorg( righttri, secondpoint ); +setdest( righttri, firstpoint ); +lprev( lefttri, bottommost ); +lastpoint = secondpoint; +while ( heapsize > 0 ) { +nextevent = eventheap[0]; +eventheapdelete( eventheap, heapsize, 0 ); +heapsize--; +check4events = 1; +if ( nextevent->xkey < xmin ) { +decode( nextevent->eventptr, fliptri ); +oprev( fliptri, farlefttri ); +check4deadevent( &farlefttri, &freeevents, eventheap, &heapsize ); +onext( fliptri, farrighttri ); +check4deadevent( &farrighttri, &freeevents, eventheap, &heapsize ); + +if ( triedgeequal( farlefttri, bottommost )) { +lprev( fliptri, bottommost ); +} +flip( &fliptri ); +setapex( fliptri, NULL ); +lprev( fliptri, lefttri ); +lnext( fliptri, righttri ); +sym( lefttri, farlefttri ); + +if ( randomnation( SAMPLERATE ) == 0 ) { +symself( fliptri ); +dest( fliptri, leftpoint ); +apex( fliptri, midpoint ); +org( fliptri, rightpoint ); +splayroot = circletopinsert( splayroot, &lefttri, leftpoint, midpoint, +rightpoint, nextevent->ykey ); +} +} +else { +nextpoint = (point) nextevent->eventptr; +if (( nextpoint[0] == lastpoint[0] ) && ( nextpoint[1] == lastpoint[1] )) { +printf( +"Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n", +nextpoint[0], nextpoint[1] ); /* Commented out - would eliminate point from output .node file. setpointmark(nextpoint, DEADPOINT); */ - check4events = 0; - } - else { - lastpoint = nextpoint; +check4events = 0; +} +else { +lastpoint = nextpoint; - splayroot = frontlocate( splayroot, &bottommost, nextpoint, &searchtri, - &farrightflag ); +splayroot = frontlocate( splayroot, &bottommost, nextpoint, &searchtri, +&farrightflag ); /* triedgecopy(bottommost, searchtri); farrightflag = 0; @@ -8626,78 +8813,78 @@ long sweeplinedelaunay(){ } */ - check4deadevent( &searchtri, &freeevents, eventheap, &heapsize ); - - triedgecopy( searchtri, farrighttri ); - sym( searchtri, farlefttri ); - maketriangle( &lefttri ); - maketriangle( &righttri ); - dest( farrighttri, connectpoint ); - setorg( lefttri, connectpoint ); - setdest( lefttri, nextpoint ); - setorg( righttri, nextpoint ); - setdest( righttri, connectpoint ); - bond( lefttri, righttri ); - lnextself( lefttri ); - lprevself( righttri ); - bond( lefttri, righttri ); - lnextself( lefttri ); - lprevself( righttri ); - bond( lefttri, farlefttri ); - bond( righttri, farrighttri ); - if ( !farrightflag && triedgeequal( farrighttri, bottommost ) ) { - triedgecopy( lefttri, bottommost ); - } - - if ( randomnation( SAMPLERATE ) == 0 ) { - splayroot = splayinsert( splayroot, &lefttri, nextpoint ); - } - else if ( randomnation( SAMPLERATE ) == 0 ) { - lnext( righttri, inserttri ); - splayroot = splayinsert( splayroot, &inserttri, nextpoint ); - } - } - } - nextevent->eventptr = (VOID *) freeevents; - freeevents = nextevent; - - if ( check4events ) { - apex( farlefttri, leftpoint ); - dest( lefttri, midpoint ); - apex( lefttri, rightpoint ); - lefttest = counterclockwise( leftpoint, midpoint, rightpoint ); - if ( lefttest > 0.0 ) { - newevent = freeevents; - freeevents = (struct event *) freeevents->eventptr; - newevent->xkey = xminextreme; - newevent->ykey = circletop( leftpoint, midpoint, rightpoint, - lefttest ); - newevent->eventptr = (VOID *) encode( lefttri ); - eventheapinsert( eventheap, heapsize, newevent ); - heapsize++; - setorg( lefttri, newevent ); - } - apex( righttri, leftpoint ); - org( righttri, midpoint ); - apex( farrighttri, rightpoint ); - righttest = counterclockwise( leftpoint, midpoint, rightpoint ); - if ( righttest > 0.0 ) { - newevent = freeevents; - freeevents = (struct event *) freeevents->eventptr; - newevent->xkey = xminextreme; - newevent->ykey = circletop( leftpoint, midpoint, rightpoint, - righttest ); - newevent->eventptr = (VOID *) encode( farrighttri ); - eventheapinsert( eventheap, heapsize, newevent ); - heapsize++; - setorg( farrighttri, newevent ); - } - } - } - - pooldeinit( &splaynodes ); - lprevself( bottommost ); - return removeghosts( &bottommost ); +check4deadevent( &searchtri, &freeevents, eventheap, &heapsize ); + +triedgecopy( searchtri, farrighttri ); +sym( searchtri, farlefttri ); +maketriangle( &lefttri ); +maketriangle( &righttri ); +dest( farrighttri, connectpoint ); +setorg( lefttri, connectpoint ); +setdest( lefttri, nextpoint ); +setorg( righttri, nextpoint ); +setdest( righttri, connectpoint ); +bond( lefttri, righttri ); +lnextself( lefttri ); +lprevself( righttri ); +bond( lefttri, righttri ); +lnextself( lefttri ); +lprevself( righttri ); +bond( lefttri, farlefttri ); +bond( righttri, farrighttri ); +if ( !farrightflag && triedgeequal( farrighttri, bottommost )) { +triedgecopy( lefttri, bottommost ); +} + +if ( randomnation( SAMPLERATE ) == 0 ) { +splayroot = splayinsert( splayroot, &lefttri, nextpoint ); +} +else if ( randomnation( SAMPLERATE ) == 0 ) { +lnext( righttri, inserttri ); +splayroot = splayinsert( splayroot, &inserttri, nextpoint ); +} +} +} +nextevent->eventptr = (VOID *) freeevents; +freeevents = nextevent; + +if ( check4events ) { +apex( farlefttri, leftpoint ); +dest( lefttri, midpoint ); +apex( lefttri, rightpoint ); +lefttest = counterclockwise( leftpoint, midpoint, rightpoint ); +if ( lefttest > 0.0 ) { +newevent = freeevents; +freeevents = (struct event *) freeevents->eventptr; +newevent->xkey = xminextreme; +newevent->ykey = circletop( leftpoint, midpoint, rightpoint, +lefttest ); +newevent->eventptr = (VOID *) encode( lefttri ); +eventheapinsert( eventheap, heapsize, newevent ); +heapsize++; +setorg( lefttri, newevent ); +} +apex( righttri, leftpoint ); +org( righttri, midpoint ); +apex( farrighttri, rightpoint ); +righttest = counterclockwise( leftpoint, midpoint, rightpoint ); +if ( righttest > 0.0 ) { +newevent = freeevents; +freeevents = (struct event *) freeevents->eventptr; +newevent->xkey = xminextreme; +newevent->ykey = circletop( leftpoint, midpoint, rightpoint, +righttest ); +newevent->eventptr = (VOID *) encode( farrighttri ); +eventheapinsert( eventheap, heapsize, newevent ); +heapsize++; +setorg( farrighttri, newevent ); +} +} +} + +pooldeinit( &splaynodes ); +lprevself( bottommost ); +return removeghosts( &bottommost ); } #endif /* not REDUCED */ @@ -8717,37 +8904,38 @@ long sweeplinedelaunay(){ /*****************************************************************************/ long delaunay(){ - eextras = 0; - initializetrisegpools(); - -#ifdef REDUCED - if ( !quiet ) { - printf( - "Constructing Delaunay triangulation by divide-and-conquer method.\n" ); - } - return divconqdelaunay(); +eextras = 0; +initializetrisegpools(); + +#ifdef +REDUCED +if ( !quiet ) { +printf( +"Constructing Delaunay triangulation by divide-and-conquer method.\n" ); +} +return divconqdelaunay(); #else /* not REDUCED */ - if ( !quiet ) { - printf( "Constructing Delaunay triangulation " ); - if ( incremental ) { - printf( "by incremental method.\n" ); - } - else if ( sweepline ) { - printf( "by sweepline method.\n" ); - } - else { - printf( "by divide-and-conquer method.\n" ); - } - } - if ( incremental ) { - return incrementaldelaunay(); - } - else if ( sweepline ) { - return sweeplinedelaunay(); - } - else { - return divconqdelaunay(); - } +if ( !quiet ) { +printf( "Constructing Delaunay triangulation " ); +if ( incremental ) { +printf( "by incremental method.\n" ); +} +else if ( sweepline ) { +printf( "by sweepline method.\n" ); +} +else { +printf( "by divide-and-conquer method.\n" ); +} +} +if ( incremental ) { +return incrementaldelaunay(); +} +else if ( sweepline ) { +return sweeplinedelaunay(); +} +else { +return divconqdelaunay(); +} #endif /* not REDUCED */ } @@ -8776,13 +8964,15 @@ long delaunay(){ /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY -#ifdef TRILIBRARY +#ifdef +TRILIBRARY int reconstruct( trianglelist, triangleattriblist, trianglearealist, elements, - corners, attribs, segmentlist, segmentmarkerlist, - numberofsegments ) +corners, attribs, segmentlist, segmentmarkerlist, +numberofsegments ) int *trianglelist; REAL *triangleattriblist; REAL *trianglearealist; @@ -8804,443 +8994,454 @@ FILE *polyfile; #endif /* not TRILIBRARY */ { -#ifdef TRILIBRARY - int pointindex; - int attribindex; +#ifdef +TRILIBRARY +int pointindex; +int attribindex; #else /* not TRILIBRARY */ - FILE *elefile; - FILE *areafile; - char inputline[INPUTLINESIZE]; - char *stringptr; - int areaelements; +FILE *elefile; +FILE *areafile; +char inputline[INPUTLINESIZE]; +char *stringptr; +int areaelements; #endif /* not TRILIBRARY */ - struct triedge triangleloop; - struct triedge triangleleft; - struct triedge checktri; - struct triedge checkleft; - struct triedge checkneighbor; - struct edge shelleloop; - triangle *vertexarray; - triangle *prevlink; - triangle nexttri; - point tdest, tapex; - point checkdest, checkapex; - point shorg; - point killpoint; - REAL area; - int corner[3]; - int end[2]; - int killpointindex; - int incorners; - int segmentmarkers; - int boundmarker; - int aroundpoint; - long hullsize; - int notfound; - int elementnumber, segmentnumber; - int i, j; - triangle ptr; /* Temporary variable used by sym(). */ - -#ifdef TRILIBRARY - inelements = elements; - incorners = corners; - if ( incorners < 3 ) { - printf( "Error: Triangles must have at least 3 points.\n" ); - exit( 1 ); - } - eextras = attribs; +struct triedge triangleloop; +struct triedge triangleleft; +struct triedge checktri; +struct triedge checkleft; +struct triedge checkneighbor; +struct edge shelleloop; +triangle *vertexarray; +triangle *prevlink; +triangle nexttri; +point tdest, tapex; +point checkdest, checkapex; +point shorg; +point killpoint; +REAL area; +int corner[3]; +int end[2]; +int killpointindex; +int incorners; +int segmentmarkers; +int boundmarker; +int aroundpoint; +long hullsize; +int notfound; +int elementnumber, segmentnumber; +int i, j; +triangle ptr; /* Temporary variable used by sym(). */ + +#ifdef +TRILIBRARY +inelements = elements; +incorners = corners; +if ( incorners < 3 ) { +printf( "Error: Triangles must have at least 3 points.\n" ); +exit( 1 ); +} +eextras = attribs; #else /* not TRILIBRARY */ - /* Read the triangles from an .ele file. */ - if ( !quiet ) { - printf( "Opening %s.\n", elefilename ); - } - elefile = fopen( elefilename, "r" ); - if ( elefile == (FILE *) NULL ) { - printf( " Error: Cannot access file %s.\n", elefilename ); - exit( 1 ); - } - /* Read number of triangles, number of points per triangle, and */ - /* number of triangle attributes from .ele file. */ - stringptr = readline( inputline, elefile, elefilename ); - inelements = (int) strtol( stringptr, &stringptr, 0 ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - incorners = 3; - } - else { - incorners = (int) strtol( stringptr, &stringptr, 0 ); - if ( incorners < 3 ) { - printf( "Error: Triangles in %s must have at least 3 points.\n", - elefilename ); - exit( 1 ); - } - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - eextras = 0; - } - else { - eextras = (int) strtol( stringptr, &stringptr, 0 ); - } +/* Read the triangles from an .ele file. */ +if ( !quiet ) { +printf( "Opening %s.\n", elefilename ); +} +elefile = fopen( elefilename, "r" ); +if ( elefile == (FILE *) NULL ) { +printf( " Error: Cannot access file %s.\n", elefilename ); +exit( 1 ); +} +/* Read number of triangles, number of points per triangle, and */ +/* number of triangle attributes from .ele file. */ +stringptr = readline( inputline, elefile, elefilename ); +inelements = (int) strtol( stringptr, &stringptr, 0 ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +incorners = 3; +} +else { +incorners = (int) strtol( stringptr, &stringptr, 0 ); +if ( incorners < 3 ) { +printf( "Error: Triangles in %s must have at least 3 points.\n", +elefilename ); +exit( 1 ); +} +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +eextras = 0; +} +else { +eextras = (int) strtol( stringptr, &stringptr, 0 ); +} #endif /* not TRILIBRARY */ - initializetrisegpools(); +initializetrisegpools(); - /* Create the triangles. */ - for ( elementnumber = 1; elementnumber <= inelements; elementnumber++ ) { - maketriangle( &triangleloop ); - /* Mark the triangle as living. */ - triangleloop.tri[3] = (triangle) triangleloop.tri; - } +/* Create the triangles. */ +for ( elementnumber = 1; elementnumber <= inelements; elementnumber++ ) { +maketriangle( &triangleloop ); +/* Mark the triangle as living. */ +triangleloop.tri[3] = (triangle) triangleloop.tri; +} - if ( poly ) { -#ifdef TRILIBRARY - insegments = numberofsegments; - segmentmarkers = segmentmarkerlist != (int *) NULL; +if ( poly ) { +#ifdef +TRILIBRARY +insegments = numberofsegments; +segmentmarkers = segmentmarkerlist != (int *) NULL; #else /* not TRILIBRARY */ - /* Read number of segments and number of segment */ - /* boundary markers from .poly file. */ - stringptr = readline( inputline, polyfile, inpolyfilename ); - insegments = (int) strtol( stringptr, &stringptr, 0 ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - segmentmarkers = 0; - } - else { - segmentmarkers = (int) strtol( stringptr, &stringptr, 0 ); - } +/* Read number of segments and number of segment */ +/* boundary markers from .poly file. */ +stringptr = readline( inputline, polyfile, inpolyfilename ); +insegments = (int) strtol( stringptr, &stringptr, 0 ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +segmentmarkers = 0; +} +else { +segmentmarkers = (int) strtol( stringptr, &stringptr, 0 ); +} #endif /* not TRILIBRARY */ - /* Create the shell edges. */ - for ( segmentnumber = 1; segmentnumber <= insegments; segmentnumber++ ) { - makeshelle( &shelleloop ); - /* Mark the shell edge as living. */ - shelleloop.sh[2] = (shelle) shelleloop.sh; - } - } - -#ifdef TRILIBRARY - pointindex = 0; - attribindex = 0; +/* Create the shell edges. */ +for ( segmentnumber = 1; segmentnumber <= insegments; segmentnumber++ ) { +makeshelle( &shelleloop ); +/* Mark the shell edge as living. */ +shelleloop.sh[2] = (shelle) shelleloop.sh; +} +} + +#ifdef +TRILIBRARY +pointindex = 0; +attribindex = 0; #else /* not TRILIBRARY */ - if ( vararea ) { - /* Open an .area file, check for consistency with the .ele file. */ - if ( !quiet ) { - printf( "Opening %s.\n", areafilename ); - } - areafile = fopen( areafilename, "r" ); - if ( areafile == (FILE *) NULL ) { - printf( " Error: Cannot access file %s.\n", areafilename ); - exit( 1 ); - } - stringptr = readline( inputline, areafile, areafilename ); - areaelements = (int) strtol( stringptr, &stringptr, 0 ); - if ( areaelements != inelements ) { - printf( "Error: %s and %s disagree on number of triangles.\n", - elefilename, areafilename ); - exit( 1 ); - } - } +if ( vararea ) { +/* Open an .area file, check for consistency with the .ele file. */ +if ( !quiet ) { +printf( "Opening %s.\n", areafilename ); +} +areafile = fopen( areafilename, "r" ); +if ( areafile == (FILE *) NULL ) { +printf( " Error: Cannot access file %s.\n", areafilename ); +exit( 1 ); +} +stringptr = readline( inputline, areafile, areafilename ); +areaelements = (int) strtol( stringptr, &stringptr, 0 ); +if ( areaelements != inelements ) { +printf( "Error: %s and %s disagree on number of triangles.\n", +elefilename, areafilename ); +exit( 1 ); +} +} #endif /* not TRILIBRARY */ - if ( !quiet ) { - printf( "Reconstructing mesh.\n" ); - } - /* Allocate a temporary array that maps each point to some adjacent */ - /* triangle. I took care to allocate all the permanent memory for */ - /* triangles and shell edges first. */ - vertexarray = (triangle *) malloc( points.items * sizeof( triangle ) ); - if ( vertexarray == (triangle *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - /* Each point is initially unrepresented. */ - for ( i = 0; i < points.items; i++ ) { - vertexarray[i] = (triangle) dummytri; - } - - if ( verbose ) { - printf( " Assembling triangles.\n" ); - } - /* Read the triangles from the .ele file, and link */ - /* together those that share an edge. */ - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - elementnumber = firstnumber; - while ( triangleloop.tri != (triangle *) NULL ) { -#ifdef TRILIBRARY - /* Copy the triangle's three corners. */ - for ( j = 0; j < 3; j++ ) { - corner[j] = trianglelist[pointindex++]; - if ( ( corner[j] < firstnumber ) || ( corner[j] >= firstnumber + inpoints ) ) { - printf( "Error: Triangle %d has an invalid vertex index.\n", - elementnumber ); - exit( 1 ); - } - } +if ( !quiet ) { +printf( "Reconstructing mesh.\n" ); +} +/* Allocate a temporary array that maps each point to some adjacent */ +/* triangle. I took care to allocate all the permanent memory for */ +/* triangles and shell edges first. */ +vertexarray = (triangle *) malloc( points.items * sizeof( triangle )); +if ( vertexarray == (triangle *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +/* Each point is initially unrepresented. */ +for ( i = 0; i < points.items; i++ ) { +vertexarray[i] = (triangle) dummytri; +} + +if ( verbose ) { +printf( " Assembling triangles.\n" ); +} +/* Read the triangles from the .ele file, and link */ +/* together those that share an edge. */ +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +elementnumber = firstnumber; +while ( triangleloop.tri != (triangle *) NULL ) { +#ifdef +TRILIBRARY +/* Copy the triangle's three corners. */ +for ( j = 0; j < 3; j++ ) { +corner[j] = trianglelist[pointindex++]; +if (( corner[j] < firstnumber ) || ( corner[j] >= firstnumber + inpoints )) { +printf( "Error: Triangle %d has an invalid vertex index.\n", +elementnumber ); +exit( 1 ); +} +} #else /* not TRILIBRARY */ - /* Read triangle number and the triangle's three corners. */ - stringptr = readline( inputline, elefile, elefilename ); - for ( j = 0; j < 3; j++ ) { - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Triangle %d is missing point %d in %s.\n", - elementnumber, j + 1, elefilename ); - exit( 1 ); - } - else { - corner[j] = (int) strtol( stringptr, &stringptr, 0 ); - if ( ( corner[j] < firstnumber ) || - ( corner[j] >= firstnumber + inpoints ) ) { - printf( "Error: Triangle %d has an invalid vertex index.\n", - elementnumber ); - exit( 1 ); - } - } - } +/* Read triangle number and the triangle's three corners. */ +stringptr = readline( inputline, elefile, elefilename ); +for ( j = 0; j < 3; j++ ) { +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Triangle %d is missing point %d in %s.\n", +elementnumber, j + 1, elefilename ); +exit( 1 ); +} +else { +corner[j] = (int) strtol( stringptr, &stringptr, 0 ); +if (( corner[j] < firstnumber ) || +( corner[j] >= firstnumber + inpoints )) { +printf( "Error: Triangle %d has an invalid vertex index.\n", +elementnumber ); +exit( 1 ); +} +} +} #endif /* not TRILIBRARY */ - /* Find out about (and throw away) extra nodes. */ - for ( j = 3; j < incorners; j++ ) { -#ifdef TRILIBRARY - killpointindex = trianglelist[pointindex++]; +/* Find out about (and throw away) extra nodes. */ +for ( j = 3; j < incorners; j++ ) { +#ifdef +TRILIBRARY +killpointindex = trianglelist[pointindex++]; #else /* not TRILIBRARY */ - stringptr = findfield( stringptr ); - if ( *stringptr != '\0' ) { - killpointindex = (int) strtol( stringptr, &stringptr, 0 ); +stringptr = findfield( stringptr ); +if ( *stringptr != '\0' ) { +killpointindex = (int) strtol( stringptr, &stringptr, 0 ); #endif /* not TRILIBRARY */ - if ( ( killpointindex >= firstnumber ) && - ( killpointindex < firstnumber + inpoints ) ) { - /* Delete the non-corner point if it's not already deleted. */ - killpoint = getpoint( killpointindex ); - if ( pointmark( killpoint ) != DEADPOINT ) { - pointdealloc( killpoint ); - } - } -#ifndef TRILIBRARY - } +if (( killpointindex >= firstnumber ) && +( killpointindex < firstnumber + inpoints )) { +/* Delete the non-corner point if it's not already deleted. */ +killpoint = getpoint( killpointindex ); +if ( pointmark( killpoint ) != DEADPOINT ) { +pointdealloc( killpoint ); +} +} +#ifndef +TRILIBRARY +} #endif /* not TRILIBRARY */ - } +} - /* Read the triangle's attributes. */ - for ( j = 0; j < eextras; j++ ) { -#ifdef TRILIBRARY - setelemattribute( triangleloop, j, triangleattriblist[attribindex++] ); +/* Read the triangle's attributes. */ +for ( j = 0; j < eextras; j++ ) { +#ifdef +TRILIBRARY +setelemattribute( triangleloop, j, triangleattriblist[attribindex++] ); #else /* not TRILIBRARY */ - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - setelemattribute( triangleloop, j, 0 ); - } - else { - setelemattribute( triangleloop, j, - (REAL) strtod( stringptr, &stringptr ) ); - } +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +setelemattribute( triangleloop, j, 0 ); +} +else { +setelemattribute( triangleloop, j, +(REAL) strtod( stringptr, &stringptr )); +} #endif /* not TRILIBRARY */ - } +} - if ( vararea ) { -#ifdef TRILIBRARY - area = trianglearealist[elementnumber - firstnumber]; +if ( vararea ) { +#ifdef +TRILIBRARY +area = trianglearealist[elementnumber - firstnumber]; #else /* not TRILIBRARY */ - /* Read an area constraint from the .area file. */ - stringptr = readline( inputline, areafile, areafilename ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - area = -1.0; /* No constraint on this triangle. */ - } - else { - area = (REAL) strtod( stringptr, &stringptr ); - } +/* Read an area constraint from the .area file. */ +stringptr = readline( inputline, areafile, areafilename ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +area = -1.0; /* No constraint on this triangle. */ +} +else { +area = (REAL) strtod( stringptr, &stringptr ); +} #endif /* not TRILIBRARY */ - setareabound( triangleloop, area ); - } - - /* Set the triangle's vertices. */ - triangleloop.orient = 0; - setorg( triangleloop, getpoint( corner[0] ) ); - setdest( triangleloop, getpoint( corner[1] ) ); - setapex( triangleloop, getpoint( corner[2] ) ); - /* Try linking the triangle to others that share these vertices. */ - for ( triangleloop.orient = 0; triangleloop.orient < 3; - triangleloop.orient++ ) { - /* Take the number for the origin of triangleloop. */ - aroundpoint = corner[triangleloop.orient]; - /* Look for other triangles having this vertex. */ - nexttri = vertexarray[aroundpoint - firstnumber]; - /* Link the current triangle to the next one in the stack. */ - triangleloop.tri[6 + triangleloop.orient] = nexttri; - /* Push the current triangle onto the stack. */ - vertexarray[aroundpoint - firstnumber] = encode( triangleloop ); - decode( nexttri, checktri ); - if ( checktri.tri != dummytri ) { - dest( triangleloop, tdest ); - apex( triangleloop, tapex ); - /* Look for other triangles that share an edge. */ - do { - dest( checktri, checkdest ); - apex( checktri, checkapex ); - if ( tapex == checkdest ) { - /* The two triangles share an edge; bond them together. */ - lprev( triangleloop, triangleleft ); - bond( triangleleft, checktri ); - } - if ( tdest == checkapex ) { - /* The two triangles share an edge; bond them together. */ - lprev( checktri, checkleft ); - bond( triangleloop, checkleft ); - } - /* Find the next triangle in the stack. */ - nexttri = checktri.tri[6 + checktri.orient]; - decode( nexttri, checktri ); - } while ( checktri.tri != dummytri ); - } - } - triangleloop.tri = triangletraverse(); - elementnumber++; - } - -#ifdef TRILIBRARY - pointindex = 0; +setareabound( triangleloop, area ); +} + +/* Set the triangle's vertices. */ +triangleloop.orient = 0; +setorg( triangleloop, getpoint( corner[0] )); +setdest( triangleloop, getpoint( corner[1] )); +setapex( triangleloop, getpoint( corner[2] )); +/* Try linking the triangle to others that share these vertices. */ +for ( triangleloop.orient = 0; triangleloop.orient < 3; +triangleloop.orient++ ) { +/* Take the number for the origin of triangleloop. */ +aroundpoint = corner[triangleloop.orient]; +/* Look for other triangles having this vertex. */ +nexttri = vertexarray[aroundpoint - firstnumber]; +/* Link the current triangle to the next one in the stack. */ +triangleloop.tri[6 + triangleloop.orient] = nexttri; +/* Push the current triangle onto the stack. */ +vertexarray[aroundpoint - firstnumber] = encode( triangleloop ); +decode( nexttri, checktri ); +if ( checktri.tri != dummytri ) { +dest( triangleloop, tdest ); +apex( triangleloop, tapex ); +/* Look for other triangles that share an edge. */ +do { +dest( checktri, checkdest ); +apex( checktri, checkapex ); +if ( tapex == checkdest ) { +/* The two triangles share an edge; bond them together. */ +lprev( triangleloop, triangleleft ); +bond( triangleleft, checktri ); +} +if ( tdest == checkapex ) { +/* The two triangles share an edge; bond them together. */ +lprev( checktri, checkleft ); +bond( triangleloop, checkleft ); +} +/* Find the next triangle in the stack. */ +nexttri = checktri.tri[6 + checktri.orient]; +decode( nexttri, checktri ); +} while ( checktri.tri != dummytri ); +} +} +triangleloop.tri = triangletraverse(); +elementnumber++; +} + +#ifdef +TRILIBRARY +pointindex = 0; #else /* not TRILIBRARY */ - fclose( elefile ); - if ( vararea ) { - fclose( areafile ); - } +fclose( elefile ); +if ( vararea ) { +fclose( areafile ); +} #endif /* not TRILIBRARY */ - hullsize = 0; /* Prepare to count the boundary edges. */ - if ( poly ) { - if ( verbose ) { - printf( " Marking segments in triangulation.\n" ); - } - /* Read the segments from the .poly file, and link them */ - /* to their neighboring triangles. */ - boundmarker = 0; - traversalinit( &shelles ); - shelleloop.sh = shelletraverse(); - segmentnumber = firstnumber; - while ( shelleloop.sh != (shelle *) NULL ) { -#ifdef TRILIBRARY - end[0] = segmentlist[pointindex++]; - end[1] = segmentlist[pointindex++]; - if ( segmentmarkers ) { - boundmarker = segmentmarkerlist[segmentnumber - firstnumber]; - } +hullsize = 0; /* Prepare to count the boundary edges. */ +if ( poly ) { +if ( verbose ) { +printf( " Marking segments in triangulation.\n" ); +} +/* Read the segments from the .poly file, and link them */ +/* to their neighboring triangles. */ +boundmarker = 0; +traversalinit( &shelles ); +shelleloop.sh = shelletraverse(); +segmentnumber = firstnumber; +while ( shelleloop.sh != (shelle *) NULL ) { +#ifdef +TRILIBRARY +end[0] = segmentlist[pointindex++]; +end[1] = segmentlist[pointindex++]; +if ( segmentmarkers ) { +boundmarker = segmentmarkerlist[segmentnumber - firstnumber]; +} #else /* not TRILIBRARY */ - /* Read the endpoints of each segment, and possibly a boundary marker. */ - stringptr = readline( inputline, polyfile, inpolyfilename ); - /* Skip the first (segment number) field. */ - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Segment %d has no endpoints in %s.\n", segmentnumber, - polyfilename ); - exit( 1 ); - } - else { - end[0] = (int) strtol( stringptr, &stringptr, 0 ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Segment %d is missing its second endpoint in %s.\n", - segmentnumber, polyfilename ); - exit( 1 ); - } - else { - end[1] = (int) strtol( stringptr, &stringptr, 0 ); - } - if ( segmentmarkers ) { - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - boundmarker = 0; - } - else { - boundmarker = (int) strtol( stringptr, &stringptr, 0 ); - } - } +/* Read the endpoints of each segment, and possibly a boundary marker. */ +stringptr = readline( inputline, polyfile, inpolyfilename ); +/* Skip the first (segment number) field. */ +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Segment %d has no endpoints in %s.\n", segmentnumber, +polyfilename ); +exit( 1 ); +} +else { +end[0] = (int) strtol( stringptr, &stringptr, 0 ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Segment %d is missing its second endpoint in %s.\n", +segmentnumber, polyfilename ); +exit( 1 ); +} +else { +end[1] = (int) strtol( stringptr, &stringptr, 0 ); +} +if ( segmentmarkers ) { +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +boundmarker = 0; +} +else { +boundmarker = (int) strtol( stringptr, &stringptr, 0 ); +} +} #endif /* not TRILIBRARY */ - for ( j = 0; j < 2; j++ ) { - if ( ( end[j] < firstnumber ) || ( end[j] >= firstnumber + inpoints ) ) { - printf( "Error: Segment %d has an invalid vertex index.\n", - segmentnumber ); - exit( 1 ); - } - } - - /* set the shell edge's vertices. */ - shelleloop.shorient = 0; - setsorg( shelleloop, getpoint( end[0] ) ); - setsdest( shelleloop, getpoint( end[1] ) ); - setmark( shelleloop, boundmarker ); - /* Try linking the shell edge to triangles that share these vertices. */ - for ( shelleloop.shorient = 0; shelleloop.shorient < 2; - shelleloop.shorient++ ) { - /* Take the number for the destination of shelleloop. */ - aroundpoint = end[1 - shelleloop.shorient]; - /* Look for triangles having this vertex. */ - prevlink = &vertexarray[aroundpoint - firstnumber]; - nexttri = vertexarray[aroundpoint - firstnumber]; - decode( nexttri, checktri ); - sorg( shelleloop, shorg ); - notfound = 1; - /* Look for triangles having this edge. Note that I'm only */ - /* comparing each triangle's destination with the shell edge; */ - /* each triangle's apex is handled through a different vertex. */ - /* Because each triangle appears on three vertices' lists, each */ - /* occurrence of a triangle on a list can (and does) represent */ - /* an edge. In this way, most edges are represented twice, and */ - /* every triangle-segment bond is represented once. */ - while ( notfound && ( checktri.tri != dummytri ) ) { - dest( checktri, checkdest ); - if ( shorg == checkdest ) { - /* We have a match. Remove this triangle from the list. */ - *prevlink = checktri.tri[6 + checktri.orient]; - /* Bond the shell edge to the triangle. */ - tsbond( checktri, shelleloop ); - /* Check if this is a boundary edge. */ - sym( checktri, checkneighbor ); - if ( checkneighbor.tri == dummytri ) { - /* The next line doesn't insert a shell edge (because there's */ - /* already one there), but it sets the boundary markers of */ - /* the existing shell edge and its vertices. */ - insertshelle( &checktri, 1 ); - hullsize++; - } - notfound = 0; - } - /* Find the next triangle in the stack. */ - prevlink = &checktri.tri[6 + checktri.orient]; - nexttri = checktri.tri[6 + checktri.orient]; - decode( nexttri, checktri ); - } - } - shelleloop.sh = shelletraverse(); - segmentnumber++; - } - } - - /* Mark the remaining edges as not being attached to any shell edge. */ - /* Also, count the (yet uncounted) boundary edges. */ - for ( i = 0; i < points.items; i++ ) { - /* Search the stack of triangles adjacent to a point. */ - nexttri = vertexarray[i]; - decode( nexttri, checktri ); - while ( checktri.tri != dummytri ) { - /* Find the next triangle in the stack before this */ - /* information gets overwritten. */ - nexttri = checktri.tri[6 + checktri.orient]; - /* No adjacent shell edge. (This overwrites the stack info.) */ - tsdissolve( checktri ); - sym( checktri, checkneighbor ); - if ( checkneighbor.tri == dummytri ) { - insertshelle( &checktri, 1 ); - hullsize++; - } - decode( nexttri, checktri ); - } - } - - free( vertexarray ); - return hullsize; +for ( j = 0; j < 2; j++ ) { +if (( end[j] < firstnumber ) || ( end[j] >= firstnumber + inpoints )) { +printf( "Error: Segment %d has an invalid vertex index.\n", +segmentnumber ); +exit( 1 ); +} +} + +/* set the shell edge's vertices. */ +shelleloop.shorient = 0; +setsorg( shelleloop, getpoint( end[0] )); +setsdest( shelleloop, getpoint( end[1] )); +setmark( shelleloop, boundmarker ); +/* Try linking the shell edge to triangles that share these vertices. */ +for ( shelleloop.shorient = 0; shelleloop.shorient < 2; +shelleloop.shorient++ ) { +/* Take the number for the destination of shelleloop. */ +aroundpoint = end[1 - shelleloop.shorient]; +/* Look for triangles having this vertex. */ +prevlink = &vertexarray[aroundpoint - firstnumber]; +nexttri = vertexarray[aroundpoint - firstnumber]; +decode( nexttri, checktri ); +sorg( shelleloop, shorg ); +notfound = 1; +/* Look for triangles having this edge. Note that I'm only */ +/* comparing each triangle's destination with the shell edge; */ +/* each triangle's apex is handled through a different vertex. */ +/* Because each triangle appears on three vertices' lists, each */ +/* occurrence of a triangle on a list can (and does) represent */ +/* an edge. In this way, most edges are represented twice, and */ +/* every triangle-segment bond is represented once. */ +while ( notfound && ( checktri.tri != dummytri )) { +dest( checktri, checkdest ); +if ( shorg == checkdest ) { +/* We have a match. Remove this triangle from the list. */ +*prevlink = checktri.tri[6 + checktri.orient]; +/* Bond the shell edge to the triangle. */ +tsbond( checktri, shelleloop ); +/* Check if this is a boundary edge. */ +sym( checktri, checkneighbor ); +if ( checkneighbor.tri == dummytri ) { +/* The next line doesn't insert a shell edge (because there's */ +/* already one there), but it sets the boundary markers of */ +/* the existing shell edge and its vertices. */ +insertshelle( &checktri, 1 ); +hullsize++; +} +notfound = 0; +} +/* Find the next triangle in the stack. */ +prevlink = &checktri.tri[6 + checktri.orient]; +nexttri = checktri.tri[6 + checktri.orient]; +decode( nexttri, checktri ); +} +} +shelleloop.sh = shelletraverse(); +segmentnumber++; +} +} + +/* Mark the remaining edges as not being attached to any shell edge. */ +/* Also, count the (yet uncounted) boundary edges. */ +for ( i = 0; i < points.items; i++ ) { +/* Search the stack of triangles adjacent to a point. */ +nexttri = vertexarray[i]; +decode( nexttri, checktri ); +while ( checktri.tri != dummytri ) { +/* Find the next triangle in the stack before this */ +/* information gets overwritten. */ +nexttri = checktri.tri[6 + checktri.orient]; +/* No adjacent shell edge. (This overwrites the stack info.) */ +tsdissolve( checktri ); +sym( checktri, checkneighbor ); +if ( checkneighbor.tri == dummytri ) { +insertshelle( &checktri, 1 ); +hullsize++; +} +decode( nexttri, checktri ); +} +} + +free( vertexarray ); +return hullsize; } #endif /* not CDT_ONLY */ @@ -9274,73 +9475,73 @@ enum finddirectionresult finddirection( searchtri, endpoint ) struct triedge *searchtri; point endpoint; { - struct triedge checktri; - point startpoint; - point leftpoint, rightpoint; - REAL leftccw, rightccw; - int leftflag, rightflag; - triangle ptr; /* Temporary variable used by onext() and oprev(). */ - - org( *searchtri, startpoint ); - dest( *searchtri, rightpoint ); - apex( *searchtri, leftpoint ); - /* Is `endpoint' to the left? */ - leftccw = counterclockwise( endpoint, startpoint, leftpoint ); - leftflag = leftccw > 0.0; - /* Is `endpoint' to the right? */ - rightccw = counterclockwise( startpoint, endpoint, rightpoint ); - rightflag = rightccw > 0.0; - if ( leftflag && rightflag ) { - /* `searchtri' faces directly away from `endpoint'. We could go */ - /* left or right. Ask whether it's a triangle or a boundary */ - /* on the left. */ - onext( *searchtri, checktri ); - if ( checktri.tri == dummytri ) { - leftflag = 0; - } - else { - rightflag = 0; - } - } - while ( leftflag ) { - /* Turn left until satisfied. */ - onextself( *searchtri ); - if ( searchtri->tri == dummytri ) { - printf( "Internal error in finddirection(): Unable to find a\n" ); - printf( " triangle leading from (%.12g, %.12g) to", startpoint[0], - startpoint[1] ); - printf( " (%.12g, %.12g).\n", endpoint[0], endpoint[1] ); - internalerror(); - } - apex( *searchtri, leftpoint ); - rightccw = leftccw; - leftccw = counterclockwise( endpoint, startpoint, leftpoint ); - leftflag = leftccw > 0.0; - } - while ( rightflag ) { - /* Turn right until satisfied. */ - oprevself( *searchtri ); - if ( searchtri->tri == dummytri ) { - printf( "Internal error in finddirection(): Unable to find a\n" ); - printf( " triangle leading from (%.12g, %.12g) to", startpoint[0], - startpoint[1] ); - printf( " (%.12g, %.12g).\n", endpoint[0], endpoint[1] ); - internalerror(); - } - dest( *searchtri, rightpoint ); - leftccw = rightccw; - rightccw = counterclockwise( startpoint, endpoint, rightpoint ); - rightflag = rightccw > 0.0; - } - if ( leftccw == 0.0 ) { - return LEFTCOLLINEAR; - } - else if ( rightccw == 0.0 ) { - return RIGHTCOLLINEAR; - } - else { - return WITHIN; - } +struct triedge checktri; +point startpoint; +point leftpoint, rightpoint; +REAL leftccw, rightccw; +int leftflag, rightflag; +triangle ptr; /* Temporary variable used by onext() and oprev(). */ + +org( *searchtri, startpoint ); +dest( *searchtri, rightpoint ); +apex( *searchtri, leftpoint ); +/* Is `endpoint' to the left? */ +leftccw = counterclockwise( endpoint, startpoint, leftpoint ); +leftflag = leftccw > 0.0; +/* Is `endpoint' to the right? */ +rightccw = counterclockwise( startpoint, endpoint, rightpoint ); +rightflag = rightccw > 0.0; +if ( leftflag && rightflag ) { +/* `searchtri' faces directly away from `endpoint'. We could go */ +/* left or right. Ask whether it's a triangle or a boundary */ +/* on the left. */ +onext( *searchtri, checktri ); +if ( checktri.tri == dummytri ) { +leftflag = 0; +} +else { +rightflag = 0; +} +} +while ( leftflag ) { +/* Turn left until satisfied. */ +onextself( *searchtri ); +if ( searchtri->tri == dummytri ) { +printf( "Internal error in finddirection(): Unable to find a\n" ); +printf( " triangle leading from (%.12g, %.12g) to", startpoint[0], +startpoint[1] ); +printf( " (%.12g, %.12g).\n", endpoint[0], endpoint[1] ); +internalerror(); +} +apex( *searchtri, leftpoint ); +rightccw = leftccw; +leftccw = counterclockwise( endpoint, startpoint, leftpoint ); +leftflag = leftccw > 0.0; +} +while ( rightflag ) { +/* Turn right until satisfied. */ +oprevself( *searchtri ); +if ( searchtri->tri == dummytri ) { +printf( "Internal error in finddirection(): Unable to find a\n" ); +printf( " triangle leading from (%.12g, %.12g) to", startpoint[0], +startpoint[1] ); +printf( " (%.12g, %.12g).\n", endpoint[0], endpoint[1] ); +internalerror(); +} +dest( *searchtri, rightpoint ); +leftccw = rightccw; +rightccw = counterclockwise( startpoint, endpoint, rightpoint ); +rightflag = rightccw > 0.0; +} +if ( leftccw == 0.0 ) { +return LEFTCOLLINEAR; +} +else if ( rightccw == 0.0 ) { +return RIGHTCOLLINEAR; +} +else { +return WITHIN; +} } /*****************************************************************************/ @@ -9365,74 +9566,74 @@ struct triedge *splittri; struct edge *splitshelle; point endpoint2; { - point endpoint1; - point torg, tdest; - point leftpoint, rightpoint; - point newpoint; - enum insertsiteresult success; - enum finddirectionresult collinear; - REAL ex, ey; - REAL tx, ty; - REAL etx, ety; - REAL split, denom; - int i; - triangle ptr; /* Temporary variable used by onext(). */ - - /* Find the other three segment endpoints. */ - apex( *splittri, endpoint1 ); - org( *splittri, torg ); - dest( *splittri, tdest ); - /* Segment intersection formulae; see the Antonio reference. */ - tx = tdest[0] - torg[0]; - ty = tdest[1] - torg[1]; - ex = endpoint2[0] - endpoint1[0]; - ey = endpoint2[1] - endpoint1[1]; - etx = torg[0] - endpoint2[0]; - ety = torg[1] - endpoint2[1]; - denom = ty * ex - tx * ey; - if ( denom == 0.0 ) { - printf( "Internal error in segmentintersection():" ); - printf( " Attempt to find intersection of parallel segments.\n" ); - internalerror(); - } - split = ( ey * etx - ex * ety ) / denom; - /* Create the new point. */ - newpoint = (point) poolalloc( &points ); - /* Interpolate its coordinate and attributes. */ - for ( i = 0; i < 2 + nextras; i++ ) { - newpoint[i] = torg[i] + split * ( tdest[i] - torg[i] ); - } - setpointmark( newpoint, mark( *splitshelle ) ); - if ( verbose > 1 ) { - printf( - " Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n", - torg[0], torg[1], tdest[0], tdest[1], newpoint[0], newpoint[1] ); - } - /* Insert the intersection point. This should always succeed. */ - success = insertsite( newpoint, splittri, splitshelle, 0, 0 ); - if ( success != SUCCESSFULPOINT ) { - printf( "Internal error in segmentintersection():\n" ); - printf( " Failure to split a segment.\n" ); - internalerror(); - } - if ( steinerleft > 0 ) { - steinerleft--; - } - /* Inserting the point may have caused edge flips. We wish to rediscover */ - /* the edge connecting endpoint1 to the new intersection point. */ - collinear = finddirection( splittri, endpoint1 ); - dest( *splittri, rightpoint ); - apex( *splittri, leftpoint ); - if ( ( leftpoint[0] == endpoint1[0] ) && ( leftpoint[1] == endpoint1[1] ) ) { - onextself( *splittri ); - } - else if ( ( rightpoint[0] != endpoint1[0] ) || - ( rightpoint[1] != endpoint1[1] ) ) { - printf( "Internal error in segmentintersection():\n" ); - printf( " Topological inconsistency after splitting a segment.\n" ); - internalerror(); - } - /* `splittri' should have destination endpoint1. */ +point endpoint1; +point torg, tdest; +point leftpoint, rightpoint; +point newpoint; +enum insertsiteresult success; +enum finddirectionresult collinear; +REAL ex, ey; +REAL tx, ty; +REAL etx, ety; +REAL split, denom; +int i; +triangle ptr; /* Temporary variable used by onext(). */ + +/* Find the other three segment endpoints. */ +apex( *splittri, endpoint1 ); +org( *splittri, torg ); +dest( *splittri, tdest ); +/* Segment intersection formulae; see the Antonio reference. */ +tx = tdest[0] - torg[0]; +ty = tdest[1] - torg[1]; +ex = endpoint2[0] - endpoint1[0]; +ey = endpoint2[1] - endpoint1[1]; +etx = torg[0] - endpoint2[0]; +ety = torg[1] - endpoint2[1]; +denom = ty * ex - tx * ey; +if ( denom == 0.0 ) { +printf( "Internal error in segmentintersection():" ); +printf( " Attempt to find intersection of parallel segments.\n" ); +internalerror(); +} +split = ( ey * etx - ex * ety ) / denom; +/* Create the new point. */ +newpoint = (point) poolalloc( &points ); +/* Interpolate its coordinate and attributes. */ +for ( i = 0; i < 2 + nextras; i++ ) { +newpoint[i] = torg[i] + split * ( tdest[i] - torg[i] ); +} +setpointmark( newpoint, mark( *splitshelle )); +if ( verbose > 1 ) { +printf( +" Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n", +torg[0], torg[1], tdest[0], tdest[1], newpoint[0], newpoint[1] ); +} +/* Insert the intersection point. This should always succeed. */ +success = insertsite( newpoint, splittri, splitshelle, 0, 0 ); +if ( success != SUCCESSFULPOINT ) { +printf( "Internal error in segmentintersection():\n" ); +printf( " Failure to split a segment.\n" ); +internalerror(); +} +if ( steinerleft > 0 ) { +steinerleft--; +} +/* Inserting the point may have caused edge flips. We wish to rediscover */ +/* the edge connecting endpoint1 to the new intersection point. */ +collinear = finddirection( splittri, endpoint1 ); +dest( *splittri, rightpoint ); +apex( *splittri, leftpoint ); +if (( leftpoint[0] == endpoint1[0] ) && ( leftpoint[1] == endpoint1[1] )) { +onextself( *splittri ); +} +else if (( rightpoint[0] != endpoint1[0] ) || +( rightpoint[1] != endpoint1[1] )) { +printf( "Internal error in segmentintersection():\n" ); +printf( " Topological inconsistency after splitting a segment.\n" ); +internalerror(); +} +/* `splittri' should have destination endpoint1. */ } /*****************************************************************************/ @@ -9466,59 +9667,59 @@ struct triedge *searchtri; point endpoint2; int newmark; { - struct triedge crosstri; - struct edge crossedge; - point leftpoint, rightpoint; - point endpoint1; - enum finddirectionresult collinear; - shelle sptr; /* Temporary variable used by tspivot(). */ - - collinear = finddirection( searchtri, endpoint2 ); - dest( *searchtri, rightpoint ); - apex( *searchtri, leftpoint ); - if ( ( ( leftpoint[0] == endpoint2[0] ) && ( leftpoint[1] == endpoint2[1] ) ) || - ( ( rightpoint[0] == endpoint2[0] ) && ( rightpoint[1] == endpoint2[1] ) ) ) { - /* The segment is already an edge in the mesh. */ - if ( ( leftpoint[0] == endpoint2[0] ) && ( leftpoint[1] == endpoint2[1] ) ) { - lprevself( *searchtri ); - } - /* Insert a shell edge, if there isn't already one there. */ - insertshelle( searchtri, newmark ); - return 1; - } - else if ( collinear == LEFTCOLLINEAR ) { - /* We've collided with a point between the segment's endpoints. */ - /* Make the collinear point be the triangle's origin. */ - lprevself( *searchtri ); - insertshelle( searchtri, newmark ); - /* Insert the remainder of the segment. */ - return scoutsegment( searchtri, endpoint2, newmark ); - } - else if ( collinear == RIGHTCOLLINEAR ) { - /* We've collided with a point between the segment's endpoints. */ - insertshelle( searchtri, newmark ); - /* Make the collinear point be the triangle's origin. */ - lnextself( *searchtri ); - /* Insert the remainder of the segment. */ - return scoutsegment( searchtri, endpoint2, newmark ); - } - else { - lnext( *searchtri, crosstri ); - tspivot( crosstri, crossedge ); - /* Check for a crossing segment. */ - if ( crossedge.sh == dummysh ) { - return 0; - } - else { - org( *searchtri, endpoint1 ); - /* Insert a point at the intersection. */ - segmentintersection( &crosstri, &crossedge, endpoint2 ); - triedgecopy( crosstri, *searchtri ); - insertshelle( searchtri, newmark ); - /* Insert the remainder of the segment. */ - return scoutsegment( searchtri, endpoint2, newmark ); - } - } +struct triedge crosstri; +struct edge crossedge; +point leftpoint, rightpoint; +point endpoint1; +enum finddirectionresult collinear; +shelle sptr; /* Temporary variable used by tspivot(). */ + +collinear = finddirection( searchtri, endpoint2 ); +dest( *searchtri, rightpoint ); +apex( *searchtri, leftpoint ); +if ((( leftpoint[0] == endpoint2[0] ) && ( leftpoint[1] == endpoint2[1] )) || +(( rightpoint[0] == endpoint2[0] ) && ( rightpoint[1] == endpoint2[1] ))) { +/* The segment is already an edge in the mesh. */ +if (( leftpoint[0] == endpoint2[0] ) && ( leftpoint[1] == endpoint2[1] )) { +lprevself( *searchtri ); +} +/* Insert a shell edge, if there isn't already one there. */ +insertshelle( searchtri, newmark ); +return 1; +} +else if ( collinear == LEFTCOLLINEAR ) { +/* We've collided with a point between the segment's endpoints. */ +/* Make the collinear point be the triangle's origin. */ +lprevself( *searchtri ); +insertshelle( searchtri, newmark ); +/* Insert the remainder of the segment. */ +return scoutsegment( searchtri, endpoint2, newmark ); +} +else if ( collinear == RIGHTCOLLINEAR ) { +/* We've collided with a point between the segment's endpoints. */ +insertshelle( searchtri, newmark ); +/* Make the collinear point be the triangle's origin. */ +lnextself( *searchtri ); +/* Insert the remainder of the segment. */ +return scoutsegment( searchtri, endpoint2, newmark ); +} +else { +lnext( *searchtri, crosstri ); +tspivot( crosstri, crossedge ); +/* Check for a crossing segment. */ +if ( crossedge.sh == dummysh ) { +return 0; +} +else { +org( *searchtri, endpoint1 ); +/* Insert a point at the intersection. */ +segmentintersection( &crosstri, &crossedge, endpoint2 ); +triedgecopy( crosstri, *searchtri ); +insertshelle( searchtri, newmark ); +/* Insert the remainder of the segment. */ +return scoutsegment( searchtri, endpoint2, newmark ); +} +} } /*****************************************************************************/ @@ -9540,91 +9741,93 @@ int newmark; /* */ /*****************************************************************************/ -#ifndef REDUCED -#ifndef CDT_ONLY +#ifndef +REDUCED +#ifndef +CDT_ONLY void conformingedge( endpoint1, endpoint2, newmark ) point endpoint1; point endpoint2; int newmark; { - struct triedge searchtri1, searchtri2; - struct edge brokenshelle; - point newpoint; - point midpoint1, midpoint2; - enum insertsiteresult success; - int result1, result2; - int i; - shelle sptr; /* Temporary variable used by tspivot(). */ - - if ( verbose > 2 ) { - printf( "Forcing segment into triangulation by recursive splitting:\n" ); - printf( " (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1], - endpoint2[0], endpoint2[1] ); - } - /* Create a new point to insert in the middle of the segment. */ - newpoint = (point) poolalloc( &points ); - /* Interpolate coordinates and attributes. */ - for ( i = 0; i < 2 + nextras; i++ ) { - newpoint[i] = 0.5 * ( endpoint1[i] + endpoint2[i] ); - } - setpointmark( newpoint, newmark ); - /* Find a boundary triangle to search from. */ - searchtri1.tri = (triangle *) NULL; - /* Attempt to insert the new point. */ - success = insertsite( newpoint, &searchtri1, (struct edge *) NULL, 0, 0 ); - if ( success == DUPLICATEPOINT ) { - if ( verbose > 2 ) { - printf( " Segment intersects existing point (%.12g, %.12g).\n", - newpoint[0], newpoint[1] ); - } - /* Use the point that's already there. */ - pointdealloc( newpoint ); - org( searchtri1, newpoint ); - } - else { - if ( success == VIOLATINGPOINT ) { - if ( verbose > 2 ) { - printf( " Two segments intersect at (%.12g, %.12g).\n", - newpoint[0], newpoint[1] ); - } - /* By fluke, we've landed right on another segment. Split it. */ - tspivot( searchtri1, brokenshelle ); - success = insertsite( newpoint, &searchtri1, &brokenshelle, 0, 0 ); - if ( success != SUCCESSFULPOINT ) { - printf( "Internal error in conformingedge():\n" ); - printf( " Failure to split a segment.\n" ); - internalerror(); - } - } - /* The point has been inserted successfully. */ - if ( steinerleft > 0 ) { - steinerleft--; - } - } - triedgecopy( searchtri1, searchtri2 ); - result1 = scoutsegment( &searchtri1, endpoint1, newmark ); - result2 = scoutsegment( &searchtri2, endpoint2, newmark ); - if ( !result1 ) { - /* The origin of searchtri1 may have changed if a collision with an */ - /* intervening vertex on the segment occurred. */ - org( searchtri1, midpoint1 ); - conformingedge( midpoint1, endpoint1, newmark ); - } - if ( !result2 ) { - /* The origin of searchtri2 may have changed if a collision with an */ - /* intervening vertex on the segment occurred. */ - org( searchtri2, midpoint2 ); - conformingedge( midpoint2, endpoint2, newmark ); - } +struct triedge searchtri1, searchtri2; +struct edge brokenshelle; +point newpoint; +point midpoint1, midpoint2; +enum insertsiteresult success; +int result1, result2; +int i; +shelle sptr; /* Temporary variable used by tspivot(). */ + +if ( verbose > 2 ) { +printf( "Forcing segment into triangulation by recursive splitting:\n" ); +printf( " (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1], +endpoint2[0], endpoint2[1] ); } - -#endif /* not CDT_ONLY */ -#endif /* not REDUCED */ - -/*****************************************************************************/ -/* */ -/* delaunayfixup() Enforce the Delaunay condition at an edge, fanning out */ +/* Create a new point to insert in the middle of the segment. */ +newpoint = (point) poolalloc( &points ); +/* Interpolate coordinates and attributes. */ +for ( i = 0; i < 2 + nextras; i++ ) { +newpoint[i] = 0.5 * ( endpoint1[i] + endpoint2[i] ); +} +setpointmark( newpoint, newmark ); +/* Find a boundary triangle to search from. */ +searchtri1.tri = (triangle *) NULL; +/* Attempt to insert the new point. */ +success = insertsite( newpoint, &searchtri1, (struct edge *) NULL, 0, 0 ); +if ( success == DUPLICATEPOINT ) { +if ( verbose > 2 ) { +printf( " Segment intersects existing point (%.12g, %.12g).\n", +newpoint[0], newpoint[1] ); +} +/* Use the point that's already there. */ +pointdealloc( newpoint ); +org( searchtri1, newpoint ); +} +else { +if ( success == VIOLATINGPOINT ) { +if ( verbose > 2 ) { +printf( " Two segments intersect at (%.12g, %.12g).\n", +newpoint[0], newpoint[1] ); +} +/* By fluke, we've landed right on another segment. Split it. */ +tspivot( searchtri1, brokenshelle ); +success = insertsite( newpoint, &searchtri1, &brokenshelle, 0, 0 ); +if ( success != SUCCESSFULPOINT ) { +printf( "Internal error in conformingedge():\n" ); +printf( " Failure to split a segment.\n" ); +internalerror(); +} +} +/* The point has been inserted successfully. */ +if ( steinerleft > 0 ) { +steinerleft--; +} +} +triedgecopy( searchtri1, searchtri2 ); +result1 = scoutsegment( &searchtri1, endpoint1, newmark ); +result2 = scoutsegment( &searchtri2, endpoint2, newmark ); +if ( !result1 ) { +/* The origin of searchtri1 may have changed if a collision with an */ +/* intervening vertex on the segment occurred. */ +org( searchtri1, midpoint1 ); +conformingedge( midpoint1, endpoint1, newmark ); +} +if ( !result2 ) { +/* The origin of searchtri2 may have changed if a collision with an */ +/* intervening vertex on the segment occurred. */ +org( searchtri2, midpoint2 ); +conformingedge( midpoint2, endpoint2, newmark ); +} +} + +#endif /* not CDT_ONLY */ +#endif /* not REDUCED */ + +/*****************************************************************************/ +/* */ +/* delaunayfixup() Enforce the Delaunay condition at an edge, fanning out */ /* recursively from an existing point. Pay special */ /* attention to stacking inverted triangles. */ /* */ @@ -9664,58 +9867,58 @@ void delaunayfixup( fixuptri, leftside ) struct triedge *fixuptri; int leftside; { - struct triedge neartri; - struct triedge fartri; - struct edge faredge; - point nearpoint, leftpoint, rightpoint, farpoint; - triangle ptr; /* Temporary variable used by sym(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - lnext( *fixuptri, neartri ); - sym( neartri, fartri ); - /* Check if the edge opposite the origin of fixuptri can be flipped. */ - if ( fartri.tri == dummytri ) { - return; - } - tspivot( neartri, faredge ); - if ( faredge.sh != dummysh ) { - return; - } - /* Find all the relevant vertices. */ - apex( neartri, nearpoint ); - org( neartri, leftpoint ); - dest( neartri, rightpoint ); - apex( fartri, farpoint ); - /* Check whether the previous polygon vertex is a reflex vertex. */ - if ( leftside ) { - if ( counterclockwise( nearpoint, leftpoint, farpoint ) <= 0.0 ) { - /* leftpoint is a reflex vertex too. Nothing can */ - /* be done until a convex section is found. */ - return; - } - } - else { - if ( counterclockwise( farpoint, rightpoint, nearpoint ) <= 0.0 ) { - /* rightpoint is a reflex vertex too. Nothing can */ - /* be done until a convex section is found. */ - return; - } - } - if ( counterclockwise( rightpoint, leftpoint, farpoint ) > 0.0 ) { - /* fartri is not an inverted triangle, and farpoint is not a reflex */ - /* vertex. As there are no reflex vertices, fixuptri isn't an */ - /* inverted triangle, either. Hence, test the edge between the */ - /* triangles to ensure it is locally Delaunay. */ - if ( incircle( leftpoint, farpoint, rightpoint, nearpoint ) <= 0.0 ) { - return; - } - /* Not locally Delaunay; go on to an edge flip. */ - } /* else fartri is inverted; remove it from the stack by flipping. */ - flip( &neartri ); - lprevself( *fixuptri ); /* Restore the origin of fixuptri after the flip. */ - /* Recursively process the two triangles that result from the flip. */ - delaunayfixup( fixuptri, leftside ); - delaunayfixup( &fartri, leftside ); +struct triedge neartri; +struct triedge fartri; +struct edge faredge; +point nearpoint, leftpoint, rightpoint, farpoint; +triangle ptr; /* Temporary variable used by sym(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +lnext( *fixuptri, neartri ); +sym( neartri, fartri ); +/* Check if the edge opposite the origin of fixuptri can be flipped. */ +if ( fartri.tri == dummytri ) { +return; +} +tspivot( neartri, faredge ); +if ( faredge.sh != dummysh ) { +return; +} +/* Find all the relevant vertices. */ +apex( neartri, nearpoint ); +org( neartri, leftpoint ); +dest( neartri, rightpoint ); +apex( fartri, farpoint ); +/* Check whether the previous polygon vertex is a reflex vertex. */ +if ( leftside ) { +if ( counterclockwise( nearpoint, leftpoint, farpoint ) <= 0.0 ) { +/* leftpoint is a reflex vertex too. Nothing can */ +/* be done until a convex section is found. */ +return; +} +} +else { +if ( counterclockwise( farpoint, rightpoint, nearpoint ) <= 0.0 ) { +/* rightpoint is a reflex vertex too. Nothing can */ +/* be done until a convex section is found. */ +return; +} +} +if ( counterclockwise( rightpoint, leftpoint, farpoint ) > 0.0 ) { +/* fartri is not an inverted triangle, and farpoint is not a reflex */ +/* vertex. As there are no reflex vertices, fixuptri isn't an */ +/* inverted triangle, either. Hence, test the edge between the */ +/* triangles to ensure it is locally Delaunay. */ +if ( incircle( leftpoint, farpoint, rightpoint, nearpoint ) <= 0.0 ) { +return; +} +/* Not locally Delaunay; go on to an edge flip. */ +} /* else fartri is inverted; remove it from the stack by flipping. */ +flip( &neartri ); +lprevself( *fixuptri ); /* Restore the origin of fixuptri after the flip. */ +/* Recursively process the two triangles that result from the flip. */ +delaunayfixup( fixuptri, leftside ); +delaunayfixup( &fartri, leftside ); } /*****************************************************************************/ @@ -9777,91 +9980,91 @@ struct triedge *starttri; point endpoint2; int newmark; { - struct triedge fixuptri, fixuptri2; - struct edge fixupedge; - point endpoint1; - point farpoint; - REAL area; - int collision; - int done; - triangle ptr; /* Temporary variable used by sym() and oprev(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - org( *starttri, endpoint1 ); - lnext( *starttri, fixuptri ); - flip( &fixuptri ); - /* `collision' indicates whether we have found a point directly */ - /* between endpoint1 and endpoint2. */ - collision = 0; - done = 0; - do { - org( fixuptri, farpoint ); - /* `farpoint' is the extreme point of the polygon we are "digging" */ - /* to get from endpoint1 to endpoint2. */ - if ( ( farpoint[0] == endpoint2[0] ) && ( farpoint[1] == endpoint2[1] ) ) { - oprev( fixuptri, fixuptri2 ); - /* Enforce the Delaunay condition around endpoint2. */ - delaunayfixup( &fixuptri, 0 ); - delaunayfixup( &fixuptri2, 1 ); - done = 1; - } - else { - /* Check whether farpoint is to the left or right of the segment */ - /* being inserted, to decide which edge of fixuptri to dig */ - /* through next. */ - area = counterclockwise( endpoint1, endpoint2, farpoint ); - if ( area == 0.0 ) { - /* We've collided with a point between endpoint1 and endpoint2. */ - collision = 1; - oprev( fixuptri, fixuptri2 ); - /* Enforce the Delaunay condition around farpoint. */ - delaunayfixup( &fixuptri, 0 ); - delaunayfixup( &fixuptri2, 1 ); - done = 1; - } - else { - if ( area > 0.0 ) { /* farpoint is to the left of the segment. */ - oprev( fixuptri, fixuptri2 ); - /* Enforce the Delaunay condition around farpoint, on the */ - /* left side of the segment only. */ - delaunayfixup( &fixuptri2, 1 ); - /* Flip the edge that crosses the segment. After the edge is */ - /* flipped, one of its endpoints is the fan vertex, and the */ - /* destination of fixuptri is the fan vertex. */ - lprevself( fixuptri ); - } - else { /* farpoint is to the right of the segment. */ - delaunayfixup( &fixuptri, 0 ); - /* Flip the edge that crosses the segment. After the edge is */ - /* flipped, one of its endpoints is the fan vertex, and the */ - /* destination of fixuptri is the fan vertex. */ - oprevself( fixuptri ); - } - /* Check for two intersecting segments. */ - tspivot( fixuptri, fixupedge ); - if ( fixupedge.sh == dummysh ) { - flip( &fixuptri ); /* May create an inverted triangle on the left. */ - } - else { - /* We've collided with a segment between endpoint1 and endpoint2. */ - collision = 1; - /* Insert a point at the intersection. */ - segmentintersection( &fixuptri, &fixupedge, endpoint2 ); - done = 1; - } - } - } - } while ( !done ); - /* Insert a shell edge to make the segment permanent. */ - insertshelle( &fixuptri, newmark ); - /* If there was a collision with an interceding vertex, install another */ - /* segment connecting that vertex with endpoint2. */ - if ( collision ) { - /* Insert the remainder of the segment. */ - if ( !scoutsegment( &fixuptri, endpoint2, newmark ) ) { - constrainededge( &fixuptri, endpoint2, newmark ); - } - } +struct triedge fixuptri, fixuptri2; +struct edge fixupedge; +point endpoint1; +point farpoint; +REAL area; +int collision; +int done; +triangle ptr; /* Temporary variable used by sym() and oprev(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +org( *starttri, endpoint1 ); +lnext( *starttri, fixuptri ); +flip( &fixuptri ); +/* `collision' indicates whether we have found a point directly */ +/* between endpoint1 and endpoint2. */ +collision = 0; +done = 0; +do { +org( fixuptri, farpoint ); +/* `farpoint' is the extreme point of the polygon we are "digging" */ +/* to get from endpoint1 to endpoint2. */ +if (( farpoint[0] == endpoint2[0] ) && ( farpoint[1] == endpoint2[1] )) { +oprev( fixuptri, fixuptri2 ); +/* Enforce the Delaunay condition around endpoint2. */ +delaunayfixup( &fixuptri, 0 ); +delaunayfixup( &fixuptri2, 1 ); +done = 1; +} +else { +/* Check whether farpoint is to the left or right of the segment */ +/* being inserted, to decide which edge of fixuptri to dig */ +/* through next. */ +area = counterclockwise( endpoint1, endpoint2, farpoint ); +if ( area == 0.0 ) { +/* We've collided with a point between endpoint1 and endpoint2. */ +collision = 1; +oprev( fixuptri, fixuptri2 ); +/* Enforce the Delaunay condition around farpoint. */ +delaunayfixup( &fixuptri, 0 ); +delaunayfixup( &fixuptri2, 1 ); +done = 1; +} +else { +if ( area > 0.0 ) { /* farpoint is to the left of the segment. */ +oprev( fixuptri, fixuptri2 ); +/* Enforce the Delaunay condition around farpoint, on the */ +/* left side of the segment only. */ +delaunayfixup( &fixuptri2, 1 ); +/* Flip the edge that crosses the segment. After the edge is */ +/* flipped, one of its endpoints is the fan vertex, and the */ +/* destination of fixuptri is the fan vertex. */ +lprevself( fixuptri ); +} +else { /* farpoint is to the right of the segment. */ +delaunayfixup( &fixuptri, 0 ); +/* Flip the edge that crosses the segment. After the edge is */ +/* flipped, one of its endpoints is the fan vertex, and the */ +/* destination of fixuptri is the fan vertex. */ +oprevself( fixuptri ); +} +/* Check for two intersecting segments. */ +tspivot( fixuptri, fixupedge ); +if ( fixupedge.sh == dummysh ) { +flip( &fixuptri ); /* May create an inverted triangle on the left. */ +} +else { +/* We've collided with a segment between endpoint1 and endpoint2. */ +collision = 1; +/* Insert a point at the intersection. */ +segmentintersection( &fixuptri, &fixupedge, endpoint2 ); +done = 1; +} +} +} +} while ( !done ); +/* Insert a shell edge to make the segment permanent. */ +insertshelle( &fixuptri, newmark ); +/* If there was a collision with an interceding vertex, install another */ +/* segment connecting that vertex with endpoint2. */ +if ( collision ) { +/* Insert the remainder of the segment. */ +if ( !scoutsegment( &fixuptri, endpoint2, newmark )) { +constrainededge( &fixuptri, endpoint2, newmark ); +} +} } /*****************************************************************************/ @@ -9875,95 +10078,99 @@ point endpoint1; point endpoint2; int newmark; { - struct triedge searchtri1, searchtri2; - triangle encodedtri; - point checkpoint; - triangle ptr; /* Temporary variable used by sym(). */ - - if ( verbose > 1 ) { - printf( " Connecting (%.12g, %.12g) to (%.12g, %.12g).\n", - endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1] ); - } - - /* Find a triangle whose origin is the segment's first endpoint. */ - checkpoint = (point) NULL; - encodedtri = point2tri( endpoint1 ); - if ( encodedtri != (triangle) NULL ) { - decode( encodedtri, searchtri1 ); - org( searchtri1, checkpoint ); - } - if ( checkpoint != endpoint1 ) { - /* Find a boundary triangle to search from. */ - searchtri1.tri = dummytri; - searchtri1.orient = 0; - symself( searchtri1 ); - /* Search for the segment's first endpoint by point location. */ - if ( locate( endpoint1, &searchtri1 ) != ONVERTEX ) { - printf( - "Internal error in insertsegment(): Unable to locate PSLG point\n" ); - printf( " (%.12g, %.12g) in triangulation.\n", - endpoint1[0], endpoint1[1] ); - internalerror(); - } - } - /* Remember this triangle to improve subsequent point location. */ - triedgecopy( searchtri1, recenttri ); - /* Scout the beginnings of a path from the first endpoint */ - /* toward the second. */ - if ( scoutsegment( &searchtri1, endpoint2, newmark ) ) { - /* The segment was easily inserted. */ - return; - } - /* The first endpoint may have changed if a collision with an intervening */ - /* vertex on the segment occurred. */ - org( searchtri1, endpoint1 ); - - /* Find a triangle whose origin is the segment's second endpoint. */ - checkpoint = (point) NULL; - encodedtri = point2tri( endpoint2 ); - if ( encodedtri != (triangle) NULL ) { - decode( encodedtri, searchtri2 ); - org( searchtri2, checkpoint ); - } - if ( checkpoint != endpoint2 ) { - /* Find a boundary triangle to search from. */ - searchtri2.tri = dummytri; - searchtri2.orient = 0; - symself( searchtri2 ); - /* Search for the segment's second endpoint by point location. */ - if ( locate( endpoint2, &searchtri2 ) != ONVERTEX ) { - printf( - "Internal error in insertsegment(): Unable to locate PSLG point\n" ); - printf( " (%.12g, %.12g) in triangulation.\n", - endpoint2[0], endpoint2[1] ); - internalerror(); - } - } - /* Remember this triangle to improve subsequent point location. */ - triedgecopy( searchtri2, recenttri ); - /* Scout the beginnings of a path from the second endpoint */ - /* toward the first. */ - if ( scoutsegment( &searchtri2, endpoint1, newmark ) ) { - /* The segment was easily inserted. */ - return; - } - /* The second endpoint may have changed if a collision with an intervening */ - /* vertex on the segment occurred. */ - org( searchtri2, endpoint2 ); - -#ifndef REDUCED -#ifndef CDT_ONLY - if ( splitseg ) { - /* Insert vertices to force the segment into the triangulation. */ - conformingedge( endpoint1, endpoint2, newmark ); - } - else { +struct triedge searchtri1, searchtri2; +triangle encodedtri; +point checkpoint; +triangle ptr; /* Temporary variable used by sym(). */ + +if ( verbose > 1 ) { +printf( " Connecting (%.12g, %.12g) to (%.12g, %.12g).\n", +endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1] ); +} + +/* Find a triangle whose origin is the segment's first endpoint. */ +checkpoint = (point) NULL; +encodedtri = point2tri( endpoint1 ); +if ( encodedtri != (triangle) NULL ) { +decode( encodedtri, searchtri1 ); +org( searchtri1, checkpoint ); +} +if ( checkpoint != endpoint1 ) { +/* Find a boundary triangle to search from. */ +searchtri1.tri = dummytri; +searchtri1.orient = 0; +symself( searchtri1 ); +/* Search for the segment's first endpoint by point location. */ +if ( locate( endpoint1, &searchtri1 ) != ONVERTEX ) { +printf( +"Internal error in insertsegment(): Unable to locate PSLG point\n" ); +printf( " (%.12g, %.12g) in triangulation.\n", +endpoint1[0], endpoint1[1] ); +internalerror(); +} +} +/* Remember this triangle to improve subsequent point location. */ +triedgecopy( searchtri1, recenttri ); +/* Scout the beginnings of a path from the first endpoint */ +/* toward the second. */ +if ( scoutsegment( &searchtri1, endpoint2, newmark )) { +/* The segment was easily inserted. */ +return; +} +/* The first endpoint may have changed if a collision with an intervening */ +/* vertex on the segment occurred. */ +org( searchtri1, endpoint1 ); + +/* Find a triangle whose origin is the segment's second endpoint. */ +checkpoint = (point) NULL; +encodedtri = point2tri( endpoint2 ); +if ( encodedtri != (triangle) NULL ) { +decode( encodedtri, searchtri2 ); +org( searchtri2, checkpoint ); +} +if ( checkpoint != endpoint2 ) { +/* Find a boundary triangle to search from. */ +searchtri2.tri = dummytri; +searchtri2.orient = 0; +symself( searchtri2 ); +/* Search for the segment's second endpoint by point location. */ +if ( locate( endpoint2, &searchtri2 ) != ONVERTEX ) { +printf( +"Internal error in insertsegment(): Unable to locate PSLG point\n" ); +printf( " (%.12g, %.12g) in triangulation.\n", +endpoint2[0], endpoint2[1] ); +internalerror(); +} +} +/* Remember this triangle to improve subsequent point location. */ +triedgecopy( searchtri2, recenttri ); +/* Scout the beginnings of a path from the second endpoint */ +/* toward the first. */ +if ( scoutsegment( &searchtri2, endpoint1, newmark )) { +/* The segment was easily inserted. */ +return; +} +/* The second endpoint may have changed if a collision with an intervening */ +/* vertex on the segment occurred. */ +org( searchtri2, endpoint2 ); + +#ifndef +REDUCED +#ifndef +CDT_ONLY +if ( splitseg ) { +/* Insert vertices to force the segment into the triangulation. */ +conformingedge( endpoint1, endpoint2, newmark ); +} +else { #endif /* not CDT_ONLY */ #endif /* not REDUCED */ - /* Insert the segment directly into the triangulation. */ - constrainededge( &searchtri1, endpoint2, newmark ); -#ifndef REDUCED -#ifndef CDT_ONLY +/* Insert the segment directly into the triangulation. */ +constrainededge( &searchtri1, endpoint2, newmark ); +#ifndef +REDUCED +#ifndef +CDT_ONLY } #endif /* not CDT_ONLY */ #endif /* not REDUCED */ @@ -9976,29 +10183,29 @@ int newmark; /*****************************************************************************/ void markhull(){ - struct triedge hulltri; - struct triedge nexttri; - struct triedge starttri; - triangle ptr; /* Temporary variable used by sym() and oprev(). */ - - /* Find a triangle handle on the hull. */ - hulltri.tri = dummytri; - hulltri.orient = 0; - symself( hulltri ); - /* Remember where we started so we know when to stop. */ - triedgecopy( hulltri, starttri ); - /* Go once counterclockwise around the convex hull. */ - do { - /* Create a shell edge if there isn't already one here. */ - insertshelle( &hulltri, 1 ); - /* To find the next hull edge, go clockwise around the next vertex. */ - lnextself( hulltri ); - oprev( hulltri, nexttri ); - while ( nexttri.tri != dummytri ) { - triedgecopy( nexttri, hulltri ); - oprev( hulltri, nexttri ); - } - } while ( !triedgeequal( hulltri, starttri ) ); +struct triedge hulltri; +struct triedge nexttri; +struct triedge starttri; +triangle ptr; /* Temporary variable used by sym() and oprev(). */ + +/* Find a triangle handle on the hull. */ +hulltri.tri = dummytri; +hulltri.orient = 0; +symself( hulltri ); +/* Remember where we started so we know when to stop. */ +triedgecopy( hulltri, starttri ); +/* Go once counterclockwise around the convex hull. */ +do { +/* Create a shell edge if there isn't already one here. */ +insertshelle( &hulltri, 1 ); +/* To find the next hull edge, go clockwise around the next vertex. */ +lnextself( hulltri ); +oprev( hulltri, nexttri ); +while ( nexttri.tri != dummytri ) { +triedgecopy( nexttri, hulltri ); +oprev( hulltri, nexttri ); +} +} while ( !triedgeequal( hulltri, starttri )); } /*****************************************************************************/ @@ -10011,7 +10218,8 @@ void markhull(){ /* */ /*****************************************************************************/ -#ifdef TRILIBRARY +#ifdef +TRILIBRARY int formskeleton( segmentlist, segmentmarkerlist, numberofsegments ) int *segmentlist; @@ -10027,128 +10235,131 @@ char *polyfilename; #endif /* not TRILIBRARY */ { -#ifdef TRILIBRARY - char polyfilename[6]; - int index; +#ifdef +TRILIBRARY +char polyfilename[6]; +int index; #else /* not TRILIBRARY */ - char inputline[INPUTLINESIZE]; - char *stringptr; +char inputline[INPUTLINESIZE]; +char *stringptr; #endif /* not TRILIBRARY */ - point endpoint1, endpoint2; - int segments; - int segmentmarkers; - int end1, end2; - int boundmarker; - int i; - - if ( poly ) { - if ( !quiet ) { - printf( "Inserting segments into Delaunay triangulation.\n" ); - } -#ifdef TRILIBRARY - strcpy( polyfilename, "input" ); - segments = numberofsegments; - segmentmarkers = segmentmarkerlist != (int *) NULL; - index = 0; +point endpoint1, endpoint2; +int segments; +int segmentmarkers; +int end1, end2; +int boundmarker; +int i; + +if ( poly ) { +if ( !quiet ) { +printf( "Inserting segments into Delaunay triangulation.\n" ); +} +#ifdef +TRILIBRARY +strcpy( polyfilename, "input" ); +segments = numberofsegments; +segmentmarkers = segmentmarkerlist != (int *) NULL; +index = 0; #else /* not TRILIBRARY */ - /* Read the segments from a .poly file. */ - /* Read number of segments and number of boundary markers. */ - stringptr = readline( inputline, polyfile, polyfilename ); - segments = (int) strtol( stringptr, &stringptr, 0 ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - segmentmarkers = 0; - } - else { - segmentmarkers = (int) strtol( stringptr, &stringptr, 0 ); - } +/* Read the segments from a .poly file. */ +/* Read number of segments and number of boundary markers. */ +stringptr = readline( inputline, polyfile, polyfilename ); +segments = (int) strtol( stringptr, &stringptr, 0 ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +segmentmarkers = 0; +} +else { +segmentmarkers = (int) strtol( stringptr, &stringptr, 0 ); +} #endif /* not TRILIBRARY */ - /* If segments are to be inserted, compute a mapping */ - /* from points to triangles. */ - if ( segments > 0 ) { - if ( verbose ) { - printf( " Inserting PSLG segments.\n" ); - } - makepointmap(); - } - - boundmarker = 0; - /* Read and insert the segments. */ - for ( i = 1; i <= segments; i++ ) { -#ifdef TRILIBRARY - end1 = segmentlist[index++]; - end2 = segmentlist[index++]; - if ( segmentmarkers ) { - boundmarker = segmentmarkerlist[i - 1]; - } +/* If segments are to be inserted, compute a mapping */ +/* from points to triangles. */ +if ( segments > 0 ) { +if ( verbose ) { +printf( " Inserting PSLG segments.\n" ); +} +makepointmap(); +} + +boundmarker = 0; +/* Read and insert the segments. */ +for ( i = 1; i <= segments; i++ ) { +#ifdef +TRILIBRARY +end1 = segmentlist[index++]; +end2 = segmentlist[index++]; +if ( segmentmarkers ) { +boundmarker = segmentmarkerlist[i - 1]; +} #else /* not TRILIBRARY */ - stringptr = readline( inputline, polyfile, inpolyfilename ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Segment %d has no endpoints in %s.\n", i, - polyfilename ); - exit( 1 ); - } - else { - end1 = (int) strtol( stringptr, &stringptr, 0 ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Segment %d is missing its second endpoint in %s.\n", i, - polyfilename ); - exit( 1 ); - } - else { - end2 = (int) strtol( stringptr, &stringptr, 0 ); - } - if ( segmentmarkers ) { - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - boundmarker = 0; - } - else { - boundmarker = (int) strtol( stringptr, &stringptr, 0 ); - } - } +stringptr = readline( inputline, polyfile, inpolyfilename ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Segment %d has no endpoints in %s.\n", i, +polyfilename ); +exit( 1 ); +} +else { +end1 = (int) strtol( stringptr, &stringptr, 0 ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Segment %d is missing its second endpoint in %s.\n", i, +polyfilename ); +exit( 1 ); +} +else { +end2 = (int) strtol( stringptr, &stringptr, 0 ); +} +if ( segmentmarkers ) { +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +boundmarker = 0; +} +else { +boundmarker = (int) strtol( stringptr, &stringptr, 0 ); +} +} #endif /* not TRILIBRARY */ - if ( ( end1 < firstnumber ) || ( end1 >= firstnumber + inpoints ) ) { - if ( !quiet ) { - printf( "Warning: Invalid first endpoint of segment %d in %s.\n", i, - polyfilename ); - } - } - else if ( ( end2 < firstnumber ) || ( end2 >= firstnumber + inpoints ) ) { - if ( !quiet ) { - printf( "Warning: Invalid second endpoint of segment %d in %s.\n", i, - polyfilename ); - } - } - else { - endpoint1 = getpoint( end1 ); - endpoint2 = getpoint( end2 ); - if ( ( endpoint1[0] == endpoint2[0] ) && ( endpoint1[1] == endpoint2[1] ) ) { - if ( !quiet ) { - printf( "Warning: Endpoints of segment %d are coincident in %s.\n", - i, polyfilename ); - } - } - else { - insertsegment( endpoint1, endpoint2, boundmarker ); - } - } - } - } - else { - segments = 0; - } - if ( convex || !poly ) { - /* Enclose the convex hull with shell edges. */ - if ( verbose ) { - printf( " Enclosing convex hull with segments.\n" ); - } - markhull(); - } - return segments; +if (( end1 < firstnumber ) || ( end1 >= firstnumber + inpoints )) { +if ( !quiet ) { +printf( "Warning: Invalid first endpoint of segment %d in %s.\n", i, +polyfilename ); +} +} +else if (( end2 < firstnumber ) || ( end2 >= firstnumber + inpoints )) { +if ( !quiet ) { +printf( "Warning: Invalid second endpoint of segment %d in %s.\n", i, +polyfilename ); +} +} +else { +endpoint1 = getpoint( end1 ); +endpoint2 = getpoint( end2 ); +if (( endpoint1[0] == endpoint2[0] ) && ( endpoint1[1] == endpoint2[1] )) { +if ( !quiet ) { +printf( "Warning: Endpoints of segment %d are coincident in %s.\n", +i, polyfilename ); +} +} +else { +insertsegment( endpoint1, endpoint2, boundmarker ); +} +} +} +} +else { +segments = 0; +} +if ( convex || !poly ) { +/* Enclose the convex hull with shell edges. */ +if ( verbose ) { +printf( " Enclosing convex hull with segments.\n" ); +} +markhull(); +} +return segments; } /** **/ @@ -10168,59 +10379,59 @@ char *polyfilename; /*****************************************************************************/ void infecthull(){ - struct triedge hulltri; - struct triedge nexttri; - struct triedge starttri; - struct edge hulledge; - triangle **deadtri; - point horg, hdest; - triangle ptr; /* Temporary variable used by sym(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - if ( verbose ) { - printf( " Marking concavities (external triangles) for elimination.\n" ); - } - /* Find a triangle handle on the hull. */ - hulltri.tri = dummytri; - hulltri.orient = 0; - symself( hulltri ); - /* Remember where we started so we know when to stop. */ - triedgecopy( hulltri, starttri ); - /* Go once counterclockwise around the convex hull. */ - do { - /* Ignore triangles that are already infected. */ - if ( !infected( hulltri ) ) { - /* Is the triangle protected by a shell edge? */ - tspivot( hulltri, hulledge ); - if ( hulledge.sh == dummysh ) { - /* The triangle is not protected; infect it. */ - infect( hulltri ); - deadtri = (triangle **) poolalloc( &viri ); - *deadtri = hulltri.tri; - } - else { - /* The triangle is protected; set boundary markers if appropriate. */ - if ( mark( hulledge ) == 0 ) { - setmark( hulledge, 1 ); - org( hulltri, horg ); - dest( hulltri, hdest ); - if ( pointmark( horg ) == 0 ) { - setpointmark( horg, 1 ); - } - if ( pointmark( hdest ) == 0 ) { - setpointmark( hdest, 1 ); - } - } - } - } - /* To find the next hull edge, go clockwise around the next vertex. */ - lnextself( hulltri ); - oprev( hulltri, nexttri ); - while ( nexttri.tri != dummytri ) { - triedgecopy( nexttri, hulltri ); - oprev( hulltri, nexttri ); - } - } while ( !triedgeequal( hulltri, starttri ) ); +struct triedge hulltri; +struct triedge nexttri; +struct triedge starttri; +struct edge hulledge; +triangle **deadtri; +point horg, hdest; +triangle ptr; /* Temporary variable used by sym(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +if ( verbose ) { +printf( " Marking concavities (external triangles) for elimination.\n" ); +} +/* Find a triangle handle on the hull. */ +hulltri.tri = dummytri; +hulltri.orient = 0; +symself( hulltri ); +/* Remember where we started so we know when to stop. */ +triedgecopy( hulltri, starttri ); +/* Go once counterclockwise around the convex hull. */ +do { +/* Ignore triangles that are already infected. */ +if ( !infected( hulltri )) { +/* Is the triangle protected by a shell edge? */ +tspivot( hulltri, hulledge ); +if ( hulledge.sh == dummysh ) { +/* The triangle is not protected; infect it. */ +infect( hulltri ); +deadtri = (triangle **) poolalloc( &viri ); +*deadtri = hulltri.tri; +} +else { +/* The triangle is protected; set boundary markers if appropriate. */ +if ( mark( hulledge ) == 0 ) { +setmark( hulledge, 1 ); +org( hulltri, horg ); +dest( hulltri, hdest ); +if ( pointmark( horg ) == 0 ) { +setpointmark( horg, 1 ); +} +if ( pointmark( hdest ) == 0 ) { +setpointmark( hdest, 1 ); +} +} +} +} +/* To find the next hull edge, go clockwise around the next vertex. */ +lnextself( hulltri ); +oprev( hulltri, nexttri ); +while ( nexttri.tri != dummytri ) { +triedgecopy( nexttri, hulltri ); +oprev( hulltri, nexttri ); +} +} while ( !triedgeequal( hulltri, starttri )); } /*****************************************************************************/ @@ -10241,193 +10452,193 @@ void infecthull(){ /*****************************************************************************/ void plague(){ - struct triedge testtri; - struct triedge neighbor; - triangle **virusloop; - triangle **deadtri; - struct edge neighborshelle; - point testpoint; - point norg, ndest; - point deadorg, deaddest, deadapex; - int killorg; - triangle ptr; /* Temporary variable used by sym() and onext(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - if ( verbose ) { - printf( " Marking neighbors of marked triangles.\n" ); - } - /* Loop through all the infected triangles, spreading the virus to */ - /* their neighbors, then to their neighbors' neighbors. */ - traversalinit( &viri ); - virusloop = (triangle **) traverse( &viri ); - while ( virusloop != (triangle **) NULL ) { - testtri.tri = *virusloop; - /* A triangle is marked as infected by messing with one of its shell */ - /* edges, setting it to an illegal value. Hence, we have to */ - /* temporarily uninfect this triangle so that we can examine its */ - /* adjacent shell edges. */ - uninfect( testtri ); - if ( verbose > 2 ) { - /* Assign the triangle an orientation for convenience in */ - /* checking its points. */ - testtri.orient = 0; - org( testtri, deadorg ); - dest( testtri, deaddest ); - apex( testtri, deadapex ); - printf( " Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", - deadorg[0], deadorg[1], deaddest[0], deaddest[1], - deadapex[0], deadapex[1] ); - } - /* Check each of the triangle's three neighbors. */ - for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) { - /* Find the neighbor. */ - sym( testtri, neighbor ); - /* Check for a shell between the triangle and its neighbor. */ - tspivot( testtri, neighborshelle ); - /* Check if the neighbor is nonexistent or already infected. */ - if ( ( neighbor.tri == dummytri ) || infected( neighbor ) ) { - if ( neighborshelle.sh != dummysh ) { - /* There is a shell edge separating the triangle from its */ - /* neighbor, but both triangles are dying, so the shell */ - /* edge dies too. */ - shelledealloc( neighborshelle.sh ); - if ( neighbor.tri != dummytri ) { - /* Make sure the shell edge doesn't get deallocated again */ - /* later when the infected neighbor is visited. */ - uninfect( neighbor ); - tsdissolve( neighbor ); - infect( neighbor ); - } - } - } - else { /* The neighbor exists and is not infected. */ - if ( neighborshelle.sh == dummysh ) { - /* There is no shell edge protecting the neighbor, so */ - /* the neighbor becomes infected. */ - if ( verbose > 2 ) { - org( neighbor, deadorg ); - dest( neighbor, deaddest ); - apex( neighbor, deadapex ); - printf( - " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", - deadorg[0], deadorg[1], deaddest[0], deaddest[1], - deadapex[0], deadapex[1] ); - } - infect( neighbor ); - /* Ensure that the neighbor's neighbors will be infected. */ - deadtri = (triangle **) poolalloc( &viri ); - *deadtri = neighbor.tri; - } - else { /* The neighbor is protected by a shell edge. */ - /* Remove this triangle from the shell edge. */ - stdissolve( neighborshelle ); - /* The shell edge becomes a boundary. Set markers accordingly. */ - if ( mark( neighborshelle ) == 0 ) { - setmark( neighborshelle, 1 ); - } - org( neighbor, norg ); - dest( neighbor, ndest ); - if ( pointmark( norg ) == 0 ) { - setpointmark( norg, 1 ); - } - if ( pointmark( ndest ) == 0 ) { - setpointmark( ndest, 1 ); - } - } - } - } - /* Remark the triangle as infected, so it doesn't get added to the */ - /* virus pool again. */ - infect( testtri ); - virusloop = (triangle **) traverse( &viri ); - } - - if ( verbose ) { - printf( " Deleting marked triangles.\n" ); - } - traversalinit( &viri ); - virusloop = (triangle **) traverse( &viri ); - while ( virusloop != (triangle **) NULL ) { - testtri.tri = *virusloop; - - /* Check each of the three corners of the triangle for elimination. */ - /* This is done by walking around each point, checking if it is */ - /* still connected to at least one live triangle. */ - for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) { - org( testtri, testpoint ); - /* Check if the point has already been tested. */ - if ( testpoint != (point) NULL ) { - killorg = 1; - /* Mark the corner of the triangle as having been tested. */ - setorg( testtri, NULL ); - /* Walk counterclockwise about the point. */ - onext( testtri, neighbor ); - /* Stop upon reaching a boundary or the starting triangle. */ - while ( ( neighbor.tri != dummytri ) - && ( !triedgeequal( neighbor, testtri ) ) ) { - if ( infected( neighbor ) ) { - /* Mark the corner of this triangle as having been tested. */ - setorg( neighbor, NULL ); - } - else { - /* A live triangle. The point survives. */ - killorg = 0; - } - /* Walk counterclockwise about the point. */ - onextself( neighbor ); - } - /* If we reached a boundary, we must walk clockwise as well. */ - if ( neighbor.tri == dummytri ) { - /* Walk clockwise about the point. */ - oprev( testtri, neighbor ); - /* Stop upon reaching a boundary. */ - while ( neighbor.tri != dummytri ) { - if ( infected( neighbor ) ) { - /* Mark the corner of this triangle as having been tested. */ - setorg( neighbor, NULL ); - } - else { - /* A live triangle. The point survives. */ - killorg = 0; - } - /* Walk clockwise about the point. */ - oprevself( neighbor ); - } - } - if ( killorg ) { - if ( verbose > 1 ) { - printf( " Deleting point (%.12g, %.12g)\n", - testpoint[0], testpoint[1] ); - } - pointdealloc( testpoint ); - } - } - } - - /* Record changes in the number of boundary edges, and disconnect */ - /* dead triangles from their neighbors. */ - for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) { - sym( testtri, neighbor ); - if ( neighbor.tri == dummytri ) { - /* There is no neighboring triangle on this edge, so this edge */ - /* is a boundary edge. This triangle is being deleted, so this */ - /* boundary edge is deleted. */ - hullsize--; - } - else { - /* Disconnect the triangle from its neighbor. */ - dissolve( neighbor ); - /* There is a neighboring triangle on this edge, so this edge */ - /* becomes a boundary edge when this triangle is deleted. */ - hullsize++; - } - } - /* Return the dead triangle to the pool of triangles. */ - triangledealloc( testtri.tri ); - virusloop = (triangle **) traverse( &viri ); - } - /* Empty the virus pool. */ - poolrestart( &viri ); +struct triedge testtri; +struct triedge neighbor; +triangle **virusloop; +triangle **deadtri; +struct edge neighborshelle; +point testpoint; +point norg, ndest; +point deadorg, deaddest, deadapex; +int killorg; +triangle ptr; /* Temporary variable used by sym() and onext(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +if ( verbose ) { +printf( " Marking neighbors of marked triangles.\n" ); +} +/* Loop through all the infected triangles, spreading the virus to */ +/* their neighbors, then to their neighbors' neighbors. */ +traversalinit( &viri ); +virusloop = (triangle **) traverse( &viri ); +while ( virusloop != (triangle **) NULL ) { +testtri.tri = *virusloop; +/* A triangle is marked as infected by messing with one of its shell */ +/* edges, setting it to an illegal value. Hence, we have to */ +/* temporarily uninfect this triangle so that we can examine its */ +/* adjacent shell edges. */ +uninfect( testtri ); +if ( verbose > 2 ) { +/* Assign the triangle an orientation for convenience in */ +/* checking its points. */ +testtri.orient = 0; +org( testtri, deadorg ); +dest( testtri, deaddest ); +apex( testtri, deadapex ); +printf( " Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", +deadorg[0], deadorg[1], deaddest[0], deaddest[1], +deadapex[0], deadapex[1] ); +} +/* Check each of the triangle's three neighbors. */ +for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) { +/* Find the neighbor. */ +sym( testtri, neighbor ); +/* Check for a shell between the triangle and its neighbor. */ +tspivot( testtri, neighborshelle ); +/* Check if the neighbor is nonexistent or already infected. */ +if (( neighbor.tri == dummytri ) || infected( neighbor )) { +if ( neighborshelle.sh != dummysh ) { +/* There is a shell edge separating the triangle from its */ +/* neighbor, but both triangles are dying, so the shell */ +/* edge dies too. */ +shelledealloc( neighborshelle.sh ); +if ( neighbor.tri != dummytri ) { +/* Make sure the shell edge doesn't get deallocated again */ +/* later when the infected neighbor is visited. */ +uninfect( neighbor ); +tsdissolve( neighbor ); +infect( neighbor ); +} +} +} +else { /* The neighbor exists and is not infected. */ +if ( neighborshelle.sh == dummysh ) { +/* There is no shell edge protecting the neighbor, so */ +/* the neighbor becomes infected. */ +if ( verbose > 2 ) { +org( neighbor, deadorg ); +dest( neighbor, deaddest ); +apex( neighbor, deadapex ); +printf( +" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", +deadorg[0], deadorg[1], deaddest[0], deaddest[1], +deadapex[0], deadapex[1] ); +} +infect( neighbor ); +/* Ensure that the neighbor's neighbors will be infected. */ +deadtri = (triangle **) poolalloc( &viri ); +*deadtri = neighbor.tri; +} +else { /* The neighbor is protected by a shell edge. */ +/* Remove this triangle from the shell edge. */ +stdissolve( neighborshelle ); +/* The shell edge becomes a boundary. Set markers accordingly. */ +if ( mark( neighborshelle ) == 0 ) { +setmark( neighborshelle, 1 ); +} +org( neighbor, norg ); +dest( neighbor, ndest ); +if ( pointmark( norg ) == 0 ) { +setpointmark( norg, 1 ); +} +if ( pointmark( ndest ) == 0 ) { +setpointmark( ndest, 1 ); +} +} +} +} +/* Remark the triangle as infected, so it doesn't get added to the */ +/* virus pool again. */ +infect( testtri ); +virusloop = (triangle **) traverse( &viri ); +} + +if ( verbose ) { +printf( " Deleting marked triangles.\n" ); +} +traversalinit( &viri ); +virusloop = (triangle **) traverse( &viri ); +while ( virusloop != (triangle **) NULL ) { +testtri.tri = *virusloop; + +/* Check each of the three corners of the triangle for elimination. */ +/* This is done by walking around each point, checking if it is */ +/* still connected to at least one live triangle. */ +for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) { +org( testtri, testpoint ); +/* Check if the point has already been tested. */ +if ( testpoint != (point) NULL ) { +killorg = 1; +/* Mark the corner of the triangle as having been tested. */ +setorg( testtri, NULL ); +/* Walk counterclockwise about the point. */ +onext( testtri, neighbor ); +/* Stop upon reaching a boundary or the starting triangle. */ +while (( neighbor.tri != dummytri ) +&& ( !triedgeequal( neighbor, testtri ))) { +if ( infected( neighbor )) { +/* Mark the corner of this triangle as having been tested. */ +setorg( neighbor, NULL ); +} +else { +/* A live triangle. The point survives. */ +killorg = 0; +} +/* Walk counterclockwise about the point. */ +onextself( neighbor ); +} +/* If we reached a boundary, we must walk clockwise as well. */ +if ( neighbor.tri == dummytri ) { +/* Walk clockwise about the point. */ +oprev( testtri, neighbor ); +/* Stop upon reaching a boundary. */ +while ( neighbor.tri != dummytri ) { +if ( infected( neighbor )) { +/* Mark the corner of this triangle as having been tested. */ +setorg( neighbor, NULL ); +} +else { +/* A live triangle. The point survives. */ +killorg = 0; +} +/* Walk clockwise about the point. */ +oprevself( neighbor ); +} +} +if ( killorg ) { +if ( verbose > 1 ) { +printf( " Deleting point (%.12g, %.12g)\n", +testpoint[0], testpoint[1] ); +} +pointdealloc( testpoint ); +} +} +} + +/* Record changes in the number of boundary edges, and disconnect */ +/* dead triangles from their neighbors. */ +for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) { +sym( testtri, neighbor ); +if ( neighbor.tri == dummytri ) { +/* There is no neighboring triangle on this edge, so this edge */ +/* is a boundary edge. This triangle is being deleted, so this */ +/* boundary edge is deleted. */ +hullsize--; +} +else { +/* Disconnect the triangle from its neighbor. */ +dissolve( neighbor ); +/* There is a neighboring triangle on this edge, so this edge */ +/* becomes a boundary edge when this triangle is deleted. */ +hullsize++; +} +} +/* Return the dead triangle to the pool of triangles. */ +triangledealloc( testtri.tri ); +virusloop = (triangle **) traverse( &viri ); +} +/* Empty the virus pool. */ +poolrestart( &viri ); } /*****************************************************************************/ @@ -10449,93 +10660,93 @@ void regionplague( attribute, area ) REAL attribute; REAL area; { - struct triedge testtri; - struct triedge neighbor; - triangle **virusloop; - triangle **regiontri; - struct edge neighborshelle; - point regionorg, regiondest, regionapex; - triangle ptr; /* Temporary variable used by sym() and onext(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - if ( verbose > 1 ) { - printf( " Marking neighbors of marked triangles.\n" ); - } - /* Loop through all the infected triangles, spreading the attribute */ - /* and/or area constraint to their neighbors, then to their neighbors' */ - /* neighbors. */ - traversalinit( &viri ); - virusloop = (triangle **) traverse( &viri ); - while ( virusloop != (triangle **) NULL ) { - testtri.tri = *virusloop; - /* A triangle is marked as infected by messing with one of its shell */ - /* edges, setting it to an illegal value. Hence, we have to */ - /* temporarily uninfect this triangle so that we can examine its */ - /* adjacent shell edges. */ - uninfect( testtri ); - if ( regionattrib ) { - /* Set an attribute. */ - setelemattribute( testtri, eextras, attribute ); - } - if ( vararea ) { - /* Set an area constraint. */ - setareabound( testtri, area ); - } - if ( verbose > 2 ) { - /* Assign the triangle an orientation for convenience in */ - /* checking its points. */ - testtri.orient = 0; - org( testtri, regionorg ); - dest( testtri, regiondest ); - apex( testtri, regionapex ); - printf( " Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", - regionorg[0], regionorg[1], regiondest[0], regiondest[1], - regionapex[0], regionapex[1] ); - } - /* Check each of the triangle's three neighbors. */ - for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) { - /* Find the neighbor. */ - sym( testtri, neighbor ); - /* Check for a shell between the triangle and its neighbor. */ - tspivot( testtri, neighborshelle ); - /* Make sure the neighbor exists, is not already infected, and */ - /* isn't protected by a shell edge. */ - if ( ( neighbor.tri != dummytri ) && !infected( neighbor ) - && ( neighborshelle.sh == dummysh ) ) { - if ( verbose > 2 ) { - org( neighbor, regionorg ); - dest( neighbor, regiondest ); - apex( neighbor, regionapex ); - printf( " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", - regionorg[0], regionorg[1], regiondest[0], regiondest[1], - regionapex[0], regionapex[1] ); - } - /* Infect the neighbor. */ - infect( neighbor ); - /* Ensure that the neighbor's neighbors will be infected. */ - regiontri = (triangle **) poolalloc( &viri ); - *regiontri = neighbor.tri; - } - } - /* Remark the triangle as infected, so it doesn't get added to the */ - /* virus pool again. */ - infect( testtri ); - virusloop = (triangle **) traverse( &viri ); - } - - /* Uninfect all triangles. */ - if ( verbose > 1 ) { - printf( " Unmarking marked triangles.\n" ); - } - traversalinit( &viri ); - virusloop = (triangle **) traverse( &viri ); - while ( virusloop != (triangle **) NULL ) { - testtri.tri = *virusloop; - uninfect( testtri ); - virusloop = (triangle **) traverse( &viri ); - } - /* Empty the virus pool. */ - poolrestart( &viri ); +struct triedge testtri; +struct triedge neighbor; +triangle **virusloop; +triangle **regiontri; +struct edge neighborshelle; +point regionorg, regiondest, regionapex; +triangle ptr; /* Temporary variable used by sym() and onext(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +if ( verbose > 1 ) { +printf( " Marking neighbors of marked triangles.\n" ); +} +/* Loop through all the infected triangles, spreading the attribute */ +/* and/or area constraint to their neighbors, then to their neighbors' */ +/* neighbors. */ +traversalinit( &viri ); +virusloop = (triangle **) traverse( &viri ); +while ( virusloop != (triangle **) NULL ) { +testtri.tri = *virusloop; +/* A triangle is marked as infected by messing with one of its shell */ +/* edges, setting it to an illegal value. Hence, we have to */ +/* temporarily uninfect this triangle so that we can examine its */ +/* adjacent shell edges. */ +uninfect( testtri ); +if ( regionattrib ) { +/* Set an attribute. */ +setelemattribute( testtri, eextras, attribute ); +} +if ( vararea ) { +/* Set an area constraint. */ +setareabound( testtri, area ); +} +if ( verbose > 2 ) { +/* Assign the triangle an orientation for convenience in */ +/* checking its points. */ +testtri.orient = 0; +org( testtri, regionorg ); +dest( testtri, regiondest ); +apex( testtri, regionapex ); +printf( " Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", +regionorg[0], regionorg[1], regiondest[0], regiondest[1], +regionapex[0], regionapex[1] ); +} +/* Check each of the triangle's three neighbors. */ +for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) { +/* Find the neighbor. */ +sym( testtri, neighbor ); +/* Check for a shell between the triangle and its neighbor. */ +tspivot( testtri, neighborshelle ); +/* Make sure the neighbor exists, is not already infected, and */ +/* isn't protected by a shell edge. */ +if (( neighbor.tri != dummytri ) && !infected( neighbor ) +&& ( neighborshelle.sh == dummysh )) { +if ( verbose > 2 ) { +org( neighbor, regionorg ); +dest( neighbor, regiondest ); +apex( neighbor, regionapex ); +printf( " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", +regionorg[0], regionorg[1], regiondest[0], regiondest[1], +regionapex[0], regionapex[1] ); +} +/* Infect the neighbor. */ +infect( neighbor ); +/* Ensure that the neighbor's neighbors will be infected. */ +regiontri = (triangle **) poolalloc( &viri ); +*regiontri = neighbor.tri; +} +} +/* Remark the triangle as infected, so it doesn't get added to the */ +/* virus pool again. */ +infect( testtri ); +virusloop = (triangle **) traverse( &viri ); +} + +/* Uninfect all triangles. */ +if ( verbose > 1 ) { +printf( " Unmarking marked triangles.\n" ); +} +traversalinit( &viri ); +virusloop = (triangle **) traverse( &viri ); +while ( virusloop != (triangle **) NULL ) { +testtri.tri = *virusloop; +uninfect( testtri ); +virusloop = (triangle **) traverse( &viri ); +} +/* Empty the virus pool. */ +poolrestart( &viri ); } /*****************************************************************************/ @@ -10556,168 +10767,168 @@ int holes; REAL *regionlist; int regions; { - struct triedge searchtri; - struct triedge triangleloop; - struct triedge *regiontris; - triangle **holetri; - triangle **regiontri; - point searchorg, searchdest; - enum locateresult intersect; - int i; - triangle ptr; /* Temporary variable used by sym(). */ - - if ( !( quiet || ( noholes && convex ) ) ) { - printf( "Removing unwanted triangles.\n" ); - if ( verbose && ( holes > 0 ) ) { - printf( " Marking holes for elimination.\n" ); - } - } - - if ( regions > 0 ) { - /* Allocate storage for the triangles in which region points fall. */ - regiontris = (struct triedge *) malloc( regions * sizeof( struct triedge ) ); - if ( regiontris == (struct triedge *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - - if ( ( ( holes > 0 ) && !noholes ) || !convex || ( regions > 0 ) ) { - /* Initialize a pool of viri to be used for holes, concavities, */ - /* regional attributes, and/or regional area constraints. */ - poolinit( &viri, sizeof( triangle * ), VIRUSPERBLOCK, POINTER, 0 ); - } - - if ( !convex ) { - /* Mark as infected any unprotected triangles on the boundary. */ - /* This is one way by which concavities are created. */ - infecthull(); - } - - if ( ( holes > 0 ) && !noholes ) { - /* Infect each triangle in which a hole lies. */ - for ( i = 0; i < 2 * holes; i += 2 ) { - /* Ignore holes that aren't within the bounds of the mesh. */ - if ( ( holelist[i] >= xmin ) && ( holelist[i] <= xmax ) - && ( holelist[i + 1] >= ymin ) && ( holelist[i + 1] <= ymax ) ) { - /* Start searching from some triangle on the outer boundary. */ - searchtri.tri = dummytri; - searchtri.orient = 0; - symself( searchtri ); - /* Ensure that the hole is to the left of this boundary edge; */ - /* otherwise, locate() will falsely report that the hole */ - /* falls within the starting triangle. */ - org( searchtri, searchorg ); - dest( searchtri, searchdest ); - if ( counterclockwise( searchorg, searchdest, &holelist[i] ) > 0.0 ) { - /* Find a triangle that contains the hole. */ - intersect = locate( &holelist[i], &searchtri ); - if ( ( intersect != OUTSIDE ) && ( !infected( searchtri ) ) ) { - /* Infect the triangle. This is done by marking the triangle */ - /* as infect and including the triangle in the virus pool. */ - infect( searchtri ); - holetri = (triangle **) poolalloc( &viri ); - *holetri = searchtri.tri; - } - } - } - } - } - - /* Now, we have to find all the regions BEFORE we carve the holes, because */ - /* locate() won't work when the triangulation is no longer convex. */ - /* (Incidentally, this is the reason why regional attributes and area */ - /* constraints can't be used when refining a preexisting mesh, which */ - /* might not be convex; they can only be used with a freshly */ - /* triangulated PSLG.) */ - if ( regions > 0 ) { - /* Find the starting triangle for each region. */ - for ( i = 0; i < regions; i++ ) { - regiontris[i].tri = dummytri; - /* Ignore region points that aren't within the bounds of the mesh. */ - if ( ( regionlist[4 * i] >= xmin ) && ( regionlist[4 * i] <= xmax ) && - ( regionlist[4 * i + 1] >= ymin ) && ( regionlist[4 * i + 1] <= ymax ) ) { - /* Start searching from some triangle on the outer boundary. */ - searchtri.tri = dummytri; - searchtri.orient = 0; - symself( searchtri ); - /* Ensure that the region point is to the left of this boundary */ - /* edge; otherwise, locate() will falsely report that the */ - /* region point falls within the starting triangle. */ - org( searchtri, searchorg ); - dest( searchtri, searchdest ); - if ( counterclockwise( searchorg, searchdest, ®ionlist[4 * i] ) > - 0.0 ) { - /* Find a triangle that contains the region point. */ - intersect = locate( ®ionlist[4 * i], &searchtri ); - if ( ( intersect != OUTSIDE ) && ( !infected( searchtri ) ) ) { - /* Record the triangle for processing after the */ - /* holes have been carved. */ - triedgecopy( searchtri, regiontris[i] ); - } - } - } - } - } - - if ( viri.items > 0 ) { - /* Carve the holes and concavities. */ - plague(); - } - /* The virus pool should be empty now. */ - - if ( regions > 0 ) { - if ( !quiet ) { - if ( regionattrib ) { - if ( vararea ) { - printf( "Spreading regional attributes and area constraints.\n" ); - } - else { - printf( "Spreading regional attributes.\n" ); - } - } - else { - printf( "Spreading regional area constraints.\n" ); - } - } - if ( regionattrib && !refine ) { - /* Assign every triangle a regional attribute of zero. */ - traversalinit( &triangles ); - triangleloop.orient = 0; - triangleloop.tri = triangletraverse(); - while ( triangleloop.tri != (triangle *) NULL ) { - setelemattribute( triangleloop, eextras, 0.0 ); - triangleloop.tri = triangletraverse(); - } - } - for ( i = 0; i < regions; i++ ) { - if ( regiontris[i].tri != dummytri ) { - /* Make sure the triangle under consideration still exists. */ - /* It may have been eaten by the virus. */ - if ( regiontris[i].tri[3] != (triangle) NULL ) { - /* Put one triangle in the virus pool. */ - infect( regiontris[i] ); - regiontri = (triangle **) poolalloc( &viri ); - *regiontri = regiontris[i].tri; - /* Apply one region's attribute and/or area constraint. */ - regionplague( regionlist[4 * i + 2], regionlist[4 * i + 3] ); - /* The virus pool should be empty now. */ - } - } - } - if ( regionattrib && !refine ) { - /* Note the fact that each triangle has an additional attribute. */ - eextras++; - } - } - - /* Free up memory. */ - if ( ( ( holes > 0 ) && !noholes ) || !convex || ( regions > 0 ) ) { - pooldeinit( &viri ); - } - if ( regions > 0 ) { - free( regiontris ); - } +struct triedge searchtri; +struct triedge triangleloop; +struct triedge *regiontris; +triangle **holetri; +triangle **regiontri; +point searchorg, searchdest; +enum locateresult intersect; +int i; +triangle ptr; /* Temporary variable used by sym(). */ + +if ( !( quiet || ( noholes && convex ))) { +printf( "Removing unwanted triangles.\n" ); +if ( verbose && ( holes > 0 )) { +printf( " Marking holes for elimination.\n" ); +} +} + +if ( regions > 0 ) { +/* Allocate storage for the triangles in which region points fall. */ +regiontris = (struct triedge *) malloc( regions * sizeof( struct triedge )); +if ( regiontris == (struct triedge *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} + +if ((( holes > 0 ) && !noholes ) || !convex || ( regions > 0 )) { +/* Initialize a pool of viri to be used for holes, concavities, */ +/* regional attributes, and/or regional area constraints. */ +poolinit( &viri, sizeof( triangle * ), VIRUSPERBLOCK, POINTER, 0 ); +} + +if ( !convex ) { +/* Mark as infected any unprotected triangles on the boundary. */ +/* This is one way by which concavities are created. */ +infecthull(); +} + +if (( holes > 0 ) && !noholes ) { +/* Infect each triangle in which a hole lies. */ +for ( i = 0; i < 2 * holes; i += 2 ) { +/* Ignore holes that aren't within the bounds of the mesh. */ +if (( holelist[i] >= xmin ) && ( holelist[i] <= xmax ) +&& ( holelist[i + 1] >= ymin ) && ( holelist[i + 1] <= ymax )) { +/* Start searching from some triangle on the outer boundary. */ +searchtri.tri = dummytri; +searchtri.orient = 0; +symself( searchtri ); +/* Ensure that the hole is to the left of this boundary edge; */ +/* otherwise, locate() will falsely report that the hole */ +/* falls within the starting triangle. */ +org( searchtri, searchorg ); +dest( searchtri, searchdest ); +if ( counterclockwise( searchorg, searchdest, &holelist[i] ) > 0.0 ) { +/* Find a triangle that contains the hole. */ +intersect = locate( &holelist[i], &searchtri ); +if (( intersect != OUTSIDE ) && ( !infected( searchtri ))) { +/* Infect the triangle. This is done by marking the triangle */ +/* as infect and including the triangle in the virus pool. */ +infect( searchtri ); +holetri = (triangle **) poolalloc( &viri ); +*holetri = searchtri.tri; +} +} +} +} +} + +/* Now, we have to find all the regions BEFORE we carve the holes, because */ +/* locate() won't work when the triangulation is no longer convex. */ +/* (Incidentally, this is the reason why regional attributes and area */ +/* constraints can't be used when refining a preexisting mesh, which */ +/* might not be convex; they can only be used with a freshly */ +/* triangulated PSLG.) */ +if ( regions > 0 ) { +/* Find the starting triangle for each region. */ +for ( i = 0; i < regions; i++ ) { +regiontris[i].tri = dummytri; +/* Ignore region points that aren't within the bounds of the mesh. */ +if (( regionlist[4 * i] >= xmin ) && ( regionlist[4 * i] <= xmax ) && +( regionlist[4 * i + 1] >= ymin ) && ( regionlist[4 * i + 1] <= ymax )) { +/* Start searching from some triangle on the outer boundary. */ +searchtri.tri = dummytri; +searchtri.orient = 0; +symself( searchtri ); +/* Ensure that the region point is to the left of this boundary */ +/* edge; otherwise, locate() will falsely report that the */ +/* region point falls within the starting triangle. */ +org( searchtri, searchorg ); +dest( searchtri, searchdest ); +if ( counterclockwise( searchorg, searchdest, ®ionlist[4 * i] ) > +0.0 ) { +/* Find a triangle that contains the region point. */ +intersect = locate( ®ionlist[4 * i], &searchtri ); +if (( intersect != OUTSIDE ) && ( !infected( searchtri ))) { +/* Record the triangle for processing after the */ +/* holes have been carved. */ +triedgecopy( searchtri, regiontris[i] ); +} +} +} +} +} + +if ( viri.items > 0 ) { +/* Carve the holes and concavities. */ +plague(); +} +/* The virus pool should be empty now. */ + +if ( regions > 0 ) { +if ( !quiet ) { +if ( regionattrib ) { +if ( vararea ) { +printf( "Spreading regional attributes and area constraints.\n" ); +} +else { +printf( "Spreading regional attributes.\n" ); +} +} +else { +printf( "Spreading regional area constraints.\n" ); +} +} +if ( regionattrib && !refine ) { +/* Assign every triangle a regional attribute of zero. */ +traversalinit( &triangles ); +triangleloop.orient = 0; +triangleloop.tri = triangletraverse(); +while ( triangleloop.tri != (triangle *) NULL ) { +setelemattribute( triangleloop, eextras, 0.0 ); +triangleloop.tri = triangletraverse(); +} +} +for ( i = 0; i < regions; i++ ) { +if ( regiontris[i].tri != dummytri ) { +/* Make sure the triangle under consideration still exists. */ +/* It may have been eaten by the virus. */ +if ( regiontris[i].tri[3] != (triangle) NULL ) { +/* Put one triangle in the virus pool. */ +infect( regiontris[i] ); +regiontri = (triangle **) poolalloc( &viri ); +*regiontri = regiontris[i].tri; +/* Apply one region's attribute and/or area constraint. */ +regionplague( regionlist[4 * i + 2], regionlist[4 * i + 3] ); +/* The virus pool should be empty now. */ +} +} +} +if ( regionattrib && !refine ) { +/* Note the fact that each triangle has an additional attribute. */ +eextras++; +} +} + +/* Free up memory. */ +if ((( holes > 0 ) && !noholes ) || !convex || ( regions > 0 )) { +pooldeinit( &viri ); +} +if ( regions > 0 ) { +free( regiontris ); +} } /** **/ @@ -10735,20 +10946,21 @@ int regions; /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void tallyencs(){ - struct edge edgeloop; - int dummy; - - traversalinit( &shelles ); - edgeloop.shorient = 0; - edgeloop.sh = shelletraverse(); - while ( edgeloop.sh != (shelle *) NULL ) { - /* If the segment is encroached, add it to the list. */ - dummy = checkedge4encroach( &edgeloop ); - edgeloop.sh = shelletraverse(); - } +struct edge edgeloop; +int dummy; + +traversalinit( &shelles ); +edgeloop.shorient = 0; +edgeloop.sh = shelletraverse(); +while ( edgeloop.sh != (shelle *) NULL ) { +/* If the segment is encroached, add it to the list. */ +dummy = checkedge4encroach( &edgeloop ); +edgeloop.sh = shelletraverse(); +} } #endif /* not CDT_ONLY */ @@ -10759,15 +10971,17 @@ void tallyencs(){ /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void precisionerror(){ - printf( "Try increasing the area criterion and/or reducing the minimum\n" ); - printf( " allowable angle so that tiny triangles are not created.\n" ); -#ifdef SINGLE - printf( "Alternatively, try recompiling me with double precision\n" ); - printf( " arithmetic (by removing \"#define SINGLE\" from the\n" ); - printf( " source file or \"-DSINGLE\" from the makefile).\n" ); +printf( "Try increasing the area criterion and/or reducing the minimum\n" ); +printf( " allowable angle so that tiny triangles are not created.\n" ); +#ifdef +SINGLE +printf( "Alternatively, try recompiling me with double precision\n" ); +printf( " arithmetic (by removing \"#define SINGLE\" from the\n" ); +printf( " source file or \"-DSINGLE\" from the makefile).\n" ); #endif /* SINGLE */ } @@ -10790,138 +11004,139 @@ void precisionerror(){ /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void repairencs( flaws ) int flaws; { - struct triedge enctri; - struct triedge testtri; - struct edge *encloop; - struct edge testsh; - point eorg, edest; - point newpoint; - enum insertsiteresult success; - REAL segmentlength, nearestpoweroftwo; - REAL split; - int acuteorg, acutedest; - int dummy; - int i; - triangle ptr; /* Temporary variable used by stpivot(). */ - shelle sptr; /* Temporary variable used by snext(). */ - - while ( ( badsegments.items > 0 ) && ( steinerleft != 0 ) ) { - traversalinit( &badsegments ); - encloop = badsegmenttraverse(); - while ( ( encloop != (struct edge *) NULL ) && ( steinerleft != 0 ) ) { - /* To decide where to split a segment, we need to know if the */ - /* segment shares an endpoint with an adjacent segment. */ - /* The concern is that, if we simply split every encroached */ - /* segment in its center, two adjacent segments with a small */ - /* angle between them might lead to an infinite loop; each */ - /* point added to split one segment will encroach upon the */ - /* other segment, which must then be split with a point that */ - /* will encroach upon the first segment, and so on forever. */ - /* To avoid this, imagine a set of concentric circles, whose */ - /* radii are powers of two, about each segment endpoint. */ - /* These concentric circles determine where the segment is */ - /* split. (If both endpoints are shared with adjacent */ - /* segments, split the segment in the middle, and apply the */ - /* concentric shells for later splittings.) */ - - /* Is the origin shared with another segment? */ - stpivot( *encloop, enctri ); - lnext( enctri, testtri ); - tspivot( testtri, testsh ); - acuteorg = testsh.sh != dummysh; - /* Is the destination shared with another segment? */ - lnextself( testtri ); - tspivot( testtri, testsh ); - acutedest = testsh.sh != dummysh; - /* Now, check the other side of the segment, if there's a triangle */ - /* there. */ - sym( enctri, testtri ); - if ( testtri.tri != dummytri ) { - /* Is the destination shared with another segment? */ - lnextself( testtri ); - tspivot( testtri, testsh ); - acutedest = acutedest || ( testsh.sh != dummysh ); - /* Is the origin shared with another segment? */ - lnextself( testtri ); - tspivot( testtri, testsh ); - acuteorg = acuteorg || ( testsh.sh != dummysh ); - } - - sorg( *encloop, eorg ); - sdest( *encloop, edest ); - /* Use the concentric circles if exactly one endpoint is shared */ - /* with another adjacent segment. */ - if ( acuteorg ^ acutedest ) { - segmentlength = sqrt( ( edest[0] - eorg[0] ) * ( edest[0] - eorg[0] ) - + ( edest[1] - eorg[1] ) * ( edest[1] - eorg[1] ) ); - /* Find the power of two nearest the segment's length. */ - nearestpoweroftwo = 1.0; - while ( segmentlength > SQUAREROOTTWO * nearestpoweroftwo ) { - nearestpoweroftwo *= 2.0; - } - while ( segmentlength < ( 0.5 * SQUAREROOTTWO ) * nearestpoweroftwo ) { - nearestpoweroftwo *= 0.5; - } - /* Where do we split the segment? */ - split = 0.5 * nearestpoweroftwo / segmentlength; - if ( acutedest ) { - split = 1.0 - split; - } - } - else { - /* If we're not worried about adjacent segments, split */ - /* this segment in the middle. */ - split = 0.5; - } - - /* Create the new point. */ - newpoint = (point) poolalloc( &points ); - /* Interpolate its coordinate and attributes. */ - for ( i = 0; i < 2 + nextras; i++ ) { - newpoint[i] = ( 1.0 - split ) * eorg[i] + split * edest[i]; - } - setpointmark( newpoint, mark( *encloop ) ); - if ( verbose > 1 ) { - printf( - " Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n", - eorg[0], eorg[1], edest[0], edest[1], newpoint[0], newpoint[1] ); - } - /* Check whether the new point lies on an endpoint. */ - if ( ( ( newpoint[0] == eorg[0] ) && ( newpoint[1] == eorg[1] ) ) - || ( ( newpoint[0] == edest[0] ) && ( newpoint[1] == edest[1] ) ) ) { - printf( "Error: Ran out of precision at (%.12g, %.12g).\n", - newpoint[0], newpoint[1] ); - printf( "I attempted to split a segment to a smaller size than can\n" ); - printf( " be accommodated by the finite precision of floating point\n" - ); - printf( " arithmetic.\n" ); - precisionerror(); - exit( 1 ); - } - /* Insert the splitting point. This should always succeed. */ - success = insertsite( newpoint, &enctri, encloop, flaws, flaws ); - if ( ( success != SUCCESSFULPOINT ) && ( success != ENCROACHINGPOINT ) ) { - printf( "Internal error in repairencs():\n" ); - printf( " Failure to split a segment.\n" ); - internalerror(); - } - if ( steinerleft > 0 ) { - steinerleft--; - } - /* Check the two new subsegments to see if they're encroached. */ - dummy = checkedge4encroach( encloop ); - snextself( *encloop ); - dummy = checkedge4encroach( encloop ); - - badsegmentdealloc( encloop ); - encloop = badsegmenttraverse(); - } - } +struct triedge enctri; +struct triedge testtri; +struct edge *encloop; +struct edge testsh; +point eorg, edest; +point newpoint; +enum insertsiteresult success; +REAL segmentlength, nearestpoweroftwo; +REAL split; +int acuteorg, acutedest; +int dummy; +int i; +triangle ptr; /* Temporary variable used by stpivot(). */ +shelle sptr; /* Temporary variable used by snext(). */ + +while (( badsegments.items > 0 ) && ( steinerleft != 0 )) { +traversalinit( &badsegments ); +encloop = badsegmenttraverse(); +while (( encloop != (struct edge *) NULL ) && ( steinerleft != 0 )) { +/* To decide where to split a segment, we need to know if the */ +/* segment shares an endpoint with an adjacent segment. */ +/* The concern is that, if we simply split every encroached */ +/* segment in its center, two adjacent segments with a small */ +/* angle between them might lead to an infinite loop; each */ +/* point added to split one segment will encroach upon the */ +/* other segment, which must then be split with a point that */ +/* will encroach upon the first segment, and so on forever. */ +/* To avoid this, imagine a set of concentric circles, whose */ +/* radii are powers of two, about each segment endpoint. */ +/* These concentric circles determine where the segment is */ +/* split. (If both endpoints are shared with adjacent */ +/* segments, split the segment in the middle, and apply the */ +/* concentric shells for later splittings.) */ + +/* Is the origin shared with another segment? */ +stpivot( *encloop, enctri ); +lnext( enctri, testtri ); +tspivot( testtri, testsh ); +acuteorg = testsh.sh != dummysh; +/* Is the destination shared with another segment? */ +lnextself( testtri ); +tspivot( testtri, testsh ); +acutedest = testsh.sh != dummysh; +/* Now, check the other side of the segment, if there's a triangle */ +/* there. */ +sym( enctri, testtri ); +if ( testtri.tri != dummytri ) { +/* Is the destination shared with another segment? */ +lnextself( testtri ); +tspivot( testtri, testsh ); +acutedest = acutedest || ( testsh.sh != dummysh ); +/* Is the origin shared with another segment? */ +lnextself( testtri ); +tspivot( testtri, testsh ); +acuteorg = acuteorg || ( testsh.sh != dummysh ); +} + +sorg( *encloop, eorg ); +sdest( *encloop, edest ); +/* Use the concentric circles if exactly one endpoint is shared */ +/* with another adjacent segment. */ +if ( acuteorg ^ acutedest ) { +segmentlength = sqrt(( edest[0] - eorg[0] ) * ( edest[0] - eorg[0] ) ++ ( edest[1] - eorg[1] ) * ( edest[1] - eorg[1] )); +/* Find the power of two nearest the segment's length. */ +nearestpoweroftwo = 1.0; +while ( segmentlength > SQUAREROOTTWO * nearestpoweroftwo ) { +nearestpoweroftwo *= 2.0; +} +while ( segmentlength < ( 0.5 * SQUAREROOTTWO ) * nearestpoweroftwo ) { +nearestpoweroftwo *= 0.5; +} +/* Where do we split the segment? */ +split = 0.5 * nearestpoweroftwo / segmentlength; +if ( acutedest ) { +split = 1.0 - split; +} +} +else { +/* If we're not worried about adjacent segments, split */ +/* this segment in the middle. */ +split = 0.5; +} + +/* Create the new point. */ +newpoint = (point) poolalloc( &points ); +/* Interpolate its coordinate and attributes. */ +for ( i = 0; i < 2 + nextras; i++ ) { +newpoint[i] = ( 1.0 - split ) * eorg[i] + split * edest[i]; +} +setpointmark( newpoint, mark( *encloop )); +if ( verbose > 1 ) { +printf( +" Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n", +eorg[0], eorg[1], edest[0], edest[1], newpoint[0], newpoint[1] ); +} +/* Check whether the new point lies on an endpoint. */ +if ((( newpoint[0] == eorg[0] ) && ( newpoint[1] == eorg[1] )) +|| (( newpoint[0] == edest[0] ) && ( newpoint[1] == edest[1] ))) { +printf( "Error: Ran out of precision at (%.12g, %.12g).\n", +newpoint[0], newpoint[1] ); +printf( "I attempted to split a segment to a smaller size than can\n" ); +printf( " be accommodated by the finite precision of floating point\n" +); +printf( " arithmetic.\n" ); +precisionerror(); +exit( 1 ); +} +/* Insert the splitting point. This should always succeed. */ +success = insertsite( newpoint, &enctri, encloop, flaws, flaws ); +if (( success != SUCCESSFULPOINT ) && ( success != ENCROACHINGPOINT )) { +printf( "Internal error in repairencs():\n" ); +printf( " Failure to split a segment.\n" ); +internalerror(); +} +if ( steinerleft > 0 ) { +steinerleft--; +} +/* Check the two new subsegments to see if they're encroached. */ +dummy = checkedge4encroach( encloop ); +snextself( *encloop ); +dummy = checkedge4encroach( encloop ); + +badsegmentdealloc( encloop ); +encloop = badsegmenttraverse(); +} +} } #endif /* not CDT_ONLY */ @@ -10932,22 +11147,23 @@ int flaws; /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void tallyfaces(){ - struct triedge triangleloop; +struct triedge triangleloop; - if ( verbose ) { - printf( " Making a list of bad triangles.\n" ); - } - traversalinit( &triangles ); - triangleloop.orient = 0; - triangleloop.tri = triangletraverse(); - while ( triangleloop.tri != (triangle *) NULL ) { - /* If the triangle is bad, enqueue it. */ - testtriangle( &triangleloop ); - triangleloop.tri = triangletraverse(); - } +if ( verbose ) { +printf( " Making a list of bad triangles.\n" ); +} +traversalinit( &triangles ); +triangleloop.orient = 0; +triangleloop.tri = triangletraverse(); +while ( triangleloop.tri != (triangle *) NULL ) { +/* If the triangle is bad, enqueue it. */ +testtriangle( &triangleloop ); +triangleloop.tri = triangletraverse(); +} } #endif /* not CDT_ONLY */ @@ -10967,7 +11183,7 @@ void tallyfaces(){ /*****************************************************************************/ enum circumcenterresult findcircumcenter( torg, tdest, tapex, circumcenter, - xi, eta ) +xi, eta ) point torg; point tdest; point tapex; @@ -10975,56 +11191,56 @@ point circumcenter; REAL *xi; REAL *eta; { - REAL xdo, ydo, xao, yao, xad, yad; - REAL dodist, aodist, addist; - REAL denominator; - REAL dx, dy; - - circumcentercount++; - - /* Compute the circumcenter of the triangle. */ - xdo = tdest[0] - torg[0]; - ydo = tdest[1] - torg[1]; - xao = tapex[0] - torg[0]; - yao = tapex[1] - torg[1]; - dodist = xdo * xdo + ydo * ydo; - aodist = xao * xao + yao * yao; - if ( noexact ) { - denominator = (REAL)( 0.5 / ( xdo * yao - xao * ydo ) ); - } - else { - /* Use the counterclockwise() routine to ensure a positive (and */ - /* reasonably accurate) result, avoiding any possibility of */ - /* division by zero. */ - denominator = (REAL)( 0.5 / counterclockwise( tdest, tapex, torg ) ); - /* Don't count the above as an orientation test. */ - counterclockcount--; - } - circumcenter[0] = torg[0] - ( ydo * aodist - yao * dodist ) * denominator; - circumcenter[1] = torg[1] + ( xdo * aodist - xao * dodist ) * denominator; - - /* To interpolate point attributes for the new point inserted at */ - /* the circumcenter, define a coordinate system with a xi-axis, */ - /* directed from the triangle's origin to its destination, and */ - /* an eta-axis, directed from its origin to its apex. */ - /* Calculate the xi and eta coordinates of the circumcenter. */ - dx = circumcenter[0] - torg[0]; - dy = circumcenter[1] - torg[1]; - *xi = (REAL)( ( dx * yao - xao * dy ) * ( 2.0 * denominator ) ); - *eta = (REAL)( ( xdo * dy - dx * ydo ) * ( 2.0 * denominator ) ); - - xad = tapex[0] - tdest[0]; - yad = tapex[1] - tdest[1]; - addist = xad * xad + yad * yad; - if ( ( addist < dodist ) && ( addist < aodist ) ) { - return OPPOSITEORG; - } - else if ( dodist < aodist ) { - return OPPOSITEAPEX; - } - else { - return OPPOSITEDEST; - } +REAL xdo, ydo, xao, yao, xad, yad; +REAL dodist, aodist, addist; +REAL denominator; +REAL dx, dy; + +circumcentercount++; + +/* Compute the circumcenter of the triangle. */ +xdo = tdest[0] - torg[0]; +ydo = tdest[1] - torg[1]; +xao = tapex[0] - torg[0]; +yao = tapex[1] - torg[1]; +dodist = xdo * xdo + ydo * ydo; +aodist = xao * xao + yao * yao; +if ( noexact ) { +denominator = (REAL)( 0.5 / ( xdo * yao - xao * ydo )); +} +else { +/* Use the counterclockwise() routine to ensure a positive (and */ +/* reasonably accurate) result, avoiding any possibility of */ +/* division by zero. */ +denominator = (REAL)( 0.5 / counterclockwise( tdest, tapex, torg )); +/* Don't count the above as an orientation test. */ +counterclockcount--; +} +circumcenter[0] = torg[0] - ( ydo * aodist - yao * dodist ) * denominator; +circumcenter[1] = torg[1] + ( xdo * aodist - xao * dodist ) * denominator; + +/* To interpolate point attributes for the new point inserted at */ +/* the circumcenter, define a coordinate system with a xi-axis, */ +/* directed from the triangle's origin to its destination, and */ +/* an eta-axis, directed from its origin to its apex. */ +/* Calculate the xi and eta coordinates of the circumcenter. */ +dx = circumcenter[0] - torg[0]; +dy = circumcenter[1] - torg[1]; +*xi = (REAL)(( dx * yao - xao * dy ) * ( 2.0 * denominator )); +*eta = (REAL)(( xdo * dy - dx * ydo ) * ( 2.0 * denominator )); + +xad = tapex[0] - tdest[0]; +yad = tapex[1] - tdest[1]; +addist = xad * xad + yad * yad; +if (( addist < dodist ) && ( addist < aodist )) { +return OPPOSITEORG; +} +else if ( dodist < aodist ) { +return OPPOSITEAPEX; +} +else { +return OPPOSITEDEST; +} } /*****************************************************************************/ @@ -11035,108 +11251,109 @@ REAL *eta; /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void splittriangle( badtri ) struct badface *badtri; { - point borg, bdest, bapex; - point newpoint; - REAL xi, eta; - enum insertsiteresult success; - enum circumcenterresult shortedge; - int errorflag; - int i; - - org( badtri->badfacetri, borg ); - dest( badtri->badfacetri, bdest ); - apex( badtri->badfacetri, bapex ); - /* Make sure that this triangle is still the same triangle it was */ - /* when it was tested and determined to be of bad quality. */ - /* Subsequent transformations may have made it a different triangle. */ - if ( ( borg == badtri->faceorg ) && ( bdest == badtri->facedest ) && - ( bapex == badtri->faceapex ) ) { - if ( verbose > 1 ) { - printf( " Splitting this triangle at its circumcenter:\n" ); - printf( " (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0], - borg[1], bdest[0], bdest[1], bapex[0], bapex[1] ); - } - errorflag = 0; - /* Create a new point at the triangle's circumcenter. */ - newpoint = (point) poolalloc( &points ); - shortedge = findcircumcenter( borg, bdest, bapex, newpoint, &xi, &eta ); - /* Check whether the new point lies on a triangle vertex. */ - if ( ( ( newpoint[0] == borg[0] ) && ( newpoint[1] == borg[1] ) ) - || ( ( newpoint[0] == bdest[0] ) && ( newpoint[1] == bdest[1] ) ) - || ( ( newpoint[0] == bapex[0] ) && ( newpoint[1] == bapex[1] ) ) ) { - if ( !quiet ) { - printf( "Warning: New point (%.12g, %.12g) falls on existing vertex.\n" - , newpoint[0], newpoint[1] ); - errorflag = 1; - } - pointdealloc( newpoint ); - } - else { - for ( i = 2; i < 2 + nextras; i++ ) { - /* Interpolate the point attributes at the circumcenter. */ - newpoint[i] = borg[i] + xi * ( bdest[i] - borg[i] ) - + eta * ( bapex[i] - borg[i] ); - } - /* The new point must be in the interior, and have a marker of zero. */ - setpointmark( newpoint, 0 ); - /* Ensure that the handle `badtri->badfacetri' represents the shortest */ - /* edge of the triangle. This ensures that the circumcenter must */ - /* fall to the left of this edge, so point location will work. */ - if ( shortedge == OPPOSITEORG ) { - lnextself( badtri->badfacetri ); - } - else if ( shortedge == OPPOSITEDEST ) { - lprevself( badtri->badfacetri ); - } - /* Insert the circumcenter, searching from the edge of the triangle, */ - /* and maintain the Delaunay property of the triangulation. */ - success = insertsite( newpoint, &( badtri->badfacetri ), - (struct edge *) NULL, 1, 1 ); - if ( success == SUCCESSFULPOINT ) { - if ( steinerleft > 0 ) { - steinerleft--; - } - } - else if ( success == ENCROACHINGPOINT ) { - /* If the newly inserted point encroaches upon a segment, delete it. */ - deletesite( &( badtri->badfacetri ) ); - } - else if ( success == VIOLATINGPOINT ) { - /* Failed to insert the new point, but some segment was */ - /* marked as being encroached. */ - pointdealloc( newpoint ); - } - else { /* success == DUPLICATEPOINT */ - /* Failed to insert the new point because a vertex is already there. */ - if ( !quiet ) { - printf( - "Warning: New point (%.12g, %.12g) falls on existing vertex.\n" - , newpoint[0], newpoint[1] ); - errorflag = 1; - } - pointdealloc( newpoint ); - } - } - if ( errorflag ) { - if ( verbose ) { - printf( " The new point is at the circumcenter of triangle\n" ); - printf( " (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", - borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1] ); - } - printf( "This probably means that I am trying to refine triangles\n" ); - printf( " to a smaller size than can be accommodated by the finite\n" ); - printf( " precision of floating point arithmetic. (You can be\n" ); - printf( " sure of this if I fail to terminate.)\n" ); - precisionerror(); - } - } - /* Return the bad triangle to the pool. */ - pooldealloc( &badtriangles, (VOID *) badtri ); +point borg, bdest, bapex; +point newpoint; +REAL xi, eta; +enum insertsiteresult success; +enum circumcenterresult shortedge; +int errorflag; +int i; + +org( badtri->badfacetri, borg ); +dest( badtri->badfacetri, bdest ); +apex( badtri->badfacetri, bapex ); +/* Make sure that this triangle is still the same triangle it was */ +/* when it was tested and determined to be of bad quality. */ +/* Subsequent transformations may have made it a different triangle. */ +if (( borg == badtri->faceorg ) && ( bdest == badtri->facedest ) && +( bapex == badtri->faceapex )) { +if ( verbose > 1 ) { +printf( " Splitting this triangle at its circumcenter:\n" ); +printf( " (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0], +borg[1], bdest[0], bdest[1], bapex[0], bapex[1] ); +} +errorflag = 0; +/* Create a new point at the triangle's circumcenter. */ +newpoint = (point) poolalloc( &points ); +shortedge = findcircumcenter( borg, bdest, bapex, newpoint, &xi, &eta ); +/* Check whether the new point lies on a triangle vertex. */ +if ((( newpoint[0] == borg[0] ) && ( newpoint[1] == borg[1] )) +|| (( newpoint[0] == bdest[0] ) && ( newpoint[1] == bdest[1] )) +|| (( newpoint[0] == bapex[0] ) && ( newpoint[1] == bapex[1] ))) { +if ( !quiet ) { +printf( "Warning: New point (%.12g, %.12g) falls on existing vertex.\n" +, newpoint[0], newpoint[1] ); +errorflag = 1; +} +pointdealloc( newpoint ); +} +else { +for ( i = 2; i < 2 + nextras; i++ ) { +/* Interpolate the point attributes at the circumcenter. */ +newpoint[i] = borg[i] + xi * ( bdest[i] - borg[i] ) ++ eta * ( bapex[i] - borg[i] ); +} +/* The new point must be in the interior, and have a marker of zero. */ +setpointmark( newpoint, 0 ); +/* Ensure that the handle `badtri->badfacetri' represents the shortest */ +/* edge of the triangle. This ensures that the circumcenter must */ +/* fall to the left of this edge, so point location will work. */ +if ( shortedge == OPPOSITEORG ) { +lnextself( badtri->badfacetri ); +} +else if ( shortedge == OPPOSITEDEST ) { +lprevself( badtri->badfacetri ); +} +/* Insert the circumcenter, searching from the edge of the triangle, */ +/* and maintain the Delaunay property of the triangulation. */ +success = insertsite( newpoint, &( badtri->badfacetri ), +(struct edge *) NULL, 1, 1 ); +if ( success == SUCCESSFULPOINT ) { +if ( steinerleft > 0 ) { +steinerleft--; +} +} +else if ( success == ENCROACHINGPOINT ) { +/* If the newly inserted point encroaches upon a segment, delete it. */ +deletesite( &( badtri->badfacetri )); +} +else if ( success == VIOLATINGPOINT ) { +/* Failed to insert the new point, but some segment was */ +/* marked as being encroached. */ +pointdealloc( newpoint ); +} +else { /* success == DUPLICATEPOINT */ +/* Failed to insert the new point because a vertex is already there. */ +if ( !quiet ) { +printf( +"Warning: New point (%.12g, %.12g) falls on existing vertex.\n" +, newpoint[0], newpoint[1] ); +errorflag = 1; +} +pointdealloc( newpoint ); +} +} +if ( errorflag ) { +if ( verbose ) { +printf( " The new point is at the circumcenter of triangle\n" ); +printf( " (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", +borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1] ); +} +printf( "This probably means that I am trying to refine triangles\n" ); +printf( " to a smaller size than can be accommodated by the finite\n" ); +printf( " precision of floating point arithmetic. (You can be\n" ); +printf( " sure of this if I fail to terminate.)\n" ); +precisionerror(); +} +} +/* Return the bad triangle to the pool. */ +pooldealloc( &badtriangles, (VOID *) badtri ); } #endif /* not CDT_ONLY */ @@ -11148,83 +11365,84 @@ struct badface *badtri; /* */ /*****************************************************************************/ -#ifndef CDT_ONLY +#ifndef +CDT_ONLY void enforcequality(){ - int i; - - if ( !quiet ) { - printf( "Adding Steiner points to enforce quality.\n" ); - } - /* Initialize the pool of encroached segments. */ - poolinit( &badsegments, sizeof( struct edge ), BADSEGMENTPERBLOCK, POINTER, 0 ); - if ( verbose ) { - printf( " Looking for encroached segments.\n" ); - } - /* Test all segments to see if they're encroached. */ - tallyencs(); - if ( verbose && ( badsegments.items > 0 ) ) { - printf( " Splitting encroached segments.\n" ); - } - /* Note that steinerleft == -1 if an unlimited number */ - /* of Steiner points is allowed. */ - while ( ( badsegments.items > 0 ) && ( steinerleft != 0 ) ) { - /* Fix the segments without noting newly encroached segments or */ - /* bad triangles. The reason we don't want to note newly */ - /* encroached segments is because some encroached segments are */ - /* likely to be noted multiple times, and would then be blindly */ - /* split multiple times. I should fix that some time. */ - repairencs( 0 ); - /* Now, find all the segments that became encroached while adding */ - /* points to split encroached segments. */ - tallyencs(); - } - /* At this point, if we haven't run out of Steiner points, the */ - /* triangulation should be (conforming) Delaunay. */ - - /* Next, we worry about enforcing triangle quality. */ - if ( ( minangle > 0.0 ) || vararea || fixedarea ) { - /* Initialize the pool of bad triangles. */ - poolinit( &badtriangles, sizeof( struct badface ), BADTRIPERBLOCK, POINTER, - 0 ); - /* Initialize the queues of bad triangles. */ - for ( i = 0; i < 64; i++ ) { - queuefront[i] = (struct badface *) NULL; - queuetail[i] = &queuefront[i]; - } - /* Test all triangles to see if they're bad. */ - tallyfaces(); - if ( verbose ) { - printf( " Splitting bad triangles.\n" ); - } - while ( ( badtriangles.items > 0 ) && ( steinerleft != 0 ) ) { - /* Fix one bad triangle by inserting a point at its circumcenter. */ - splittriangle( dequeuebadtri() ); - /* Fix any encroached segments that may have resulted. Record */ - /* any new bad triangles or encroached segments that result. */ - if ( badsegments.items > 0 ) { - repairencs( 1 ); - } - } - } - /* At this point, if we haven't run out of Steiner points, the */ - /* triangulation should be (conforming) Delaunay and have no */ - /* low-quality triangles. */ - - /* Might we have run out of Steiner points too soon? */ - if ( !quiet && ( badsegments.items > 0 ) && ( steinerleft == 0 ) ) { - printf( "\nWarning: I ran out of Steiner points, but the mesh has\n" ); - if ( badsegments.items == 1 ) { - printf( " an encroached segment, and therefore might not be truly\n" ); - } - else { - printf( " %ld encroached segments, and therefore might not be truly\n", - badsegments.items ); - } - printf( " Delaunay. If the Delaunay property is important to you,\n" ); - printf( " try increasing the number of Steiner points (controlled by\n" ); - printf( " the -S switch) slightly and try again.\n\n" ); - } +int i; + +if ( !quiet ) { +printf( "Adding Steiner points to enforce quality.\n" ); +} +/* Initialize the pool of encroached segments. */ +poolinit( &badsegments, sizeof( struct edge ), BADSEGMENTPERBLOCK, POINTER, 0 ); +if ( verbose ) { +printf( " Looking for encroached segments.\n" ); +} +/* Test all segments to see if they're encroached. */ +tallyencs(); +if ( verbose && ( badsegments.items > 0 )) { +printf( " Splitting encroached segments.\n" ); +} +/* Note that steinerleft == -1 if an unlimited number */ +/* of Steiner points is allowed. */ +while (( badsegments.items > 0 ) && ( steinerleft != 0 )) { +/* Fix the segments without noting newly encroached segments or */ +/* bad triangles. The reason we don't want to note newly */ +/* encroached segments is because some encroached segments are */ +/* likely to be noted multiple times, and would then be blindly */ +/* split multiple times. I should fix that some time. */ +repairencs( 0 ); +/* Now, find all the segments that became encroached while adding */ +/* points to split encroached segments. */ +tallyencs(); +} +/* At this point, if we haven't run out of Steiner points, the */ +/* triangulation should be (conforming) Delaunay. */ + +/* Next, we worry about enforcing triangle quality. */ +if (( minangle > 0.0 ) || vararea || fixedarea ) { +/* Initialize the pool of bad triangles. */ +poolinit( &badtriangles, sizeof( struct badface ), BADTRIPERBLOCK, POINTER, +0 ); +/* Initialize the queues of bad triangles. */ +for ( i = 0; i < 64; i++ ) { +queuefront[i] = (struct badface *) NULL; +queuetail[i] = &queuefront[i]; +} +/* Test all triangles to see if they're bad. */ +tallyfaces(); +if ( verbose ) { +printf( " Splitting bad triangles.\n" ); +} +while (( badtriangles.items > 0 ) && ( steinerleft != 0 )) { +/* Fix one bad triangle by inserting a point at its circumcenter. */ +splittriangle( dequeuebadtri()); +/* Fix any encroached segments that may have resulted. Record */ +/* any new bad triangles or encroached segments that result. */ +if ( badsegments.items > 0 ) { +repairencs( 1 ); +} +} +} +/* At this point, if we haven't run out of Steiner points, the */ +/* triangulation should be (conforming) Delaunay and have no */ +/* low-quality triangles. */ + +/* Might we have run out of Steiner points too soon? */ +if ( !quiet && ( badsegments.items > 0 ) && ( steinerleft == 0 )) { +printf( "\nWarning: I ran out of Steiner points, but the mesh has\n" ); +if ( badsegments.items == 1 ) { +printf( " an encroached segment, and therefore might not be truly\n" ); +} +else { +printf( " %ld encroached segments, and therefore might not be truly\n", +badsegments.items ); +} +printf( " Delaunay. If the Delaunay property is important to you,\n" ); +printf( " try increasing the number of Steiner points (controlled by\n" ); +printf( " the -S switch) slightly and try again.\n\n" ); +} } #endif /* not CDT_ONLY */ @@ -11240,68 +11458,68 @@ void enforcequality(){ /*****************************************************************************/ void highorder(){ - struct triedge triangleloop, trisym; - struct edge checkmark; - point newpoint; - point torg, tdest; - int i; - triangle ptr; /* Temporary variable used by sym(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - - if ( !quiet ) { - printf( "Adding vertices for second-order triangles.\n" ); - } - /* The following line ensures that dead items in the pool of nodes */ - /* cannot be allocated for the extra nodes associated with high */ - /* order elements. This ensures that the primary nodes (at the */ - /* corners of elements) will occur earlier in the output files, and */ - /* have lower indices, than the extra nodes. */ - points.deaditemstack = (VOID *) NULL; - - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - /* To loop over the set of edges, loop over all triangles, and look at */ - /* the three edges of each triangle. If there isn't another triangle */ - /* adjacent to the edge, operate on the edge. If there is another */ - /* adjacent triangle, operate on the edge only if the current triangle */ - /* has a smaller pointer than its neighbor. This way, each edge is */ - /* considered only once. */ - while ( triangleloop.tri != (triangle *) NULL ) { - for ( triangleloop.orient = 0; triangleloop.orient < 3; - triangleloop.orient++ ) { - sym( triangleloop, trisym ); - if ( ( triangleloop.tri < trisym.tri ) || ( trisym.tri == dummytri ) ) { - org( triangleloop, torg ); - dest( triangleloop, tdest ); - /* Create a new node in the middle of the edge. Interpolate */ - /* its attributes. */ - newpoint = (point) poolalloc( &points ); - for ( i = 0; i < 2 + nextras; i++ ) { - newpoint[i] = (REAL)( 0.5 * ( torg[i] + tdest[i] ) ); - } - /* Set the new node's marker to zero or one, depending on */ - /* whether it lies on a boundary. */ - setpointmark( newpoint, trisym.tri == dummytri ); - if ( useshelles ) { - tspivot( triangleloop, checkmark ); - /* If this edge is a segment, transfer the marker to the new node. */ - if ( checkmark.sh != dummysh ) { - setpointmark( newpoint, mark( checkmark ) ); - } - } - if ( verbose > 1 ) { - printf( " Creating (%.12g, %.12g).\n", newpoint[0], newpoint[1] ); - } - /* Record the new node in the (one or two) adjacent elements. */ - triangleloop.tri[highorderindex + triangleloop.orient] = - (triangle) newpoint; - if ( trisym.tri != dummytri ) { - trisym.tri[highorderindex + trisym.orient] = (triangle) newpoint; - } - } - } - triangleloop.tri = triangletraverse(); - } +struct triedge triangleloop, trisym; +struct edge checkmark; +point newpoint; +point torg, tdest; +int i; +triangle ptr; /* Temporary variable used by sym(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +if ( !quiet ) { +printf( "Adding vertices for second-order triangles.\n" ); +} +/* The following line ensures that dead items in the pool of nodes */ +/* cannot be allocated for the extra nodes associated with high */ +/* order elements. This ensures that the primary nodes (at the */ +/* corners of elements) will occur earlier in the output files, and */ +/* have lower indices, than the extra nodes. */ +points.deaditemstack = (VOID *) NULL; + +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +/* To loop over the set of edges, loop over all triangles, and look at */ +/* the three edges of each triangle. If there isn't another triangle */ +/* adjacent to the edge, operate on the edge. If there is another */ +/* adjacent triangle, operate on the edge only if the current triangle */ +/* has a smaller pointer than its neighbor. This way, each edge is */ +/* considered only once. */ +while ( triangleloop.tri != (triangle *) NULL ) { +for ( triangleloop.orient = 0; triangleloop.orient < 3; +triangleloop.orient++ ) { +sym( triangleloop, trisym ); +if (( triangleloop.tri < trisym.tri ) || ( trisym.tri == dummytri )) { +org( triangleloop, torg ); +dest( triangleloop, tdest ); +/* Create a new node in the middle of the edge. Interpolate */ +/* its attributes. */ +newpoint = (point) poolalloc( &points ); +for ( i = 0; i < 2 + nextras; i++ ) { +newpoint[i] = (REAL)( 0.5 * ( torg[i] + tdest[i] )); +} +/* Set the new node's marker to zero or one, depending on */ +/* whether it lies on a boundary. */ +setpointmark( newpoint, trisym.tri == dummytri ); +if ( useshelles ) { +tspivot( triangleloop, checkmark ); +/* If this edge is a segment, transfer the marker to the new node. */ +if ( checkmark.sh != dummysh ) { +setpointmark( newpoint, mark( checkmark )); +} +} +if ( verbose > 1 ) { +printf( " Creating (%.12g, %.12g).\n", newpoint[0], newpoint[1] ); +} +/* Record the new node in the (one or two) adjacent elements. */ +triangleloop.tri[highorderindex + triangleloop.orient] = +(triangle) newpoint; +if ( trisym.tri != dummytri ) { +trisym.tri[highorderindex + trisym.orient] = (triangle) newpoint; +} +} +} +triangleloop.tri = triangletraverse(); +} } /********* File I/O routines begin here *********/ @@ -11317,32 +11535,33 @@ void highorder(){ /* */ /*****************************************************************************/ -#ifndef TRILIBRARY +#ifndef +TRILIBRARY char *readline( string, infile, infilename ) char *string; FILE *infile; char *infilename; { - char *result; - - /* Search for something that looks like a number. */ - do { - result = fgets( string, INPUTLINESIZE, infile ); - if ( result == (char *) NULL ) { - printf( " Error: Unexpected end of file in %s.\n", infilename ); - exit( 1 ); - } - /* Skip anything that doesn't look like a number, a comment, */ - /* or the end of a line. */ - while ( ( *result != '\0' ) && ( *result != '#' ) - && ( *result != '.' ) && ( *result != '+' ) && ( *result != '-' ) - && ( ( *result < '0' ) || ( *result > '9' ) ) ) { - result++; - } - /* If it's a comment or end of line, read another line and try again. */ - } while ( ( *result == '#' ) || ( *result == '\0' ) ); - return result; +char *result; + +/* Search for something that looks like a number. */ +do { +result = fgets( string, INPUTLINESIZE, infile ); +if ( result == (char *) NULL ) { +printf( " Error: Unexpected end of file in %s.\n", infilename ); +exit( 1 ); +} +/* Skip anything that doesn't look like a number, a comment, */ +/* or the end of a line. */ +while (( *result != '\0' ) && ( *result != '#' ) +&& ( *result != '.' ) && ( *result != '+' ) && ( *result != '-' ) +&& (( *result < '0' ) || ( *result > '9' ))) { +result++; +} +/* If it's a comment or end of line, read another line and try again. */ +} while (( *result == '#' ) || ( *result == '\0' )); +return result; } #endif /* not TRILIBRARY */ @@ -11356,229 +11575,231 @@ char *infilename; /* */ /*****************************************************************************/ -#ifndef TRILIBRARY +#ifndef +TRILIBRARY char *findfield( string ) char *string; { - char *result; - - result = string; - /* Skip the current field. Stop upon reaching whitespace. */ - while ( ( *result != '\0' ) && ( *result != '#' ) - && ( *result != ' ' ) && ( *result != '\t' ) ) { - result++; - } - /* Now skip the whitespace and anything else that doesn't look like a */ - /* number, a comment, or the end of a line. */ - while ( ( *result != '\0' ) && ( *result != '#' ) - && ( *result != '.' ) && ( *result != '+' ) && ( *result != '-' ) - && ( ( *result < '0' ) || ( *result > '9' ) ) ) { - result++; - } - /* Check for a comment (prefixed with `#'). */ - if ( *result == '#' ) { - *result = '\0'; - } - return result; +char *result; + +result = string; +/* Skip the current field. Stop upon reaching whitespace. */ +while (( *result != '\0' ) && ( *result != '#' ) +&& ( *result != ' ' ) && ( *result != '\t' )) { +result++; +} +/* Now skip the whitespace and anything else that doesn't look like a */ +/* number, a comment, or the end of a line. */ +while (( *result != '\0' ) && ( *result != '#' ) +&& ( *result != '.' ) && ( *result != '+' ) && ( *result != '-' ) +&& (( *result < '0' ) || ( *result > '9' ))) { +result++; +} +/* Check for a comment (prefixed with `#'). */ +if ( *result == '#' ) { +*result = '\0'; +} +return result; } #endif /* not TRILIBRARY */ -/*****************************************************************************/ -/* */ -/* readnodes() Read the points from a file, which may be a .node or .poly */ -/* file. */ -/* */ -/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* readnodes() Read the points from a file, which may be a .node or .poly */ +/* file. */ +/* */ +/*****************************************************************************/ + +#ifndef +TRILIBRARY + +void readnodes( nodefilename, polyfilename, polyfile ) +char *nodefilename; +char *polyfilename; +FILE **polyfile; +{ +FILE *infile; +point pointloop; +char inputline[INPUTLINESIZE]; +char *stringptr; +char *infilename; +REAL x, y; +int firstnode; +int nodemarkers; +int currentmarker; +int i, j; + +if ( poly ) { +/* Read the points from a .poly file. */ +if ( !quiet ) { +printf( "Opening %s.\n", polyfilename ); +} +*polyfile = fopen( polyfilename, "r" ); +if ( *polyfile == (FILE *) NULL ) { +printf( " Error: Cannot access file %s.\n", polyfilename ); +exit( 1 ); +} +/* Read number of points, number of dimensions, number of point */ +/* attributes, and number of boundary markers. */ +stringptr = readline( inputline, *polyfile, polyfilename ); +inpoints = (int) strtol( stringptr, &stringptr, 0 ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +mesh_dim = 2; +} +else { +mesh_dim = (int) strtol( stringptr, &stringptr, 0 ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +nextras = 0; +} +else { +nextras = (int) strtol( stringptr, &stringptr, 0 ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +nodemarkers = 0; +} +else { +nodemarkers = (int) strtol( stringptr, &stringptr, 0 ); +} +if ( inpoints > 0 ) { +infile = *polyfile; +infilename = polyfilename; +readnodefile = 0; +} +else { +/* If the .poly file claims there are zero points, that means that */ +/* the points should be read from a separate .node file. */ +readnodefile = 1; +infilename = innodefilename; +} +} +else { +readnodefile = 1; +infilename = innodefilename; +*polyfile = (FILE *) NULL; +} + +if ( readnodefile ) { +/* Read the points from a .node file. */ +if ( !quiet ) { +printf( "Opening %s.\n", innodefilename ); +} +infile = fopen( innodefilename, "r" ); +if ( infile == (FILE *) NULL ) { +printf( " Error: Cannot access file %s.\n", innodefilename ); +exit( 1 ); +} +/* Read number of points, number of dimensions, number of point */ +/* attributes, and number of boundary markers. */ +stringptr = readline( inputline, infile, innodefilename ); +inpoints = (int) strtol( stringptr, &stringptr, 0 ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +mesh_dim = 2; +} +else { +mesh_dim = (int) strtol( stringptr, &stringptr, 0 ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +nextras = 0; +} +else { +nextras = (int) strtol( stringptr, &stringptr, 0 ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +nodemarkers = 0; +} +else { +nodemarkers = (int) strtol( stringptr, &stringptr, 0 ); +} +} + +if ( inpoints < 3 ) { +printf( "Error: Input must have at least three input points.\n" ); +exit( 1 ); +} +if ( mesh_dim != 2 ) { +printf( "Error: Triangle only works with two-dimensional meshes.\n" ); +exit( 1 ); +} + +initializepointpool(); -#ifndef TRILIBRARY +/* Read the points. */ +for ( i = 0; i < inpoints; i++ ) { +pointloop = (point) poolalloc( &points ); +stringptr = readline( inputline, infile, infilename ); +if ( i == 0 ) { +firstnode = (int) strtol( stringptr, &stringptr, 0 ); +if (( firstnode == 0 ) || ( firstnode == 1 )) { +firstnumber = firstnode; +} +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Point %d has no x coordinate.\n", firstnumber + i ); +exit( 1 ); +} +x = (REAL) strtod( stringptr, &stringptr ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Point %d has no y coordinate.\n", firstnumber + i ); +exit( 1 ); +} +y = (REAL) strtod( stringptr, &stringptr ); +pointloop[0] = x; +pointloop[1] = y; +/* Read the point attributes. */ +for ( j = 2; j < 2 + nextras; j++ ) { +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +pointloop[j] = 0.0; +} +else { +pointloop[j] = (REAL) strtod( stringptr, &stringptr ); +} +} +if ( nodemarkers ) { +/* Read a point marker. */ +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +setpointmark( pointloop, 0 ); +} +else { +currentmarker = (int) strtol( stringptr, &stringptr, 0 ); +setpointmark( pointloop, currentmarker ); +} +} +else { +/* If no markers are specified in the file, they default to zero. */ +setpointmark( pointloop, 0 ); +} +/* Determine the smallest and largest x and y coordinates. */ +if ( i == 0 ) { +xmin = xmax = x; +ymin = ymax = y; +} +else { +xmin = ( x < xmin ) ? x : xmin; +xmax = ( x > xmax ) ? x : xmax; +ymin = ( y < ymin ) ? y : ymin; +ymax = ( y > ymax ) ? y : ymax; +} +} +if ( readnodefile ) { +fclose( infile ); +} -void readnodes( nodefilename, polyfilename, polyfile ) -char *nodefilename; -char *polyfilename; -FILE **polyfile; -{ - FILE *infile; - point pointloop; - char inputline[INPUTLINESIZE]; - char *stringptr; - char *infilename; - REAL x, y; - int firstnode; - int nodemarkers; - int currentmarker; - int i, j; - - if ( poly ) { - /* Read the points from a .poly file. */ - if ( !quiet ) { - printf( "Opening %s.\n", polyfilename ); - } - *polyfile = fopen( polyfilename, "r" ); - if ( *polyfile == (FILE *) NULL ) { - printf( " Error: Cannot access file %s.\n", polyfilename ); - exit( 1 ); - } - /* Read number of points, number of dimensions, number of point */ - /* attributes, and number of boundary markers. */ - stringptr = readline( inputline, *polyfile, polyfilename ); - inpoints = (int) strtol( stringptr, &stringptr, 0 ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - mesh_dim = 2; - } - else { - mesh_dim = (int) strtol( stringptr, &stringptr, 0 ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - nextras = 0; - } - else { - nextras = (int) strtol( stringptr, &stringptr, 0 ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - nodemarkers = 0; - } - else { - nodemarkers = (int) strtol( stringptr, &stringptr, 0 ); - } - if ( inpoints > 0 ) { - infile = *polyfile; - infilename = polyfilename; - readnodefile = 0; - } - else { - /* If the .poly file claims there are zero points, that means that */ - /* the points should be read from a separate .node file. */ - readnodefile = 1; - infilename = innodefilename; - } - } - else { - readnodefile = 1; - infilename = innodefilename; - *polyfile = (FILE *) NULL; - } - - if ( readnodefile ) { - /* Read the points from a .node file. */ - if ( !quiet ) { - printf( "Opening %s.\n", innodefilename ); - } - infile = fopen( innodefilename, "r" ); - if ( infile == (FILE *) NULL ) { - printf( " Error: Cannot access file %s.\n", innodefilename ); - exit( 1 ); - } - /* Read number of points, number of dimensions, number of point */ - /* attributes, and number of boundary markers. */ - stringptr = readline( inputline, infile, innodefilename ); - inpoints = (int) strtol( stringptr, &stringptr, 0 ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - mesh_dim = 2; - } - else { - mesh_dim = (int) strtol( stringptr, &stringptr, 0 ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - nextras = 0; - } - else { - nextras = (int) strtol( stringptr, &stringptr, 0 ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - nodemarkers = 0; - } - else { - nodemarkers = (int) strtol( stringptr, &stringptr, 0 ); - } - } - - if ( inpoints < 3 ) { - printf( "Error: Input must have at least three input points.\n" ); - exit( 1 ); - } - if ( mesh_dim != 2 ) { - printf( "Error: Triangle only works with two-dimensional meshes.\n" ); - exit( 1 ); - } - - initializepointpool(); - - /* Read the points. */ - for ( i = 0; i < inpoints; i++ ) { - pointloop = (point) poolalloc( &points ); - stringptr = readline( inputline, infile, infilename ); - if ( i == 0 ) { - firstnode = (int) strtol( stringptr, &stringptr, 0 ); - if ( ( firstnode == 0 ) || ( firstnode == 1 ) ) { - firstnumber = firstnode; - } - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Point %d has no x coordinate.\n", firstnumber + i ); - exit( 1 ); - } - x = (REAL) strtod( stringptr, &stringptr ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Point %d has no y coordinate.\n", firstnumber + i ); - exit( 1 ); - } - y = (REAL) strtod( stringptr, &stringptr ); - pointloop[0] = x; - pointloop[1] = y; - /* Read the point attributes. */ - for ( j = 2; j < 2 + nextras; j++ ) { - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - pointloop[j] = 0.0; - } - else { - pointloop[j] = (REAL) strtod( stringptr, &stringptr ); - } - } - if ( nodemarkers ) { - /* Read a point marker. */ - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - setpointmark( pointloop, 0 ); - } - else { - currentmarker = (int) strtol( stringptr, &stringptr, 0 ); - setpointmark( pointloop, currentmarker ); - } - } - else { - /* If no markers are specified in the file, they default to zero. */ - setpointmark( pointloop, 0 ); - } - /* Determine the smallest and largest x and y coordinates. */ - if ( i == 0 ) { - xmin = xmax = x; - ymin = ymax = y; - } - else { - xmin = ( x < xmin ) ? x : xmin; - xmax = ( x > xmax ) ? x : xmax; - ymin = ( y < ymin ) ? y : ymin; - ymax = ( y > ymax ) ? y : ymax; - } - } - if ( readnodefile ) { - fclose( infile ); - } - - /* Nonexistent x value used as a flag to mark circle events in sweepline */ - /* Delaunay algorithm. */ - xminextreme = 10 * xmin - 9 * xmax; +/* Nonexistent x value used as a flag to mark circle events in sweepline */ +/* Delaunay algorithm. */ +xminextreme = 10 * xmin - 9 * xmax; } #endif /* not TRILIBRARY */ @@ -11589,71 +11810,72 @@ FILE **polyfile; /* */ /*****************************************************************************/ -#ifdef TRILIBRARY +#ifdef +TRILIBRARY void transfernodes( pointlist, pointattriblist, pointmarkerlist, numberofpoints, - numberofpointattribs ) +numberofpointattribs ) REAL * pointlist; REAL *pointattriblist; int *pointmarkerlist; int numberofpoints; int numberofpointattribs; { - point pointloop; - REAL x, y; - int i, j; - int coordindex; - int attribindex; - - inpoints = numberofpoints; - mesh_dim = 2; - nextras = numberofpointattribs; - readnodefile = 0; - if ( inpoints < 3 ) { - printf( "Error: Input must have at least three input points.\n" ); - exit( 1 ); - } - - initializepointpool(); - - /* Read the points. */ - coordindex = 0; - attribindex = 0; - for ( i = 0; i < inpoints; i++ ) { - pointloop = (point) poolalloc( &points ); - /* Read the point coordinates. */ - x = pointloop[0] = pointlist[coordindex++]; - y = pointloop[1] = pointlist[coordindex++]; - /* Read the point attributes. */ - for ( j = 0; j < numberofpointattribs; j++ ) { - pointloop[2 + j] = pointattriblist[attribindex++]; - } - if ( pointmarkerlist != (int *) NULL ) { - /* Read a point marker. */ - setpointmark( pointloop, pointmarkerlist[i] ); - } - else { - /* If no markers are specified, they default to zero. */ - setpointmark( pointloop, 0 ); - } - x = pointloop[0]; - y = pointloop[1]; - /* Determine the smallest and largest x and y coordinates. */ - if ( i == 0 ) { - xmin = xmax = x; - ymin = ymax = y; - } - else { - xmin = ( x < xmin ) ? x : xmin; - xmax = ( x > xmax ) ? x : xmax; - ymin = ( y < ymin ) ? y : ymin; - ymax = ( y > ymax ) ? y : ymax; - } - } - - /* Nonexistent x value used as a flag to mark circle events in sweepline */ - /* Delaunay algorithm. */ - xminextreme = 10 * xmin - 9 * xmax; +point pointloop; +REAL x, y; +int i, j; +int coordindex; +int attribindex; + +inpoints = numberofpoints; +mesh_dim = 2; +nextras = numberofpointattribs; +readnodefile = 0; +if ( inpoints < 3 ) { +printf( "Error: Input must have at least three input points.\n" ); +exit( 1 ); +} + +initializepointpool(); + +/* Read the points. */ +coordindex = 0; +attribindex = 0; +for ( i = 0; i < inpoints; i++ ) { +pointloop = (point) poolalloc( &points ); +/* Read the point coordinates. */ +x = pointloop[0] = pointlist[coordindex++]; +y = pointloop[1] = pointlist[coordindex++]; +/* Read the point attributes. */ +for ( j = 0; j < numberofpointattribs; j++ ) { +pointloop[2 + j] = pointattriblist[attribindex++]; +} +if ( pointmarkerlist != (int *) NULL ) { +/* Read a point marker. */ +setpointmark( pointloop, pointmarkerlist[i] ); +} +else { +/* If no markers are specified, they default to zero. */ +setpointmark( pointloop, 0 ); +} +x = pointloop[0]; +y = pointloop[1]; +/* Determine the smallest and largest x and y coordinates. */ +if ( i == 0 ) { +xmin = xmax = x; +ymin = ymax = y; +} +else { +xmin = ( x < xmin ) ? x : xmin; +xmax = ( x > xmax ) ? x : xmax; +ymin = ( y < ymin ) ? y : ymin; +ymax = ( y > ymax ) ? y : ymax; +} +} + +/* Nonexistent x value used as a flag to mark circle events in sweepline */ +/* Delaunay algorithm. */ +xminextreme = 10 * xmin - 9 * xmax; } #endif /* TRILIBRARY */ @@ -11665,7 +11887,8 @@ int numberofpointattribs; /* */ /*****************************************************************************/ -#ifndef TRILIBRARY +#ifndef +TRILIBRARY void readholes( polyfile, polyfilename, hlist, holes, rlist, regions ) FILE * polyfile; @@ -11675,111 +11898,112 @@ int *holes; REAL **rlist; int *regions; { - REAL *holelist; - REAL *regionlist; - char inputline[INPUTLINESIZE]; - char *stringptr; - int index; - int i; - - /* Read the holes. */ - stringptr = readline( inputline, polyfile, polyfilename ); - *holes = (int) strtol( stringptr, &stringptr, 0 ); - if ( *holes > 0 ) { - holelist = (REAL *) malloc( 2 * *holes * sizeof( REAL ) ); - *hlist = holelist; - if ( holelist == (REAL *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - for ( i = 0; i < 2 * *holes; i += 2 ) { - stringptr = readline( inputline, polyfile, polyfilename ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Hole %d has no x coordinate.\n", - firstnumber + ( i >> 1 ) ); - exit( 1 ); - } - else { - holelist[i] = (REAL) strtod( stringptr, &stringptr ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Hole %d has no y coordinate.\n", - firstnumber + ( i >> 1 ) ); - exit( 1 ); - } - else { - holelist[i + 1] = (REAL) strtod( stringptr, &stringptr ); - } - } - } - else { - *hlist = (REAL *) NULL; - } - -#ifndef CDT_ONLY - if ( ( regionattrib || vararea ) && !refine ) { - /* Read the area constraints. */ - stringptr = readline( inputline, polyfile, polyfilename ); - *regions = (int) strtol( stringptr, &stringptr, 0 ); - if ( *regions > 0 ) { - regionlist = (REAL *) malloc( 4 * *regions * sizeof( REAL ) ); - *rlist = regionlist; - if ( regionlist == (REAL *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - index = 0; - for ( i = 0; i < *regions; i++ ) { - stringptr = readline( inputline, polyfile, polyfilename ); - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Region %d has no x coordinate.\n", - firstnumber + i ); - exit( 1 ); - } - else { - regionlist[index++] = (REAL) strtod( stringptr, &stringptr ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( "Error: Region %d has no y coordinate.\n", - firstnumber + i ); - exit( 1 ); - } - else { - regionlist[index++] = (REAL) strtod( stringptr, &stringptr ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - printf( - "Error: Region %d has no region attribute or area constraint.\n", - firstnumber + i ); - exit( 1 ); - } - else { - regionlist[index++] = (REAL) strtod( stringptr, &stringptr ); - } - stringptr = findfield( stringptr ); - if ( *stringptr == '\0' ) { - regionlist[index] = regionlist[index - 1]; - } - else { - regionlist[index] = (REAL) strtod( stringptr, &stringptr ); - } - index++; - } - } - } - else { - /* Set `*regions' to zero to avoid an accidental free() later. */ - *regions = 0; - *rlist = (REAL *) NULL; - } +REAL *holelist; +REAL *regionlist; +char inputline[INPUTLINESIZE]; +char *stringptr; +int index; +int i; + +/* Read the holes. */ +stringptr = readline( inputline, polyfile, polyfilename ); +*holes = (int) strtol( stringptr, &stringptr, 0 ); +if ( *holes > 0 ) { +holelist = (REAL *) malloc( 2 * *holes * sizeof( REAL )); +*hlist = holelist; +if ( holelist == (REAL *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +for ( i = 0; i < 2 * *holes; i += 2 ) { +stringptr = readline( inputline, polyfile, polyfilename ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Hole %d has no x coordinate.\n", +firstnumber + ( i >> 1 )); +exit( 1 ); +} +else { +holelist[i] = (REAL) strtod( stringptr, &stringptr ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Hole %d has no y coordinate.\n", +firstnumber + ( i >> 1 )); +exit( 1 ); +} +else { +holelist[i + 1] = (REAL) strtod( stringptr, &stringptr ); +} +} +} +else { +*hlist = (REAL *) NULL; +} + +#ifndef +CDT_ONLY +if (( regionattrib || vararea ) && !refine ) { +/* Read the area constraints. */ +stringptr = readline( inputline, polyfile, polyfilename ); +*regions = (int) strtol( stringptr, &stringptr, 0 ); +if ( *regions > 0 ) { +regionlist = (REAL *) malloc( 4 * *regions * sizeof( REAL )); +*rlist = regionlist; +if ( regionlist == (REAL *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +index = 0; +for ( i = 0; i < *regions; i++ ) { +stringptr = readline( inputline, polyfile, polyfilename ); +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Region %d has no x coordinate.\n", +firstnumber + i ); +exit( 1 ); +} +else { +regionlist[index++] = (REAL) strtod( stringptr, &stringptr ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( "Error: Region %d has no y coordinate.\n", +firstnumber + i ); +exit( 1 ); +} +else { +regionlist[index++] = (REAL) strtod( stringptr, &stringptr ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +printf( +"Error: Region %d has no region attribute or area constraint.\n", +firstnumber + i ); +exit( 1 ); +} +else { +regionlist[index++] = (REAL) strtod( stringptr, &stringptr ); +} +stringptr = findfield( stringptr ); +if ( *stringptr == '\0' ) { +regionlist[index] = regionlist[index - 1]; +} +else { +regionlist[index] = (REAL) strtod( stringptr, &stringptr ); +} +index++; +} +} +} +else { +/* Set `*regions' to zero to avoid an accidental free() later. */ +*regions = 0; +*rlist = (REAL *) NULL; +} #endif /* not CDT_ONLY */ - fclose( polyfile ); +fclose( polyfile ); } #endif /* not TRILIBRARY */ @@ -11791,22 +12015,23 @@ int *regions; /* */ /*****************************************************************************/ -#ifndef TRILIBRARY +#ifndef +TRILIBRARY void finishfile( outfile, argc, argv ) FILE * outfile; int argc; char **argv; { - int i; +int i; - fprintf( outfile, "# Generated by" ); - for ( i = 0; i < argc; i++ ) { - fprintf( outfile, " " ); - fputs( argv[i], outfile ); - } - fprintf( outfile, "\n" ); - fclose( outfile ); +fprintf( outfile, "# Generated by" ); +for ( i = 0; i < argc; i++ ) { +fprintf( outfile, " " ); +fputs( argv[i], outfile ); +} +fprintf( outfile, "\n" ); +fclose( outfile ); } #endif /* not TRILIBRARY */ @@ -11820,7 +12045,8 @@ char **argv; /* */ /*****************************************************************************/ -#ifdef TRILIBRARY +#ifdef +TRILIBRARY void writenodes( pointlist, pointattriblist, pointmarkerlist ) REAL * *pointlist; @@ -11837,107 +12063,111 @@ char **argv; #endif /* not TRILIBRARY */ { -#ifdef TRILIBRARY - REAL *plist; - REAL *palist; - int *pmlist; - int coordindex; - int attribindex; +#ifdef +TRILIBRARY +REAL *plist; +REAL *palist; +int *pmlist; +int coordindex; +int attribindex; #else /* not TRILIBRARY */ - FILE *outfile; +FILE *outfile; #endif /* not TRILIBRARY */ - point pointloop; - int pointnumber; - int i; - -#ifdef TRILIBRARY - if ( !quiet ) { - printf( "Writing points.\n" ); - } - /* Allocate memory for output points if necessary. */ - if ( *pointlist == (REAL *) NULL ) { - *pointlist = (REAL *) malloc( points.items * 2 * sizeof( REAL ) ); - if ( *pointlist == (REAL *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - /* Allocate memory for output point attributes if necessary. */ - if ( ( nextras > 0 ) && ( *pointattriblist == (REAL *) NULL ) ) { - *pointattriblist = (REAL *) malloc( points.items * nextras * sizeof( REAL ) ); - if ( *pointattriblist == (REAL *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - /* Allocate memory for output point markers if necessary. */ - if ( !nobound && ( *pointmarkerlist == (int *) NULL ) ) { - *pointmarkerlist = (int *) malloc( points.items * sizeof( int ) ); - if ( *pointmarkerlist == (int *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - plist = *pointlist; - palist = *pointattriblist; - pmlist = *pointmarkerlist; - coordindex = 0; - attribindex = 0; +point pointloop; +int pointnumber; +int i; + +#ifdef +TRILIBRARY +if ( !quiet ) { +printf( "Writing points.\n" ); +} +/* Allocate memory for output points if necessary. */ +if ( *pointlist == (REAL *) NULL ) { +*pointlist = (REAL *) malloc( points.items * 2 * sizeof( REAL )); +if ( *pointlist == (REAL *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +/* Allocate memory for output point attributes if necessary. */ +if (( nextras > 0 ) && ( *pointattriblist == (REAL *) NULL )) { +*pointattriblist = (REAL *) malloc( points.items * nextras * sizeof( REAL )); +if ( *pointattriblist == (REAL *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +/* Allocate memory for output point markers if necessary. */ +if ( !nobound && ( *pointmarkerlist == (int *) NULL )) { +*pointmarkerlist = (int *) malloc( points.items * sizeof( int )); +if ( *pointmarkerlist == (int *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +plist = *pointlist; +palist = *pointattriblist; +pmlist = *pointmarkerlist; +coordindex = 0; +attribindex = 0; #else /* not TRILIBRARY */ - if ( !quiet ) { - printf( "Writing %s.\n", nodefilename ); - } - outfile = fopen( nodefilename, "w" ); - if ( outfile == (FILE *) NULL ) { - printf( " Error: Cannot create file %s.\n", nodefilename ); - exit( 1 ); - } - /* Number of points, number of dimensions, number of point attributes, */ - /* and number of boundary markers (zero or one). */ - fprintf( outfile, "%ld %d %d %d\n", points.items, mesh_dim, nextras, - 1 - nobound ); +if ( !quiet ) { +printf( "Writing %s.\n", nodefilename ); +} +outfile = fopen( nodefilename, "w" ); +if ( outfile == (FILE *) NULL ) { +printf( " Error: Cannot create file %s.\n", nodefilename ); +exit( 1 ); +} +/* Number of points, number of dimensions, number of point attributes, */ +/* and number of boundary markers (zero or one). */ +fprintf( outfile, "%ld %d %d %d\n", points.items, mesh_dim, nextras, +1 - nobound ); #endif /* not TRILIBRARY */ - traversalinit( &points ); - pointloop = pointtraverse(); - pointnumber = firstnumber; - while ( pointloop != (point) NULL ) { -#ifdef TRILIBRARY - /* X and y coordinates. */ - plist[coordindex++] = pointloop[0]; - plist[coordindex++] = pointloop[1]; - /* Point attributes. */ - for ( i = 0; i < nextras; i++ ) { - palist[attribindex++] = pointloop[2 + i]; - } - if ( !nobound ) { - /* Copy the boundary marker. */ - pmlist[pointnumber - firstnumber] = pointmark( pointloop ); - } +traversalinit( &points ); +pointloop = pointtraverse(); +pointnumber = firstnumber; +while ( pointloop != (point) NULL ) { +#ifdef +TRILIBRARY +/* X and y coordinates. */ +plist[coordindex++] = pointloop[0]; +plist[coordindex++] = pointloop[1]; +/* Point attributes. */ +for ( i = 0; i < nextras; i++ ) { +palist[attribindex++] = pointloop[2 + i]; +} +if ( !nobound ) { +/* Copy the boundary marker. */ +pmlist[pointnumber - firstnumber] = pointmark( pointloop ); +} #else /* not TRILIBRARY */ - /* Point number, x and y coordinates. */ - fprintf( outfile, "%4d %.17g %.17g", pointnumber, pointloop[0], - pointloop[1] ); - for ( i = 0; i < nextras; i++ ) { - /* Write an attribute. */ - fprintf( outfile, " %.17g", pointloop[i + 2] ); - } - if ( nobound ) { - fprintf( outfile, "\n" ); - } - else { - /* Write the boundary marker. */ - fprintf( outfile, " %d\n", pointmark( pointloop ) ); - } +/* Point number, x and y coordinates. */ +fprintf( outfile, "%4d %.17g %.17g", pointnumber, pointloop[0], +pointloop[1] ); +for ( i = 0; i < nextras; i++ ) { +/* Write an attribute. */ +fprintf( outfile, " %.17g", pointloop[i + 2] ); +} +if ( nobound ) { +fprintf( outfile, "\n" ); +} +else { +/* Write the boundary marker. */ +fprintf( outfile, " %d\n", pointmark( pointloop )); +} #endif /* not TRILIBRARY */ - setpointmark( pointloop, pointnumber ); - pointloop = pointtraverse(); - pointnumber++; - } +setpointmark( pointloop, pointnumber ); +pointloop = pointtraverse(); +pointnumber++; +} -#ifndef TRILIBRARY - finishfile( outfile, argc, argv ); +#ifndef +TRILIBRARY +finishfile( outfile, argc, argv ); #endif /* not TRILIBRARY */ } @@ -11952,17 +12182,17 @@ char **argv; /*****************************************************************************/ void numbernodes(){ - point pointloop; - int pointnumber; - - traversalinit( &points ); - pointloop = pointtraverse(); - pointnumber = firstnumber; - while ( pointloop != (point) NULL ) { - setpointmark( pointloop, pointnumber ); - pointloop = pointtraverse(); - pointnumber++; - } +point pointloop; +int pointnumber; + +traversalinit( &points ); +pointloop = pointtraverse(); +pointnumber = firstnumber; +while ( pointloop != (point) NULL ) { +setpointmark( pointloop, pointnumber ); +pointloop = pointtraverse(); +pointnumber++; +} } /*****************************************************************************/ @@ -11971,7 +12201,8 @@ void numbernodes(){ /* */ /*****************************************************************************/ -#ifdef TRILIBRARY +#ifdef +TRILIBRARY void writeelements( trianglelist, triangleattriblist ) int **trianglelist; @@ -11987,115 +12218,121 @@ char **argv; #endif /* not TRILIBRARY */ { -#ifdef TRILIBRARY - int *tlist; - REAL *talist; - int pointindex; - int attribindex; +#ifdef +TRILIBRARY +int *tlist; +REAL *talist; +int pointindex; +int attribindex; #else /* not TRILIBRARY */ - FILE *outfile; +FILE *outfile; #endif /* not TRILIBRARY */ - struct triedge triangleloop; - point p1, p2, p3; - point mid1, mid2, mid3; - int elementnumber; - int i; - -#ifdef TRILIBRARY - if ( !quiet ) { - printf( "Writing triangles.\n" ); - } - /* Allocate memory for output triangles if necessary. */ - if ( *trianglelist == (int *) NULL ) { - *trianglelist = (int *) malloc( triangles.items * - ( ( order + 1 ) * ( order + 2 ) / 2 ) * sizeof( int ) ); - if ( *trianglelist == (int *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - /* Allocate memory for output triangle attributes if necessary. */ - if ( ( eextras > 0 ) && ( *triangleattriblist == (REAL *) NULL ) ) { - *triangleattriblist = (REAL *) malloc( triangles.items * eextras * - sizeof( REAL ) ); - if ( *triangleattriblist == (REAL *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - tlist = *trianglelist; - talist = *triangleattriblist; - pointindex = 0; - attribindex = 0; +struct triedge triangleloop; +point p1, p2, p3; +point mid1, mid2, mid3; +int elementnumber; +int i; + +#ifdef +TRILIBRARY +if ( !quiet ) { +printf( "Writing triangles.\n" ); +} +/* Allocate memory for output triangles if necessary. */ +if ( *trianglelist == (int *) NULL ) { +*trianglelist = (int *) malloc( triangles.items * +(( order + 1 ) * ( order + 2 ) / 2 ) * sizeof( int )); +if ( *trianglelist == (int *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +/* Allocate memory for output triangle attributes if necessary. */ +if (( eextras > 0 ) && ( *triangleattriblist == (REAL *) NULL )) { +*triangleattriblist = (REAL *) malloc( triangles.items * eextras * +sizeof( REAL )); +if ( *triangleattriblist == (REAL *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +tlist = *trianglelist; +talist = *triangleattriblist; +pointindex = 0; +attribindex = 0; #else /* not TRILIBRARY */ - if ( !quiet ) { - printf( "Writing %s.\n", elefilename ); - } - outfile = fopen( elefilename, "w" ); - if ( outfile == (FILE *) NULL ) { - printf( " Error: Cannot create file %s.\n", elefilename ); - exit( 1 ); - } - /* Number of triangles, points per triangle, attributes per triangle. */ - fprintf( outfile, "%ld %d %d\n", triangles.items, - ( order + 1 ) * ( order + 2 ) / 2, eextras ); +if ( !quiet ) { +printf( "Writing %s.\n", elefilename ); +} +outfile = fopen( elefilename, "w" ); +if ( outfile == (FILE *) NULL ) { +printf( " Error: Cannot create file %s.\n", elefilename ); +exit( 1 ); +} +/* Number of triangles, points per triangle, attributes per triangle. */ +fprintf( outfile, "%ld %d %d\n", triangles.items, +( order + 1 ) * ( order + 2 ) / 2, eextras ); #endif /* not TRILIBRARY */ - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - triangleloop.orient = 0; - elementnumber = firstnumber; - while ( triangleloop.tri != (triangle *) NULL ) { - org( triangleloop, p1 ); - dest( triangleloop, p2 ); - apex( triangleloop, p3 ); - if ( order == 1 ) { -#ifdef TRILIBRARY - tlist[pointindex++] = pointmark( p1 ); - tlist[pointindex++] = pointmark( p2 ); - tlist[pointindex++] = pointmark( p3 ); +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +triangleloop.orient = 0; +elementnumber = firstnumber; +while ( triangleloop.tri != (triangle *) NULL ) { +org( triangleloop, p1 ); +dest( triangleloop, p2 ); +apex( triangleloop, p3 ); +if ( order == 1 ) { +#ifdef +TRILIBRARY +tlist[pointindex++] = pointmark( p1 ); +tlist[pointindex++] = pointmark( p2 ); +tlist[pointindex++] = pointmark( p3 ); #else /* not TRILIBRARY */ - /* Triangle number, indices for three points. */ - fprintf( outfile, "%4d %4d %4d %4d", elementnumber, - pointmark( p1 ), pointmark( p2 ), pointmark( p3 ) ); +/* Triangle number, indices for three points. */ +fprintf( outfile, "%4d %4d %4d %4d", elementnumber, +pointmark( p1 ), pointmark( p2 ), pointmark( p3 )); #endif /* not TRILIBRARY */ - } - else { - mid1 = (point) triangleloop.tri[highorderindex + 1]; - mid2 = (point) triangleloop.tri[highorderindex + 2]; - mid3 = (point) triangleloop.tri[highorderindex]; -#ifdef TRILIBRARY - tlist[pointindex++] = pointmark( p1 ); - tlist[pointindex++] = pointmark( p2 ); - tlist[pointindex++] = pointmark( p3 ); - tlist[pointindex++] = pointmark( mid1 ); - tlist[pointindex++] = pointmark( mid2 ); - tlist[pointindex++] = pointmark( mid3 ); +} +else { +mid1 = (point) triangleloop.tri[highorderindex + 1]; +mid2 = (point) triangleloop.tri[highorderindex + 2]; +mid3 = (point) triangleloop.tri[highorderindex]; +#ifdef +TRILIBRARY +tlist[pointindex++] = pointmark( p1 ); +tlist[pointindex++] = pointmark( p2 ); +tlist[pointindex++] = pointmark( p3 ); +tlist[pointindex++] = pointmark( mid1 ); +tlist[pointindex++] = pointmark( mid2 ); +tlist[pointindex++] = pointmark( mid3 ); #else /* not TRILIBRARY */ - /* Triangle number, indices for six points. */ - fprintf( outfile, "%4d %4d %4d %4d %4d %4d %4d", elementnumber, - pointmark( p1 ), pointmark( p2 ), pointmark( p3 ), pointmark( mid1 ), - pointmark( mid2 ), pointmark( mid3 ) ); +/* Triangle number, indices for six points. */ +fprintf( outfile, "%4d %4d %4d %4d %4d %4d %4d", elementnumber, +pointmark( p1 ), pointmark( p2 ), pointmark( p3 ), pointmark( mid1 ), +pointmark( mid2 ), pointmark( mid3 )); #endif /* not TRILIBRARY */ - } +} -#ifdef TRILIBRARY - for ( i = 0; i < eextras; i++ ) { - talist[attribindex++] = elemattribute( triangleloop, i ); - } +#ifdef +TRILIBRARY +for ( i = 0; i < eextras; i++ ) { +talist[attribindex++] = elemattribute( triangleloop, i ); +} #else /* not TRILIBRARY */ - for ( i = 0; i < eextras; i++ ) { - fprintf( outfile, " %.17g", elemattribute( triangleloop, i ) ); - } - fprintf( outfile, "\n" ); +for ( i = 0; i < eextras; i++ ) { +fprintf( outfile, " %.17g", elemattribute( triangleloop, i )); +} +fprintf( outfile, "\n" ); #endif /* not TRILIBRARY */ - triangleloop.tri = triangletraverse(); - elementnumber++; - } +triangleloop.tri = triangletraverse(); +elementnumber++; +} -#ifndef TRILIBRARY - finishfile( outfile, argc, argv ); +#ifndef +TRILIBRARY +finishfile( outfile, argc, argv ); #endif /* not TRILIBRARY */ } @@ -12105,7 +12342,8 @@ char **argv; /* */ /*****************************************************************************/ -#ifdef TRILIBRARY +#ifdef +TRILIBRARY void writepoly( segmentlist, segmentmarkerlist ) int **segmentlist; @@ -12125,111 +12363,116 @@ char **argv; #endif /* not TRILIBRARY */ { -#ifdef TRILIBRARY - int *slist; - int *smlist; - int index; +#ifdef +TRILIBRARY +int *slist; +int *smlist; +int index; #else /* not TRILIBRARY */ - FILE *outfile; - int i; +FILE *outfile; +int i; #endif /* not TRILIBRARY */ - struct edge shelleloop; - point endpoint1, endpoint2; - int shellenumber; - -#ifdef TRILIBRARY - if ( !quiet ) { - printf( "Writing segments.\n" ); - } - /* Allocate memory for output segments if necessary. */ - if ( *segmentlist == (int *) NULL ) { - *segmentlist = (int *) malloc( shelles.items * 2 * sizeof( int ) ); - if ( *segmentlist == (int *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - /* Allocate memory for output segment markers if necessary. */ - if ( !nobound && ( *segmentmarkerlist == (int *) NULL ) ) { - *segmentmarkerlist = (int *) malloc( shelles.items * sizeof( int ) ); - if ( *segmentmarkerlist == (int *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - slist = *segmentlist; - smlist = *segmentmarkerlist; - index = 0; +struct edge shelleloop; +point endpoint1, endpoint2; +int shellenumber; + +#ifdef +TRILIBRARY +if ( !quiet ) { +printf( "Writing segments.\n" ); +} +/* Allocate memory for output segments if necessary. */ +if ( *segmentlist == (int *) NULL ) { +*segmentlist = (int *) malloc( shelles.items * 2 * sizeof( int )); +if ( *segmentlist == (int *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +/* Allocate memory for output segment markers if necessary. */ +if ( !nobound && ( *segmentmarkerlist == (int *) NULL )) { +*segmentmarkerlist = (int *) malloc( shelles.items * sizeof( int )); +if ( *segmentmarkerlist == (int *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +slist = *segmentlist; +smlist = *segmentmarkerlist; +index = 0; #else /* not TRILIBRARY */ - if ( !quiet ) { - printf( "Writing %s.\n", polyfilename ); - } - outfile = fopen( polyfilename, "w" ); - if ( outfile == (FILE *) NULL ) { - printf( " Error: Cannot create file %s.\n", polyfilename ); - exit( 1 ); - } - /* The zero indicates that the points are in a separate .node file. */ - /* Followed by number of dimensions, number of point attributes, */ - /* and number of boundary markers (zero or one). */ - fprintf( outfile, "%d %d %d %d\n", 0, mesh_dim, nextras, 1 - nobound ); - /* Number of segments, number of boundary markers (zero or one). */ - fprintf( outfile, "%ld %d\n", shelles.items, 1 - nobound ); +if ( !quiet ) { +printf( "Writing %s.\n", polyfilename ); +} +outfile = fopen( polyfilename, "w" ); +if ( outfile == (FILE *) NULL ) { +printf( " Error: Cannot create file %s.\n", polyfilename ); +exit( 1 ); +} +/* The zero indicates that the points are in a separate .node file. */ +/* Followed by number of dimensions, number of point attributes, */ +/* and number of boundary markers (zero or one). */ +fprintf( outfile, "%d %d %d %d\n", 0, mesh_dim, nextras, 1 - nobound ); +/* Number of segments, number of boundary markers (zero or one). */ +fprintf( outfile, "%ld %d\n", shelles.items, 1 - nobound ); #endif /* not TRILIBRARY */ - traversalinit( &shelles ); - shelleloop.sh = shelletraverse(); - shelleloop.shorient = 0; - shellenumber = firstnumber; - while ( shelleloop.sh != (shelle *) NULL ) { - sorg( shelleloop, endpoint1 ); - sdest( shelleloop, endpoint2 ); -#ifdef TRILIBRARY - /* Copy indices of the segment's two endpoints. */ - slist[index++] = pointmark( endpoint1 ); - slist[index++] = pointmark( endpoint2 ); - if ( !nobound ) { - /* Copy the boundary marker. */ - smlist[shellenumber - firstnumber] = mark( shelleloop ); - } +traversalinit( &shelles ); +shelleloop.sh = shelletraverse(); +shelleloop.shorient = 0; +shellenumber = firstnumber; +while ( shelleloop.sh != (shelle *) NULL ) { +sorg( shelleloop, endpoint1 ); +sdest( shelleloop, endpoint2 ); +#ifdef +TRILIBRARY +/* Copy indices of the segment's two endpoints. */ +slist[index++] = pointmark( endpoint1 ); +slist[index++] = pointmark( endpoint2 ); +if ( !nobound ) { +/* Copy the boundary marker. */ +smlist[shellenumber - firstnumber] = mark( shelleloop ); +} #else /* not TRILIBRARY */ - /* Segment number, indices of its two endpoints, and possibly a marker. */ - if ( nobound ) { - fprintf( outfile, "%4d %4d %4d\n", shellenumber, - pointmark( endpoint1 ), pointmark( endpoint2 ) ); - } - else { - fprintf( outfile, "%4d %4d %4d %4d\n", shellenumber, - pointmark( endpoint1 ), pointmark( endpoint2 ), mark( shelleloop ) ); - } +/* Segment number, indices of its two endpoints, and possibly a marker. */ +if ( nobound ) { +fprintf( outfile, "%4d %4d %4d\n", shellenumber, +pointmark( endpoint1 ), pointmark( endpoint2 )); +} +else { +fprintf( outfile, "%4d %4d %4d %4d\n", shellenumber, +pointmark( endpoint1 ), pointmark( endpoint2 ), mark( shelleloop )); +} #endif /* not TRILIBRARY */ - shelleloop.sh = shelletraverse(); - shellenumber++; - } - -#ifndef TRILIBRARY -#ifndef CDT_ONLY - fprintf( outfile, "%d\n", holes ); - if ( holes > 0 ) { - for ( i = 0; i < holes; i++ ) { - /* Hole number, x and y coordinates. */ - fprintf( outfile, "%4d %.17g %.17g\n", firstnumber + i, - holelist[2 * i], holelist[2 * i + 1] ); - } - } - if ( regions > 0 ) { - fprintf( outfile, "%d\n", regions ); - for ( i = 0; i < regions; i++ ) { - /* Region number, x and y coordinates, attribute, maximum area. */ - fprintf( outfile, "%4d %.17g %.17g %.17g %.17g\n", firstnumber + i, - regionlist[4 * i], regionlist[4 * i + 1], - regionlist[4 * i + 2], regionlist[4 * i + 3] ); - } - } +shelleloop.sh = shelletraverse(); +shellenumber++; +} + +#ifndef +TRILIBRARY +#ifndef +CDT_ONLY +fprintf( outfile, "%d\n", holes ); +if ( holes > 0 ) { +for ( i = 0; i < holes; i++ ) { +/* Hole number, x and y coordinates. */ +fprintf( outfile, "%4d %.17g %.17g\n", firstnumber + i, +holelist[2 * i], holelist[2 * i + 1] ); +} +} +if ( regions > 0 ) { +fprintf( outfile, "%d\n", regions ); +for ( i = 0; i < regions; i++ ) { +/* Region number, x and y coordinates, attribute, maximum area. */ +fprintf( outfile, "%4d %.17g %.17g %.17g %.17g\n", firstnumber + i, +regionlist[4 * i], regionlist[4 * i + 1], +regionlist[4 * i + 2], regionlist[4 * i + 3] ); +} +} #endif /* not CDT_ONLY */ - finishfile( outfile, argc, argv ); +finishfile( outfile, argc, argv ); #endif /* not TRILIBRARY */ } @@ -12239,7 +12482,8 @@ char **argv; /* */ /*****************************************************************************/ -#ifdef TRILIBRARY +#ifdef +TRILIBRARY void writeedges( edgelist, edgemarkerlist ) int **edgelist; @@ -12255,122 +12499,130 @@ char **argv; #endif /* not TRILIBRARY */ { -#ifdef TRILIBRARY - int *elist; - int *emlist; - int index; +#ifdef +TRILIBRARY +int *elist; +int *emlist; +int index; #else /* not TRILIBRARY */ - FILE *outfile; +FILE *outfile; #endif /* not TRILIBRARY */ - struct triedge triangleloop, trisym; - struct edge checkmark; - point p1, p2; - int edgenumber; - triangle ptr; /* Temporary variable used by sym(). */ - shelle sptr; /* Temporary variable used by tspivot(). */ - -#ifdef TRILIBRARY - if ( !quiet ) { - printf( "Writing edges.\n" ); - } - /* Allocate memory for edges if necessary. */ - if ( *edgelist == (int *) NULL ) { - *edgelist = (int *) malloc( edges * 2 * sizeof( int ) ); - if ( *edgelist == (int *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - /* Allocate memory for edge markers if necessary. */ - if ( !nobound && ( *edgemarkerlist == (int *) NULL ) ) { - *edgemarkerlist = (int *) malloc( edges * sizeof( int ) ); - if ( *edgemarkerlist == (int *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - elist = *edgelist; - emlist = *edgemarkerlist; - index = 0; +struct triedge triangleloop, trisym; +struct edge checkmark; +point p1, p2; +int edgenumber; +triangle ptr; /* Temporary variable used by sym(). */ +shelle sptr; /* Temporary variable used by tspivot(). */ + +#ifdef +TRILIBRARY +if ( !quiet ) { +printf( "Writing edges.\n" ); +} +/* Allocate memory for edges if necessary. */ +if ( *edgelist == (int *) NULL ) { +*edgelist = (int *) malloc( edges * 2 * sizeof( int )); +if ( *edgelist == (int *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +/* Allocate memory for edge markers if necessary. */ +if ( !nobound && ( *edgemarkerlist == (int *) NULL )) { +*edgemarkerlist = (int *) malloc( edges * sizeof( int )); +if ( *edgemarkerlist == (int *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +elist = *edgelist; +emlist = *edgemarkerlist; +index = 0; #else /* not TRILIBRARY */ - if ( !quiet ) { - printf( "Writing %s.\n", edgefilename ); - } - outfile = fopen( edgefilename, "w" ); - if ( outfile == (FILE *) NULL ) { - printf( " Error: Cannot create file %s.\n", edgefilename ); - exit( 1 ); - } - /* Number of edges, number of boundary markers (zero or one). */ - fprintf( outfile, "%ld %d\n", edges, 1 - nobound ); +if ( !quiet ) { +printf( "Writing %s.\n", edgefilename ); +} +outfile = fopen( edgefilename, "w" ); +if ( outfile == (FILE *) NULL ) { +printf( " Error: Cannot create file %s.\n", edgefilename ); +exit( 1 ); +} +/* Number of edges, number of boundary markers (zero or one). */ +fprintf( outfile, "%ld %d\n", edges, 1 - nobound ); #endif /* not TRILIBRARY */ - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - edgenumber = firstnumber; - /* To loop over the set of edges, loop over all triangles, and look at */ - /* the three edges of each triangle. If there isn't another triangle */ - /* adjacent to the edge, operate on the edge. If there is another */ - /* adjacent triangle, operate on the edge only if the current triangle */ - /* has a smaller pointer than its neighbor. This way, each edge is */ - /* considered only once. */ - while ( triangleloop.tri != (triangle *) NULL ) { - for ( triangleloop.orient = 0; triangleloop.orient < 3; - triangleloop.orient++ ) { - sym( triangleloop, trisym ); - if ( ( triangleloop.tri < trisym.tri ) || ( trisym.tri == dummytri ) ) { - org( triangleloop, p1 ); - dest( triangleloop, p2 ); -#ifdef TRILIBRARY - elist[index++] = pointmark( p1 ); - elist[index++] = pointmark( p2 ); +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +edgenumber = firstnumber; +/* To loop over the set of edges, loop over all triangles, and look at */ +/* the three edges of each triangle. If there isn't another triangle */ +/* adjacent to the edge, operate on the edge. If there is another */ +/* adjacent triangle, operate on the edge only if the current triangle */ +/* has a smaller pointer than its neighbor. This way, each edge is */ +/* considered only once. */ +while ( triangleloop.tri != (triangle *) NULL ) { +for ( triangleloop.orient = 0; triangleloop.orient < 3; +triangleloop.orient++ ) { +sym( triangleloop, trisym ); +if (( triangleloop.tri < trisym.tri ) || ( trisym.tri == dummytri )) { +org( triangleloop, p1 ); +dest( triangleloop, p2 ); +#ifdef +TRILIBRARY +elist[index++] = pointmark( p1 ); +elist[index++] = pointmark( p2 ); #endif /* TRILIBRARY */ - if ( nobound ) { -#ifndef TRILIBRARY - /* Edge number, indices of two endpoints. */ - fprintf( outfile, "%4d %d %d\n", edgenumber, - pointmark( p1 ), pointmark( p2 ) ); +if ( nobound ) { +#ifndef +TRILIBRARY +/* Edge number, indices of two endpoints. */ +fprintf( outfile, "%4d %d %d\n", edgenumber, +pointmark( p1 ), pointmark( p2 )); #endif /* not TRILIBRARY */ - } - else { - /* Edge number, indices of two endpoints, and a boundary marker. */ - /* If there's no shell edge, the boundary marker is zero. */ - if ( useshelles ) { - tspivot( triangleloop, checkmark ); - if ( checkmark.sh == dummysh ) { -#ifdef TRILIBRARY - emlist[edgenumber - firstnumber] = 0; +} +else { +/* Edge number, indices of two endpoints, and a boundary marker. */ +/* If there's no shell edge, the boundary marker is zero. */ +if ( useshelles ) { +tspivot( triangleloop, checkmark ); +if ( checkmark.sh == dummysh ) { +#ifdef +TRILIBRARY +emlist[edgenumber - firstnumber] = 0; #else /* not TRILIBRARY */ - fprintf( outfile, "%4d %d %d %d\n", edgenumber, - pointmark( p1 ), pointmark( p2 ), 0 ); +fprintf( outfile, "%4d %d %d %d\n", edgenumber, +pointmark( p1 ), pointmark( p2 ), 0 ); #endif /* not TRILIBRARY */ - } - else { -#ifdef TRILIBRARY - emlist[edgenumber - firstnumber] = mark( checkmark ); +} +else { +#ifdef +TRILIBRARY +emlist[edgenumber - firstnumber] = mark( checkmark ); #else /* not TRILIBRARY */ - fprintf( outfile, "%4d %d %d %d\n", edgenumber, - pointmark( p1 ), pointmark( p2 ), mark( checkmark ) ); +fprintf( outfile, "%4d %d %d %d\n", edgenumber, +pointmark( p1 ), pointmark( p2 ), mark( checkmark )); #endif /* not TRILIBRARY */ - } - } - else { -#ifdef TRILIBRARY - emlist[edgenumber - firstnumber] = trisym.tri == dummytri; +} +} +else { +#ifdef +TRILIBRARY +emlist[edgenumber - firstnumber] = trisym.tri == dummytri; #else /* not TRILIBRARY */ - fprintf( outfile, "%4d %d %d %d\n", edgenumber, - pointmark( p1 ), pointmark( p2 ), trisym.tri == dummytri ); +fprintf( outfile, "%4d %d %d %d\n", edgenumber, +pointmark( p1 ), pointmark( p2 ), trisym.tri == dummytri ); #endif /* not TRILIBRARY */ - } - } - edgenumber++; - } - } - triangleloop.tri = triangletraverse(); - } - -#ifndef TRILIBRARY - finishfile( outfile, argc, argv ); +} +} +edgenumber++; +} +} +triangleloop.tri = triangletraverse(); +} + +#ifndef +TRILIBRARY +finishfile( outfile, argc, argv ); #endif /* not TRILIBRARY */ } @@ -12390,10 +12642,11 @@ char **argv; /* */ /*****************************************************************************/ -#ifdef TRILIBRARY +#ifdef +TRILIBRARY void writevoronoi( vpointlist, vpointattriblist, vpointmarkerlist, vedgelist, - vedgemarkerlist, vnormlist ) +vedgemarkerlist, vnormlist ) REAL * *vpointlist; REAL **vpointattriblist; int **vpointmarkerlist; @@ -12412,199 +12665,208 @@ char **argv; #endif /* not TRILIBRARY */ { -#ifdef TRILIBRARY - REAL *plist; - REAL *palist; - int *elist; - REAL *normlist; - int coordindex; - int attribindex; +#ifdef +TRILIBRARY +REAL *plist; +REAL *palist; +int *elist; +REAL *normlist; +int coordindex; +int attribindex; #else /* not TRILIBRARY */ - FILE *outfile; +FILE *outfile; #endif /* not TRILIBRARY */ - struct triedge triangleloop, trisym; - point torg, tdest, tapex; - REAL circumcenter[2]; - REAL xi, eta; - int vnodenumber, vedgenumber; - int p1, p2; - int i; - triangle ptr; /* Temporary variable used by sym(). */ - -#ifdef TRILIBRARY - if ( !quiet ) { - printf( "Writing Voronoi vertices.\n" ); - } - /* Allocate memory for Voronoi vertices if necessary. */ - if ( *vpointlist == (REAL *) NULL ) { - *vpointlist = (REAL *) malloc( triangles.items * 2 * sizeof( REAL ) ); - if ( *vpointlist == (REAL *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - /* Allocate memory for Voronoi vertex attributes if necessary. */ - if ( *vpointattriblist == (REAL *) NULL ) { - *vpointattriblist = (REAL *) malloc( triangles.items * nextras * - sizeof( REAL ) ); - if ( *vpointattriblist == (REAL *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - *vpointmarkerlist = (int *) NULL; - plist = *vpointlist; - palist = *vpointattriblist; - coordindex = 0; - attribindex = 0; +struct triedge triangleloop, trisym; +point torg, tdest, tapex; +REAL circumcenter[2]; +REAL xi, eta; +int vnodenumber, vedgenumber; +int p1, p2; +int i; +triangle ptr; /* Temporary variable used by sym(). */ + +#ifdef +TRILIBRARY +if ( !quiet ) { +printf( "Writing Voronoi vertices.\n" ); +} +/* Allocate memory for Voronoi vertices if necessary. */ +if ( *vpointlist == (REAL *) NULL ) { +*vpointlist = (REAL *) malloc( triangles.items * 2 * sizeof( REAL )); +if ( *vpointlist == (REAL *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +/* Allocate memory for Voronoi vertex attributes if necessary. */ +if ( *vpointattriblist == (REAL *) NULL ) { +*vpointattriblist = (REAL *) malloc( triangles.items * nextras * +sizeof( REAL )); +if ( *vpointattriblist == (REAL *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +*vpointmarkerlist = (int *) NULL; +plist = *vpointlist; +palist = *vpointattriblist; +coordindex = 0; +attribindex = 0; #else /* not TRILIBRARY */ - if ( !quiet ) { - printf( "Writing %s.\n", vnodefilename ); - } - outfile = fopen( vnodefilename, "w" ); - if ( outfile == (FILE *) NULL ) { - printf( " Error: Cannot create file %s.\n", vnodefilename ); - exit( 1 ); - } - /* Number of triangles, two dimensions, number of point attributes, */ - /* zero markers. */ - fprintf( outfile, "%ld %d %d %d\n", triangles.items, 2, nextras, 0 ); +if ( !quiet ) { +printf( "Writing %s.\n", vnodefilename ); +} +outfile = fopen( vnodefilename, "w" ); +if ( outfile == (FILE *) NULL ) { +printf( " Error: Cannot create file %s.\n", vnodefilename ); +exit( 1 ); +} +/* Number of triangles, two dimensions, number of point attributes, */ +/* zero markers. */ +fprintf( outfile, "%ld %d %d %d\n", triangles.items, 2, nextras, 0 ); #endif /* not TRILIBRARY */ - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - triangleloop.orient = 0; - vnodenumber = firstnumber; - while ( triangleloop.tri != (triangle *) NULL ) { - org( triangleloop, torg ); - dest( triangleloop, tdest ); - apex( triangleloop, tapex ); - findcircumcenter( torg, tdest, tapex, circumcenter, &xi, &eta ); -#ifdef TRILIBRARY - /* X and y coordinates. */ - plist[coordindex++] = circumcenter[0]; - plist[coordindex++] = circumcenter[1]; - for ( i = 2; i < 2 + nextras; i++ ) { - /* Interpolate the point attributes at the circumcenter. */ - palist[attribindex++] = torg[i] + xi * ( tdest[i] - torg[i] ) - + eta * ( tapex[i] - torg[i] ); - } +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +triangleloop.orient = 0; +vnodenumber = firstnumber; +while ( triangleloop.tri != (triangle *) NULL ) { +org( triangleloop, torg ); +dest( triangleloop, tdest ); +apex( triangleloop, tapex ); +findcircumcenter( torg, tdest, tapex, circumcenter, &xi, &eta ); +#ifdef +TRILIBRARY +/* X and y coordinates. */ +plist[coordindex++] = circumcenter[0]; +plist[coordindex++] = circumcenter[1]; +for ( i = 2; i < 2 + nextras; i++ ) { +/* Interpolate the point attributes at the circumcenter. */ +palist[attribindex++] = torg[i] + xi * ( tdest[i] - torg[i] ) ++ eta * ( tapex[i] - torg[i] ); +} #else /* not TRILIBRARY */ - /* Voronoi vertex number, x and y coordinates. */ - fprintf( outfile, "%4d %.17g %.17g", vnodenumber, circumcenter[0], - circumcenter[1] ); - for ( i = 2; i < 2 + nextras; i++ ) { - /* Interpolate the point attributes at the circumcenter. */ - fprintf( outfile, " %.17g", torg[i] + xi * ( tdest[i] - torg[i] ) - + eta * ( tapex[i] - torg[i] ) ); - } - fprintf( outfile, "\n" ); +/* Voronoi vertex number, x and y coordinates. */ +fprintf( outfile, "%4d %.17g %.17g", vnodenumber, circumcenter[0], +circumcenter[1] ); +for ( i = 2; i < 2 + nextras; i++ ) { +/* Interpolate the point attributes at the circumcenter. */ +fprintf( outfile, " %.17g", torg[i] + xi * ( tdest[i] - torg[i] ) ++ eta * ( tapex[i] - torg[i] )); +} +fprintf( outfile, "\n" ); #endif /* not TRILIBRARY */ - *(int *) ( triangleloop.tri + 6 ) = vnodenumber; - triangleloop.tri = triangletraverse(); - vnodenumber++; - } +*(int *) ( triangleloop.tri + 6 ) = vnodenumber; +triangleloop.tri = triangletraverse(); +vnodenumber++; +} -#ifndef TRILIBRARY - finishfile( outfile, argc, argv ); +#ifndef +TRILIBRARY +finishfile( outfile, argc, argv ); #endif /* not TRILIBRARY */ -#ifdef TRILIBRARY - if ( !quiet ) { - printf( "Writing Voronoi edges.\n" ); - } - /* Allocate memory for output Voronoi edges if necessary. */ - if ( *vedgelist == (int *) NULL ) { - *vedgelist = (int *) malloc( edges * 2 * sizeof( int ) ); - if ( *vedgelist == (int *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - *vedgemarkerlist = (int *) NULL; - /* Allocate memory for output Voronoi norms if necessary. */ - if ( *vnormlist == (REAL *) NULL ) { - *vnormlist = (REAL *) malloc( edges * 2 * sizeof( REAL ) ); - if ( *vnormlist == (REAL *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - elist = *vedgelist; - normlist = *vnormlist; - coordindex = 0; +#ifdef +TRILIBRARY +if ( !quiet ) { +printf( "Writing Voronoi edges.\n" ); +} +/* Allocate memory for output Voronoi edges if necessary. */ +if ( *vedgelist == (int *) NULL ) { +*vedgelist = (int *) malloc( edges * 2 * sizeof( int )); +if ( *vedgelist == (int *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +*vedgemarkerlist = (int *) NULL; +/* Allocate memory for output Voronoi norms if necessary. */ +if ( *vnormlist == (REAL *) NULL ) { +*vnormlist = (REAL *) malloc( edges * 2 * sizeof( REAL )); +if ( *vnormlist == (REAL *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +elist = *vedgelist; +normlist = *vnormlist; +coordindex = 0; #else /* not TRILIBRARY */ - if ( !quiet ) { - printf( "Writing %s.\n", vedgefilename ); - } - outfile = fopen( vedgefilename, "w" ); - if ( outfile == (FILE *) NULL ) { - printf( " Error: Cannot create file %s.\n", vedgefilename ); - exit( 1 ); - } - /* Number of edges, zero boundary markers. */ - fprintf( outfile, "%ld %d\n", edges, 0 ); +if ( !quiet ) { +printf( "Writing %s.\n", vedgefilename ); +} +outfile = fopen( vedgefilename, "w" ); +if ( outfile == (FILE *) NULL ) { +printf( " Error: Cannot create file %s.\n", vedgefilename ); +exit( 1 ); +} +/* Number of edges, zero boundary markers. */ +fprintf( outfile, "%ld %d\n", edges, 0 ); #endif /* not TRILIBRARY */ - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - vedgenumber = firstnumber; - /* To loop over the set of edges, loop over all triangles, and look at */ - /* the three edges of each triangle. If there isn't another triangle */ - /* adjacent to the edge, operate on the edge. If there is another */ - /* adjacent triangle, operate on the edge only if the current triangle */ - /* has a smaller pointer than its neighbor. This way, each edge is */ - /* considered only once. */ - while ( triangleloop.tri != (triangle *) NULL ) { - for ( triangleloop.orient = 0; triangleloop.orient < 3; - triangleloop.orient++ ) { - sym( triangleloop, trisym ); - if ( ( triangleloop.tri < trisym.tri ) || ( trisym.tri == dummytri ) ) { - /* Find the number of this triangle (and Voronoi vertex). */ - p1 = *(int *) ( triangleloop.tri + 6 ); - if ( trisym.tri == dummytri ) { - org( triangleloop, torg ); - dest( triangleloop, tdest ); -#ifdef TRILIBRARY - /* Copy an infinite ray. Index of one endpoint, and -1. */ - elist[coordindex] = p1; - normlist[coordindex++] = tdest[1] - torg[1]; - elist[coordindex] = -1; - normlist[coordindex++] = torg[0] - tdest[0]; +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +vedgenumber = firstnumber; +/* To loop over the set of edges, loop over all triangles, and look at */ +/* the three edges of each triangle. If there isn't another triangle */ +/* adjacent to the edge, operate on the edge. If there is another */ +/* adjacent triangle, operate on the edge only if the current triangle */ +/* has a smaller pointer than its neighbor. This way, each edge is */ +/* considered only once. */ +while ( triangleloop.tri != (triangle *) NULL ) { +for ( triangleloop.orient = 0; triangleloop.orient < 3; +triangleloop.orient++ ) { +sym( triangleloop, trisym ); +if (( triangleloop.tri < trisym.tri ) || ( trisym.tri == dummytri )) { +/* Find the number of this triangle (and Voronoi vertex). */ +p1 = *(int *) ( triangleloop.tri + 6 ); +if ( trisym.tri == dummytri ) { +org( triangleloop, torg ); +dest( triangleloop, tdest ); +#ifdef +TRILIBRARY +/* Copy an infinite ray. Index of one endpoint, and -1. */ +elist[coordindex] = p1; +normlist[coordindex++] = tdest[1] - torg[1]; +elist[coordindex] = -1; +normlist[coordindex++] = torg[0] - tdest[0]; #else /* not TRILIBRARY */ - /* Write an infinite ray. Edge number, index of one endpoint, -1, */ - /* and x and y coordinates of a vector representing the */ - /* direction of the ray. */ - fprintf( outfile, "%4d %d %d %.17g %.17g\n", vedgenumber, - p1, -1, tdest[1] - torg[1], torg[0] - tdest[0] ); +/* Write an infinite ray. Edge number, index of one endpoint, -1, */ +/* and x and y coordinates of a vector representing the */ +/* direction of the ray. */ +fprintf( outfile, "%4d %d %d %.17g %.17g\n", vedgenumber, +p1, -1, tdest[1] - torg[1], torg[0] - tdest[0] ); #endif /* not TRILIBRARY */ - } - else { - /* Find the number of the adjacent triangle (and Voronoi vertex). */ - p2 = *(int *) ( trisym.tri + 6 ); - /* Finite edge. Write indices of two endpoints. */ -#ifdef TRILIBRARY - elist[coordindex] = p1; - normlist[coordindex++] = 0.0; - elist[coordindex] = p2; - normlist[coordindex++] = 0.0; +} +else { +/* Find the number of the adjacent triangle (and Voronoi vertex). */ +p2 = *(int *) ( trisym.tri + 6 ); +/* Finite edge. Write indices of two endpoints. */ +#ifdef +TRILIBRARY +elist[coordindex] = p1; +normlist[coordindex++] = 0.0; +elist[coordindex] = p2; +normlist[coordindex++] = 0.0; #else /* not TRILIBRARY */ - fprintf( outfile, "%4d %d %d\n", vedgenumber, p1, p2 ); +fprintf( outfile, "%4d %d %d\n", vedgenumber, p1, p2 ); #endif /* not TRILIBRARY */ - } - vedgenumber++; - } - } - triangleloop.tri = triangletraverse(); - } - -#ifndef TRILIBRARY - finishfile( outfile, argc, argv ); +} +vedgenumber++; +} +} +triangleloop.tri = triangletraverse(); +} + +#ifndef +TRILIBRARY +finishfile( outfile, argc, argv ); #endif /* not TRILIBRARY */ } -#ifdef TRILIBRARY +#ifdef +TRILIBRARY void writeneighbors( neighborlist ) int **neighborlist; @@ -12619,84 +12881,88 @@ char **argv; #endif /* not TRILIBRARY */ { -#ifdef TRILIBRARY - int *nlist; - int index; +#ifdef +TRILIBRARY +int *nlist; +int index; #else /* not TRILIBRARY */ - FILE *outfile; +FILE *outfile; #endif /* not TRILIBRARY */ - struct triedge triangleloop, trisym; - int elementnumber; - int neighbor1, neighbor2, neighbor3; - triangle ptr; /* Temporary variable used by sym(). */ - -#ifdef TRILIBRARY - if ( !quiet ) { - printf( "Writing neighbors.\n" ); - } - /* Allocate memory for neighbors if necessary. */ - if ( *neighborlist == (int *) NULL ) { - *neighborlist = (int *) malloc( triangles.items * 3 * sizeof( int ) ); - if ( *neighborlist == (int *) NULL ) { - printf( "Error: Out of memory.\n" ); - exit( 1 ); - } - } - nlist = *neighborlist; - index = 0; +struct triedge triangleloop, trisym; +int elementnumber; +int neighbor1, neighbor2, neighbor3; +triangle ptr; /* Temporary variable used by sym(). */ + +#ifdef +TRILIBRARY +if ( !quiet ) { +printf( "Writing neighbors.\n" ); +} +/* Allocate memory for neighbors if necessary. */ +if ( *neighborlist == (int *) NULL ) { +*neighborlist = (int *) malloc( triangles.items * 3 * sizeof( int )); +if ( *neighborlist == (int *) NULL ) { +printf( "Error: Out of memory.\n" ); +exit( 1 ); +} +} +nlist = *neighborlist; +index = 0; #else /* not TRILIBRARY */ - if ( !quiet ) { - printf( "Writing %s.\n", neighborfilename ); - } - outfile = fopen( neighborfilename, "w" ); - if ( outfile == (FILE *) NULL ) { - printf( " Error: Cannot create file %s.\n", neighborfilename ); - exit( 1 ); - } - /* Number of triangles, three edges per triangle. */ - fprintf( outfile, "%ld %d\n", triangles.items, 3 ); +if ( !quiet ) { +printf( "Writing %s.\n", neighborfilename ); +} +outfile = fopen( neighborfilename, "w" ); +if ( outfile == (FILE *) NULL ) { +printf( " Error: Cannot create file %s.\n", neighborfilename ); +exit( 1 ); +} +/* Number of triangles, three edges per triangle. */ +fprintf( outfile, "%ld %d\n", triangles.items, 3 ); #endif /* not TRILIBRARY */ - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - triangleloop.orient = 0; - elementnumber = firstnumber; - while ( triangleloop.tri != (triangle *) NULL ) { - *(int *) ( triangleloop.tri + 6 ) = elementnumber; - triangleloop.tri = triangletraverse(); - elementnumber++; - } - *(int *) ( dummytri + 6 ) = -1; - - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - elementnumber = firstnumber; - while ( triangleloop.tri != (triangle *) NULL ) { - triangleloop.orient = 1; - sym( triangleloop, trisym ); - neighbor1 = *(int *) ( trisym.tri + 6 ); - triangleloop.orient = 2; - sym( triangleloop, trisym ); - neighbor2 = *(int *) ( trisym.tri + 6 ); - triangleloop.orient = 0; - sym( triangleloop, trisym ); - neighbor3 = *(int *) ( trisym.tri + 6 ); -#ifdef TRILIBRARY - nlist[index++] = neighbor1; - nlist[index++] = neighbor2; - nlist[index++] = neighbor3; +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +triangleloop.orient = 0; +elementnumber = firstnumber; +while ( triangleloop.tri != (triangle *) NULL ) { +*(int *) ( triangleloop.tri + 6 ) = elementnumber; +triangleloop.tri = triangletraverse(); +elementnumber++; +} +*(int *) ( dummytri + 6 ) = -1; + +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +elementnumber = firstnumber; +while ( triangleloop.tri != (triangle *) NULL ) { +triangleloop.orient = 1; +sym( triangleloop, trisym ); +neighbor1 = *(int *) ( trisym.tri + 6 ); +triangleloop.orient = 2; +sym( triangleloop, trisym ); +neighbor2 = *(int *) ( trisym.tri + 6 ); +triangleloop.orient = 0; +sym( triangleloop, trisym ); +neighbor3 = *(int *) ( trisym.tri + 6 ); +#ifdef +TRILIBRARY +nlist[index++] = neighbor1; +nlist[index++] = neighbor2; +nlist[index++] = neighbor3; #else /* not TRILIBRARY */ - /* Triangle number, neighboring triangle numbers. */ - fprintf( outfile, "%4d %d %d %d\n", elementnumber, - neighbor1, neighbor2, neighbor3 ); +/* Triangle number, neighboring triangle numbers. */ +fprintf( outfile, "%4d %d %d %d\n", elementnumber, +neighbor1, neighbor2, neighbor3 ); #endif /* not TRILIBRARY */ - triangleloop.tri = triangletraverse(); - elementnumber++; - } +triangleloop.tri = triangletraverse(); +elementnumber++; +} -#ifndef TRILIBRARY - finishfile( outfile, argc, argv ); +#ifndef +TRILIBRARY +finishfile( outfile, argc, argv ); #endif /* TRILIBRARY */ } @@ -12709,54 +12975,55 @@ char **argv; /* */ /*****************************************************************************/ -#ifndef TRILIBRARY +#ifndef +TRILIBRARY void writeoff( offfilename, argc, argv ) char *offfilename; int argc; char **argv; { - FILE *outfile; - struct triedge triangleloop; - point pointloop; - point p1, p2, p3; - - if ( !quiet ) { - printf( "Writing %s.\n", offfilename ); - } - outfile = fopen( offfilename, "w" ); - if ( outfile == (FILE *) NULL ) { - printf( " Error: Cannot create file %s.\n", offfilename ); - exit( 1 ); - } - /* Number of points, triangles, and edges. */ - fprintf( outfile, "OFF\n%ld %ld %ld\n", points.items, triangles.items, - edges ); - - /* Write the points. */ - traversalinit( &points ); - pointloop = pointtraverse(); - while ( pointloop != (point) NULL ) { - /* The "0.0" is here because the OFF format uses 3D coordinates. */ - fprintf( outfile, " %.17g %.17g %.17g\n", pointloop[0], - pointloop[1], 0.0 ); - pointloop = pointtraverse(); - } - - /* Write the triangles. */ - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - triangleloop.orient = 0; - while ( triangleloop.tri != (triangle *) NULL ) { - org( triangleloop, p1 ); - dest( triangleloop, p2 ); - apex( triangleloop, p3 ); - /* The "3" means a three-vertex polygon. */ - fprintf( outfile, " 3 %4d %4d %4d\n", pointmark( p1 ) - 1, - pointmark( p2 ) - 1, pointmark( p3 ) - 1 ); - triangleloop.tri = triangletraverse(); - } - finishfile( outfile, argc, argv ); +FILE *outfile; +struct triedge triangleloop; +point pointloop; +point p1, p2, p3; + +if ( !quiet ) { +printf( "Writing %s.\n", offfilename ); +} +outfile = fopen( offfilename, "w" ); +if ( outfile == (FILE *) NULL ) { +printf( " Error: Cannot create file %s.\n", offfilename ); +exit( 1 ); +} +/* Number of points, triangles, and edges. */ +fprintf( outfile, "OFF\n%ld %ld %ld\n", points.items, triangles.items, +edges ); + +/* Write the points. */ +traversalinit( &points ); +pointloop = pointtraverse(); +while ( pointloop != (point) NULL ) { +/* The "0.0" is here because the OFF format uses 3D coordinates. */ +fprintf( outfile, " %.17g %.17g %.17g\n", pointloop[0], +pointloop[1], 0.0 ); +pointloop = pointtraverse(); +} + +/* Write the triangles. */ +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +triangleloop.orient = 0; +while ( triangleloop.tri != (triangle *) NULL ) { +org( triangleloop, p1 ); +dest( triangleloop, p2 ); +apex( triangleloop, p3 ); +/* The "3" means a three-vertex polygon. */ +fprintf( outfile, " 3 %4d %4d %4d\n", pointmark( p1 ) - 1, +pointmark( p2 ) - 1, pointmark( p3 ) - 1 ); +triangleloop.tri = triangletraverse(); +} +finishfile( outfile, argc, argv ); } #endif /* not TRILIBRARY */ @@ -12772,198 +13039,198 @@ char **argv; /*****************************************************************************/ void quality_statistics(){ - struct triedge triangleloop; - point p[3]; - REAL cossquaretable[8]; - REAL ratiotable[16]; - REAL dx[3], dy[3]; - REAL edgelength[3]; - REAL dotproduct; - REAL cossquare; - REAL triarea; - REAL shortest, longest; - REAL trilongest2; - REAL smallestarea, biggestarea; - REAL triminaltitude2; - REAL minaltitude; - REAL triaspect2; - REAL worstaspect; - REAL smallestangle, biggestangle; - REAL radconst, degconst; - int angletable[18]; - int aspecttable[16]; - int aspectindex; - int tendegree; - int acutebiggest; - int i, ii, j, k; - - printf( "Mesh quality statistics:\n\n" ); - radconst = (REAL)( PI / 18.0 ); - degconst = (REAL)( 180.0 / PI ); - for ( i = 0; i < 8; i++ ) { - cossquaretable[i] = (REAL)( cos( radconst * (REAL) ( i + 1 ) ) ); - cossquaretable[i] = cossquaretable[i] * cossquaretable[i]; - } - for ( i = 0; i < 18; i++ ) { - angletable[i] = 0; - } - - ratiotable[0] = 1.5; ratiotable[1] = 2.0; - ratiotable[2] = 2.5; ratiotable[3] = 3.0; - ratiotable[4] = 4.0; ratiotable[5] = 6.0; - ratiotable[6] = 10.0; ratiotable[7] = 15.0; - ratiotable[8] = 25.0; ratiotable[9] = 50.0; - ratiotable[10] = 100.0; ratiotable[11] = 300.0; - ratiotable[12] = 1000.0; ratiotable[13] = 10000.0; - ratiotable[14] = 100000.0; ratiotable[15] = 0.0; - for ( i = 0; i < 16; i++ ) { - aspecttable[i] = 0; - } - - worstaspect = 0.0; - minaltitude = xmax - xmin + ymax - ymin; - minaltitude = minaltitude * minaltitude; - shortest = minaltitude; - longest = 0.0; - smallestarea = minaltitude; - biggestarea = 0.0; - worstaspect = 0.0; - smallestangle = 0.0; - biggestangle = 2.0; - acutebiggest = 1; - - traversalinit( &triangles ); - triangleloop.tri = triangletraverse(); - triangleloop.orient = 0; - while ( triangleloop.tri != (triangle *) NULL ) { - org( triangleloop, p[0] ); - dest( triangleloop, p[1] ); - apex( triangleloop, p[2] ); - trilongest2 = 0.0; - - for ( i = 0; i < 3; i++ ) { - j = plus1mod3[i]; - k = minus1mod3[i]; - dx[i] = p[j][0] - p[k][0]; - dy[i] = p[j][1] - p[k][1]; - edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i]; - if ( edgelength[i] > trilongest2 ) { - trilongest2 = edgelength[i]; - } - if ( edgelength[i] > longest ) { - longest = edgelength[i]; - } - if ( edgelength[i] < shortest ) { - shortest = edgelength[i]; - } - } - - triarea = counterclockwise( p[0], p[1], p[2] ); - if ( triarea < smallestarea ) { - smallestarea = triarea; - } - if ( triarea > biggestarea ) { - biggestarea = triarea; - } - triminaltitude2 = triarea * triarea / trilongest2; - if ( triminaltitude2 < minaltitude ) { - minaltitude = triminaltitude2; - } - triaspect2 = trilongest2 / triminaltitude2; - if ( triaspect2 > worstaspect ) { - worstaspect = triaspect2; - } - aspectindex = 0; - while ( ( triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex] ) - && ( aspectindex < 15 ) ) { - aspectindex++; - } - aspecttable[aspectindex]++; - - for ( i = 0; i < 3; i++ ) { - j = plus1mod3[i]; - k = minus1mod3[i]; - dotproduct = dx[j] * dx[k] + dy[j] * dy[k]; - cossquare = dotproduct * dotproduct / ( edgelength[j] * edgelength[k] ); - tendegree = 8; - for ( ii = 7; ii >= 0; ii-- ) { - if ( cossquare > cossquaretable[ii] ) { - tendegree = ii; - } - } - if ( dotproduct <= 0.0 ) { - angletable[tendegree]++; - if ( cossquare > smallestangle ) { - smallestangle = cossquare; - } - if ( acutebiggest && ( cossquare < biggestangle ) ) { - biggestangle = cossquare; - } - } - else { - angletable[17 - tendegree]++; - if ( acutebiggest || ( cossquare > biggestangle ) ) { - biggestangle = cossquare; - acutebiggest = 0; - } - } - } - triangleloop.tri = triangletraverse(); - } - - shortest = (REAL)sqrt( shortest ); - longest = (REAL)sqrt( longest ); - minaltitude = (REAL)sqrt( minaltitude ); - worstaspect = (REAL)sqrt( worstaspect ); - smallestarea *= 2.0; - biggestarea *= 2.0; - if ( smallestangle >= 1.0 ) { - smallestangle = 0.0; - } - else { - smallestangle = (REAL)( degconst * acos( sqrt( smallestangle ) ) ); - } - if ( biggestangle >= 1.0 ) { - biggestangle = 180.0; - } - else { - if ( acutebiggest ) { - biggestangle = (REAL)( degconst * acos( sqrt( biggestangle ) ) ); - } - else { - biggestangle = (REAL)( 180.0 - degconst * acos( sqrt( biggestangle ) ) ); - } - } - - printf( " Smallest area: %16.5g | Largest area: %16.5g\n", - smallestarea, biggestarea ); - printf( " Shortest edge: %16.5g | Longest edge: %16.5g\n", - shortest, longest ); - printf( " Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n", - minaltitude, worstaspect ); - printf( " Aspect ratio histogram:\n" ); - printf( " 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n", - ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8], - aspecttable[8] ); - for ( i = 1; i < 7; i++ ) { - printf( " %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n", - ratiotable[i - 1], ratiotable[i], aspecttable[i], - ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8] ); - } - printf( " %6.6g - %-6.6g : %8d | %6.6g - : %8d\n", - ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14], - aspecttable[15] ); - printf( - " (Triangle aspect ratio is longest edge divided by shortest altitude)\n\n" ); - printf( " Smallest angle: %15.5g | Largest angle: %15.5g\n\n", - smallestangle, biggestangle ); - printf( " Angle histogram:\n" ); - for ( i = 0; i < 9; i++ ) { - printf( " %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n", - i * 10, i * 10 + 10, angletable[i], - i * 10 + 90, i * 10 + 100, angletable[i + 9] ); - } - printf( "\n" ); +struct triedge triangleloop; +point p[3]; +REAL cossquaretable[8]; +REAL ratiotable[16]; +REAL dx[3], dy[3]; +REAL edgelength[3]; +REAL dotproduct; +REAL cossquare; +REAL triarea; +REAL shortest, longest; +REAL trilongest2; +REAL smallestarea, biggestarea; +REAL triminaltitude2; +REAL minaltitude; +REAL triaspect2; +REAL worstaspect; +REAL smallestangle, biggestangle; +REAL radconst, degconst; +int angletable[18]; +int aspecttable[16]; +int aspectindex; +int tendegree; +int acutebiggest; +int i, ii, j, k; + +printf( "Mesh quality statistics:\n\n" ); +radconst = (REAL)( PI / 18.0 ); +degconst = (REAL)( 180.0 / PI ); +for ( i = 0; i < 8; i++ ) { +cossquaretable[i] = (REAL)( cos( radconst * (REAL) ( i + 1 ))); +cossquaretable[i] = cossquaretable[i] * cossquaretable[i]; +} +for ( i = 0; i < 18; i++ ) { +angletable[i] = 0; +} + +ratiotable[0] = 1.5; ratiotable[1] = 2.0; +ratiotable[2] = 2.5; ratiotable[3] = 3.0; +ratiotable[4] = 4.0; ratiotable[5] = 6.0; +ratiotable[6] = 10.0; ratiotable[7] = 15.0; +ratiotable[8] = 25.0; ratiotable[9] = 50.0; +ratiotable[10] = 100.0; ratiotable[11] = 300.0; +ratiotable[12] = 1000.0; ratiotable[13] = 10000.0; +ratiotable[14] = 100000.0; ratiotable[15] = 0.0; +for ( i = 0; i < 16; i++ ) { +aspecttable[i] = 0; +} + +worstaspect = 0.0; +minaltitude = xmax - xmin + ymax - ymin; +minaltitude = minaltitude * minaltitude; +shortest = minaltitude; +longest = 0.0; +smallestarea = minaltitude; +biggestarea = 0.0; +worstaspect = 0.0; +smallestangle = 0.0; +biggestangle = 2.0; +acutebiggest = 1; + +traversalinit( &triangles ); +triangleloop.tri = triangletraverse(); +triangleloop.orient = 0; +while ( triangleloop.tri != (triangle *) NULL ) { +org( triangleloop, p[0] ); +dest( triangleloop, p[1] ); +apex( triangleloop, p[2] ); +trilongest2 = 0.0; + +for ( i = 0; i < 3; i++ ) { +j = plus1mod3[i]; +k = minus1mod3[i]; +dx[i] = p[j][0] - p[k][0]; +dy[i] = p[j][1] - p[k][1]; +edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i]; +if ( edgelength[i] > trilongest2 ) { +trilongest2 = edgelength[i]; +} +if ( edgelength[i] > longest ) { +longest = edgelength[i]; +} +if ( edgelength[i] < shortest ) { +shortest = edgelength[i]; +} +} + +triarea = counterclockwise( p[0], p[1], p[2] ); +if ( triarea < smallestarea ) { +smallestarea = triarea; +} +if ( triarea > biggestarea ) { +biggestarea = triarea; +} +triminaltitude2 = triarea * triarea / trilongest2; +if ( triminaltitude2 < minaltitude ) { +minaltitude = triminaltitude2; +} +triaspect2 = trilongest2 / triminaltitude2; +if ( triaspect2 > worstaspect ) { +worstaspect = triaspect2; +} +aspectindex = 0; +while (( triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex] ) +&& ( aspectindex < 15 )) { +aspectindex++; +} +aspecttable[aspectindex]++; + +for ( i = 0; i < 3; i++ ) { +j = plus1mod3[i]; +k = minus1mod3[i]; +dotproduct = dx[j] * dx[k] + dy[j] * dy[k]; +cossquare = dotproduct * dotproduct / ( edgelength[j] * edgelength[k] ); +tendegree = 8; +for ( ii = 7; ii >= 0; ii-- ) { +if ( cossquare > cossquaretable[ii] ) { +tendegree = ii; +} +} +if ( dotproduct <= 0.0 ) { +angletable[tendegree]++; +if ( cossquare > smallestangle ) { +smallestangle = cossquare; +} +if ( acutebiggest && ( cossquare < biggestangle )) { +biggestangle = cossquare; +} +} +else { +angletable[17 - tendegree]++; +if ( acutebiggest || ( cossquare > biggestangle )) { +biggestangle = cossquare; +acutebiggest = 0; +} +} +} +triangleloop.tri = triangletraverse(); +} + +shortest = (REAL)sqrt( shortest ); +longest = (REAL)sqrt( longest ); +minaltitude = (REAL)sqrt( minaltitude ); +worstaspect = (REAL)sqrt( worstaspect ); +smallestarea *= 2.0; +biggestarea *= 2.0; +if ( smallestangle >= 1.0 ) { +smallestangle = 0.0; +} +else { +smallestangle = (REAL)( degconst * acos( sqrt( smallestangle ))); +} +if ( biggestangle >= 1.0 ) { +biggestangle = 180.0; +} +else { +if ( acutebiggest ) { +biggestangle = (REAL)( degconst * acos( sqrt( biggestangle ))); +} +else { +biggestangle = (REAL)( 180.0 - degconst * acos( sqrt( biggestangle ))); +} +} + +printf( " Smallest area: %16.5g | Largest area: %16.5g\n", +smallestarea, biggestarea ); +printf( " Shortest edge: %16.5g | Longest edge: %16.5g\n", +shortest, longest ); +printf( " Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n", +minaltitude, worstaspect ); +printf( " Aspect ratio histogram:\n" ); +printf( " 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n", +ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8], +aspecttable[8] ); +for ( i = 1; i < 7; i++ ) { +printf( " %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n", +ratiotable[i - 1], ratiotable[i], aspecttable[i], +ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8] ); +} +printf( " %6.6g - %-6.6g : %8d | %6.6g - : %8d\n", +ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14], +aspecttable[15] ); +printf( +" (Triangle aspect ratio is longest edge divided by shortest altitude)\n\n" ); +printf( " Smallest angle: %15.5g | Largest angle: %15.5g\n\n", +smallestangle, biggestangle ); +printf( " Angle histogram:\n" ); +for ( i = 0; i < 9; i++ ) { +printf( " %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n", +i * 10, i * 10 + 10, angletable[i], +i * 10 + 90, i * 10 + 100, angletable[i + 9] ); +} +printf( "\n" ); } /*****************************************************************************/ @@ -12973,77 +13240,77 @@ void quality_statistics(){ /*****************************************************************************/ void statistics(){ - printf( "\nStatistics:\n\n" ); - printf( " Input points: %d\n", inpoints ); - if ( refine ) { - printf( " Input triangles: %d\n", inelements ); - } - if ( poly ) { - printf( " Input segments: %d\n", insegments ); - if ( !refine ) { - printf( " Input holes: %d\n", holes ); - } - } - - printf( "\n Mesh points: %ld\n", points.items ); - printf( " Mesh triangles: %ld\n", triangles.items ); - printf( " Mesh edges: %ld\n", edges ); - if ( poly || refine ) { - printf( " Mesh boundary edges: %ld\n", hullsize ); - printf( " Mesh segments: %ld\n\n", shelles.items ); - } - else { - printf( " Mesh convex hull edges: %ld\n\n", hullsize ); - } - if ( verbose ) { - quality_statistics(); - printf( "Memory allocation statistics:\n\n" ); - printf( " Maximum number of points: %ld\n", points.maxitems ); - printf( " Maximum number of triangles: %ld\n", triangles.maxitems ); - if ( shelles.maxitems > 0 ) { - printf( " Maximum number of segments: %ld\n", shelles.maxitems ); - } - if ( viri.maxitems > 0 ) { - printf( " Maximum number of viri: %ld\n", viri.maxitems ); - } - if ( badsegments.maxitems > 0 ) { - printf( " Maximum number of encroached segments: %ld\n", - badsegments.maxitems ); - } - if ( badtriangles.maxitems > 0 ) { - printf( " Maximum number of bad triangles: %ld\n", - badtriangles.maxitems ); - } - if ( splaynodes.maxitems > 0 ) { - printf( " Maximum number of splay tree nodes: %ld\n", - splaynodes.maxitems ); - } - printf( " Approximate heap memory use (bytes): %ld\n\n", - points.maxitems * points.itembytes - + triangles.maxitems * triangles.itembytes - + shelles.maxitems * shelles.itembytes - + viri.maxitems * viri.itembytes - + badsegments.maxitems * badsegments.itembytes - + badtriangles.maxitems * badtriangles.itembytes - + splaynodes.maxitems * splaynodes.itembytes ); - - printf( "Algorithmic statistics:\n\n" ); - printf( " Number of incircle tests: %ld\n", incirclecount ); - printf( " Number of orientation tests: %ld\n", counterclockcount ); - if ( hyperbolacount > 0 ) { - printf( " Number of right-of-hyperbola tests: %ld\n", - hyperbolacount ); - } - if ( circumcentercount > 0 ) { - printf( " Number of circumcenter computations: %ld\n", - circumcentercount ); - } - if ( circletopcount > 0 ) { - printf( " Number of circle top computations: %ld\n", - circletopcount ); - } - printf( "\n" ); - } +printf( "\nStatistics:\n\n" ); +printf( " Input points: %d\n", inpoints ); +if ( refine ) { +printf( " Input triangles: %d\n", inelements ); +} +if ( poly ) { +printf( " Input segments: %d\n", insegments ); +if ( !refine ) { +printf( " Input holes: %d\n", holes ); +} +} + +printf( "\n Mesh points: %ld\n", points.items ); +printf( " Mesh triangles: %ld\n", triangles.items ); +printf( " Mesh edges: %ld\n", edges ); +if ( poly || refine ) { +printf( " Mesh boundary edges: %ld\n", hullsize ); +printf( " Mesh segments: %ld\n\n", shelles.items ); +} +else { +printf( " Mesh convex hull edges: %ld\n\n", hullsize ); +} +if ( verbose ) { +quality_statistics(); +printf( "Memory allocation statistics:\n\n" ); +printf( " Maximum number of points: %ld\n", points.maxitems ); +printf( " Maximum number of triangles: %ld\n", triangles.maxitems ); +if ( shelles.maxitems > 0 ) { +printf( " Maximum number of segments: %ld\n", shelles.maxitems ); +} +if ( viri.maxitems > 0 ) { +printf( " Maximum number of viri: %ld\n", viri.maxitems ); +} +if ( badsegments.maxitems > 0 ) { +printf( " Maximum number of encroached segments: %ld\n", +badsegments.maxitems ); +} +if ( badtriangles.maxitems > 0 ) { +printf( " Maximum number of bad triangles: %ld\n", +badtriangles.maxitems ); +} +if ( splaynodes.maxitems > 0 ) { +printf( " Maximum number of splay tree nodes: %ld\n", +splaynodes.maxitems ); +} +printf( " Approximate heap memory use (bytes): %ld\n\n", +points.maxitems * points.itembytes ++ triangles.maxitems * triangles.itembytes ++ shelles.maxitems * shelles.itembytes ++ viri.maxitems * viri.itembytes ++ badsegments.maxitems * badsegments.itembytes ++ badtriangles.maxitems * badtriangles.itembytes ++ splaynodes.maxitems * splaynodes.itembytes ); + +printf( "Algorithmic statistics:\n\n" ); +printf( " Number of incircle tests: %ld\n", incirclecount ); +printf( " Number of orientation tests: %ld\n", counterclockcount ); +if ( hyperbolacount > 0 ) { +printf( " Number of right-of-hyperbola tests: %ld\n", +hyperbolacount ); +} +if ( circumcentercount > 0 ) { +printf( " Number of circumcenter computations: %ld\n", +circumcentercount ); +} +if ( circletopcount > 0 ) { +printf( " Number of circle top computations: %ld\n", +circletopcount ); +} +printf( "\n" ); +} } /*****************************************************************************/ @@ -13071,7 +13338,8 @@ void statistics(){ /* */ /*****************************************************************************/ -#ifdef TRILIBRARY +#ifdef +TRILIBRARY void triangulate( triswitches, in, out, vorout ) char *triswitches; @@ -13088,316 +13356,347 @@ char **argv; #endif /* not TRILIBRARY */ { - REAL *holearray; /* Array of holes. */ - REAL *regionarray; /* Array of regional attributes and area constraints. */ -#ifndef TRILIBRARY - FILE *polyfile; +REAL *holearray; /* Array of holes. */ +REAL *regionarray; /* Array of regional attributes and area constraints. */ +#ifndef +TRILIBRARY +FILE *polyfile; #endif /* not TRILIBRARY */ -#ifndef NO_TIMER - /* Variables for timing the performance of Triangle. The types are */ - /* defined in sys/time.h. */ - struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6; - struct timezone tz; +#ifndef +NO_TIMER +/* Variables for timing the performance of Triangle. The types are */ +/* defined in sys/time.h. */ +struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6; +struct timezone tz; #endif /* NO_TIMER */ -#ifndef NO_TIMER - gettimeofday( &tv0, &tz ); +#ifndef +NO_TIMER +gettimeofday( &tv0, &tz ); #endif /* NO_TIMER */ - triangleinit(); -#ifdef TRILIBRARY - parsecommandline( 1, &triswitches ); +triangleinit(); +#ifdef +TRILIBRARY +parsecommandline( 1, &triswitches ); #else /* not TRILIBRARY */ - parsecommandline( argc, argv ); +parsecommandline( argc, argv ); #endif /* not TRILIBRARY */ -#ifdef TRILIBRARY - transfernodes( in->pointlist, in->pointattributelist, in->pointmarkerlist, - in->numberofpoints, in->numberofpointattributes ); +#ifdef +TRILIBRARY +transfernodes( in->pointlist, in->pointattributelist, in->pointmarkerlist, +in->numberofpoints, in->numberofpointattributes ); #else /* not TRILIBRARY */ - readnodes( innodefilename, inpolyfilename, &polyfile ); +readnodes( innodefilename, inpolyfilename, &polyfile ); #endif /* not TRILIBRARY */ -#ifndef NO_TIMER - if ( !quiet ) { - gettimeofday( &tv1, &tz ); - } +#ifndef +NO_TIMER +if ( !quiet ) { +gettimeofday( &tv1, &tz ); +} #endif /* NO_TIMER */ -#ifdef CDT_ONLY - hullsize = delaunay(); /* Triangulate the points. */ +#ifdef +CDT_ONLY +hullsize = delaunay(); /* Triangulate the points. */ #else /* not CDT_ONLY */ - if ( refine ) { - /* Read and reconstruct a mesh. */ -#ifdef TRILIBRARY - hullsize = reconstruct( in->trianglelist, in->triangleattributelist, - in->trianglearealist, in->numberoftriangles, - in->numberofcorners, in->numberoftriangleattributes, - in->segmentlist, in->segmentmarkerlist, - in->numberofsegments ); +if ( refine ) { +/* Read and reconstruct a mesh. */ +#ifdef +TRILIBRARY +hullsize = reconstruct( in->trianglelist, in->triangleattributelist, +in->trianglearealist, in->numberoftriangles, +in->numberofcorners, in->numberoftriangleattributes, +in->segmentlist, in->segmentmarkerlist, +in->numberofsegments ); #else /* not TRILIBRARY */ - hullsize = reconstruct( inelefilename, areafilename, inpolyfilename, - polyfile ); +hullsize = reconstruct( inelefilename, areafilename, inpolyfilename, +polyfile ); #endif /* not TRILIBRARY */ - } - else { - hullsize = delaunay(); /* Triangulate the points. */ - } +} +else { +hullsize = delaunay(); /* Triangulate the points. */ +} #endif /* not CDT_ONLY */ -#ifndef NO_TIMER - if ( !quiet ) { - gettimeofday( &tv2, &tz ); - if ( refine ) { - printf( "Mesh reconstruction" ); - } - else { - printf( "Delaunay" ); - } - printf( " milliseconds: %ld\n", 1000l * ( tv2.tv_sec - tv1.tv_sec ) - + ( tv2.tv_usec - tv1.tv_usec ) / 1000l ); - } +#ifndef +NO_TIMER +if ( !quiet ) { +gettimeofday( &tv2, &tz ); +if ( refine ) { +printf( "Mesh reconstruction" ); +} +else { +printf( "Delaunay" ); +} +printf( " milliseconds: %ld\n", 1000l * ( tv2.tv_sec - tv1.tv_sec ) ++ ( tv2.tv_usec - tv1.tv_usec ) / 1000l ); +} #endif /* NO_TIMER */ - /* Ensure that no point can be mistaken for a triangular bounding */ - /* box point in insertsite(). */ - infpoint1 = (point) NULL; - infpoint2 = (point) NULL; - infpoint3 = (point) NULL; - - if ( useshelles ) { - checksegments = 1; /* Segments will be introduced next. */ - if ( !refine ) { - /* Insert PSLG segments and/or convex hull segments. */ -#ifdef TRILIBRARY - insegments = formskeleton( in->segmentlist, in->segmentmarkerlist, - in->numberofsegments ); +/* Ensure that no point can be mistaken for a triangular bounding */ +/* box point in insertsite(). */ +infpoint1 = (point) NULL; +infpoint2 = (point) NULL; +infpoint3 = (point) NULL; + +if ( useshelles ) { +checksegments = 1; /* Segments will be introduced next. */ +if ( !refine ) { +/* Insert PSLG segments and/or convex hull segments. */ +#ifdef +TRILIBRARY +insegments = formskeleton( in->segmentlist, in->segmentmarkerlist, +in->numberofsegments ); #else /* not TRILIBRARY */ - insegments = formskeleton( polyfile, inpolyfilename ); +insegments = formskeleton( polyfile, inpolyfilename ); #endif /* not TRILIBRARY */ - } - } - -#ifndef NO_TIMER - if ( !quiet ) { - gettimeofday( &tv3, &tz ); - if ( useshelles && !refine ) { - printf( "Segment milliseconds: %ld\n", - 1000l * ( tv3.tv_sec - tv2.tv_sec ) - + ( tv3.tv_usec - tv2.tv_usec ) / 1000l ); - } - } +} +} + +#ifndef +NO_TIMER +if ( !quiet ) { +gettimeofday( &tv3, &tz ); +if ( useshelles && !refine ) { +printf( "Segment milliseconds: %ld\n", +1000l * ( tv3.tv_sec - tv2.tv_sec ) ++ ( tv3.tv_usec - tv2.tv_usec ) / 1000l ); +} +} #endif /* NO_TIMER */ - if ( poly ) { -#ifdef TRILIBRARY - holearray = in->holelist; - holes = in->numberofholes; - regionarray = in->regionlist; - regions = in->numberofregions; +if ( poly ) { +#ifdef +TRILIBRARY +holearray = in->holelist; +holes = in->numberofholes; +regionarray = in->regionlist; +regions = in->numberofregions; #else /* not TRILIBRARY */ - readholes( polyfile, inpolyfilename, &holearray, &holes, - ®ionarray, ®ions ); +readholes( polyfile, inpolyfilename, &holearray, &holes, +®ionarray, ®ions ); #endif /* not TRILIBRARY */ - if ( !refine ) { - /* Carve out holes and concavities. */ - carveholes( holearray, holes, regionarray, regions ); - } - } - else { - /* Without a PSLG, there can be no holes or regional attributes */ - /* or area constraints. The following are set to zero to avoid */ - /* an accidental free() later. */ - holes = 0; - regions = 0; - } - -#ifndef NO_TIMER - if ( !quiet ) { - gettimeofday( &tv4, &tz ); - if ( poly && !refine ) { - printf( "Hole milliseconds: %ld\n", 1000l * ( tv4.tv_sec - tv3.tv_sec ) - + ( tv4.tv_usec - tv3.tv_usec ) / 1000l ); - } - } +if ( !refine ) { +/* Carve out holes and concavities. */ +carveholes( holearray, holes, regionarray, regions ); +} +} +else { +/* Without a PSLG, there can be no holes or regional attributes */ +/* or area constraints. The following are set to zero to avoid */ +/* an accidental free() later. */ +holes = 0; +regions = 0; +} + +#ifndef +NO_TIMER +if ( !quiet ) { +gettimeofday( &tv4, &tz ); +if ( poly && !refine ) { +printf( "Hole milliseconds: %ld\n", 1000l * ( tv4.tv_sec - tv3.tv_sec ) ++ ( tv4.tv_usec - tv3.tv_usec ) / 1000l ); +} +} #endif /* NO_TIMER */ -#ifndef CDT_ONLY - if ( quality ) { - enforcequality(); /* Enforce angle and area constraints. */ - } +#ifndef +CDT_ONLY +if ( quality ) { +enforcequality(); /* Enforce angle and area constraints. */ +} #endif /* not CDT_ONLY */ -#ifndef NO_TIMER - if ( !quiet ) { - gettimeofday( &tv5, &tz ); -#ifndef CDT_ONLY - if ( quality ) { - printf( "Quality milliseconds: %ld\n", - 1000l * ( tv5.tv_sec - tv4.tv_sec ) - + ( tv5.tv_usec - tv4.tv_usec ) / 1000l ); - } +#ifndef +NO_TIMER +if ( !quiet ) { +gettimeofday( &tv5, &tz ); +#ifndef +CDT_ONLY +if ( quality ) { +printf( "Quality milliseconds: %ld\n", +1000l * ( tv5.tv_sec - tv4.tv_sec ) ++ ( tv5.tv_usec - tv4.tv_usec ) / 1000l ); +} #endif /* not CDT_ONLY */ - } +} #endif /* NO_TIMER */ - /* Compute the number of edges. */ - edges = ( 3l * triangles.items + hullsize ) / 2l; - - if ( order > 1 ) { - highorder(); /* Promote elements to higher polynomial order. */ - } - if ( !quiet ) { - printf( "\n" ); - } - -#ifdef TRILIBRARY - out->numberofpoints = points.items; - out->numberofpointattributes = nextras; - out->numberoftriangles = triangles.items; - out->numberofcorners = ( order + 1 ) * ( order + 2 ) / 2; - out->numberoftriangleattributes = eextras; - out->numberofedges = edges; - if ( useshelles ) { - out->numberofsegments = shelles.items; - } - else { - out->numberofsegments = hullsize; - } - if ( vorout != (struct triangulateio *) NULL ) { - vorout->numberofpoints = triangles.items; - vorout->numberofpointattributes = nextras; - vorout->numberofedges = edges; - } +/* Compute the number of edges. */ +edges = ( 3l * triangles.items + hullsize ) / 2l; + +if ( order > 1 ) { +highorder(); /* Promote elements to higher polynomial order. */ +} +if ( !quiet ) { +printf( "\n" ); +} + +#ifdef +TRILIBRARY +out->numberofpoints = points.items; +out->numberofpointattributes = nextras; +out->numberoftriangles = triangles.items; +out->numberofcorners = ( order + 1 ) * ( order + 2 ) / 2; +out->numberoftriangleattributes = eextras; +out->numberofedges = edges; +if ( useshelles ) { +out->numberofsegments = shelles.items; +} +else { +out->numberofsegments = hullsize; +} +if ( vorout != (struct triangulateio *) NULL ) { +vorout->numberofpoints = triangles.items; +vorout->numberofpointattributes = nextras; +vorout->numberofedges = edges; +} #endif /* TRILIBRARY */ - /* If not using iteration numbers, don't write a .node file if one was */ - /* read, because the original one would be overwritten! */ - if ( nonodewritten || ( noiterationnum && readnodefile ) ) { - if ( !quiet ) { -#ifdef TRILIBRARY - printf( "NOT writing points.\n" ); +/* If not using iteration numbers, don't write a .node file if one was */ +/* read, because the original one would be overwritten! */ +if ( nonodewritten || ( noiterationnum && readnodefile )) { +if ( !quiet ) { +#ifdef +TRILIBRARY +printf( "NOT writing points.\n" ); #else /* not TRILIBRARY */ - printf( "NOT writing a .node file.\n" ); +printf( "NOT writing a .node file.\n" ); #endif /* not TRILIBRARY */ - } - numbernodes(); /* We must remember to number the points. */ - } - else { -#ifdef TRILIBRARY - writenodes( &out->pointlist, &out->pointattributelist, - &out->pointmarkerlist ); +} +numbernodes(); /* We must remember to number the points. */ +} +else { +#ifdef +TRILIBRARY +writenodes( &out->pointlist, &out->pointattributelist, +&out->pointmarkerlist ); #else /* not TRILIBRARY */ - writenodes( outnodefilename, argc, argv ); /* Numbers the points too. */ +writenodes( outnodefilename, argc, argv ); /* Numbers the points too. */ #endif /* TRILIBRARY */ - } - if ( noelewritten ) { - if ( !quiet ) { -#ifdef TRILIBRARY - printf( "NOT writing triangles.\n" ); +} +if ( noelewritten ) { +if ( !quiet ) { +#ifdef +TRILIBRARY +printf( "NOT writing triangles.\n" ); #else /* not TRILIBRARY */ - printf( "NOT writing an .ele file.\n" ); +printf( "NOT writing an .ele file.\n" ); #endif /* not TRILIBRARY */ - } - } - else { -#ifdef TRILIBRARY - writeelements( &out->trianglelist, &out->triangleattributelist ); +} +} +else { +#ifdef +TRILIBRARY +writeelements( &out->trianglelist, &out->triangleattributelist ); #else /* not TRILIBRARY */ - writeelements( outelefilename, argc, argv ); +writeelements( outelefilename, argc, argv ); #endif /* not TRILIBRARY */ - } - /* The -c switch (convex switch) causes a PSLG to be written */ - /* even if none was read. */ - if ( poly || convex ) { - /* If not using iteration numbers, don't overwrite the .poly file. */ - if ( nopolywritten || noiterationnum ) { - if ( !quiet ) { -#ifdef TRILIBRARY - printf( "NOT writing segments.\n" ); +} +/* The -c switch (convex switch) causes a PSLG to be written */ +/* even if none was read. */ +if ( poly || convex ) { +/* If not using iteration numbers, don't overwrite the .poly file. */ +if ( nopolywritten || noiterationnum ) { +if ( !quiet ) { +#ifdef +TRILIBRARY +printf( "NOT writing segments.\n" ); #else /* not TRILIBRARY */ - printf( "NOT writing a .poly file.\n" ); +printf( "NOT writing a .poly file.\n" ); #endif /* not TRILIBRARY */ - } - } - else { -#ifdef TRILIBRARY - writepoly( &out->segmentlist, &out->segmentmarkerlist ); - out->numberofholes = holes; - out->numberofregions = regions; - if ( poly ) { - out->holelist = in->holelist; - out->regionlist = in->regionlist; - } - else { - out->holelist = (REAL *) NULL; - out->regionlist = (REAL *) NULL; - } +} +} +else { +#ifdef +TRILIBRARY +writepoly( &out->segmentlist, &out->segmentmarkerlist ); +out->numberofholes = holes; +out->numberofregions = regions; +if ( poly ) { +out->holelist = in->holelist; +out->regionlist = in->regionlist; +} +else { +out->holelist = (REAL *) NULL; +out->regionlist = (REAL *) NULL; +} #else /* not TRILIBRARY */ - writepoly( outpolyfilename, holearray, holes, regionarray, regions, - argc, argv ); +writepoly( outpolyfilename, holearray, holes, regionarray, regions, +argc, argv ); #endif /* not TRILIBRARY */ - } - } -#ifndef TRILIBRARY -#ifndef CDT_ONLY - if ( regions > 0 ) { - free( regionarray ); - } +} +} +#ifndef +TRILIBRARY +#ifndef +CDT_ONLY +if ( regions > 0 ) { +free( regionarray ); +} #endif /* not CDT_ONLY */ - if ( holes > 0 ) { - free( holearray ); - } - if ( geomview ) { - writeoff( offfilename, argc, argv ); - } +if ( holes > 0 ) { +free( holearray ); +} +if ( geomview ) { +writeoff( offfilename, argc, argv ); +} #endif /* not TRILIBRARY */ - if ( edgesout ) { -#ifdef TRILIBRARY - writeedges( &out->edgelist, &out->edgemarkerlist ); +if ( edgesout ) { +#ifdef +TRILIBRARY +writeedges( &out->edgelist, &out->edgemarkerlist ); #else /* not TRILIBRARY */ - writeedges( edgefilename, argc, argv ); +writeedges( edgefilename, argc, argv ); #endif /* not TRILIBRARY */ - } - if ( voronoi ) { -#ifdef TRILIBRARY - writevoronoi( &vorout->pointlist, &vorout->pointattributelist, - &vorout->pointmarkerlist, &vorout->edgelist, - &vorout->edgemarkerlist, &vorout->normlist ); +} +if ( voronoi ) { +#ifdef +TRILIBRARY +writevoronoi( &vorout->pointlist, &vorout->pointattributelist, +&vorout->pointmarkerlist, &vorout->edgelist, +&vorout->edgemarkerlist, &vorout->normlist ); #else /* not TRILIBRARY */ - writevoronoi( vnodefilename, vedgefilename, argc, argv ); +writevoronoi( vnodefilename, vedgefilename, argc, argv ); #endif /* not TRILIBRARY */ - } - if ( neighbors ) { -#ifdef TRILIBRARY - writeneighbors( &out->neighborlist ); +} +if ( neighbors ) { +#ifdef +TRILIBRARY +writeneighbors( &out->neighborlist ); #else /* not TRILIBRARY */ - writeneighbors( neighborfilename, argc, argv ); +writeneighbors( neighborfilename, argc, argv ); #endif /* not TRILIBRARY */ - } - - if ( !quiet ) { -#ifndef NO_TIMER - gettimeofday( &tv6, &tz ); - printf( "\nOutput milliseconds: %ld\n", - 1000l * ( tv6.tv_sec - tv5.tv_sec ) - + ( tv6.tv_usec - tv5.tv_usec ) / 1000l ); - printf( "Total running milliseconds: %ld\n", - 1000l * ( tv6.tv_sec - tv0.tv_sec ) - + ( tv6.tv_usec - tv0.tv_usec ) / 1000l ); +} + +if ( !quiet ) { +#ifndef +NO_TIMER +gettimeofday( &tv6, &tz ); +printf( "\nOutput milliseconds: %ld\n", +1000l * ( tv6.tv_sec - tv5.tv_sec ) ++ ( tv6.tv_usec - tv5.tv_usec ) / 1000l ); +printf( "Total running milliseconds: %ld\n", +1000l * ( tv6.tv_sec - tv0.tv_sec ) ++ ( tv6.tv_usec - tv0.tv_usec ) / 1000l ); #endif /* NO_TIMER */ - statistics(); - } +statistics(); +} -#ifndef REDUCED - if ( docheck ) { - checkmesh(); - checkdelaunay(); - } +#ifndef +REDUCED +if ( docheck ) { +checkmesh(); +checkdelaunay(); +} #endif /* not REDUCED */ - triangledeinit(); -#ifndef TRILIBRARY - return 0; +triangledeinit(); +#ifndef +TRILIBRARY +return 0; #endif /* not TRILIBRARY */ } diff --git a/contrib/gtkgensurf/triangle.h b/contrib/gtkgensurf/triangle.h index 337da40c..f1a37e78 100644 --- a/contrib/gtkgensurf/triangle.h +++ b/contrib/gtkgensurf/triangle.h @@ -250,38 +250,38 @@ extern "C" { #endif struct triangulateio { - REAL *pointlist; /* In / out */ - REAL *pointattributelist; /* In / out */ - int *pointmarkerlist; /* In / out */ - int numberofpoints; /* In / out */ - int numberofpointattributes; /* In / out */ + REAL *pointlist; /* In / out */ + REAL *pointattributelist; /* In / out */ + int *pointmarkerlist; /* In / out */ + int numberofpoints; /* In / out */ + int numberofpointattributes; /* In / out */ - int *trianglelist; /* In / out */ - REAL *triangleattributelist; /* In / out */ - REAL *trianglearealist; /* In only */ - int *neighborlist; /* Out only */ - int numberoftriangles; /* In / out */ - int numberofcorners; /* In / out */ - int numberoftriangleattributes; /* In / out */ + int *trianglelist; /* In / out */ + REAL *triangleattributelist; /* In / out */ + REAL *trianglearealist; /* In only */ + int *neighborlist; /* Out only */ + int numberoftriangles; /* In / out */ + int numberofcorners; /* In / out */ + int numberoftriangleattributes; /* In / out */ - int *segmentlist; /* In / out */ - int *segmentmarkerlist; /* In / out */ - int numberofsegments; /* In / out */ + int *segmentlist; /* In / out */ + int *segmentmarkerlist; /* In / out */ + int numberofsegments; /* In / out */ - REAL *holelist; /* In / pointer to array copied out */ - int numberofholes; /* In / copied out */ + REAL *holelist; /* In / pointer to array copied out */ + int numberofholes; /* In / copied out */ - REAL *regionlist; /* In / pointer to array copied out */ - int numberofregions; /* In / copied out */ + REAL *regionlist; /* In / pointer to array copied out */ + int numberofregions; /* In / copied out */ - int *edgelist; /* Out only */ - int *edgemarkerlist; /* Not used with Voronoi diagram; out only */ - REAL *normlist; /* Used only with Voronoi diagram; out only */ - int numberofedges; /* Out only */ + int *edgelist; /* Out only */ + int *edgemarkerlist; /* Not used with Voronoi diagram; out only */ + REAL *normlist; /* Used only with Voronoi diagram; out only */ + int numberofedges; /* Out only */ }; -void triangulate( char *, struct triangulateio *, struct triangulateio *, - struct triangulateio * ); +void triangulate(char *, struct triangulateio *, struct triangulateio *, + struct triangulateio *); #ifdef __cplusplus } diff --git a/contrib/gtkgensurf/view.cpp b/contrib/gtkgensurf/view.cpp index 975c5cae..ce99063c 100644 --- a/contrib/gtkgensurf/view.cpp +++ b/contrib/gtkgensurf/view.cpp @@ -26,1245 +26,1193 @@ extern double backface; extern double dh, dv; -extern double xmin,xmax,ymin,ymax,zmin,zmax; +extern double xmin, xmax, ymin, ymax, zmin, zmax; double SF, SFG; // Graphics scale factors double XLo, XHi, YLo, YHi, ZLo, ZHi; -double yaw,roll; -double elevation,azimuth; +double yaw, roll; +double elevation, azimuth; int cxChar = 10, cyChar = 16; int X0, Y0; int X0G, Y0G; static Rect rcCoord; // where X= Y= is drawn static Rect rcGrid; // rectangle within rcLower that forms the border of the grid, plus - // a 3 pixel slop. +// a 3 pixel slop. static Rect rcLower; // lower half of window, where plan view is drawn static Rect rcUpper; // upper half or entire window, where isometric projection is drawn void vertex_selected(); + void texfont_init(); -void texfont_write( const char *text, int l, int t ); + +void texfont_write(const char *text, int l, int t); #define PEN_GRID { \ - g_GLTable.m_pfn_qglLineWidth( 1 ); \ - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); \ - g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); } + g_GLTable.m_pfn_qglLineWidth( 1 ); \ + g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); \ + g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); } #define PEN_RED { \ - g_GLTable.m_pfn_qglLineWidth( 2 ); \ - g_GLTable.m_pfn_qglColor3f( 1, 0, 0 ); \ - g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); } + g_GLTable.m_pfn_qglLineWidth( 2 ); \ + g_GLTable.m_pfn_qglColor3f( 1, 0, 0 ); \ + g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); } #define PEN_DASH { \ - g_GLTable.m_pfn_qglLineWidth( 1 ); \ - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); \ - g_GLTable.m_pfn_qglLineStipple( 1, 0xF0F0 ); \ - g_GLTable.m_pfn_qglEnable( GL_LINE_STIPPLE ); } - -#define DRAW_QUAD( rc,r,g,b ) { \ - g_GLTable.m_pfn_qglBegin( GL_QUADS ); \ - g_GLTable.m_pfn_qglColor3f( 0,1,0 ); \ - g_GLTable.m_pfn_qglVertex2i( rc.left - 1, rc.bottom ); \ - g_GLTable.m_pfn_qglVertex2i( rc.right, rc.bottom ); \ - g_GLTable.m_pfn_qglVertex2i( rc.right, rc.top + 1 ); \ - g_GLTable.m_pfn_qglVertex2i( rc.left - 1, rc.top + 1 ); \ - g_GLTable.m_pfn_qglColor3f( r,g,b ); \ - g_GLTable.m_pfn_qglVertex2i( rc.left, rc.bottom + 1 ); \ - g_GLTable.m_pfn_qglVertex2i( rc.right - 1, rc.bottom + 1 ); \ - g_GLTable.m_pfn_qglVertex2i( rc.right - 1, rc.top ); \ - g_GLTable.m_pfn_qglVertex2i( rc.left, rc.top ); \ - g_GLTable.m_pfn_qglEnd(); } + g_GLTable.m_pfn_qglLineWidth( 1 ); \ + g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); \ + g_GLTable.m_pfn_qglLineStipple( 1, 0xF0F0 ); \ + g_GLTable.m_pfn_qglEnable( GL_LINE_STIPPLE ); } + +#define DRAW_QUAD(rc, r, g, b) { \ + g_GLTable.m_pfn_qglBegin( GL_QUADS ); \ + g_GLTable.m_pfn_qglColor3f( 0,1,0 ); \ + g_GLTable.m_pfn_qglVertex2i( rc.left - 1, rc.bottom ); \ + g_GLTable.m_pfn_qglVertex2i( rc.right, rc.bottom ); \ + g_GLTable.m_pfn_qglVertex2i( rc.right, rc.top + 1 ); \ + g_GLTable.m_pfn_qglVertex2i( rc.left - 1, rc.top + 1 ); \ + g_GLTable.m_pfn_qglColor3f( r,g,b ); \ + g_GLTable.m_pfn_qglVertex2i( rc.left, rc.bottom + 1 ); \ + g_GLTable.m_pfn_qglVertex2i( rc.right - 1, rc.bottom + 1 ); \ + g_GLTable.m_pfn_qglVertex2i( rc.right - 1, rc.top ); \ + g_GLTable.m_pfn_qglVertex2i( rc.left, rc.top ); \ + g_GLTable.m_pfn_qglEnd(); } #ifndef ISOMETRIC double D = 65536.; -double ct[3],st[3]; +double ct[3], st[3]; double Hhi, Hlo, Vhi, Vlo; #endif #define SUBDIVS 6 -void ShowPreview(){ - if ( Preview ) { - if ( g_pWndPreview == NULL ) { - CreateViewWindow(); - } - g_pWndPreview.show(); +void ShowPreview() +{ + if (Preview) { + if (g_pWndPreview == NULL) { + CreateViewWindow(); + } + g_pWndPreview.show(); - UpdatePreview( true ); - } - else{ - gtk_widget_hide( g_pWndPreview ); - } + UpdatePreview(true); + } else { + gtk_widget_hide(g_pWndPreview); + } } -static void draw_preview(){ - int width = g_pPreviewWidget->allocation.width, height = g_pPreviewWidget->allocation.height; - - g_GLTable.m_pfn_qglClearColor( 0, 0, 0, 1 ); - g_GLTable.m_pfn_qglViewport( 0, 0, width, height ); - g_GLTable.m_pfn_qglMatrixMode( GL_PROJECTION ); - g_GLTable.m_pfn_qglLoadIdentity(); - g_GLTable.m_pfn_qglOrtho( 0, width, 0, height, -1, 1 ); - g_GLTable.m_pfn_qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - // ^Fishman - Antializing for the preview window. - if ( Antialiasing ) { - g_GLTable.m_pfn_qglEnable( GL_BLEND ); - g_GLTable.m_pfn_qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - g_GLTable.m_pfn_qglEnable( GL_LINE_SMOOTH ); - } - else - { - g_GLTable.m_pfn_qglDisable( GL_BLEND ); - g_GLTable.m_pfn_qglDisable( GL_LINE_SMOOTH ); - } - - texfont_init(); - - if ( !ValidSurface() ) { - return; - } - - rcUpper.left = 0; - rcUpper.right = width; - rcUpper.bottom = 0; - rcUpper.top = height; - rcLower.left = 0; - rcLower.right = width; - rcLower.bottom = 0; - rcLower.top = height; - - if ( VertexMode ) { - rcUpper.bottom = rcUpper.top / 2; - DrawPreview( rcUpper ); - g_GLTable.m_pfn_qglBegin( GL_LINES ); - g_GLTable.m_pfn_qglVertex2i( rcUpper.left, rcUpper.bottom ); - g_GLTable.m_pfn_qglVertex2i( rcUpper.right, rcUpper.bottom ); - g_GLTable.m_pfn_qglEnd(); - rcLower.top = rcUpper.bottom - 1; - DrawGrid( rcLower ); - rcCoord.left = rcLower.left; - rcCoord.right = rcLower.right; - rcCoord.bottom = rcLower.bottom; - rcCoord.top = rcLower.top; - rcCoord.top = rcCoord.bottom + cyChar; - rcCoord.right = rcCoord.left + 15 * cxChar; - rcGrid.left = X0G - 3; - rcGrid.bottom = Y0G - 3; - rcGrid.right = X0G + (int)( SFG * ( Hur - Hll ) ) + 3; - rcGrid.top = Y0G + (int)( SFG * ( Vur - Vll ) ) + 3; - } - else{ - DrawPreview( rcUpper ); - } +static void draw_preview() +{ + int width = g_pPreviewWidget->allocation.width, height = g_pPreviewWidget->allocation.height; + + g_GLTable.m_pfn_qglClearColor(0, 0, 0, 1); + g_GLTable.m_pfn_qglViewport(0, 0, width, height); + g_GLTable.m_pfn_qglMatrixMode(GL_PROJECTION); + g_GLTable.m_pfn_qglLoadIdentity(); + g_GLTable.m_pfn_qglOrtho(0, width, 0, height, -1, 1); + g_GLTable.m_pfn_qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // ^Fishman - Antializing for the preview window. + if (Antialiasing) { + g_GLTable.m_pfn_qglEnable(GL_BLEND); + g_GLTable.m_pfn_qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + g_GLTable.m_pfn_qglEnable(GL_LINE_SMOOTH); + } else { + g_GLTable.m_pfn_qglDisable(GL_BLEND); + g_GLTable.m_pfn_qglDisable(GL_LINE_SMOOTH); + } + + texfont_init(); + + if (!ValidSurface()) { + return; + } + + rcUpper.left = 0; + rcUpper.right = width; + rcUpper.bottom = 0; + rcUpper.top = height; + rcLower.left = 0; + rcLower.right = width; + rcLower.bottom = 0; + rcLower.top = height; + + if (VertexMode) { + rcUpper.bottom = rcUpper.top / 2; + DrawPreview(rcUpper); + g_GLTable.m_pfn_qglBegin(GL_LINES); + g_GLTable.m_pfn_qglVertex2i(rcUpper.left, rcUpper.bottom); + g_GLTable.m_pfn_qglVertex2i(rcUpper.right, rcUpper.bottom); + g_GLTable.m_pfn_qglEnd(); + rcLower.top = rcUpper.bottom - 1; + DrawGrid(rcLower); + rcCoord.left = rcLower.left; + rcCoord.right = rcLower.right; + rcCoord.bottom = rcLower.bottom; + rcCoord.top = rcLower.top; + rcCoord.top = rcCoord.bottom + cyChar; + rcCoord.right = rcCoord.left + 15 * cxChar; + rcGrid.left = X0G - 3; + rcGrid.bottom = Y0G - 3; + rcGrid.right = X0G + (int) (SFG * (Hur - Hll)) + 3; + rcGrid.top = Y0G + (int) (SFG * (Vur - Vll)) + 3; + } else { + DrawPreview(rcUpper); + } } -static gint expose( GtkWidget *widget, GdkEventExpose *event, gpointer data ){ - if ( event->count > 0 ) { - return TRUE; - } +static gint expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) +{ + if (event->count > 0) { + return TRUE; + } - if ( !g_UIGtkTable.m_pfn_glwidget_make_current( g_pPreviewWidget ) ) { - g_FuncTable.m_pfnSysPrintf( "GtkGenSurf: glMakeCurrent failed\n" ); - return TRUE; - } + if (!g_UIGtkTable.m_pfn_glwidget_make_current(g_pPreviewWidget)) { + g_FuncTable.m_pfnSysPrintf("GtkGenSurf: glMakeCurrent failed\n"); + return TRUE; + } - draw_preview(); + draw_preview(); - g_UIGtkTable.m_pfn_glwidget_swap_buffers( g_pPreviewWidget ); - g_GLTable.m_pfn_QE_CheckOpenGLForErrors(); + g_UIGtkTable.m_pfn_glwidget_swap_buffers(g_pPreviewWidget); + g_GLTable.m_pfn_QE_CheckOpenGLForErrors(); - return TRUE; + return TRUE; } -static void button_press( GtkWidget *widget, GdkEventButton *event, gpointer data ){ - Point pt = { (long)event->x, widget->allocation.height - (long)event->y }; - bool Selected; - double x,y; - int i, j, k, ks; - int i0, i1, j0, j1; - - if ( ( !VertexMode ) || ( event->button != 1 ) ) { - return; - } - - if ( !PtInRect( &rcGrid,pt ) ) { - gdk_beep(); - return; - } - - x = Hll + ( pt.x - X0G ) / SFG; - y = Vur - ( pt.y - Y0G ) / SFG; - i = (int)( floor( ( x - Hll ) / dh - 0.5 ) + 1 ); - j = (int)( floor( ( y - Vll ) / dv - 0.5 ) + 1 ); - if ( i < 0 || i > NH || j < 0 || j > NV ) { - gdk_beep(); - return; - } - - if ( !CanEdit( i,j ) ) { - gdk_beep(); - return; - } - - // Control key pressed - add this point, or remove it if already selected - if ( ( event->state & GDK_CONTROL_MASK ) != 0 ) { - Selected = FALSE; - if ( NumVerticesSelected ) { - for ( k = 0; k < NumVerticesSelected && !Selected; k++ ) - { - if ( Vertex[k].i == i && Vertex[k].j == j ) { - Selected = TRUE; - ks = k; - } - } - } - - // Already selected - unselect it. - if ( Selected ) { - if ( ks < NumVerticesSelected ) { - for ( k = ks; k < NumVerticesSelected - 1; k++ ) - { - Vertex[k].i = Vertex[k + 1].i; - Vertex[k].j = Vertex[k + 1].j; - } - NumVerticesSelected--; - } - } - else - { - Vertex[NumVerticesSelected].i = i; - Vertex[NumVerticesSelected].j = j; - NumVerticesSelected++; - } - } - else if ( ( event->state & GDK_SHIFT_MASK ) != 0 ) { - if ( NumVerticesSelected ) { - NumVerticesSelected = 1; - i0 = min( Vertex[0].i, i ); - i1 = max( Vertex[0].i, i ); - j0 = min( Vertex[0].j, j ); - j1 = max( Vertex[0].j, j ); - for ( i = i0; i <= i1; i++ ) - { - for ( j = j0; j <= j1; j++ ) - { - if ( i == 0 && j == 0 ) { - continue; - } - if ( i == NH && j == 0 ) { - continue; - } - if ( i == 0 && j == NV ) { - continue; - } - if ( i == NH && j == NV ) { - continue; - } - if ( i != Vertex[0].i || j != Vertex[0].j ) { - Vertex[NumVerticesSelected].i = i; - Vertex[NumVerticesSelected].j = j; - NumVerticesSelected++; - } - } - } - } - else - { - Vertex[0].i = i; - Vertex[0].j = j; - NumVerticesSelected = 1; - } - } - else - { - Vertex[0].i = i; - Vertex[0].j = j; - NumVerticesSelected = 1; - } - - vertex_selected(); +static void button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) +{ + Point pt = {(long) event->x, widget->allocation.height - (long) event->y}; + bool Selected; + double x, y; + int i, j, k, ks; + int i0, i1, j0, j1; + + if ((!VertexMode) || (event->button != 1)) { + return; + } + + if (!PtInRect(&rcGrid, pt)) { + gdk_beep(); + return; + } + + x = Hll + (pt.x - X0G) / SFG; + y = Vur - (pt.y - Y0G) / SFG; + i = (int) (floor((x - Hll) / dh - 0.5) + 1); + j = (int) (floor((y - Vll) / dv - 0.5) + 1); + if (i < 0 || i > NH || j < 0 || j > NV) { + gdk_beep(); + return; + } + + if (!CanEdit(i, j)) { + gdk_beep(); + return; + } + + // Control key pressed - add this point, or remove it if already selected + if ((event->state & GDK_CONTROL_MASK) != 0) { + Selected = FALSE; + if (NumVerticesSelected) { + for (k = 0; k < NumVerticesSelected && !Selected; k++) { + if (Vertex[k].i == i && Vertex[k].j == j) { + Selected = TRUE; + ks = k; + } + } + } + + // Already selected - unselect it. + if (Selected) { + if (ks < NumVerticesSelected) { + for (k = ks; k < NumVerticesSelected - 1; k++) { + Vertex[k].i = Vertex[k + 1].i; + Vertex[k].j = Vertex[k + 1].j; + } + NumVerticesSelected--; + } + } else { + Vertex[NumVerticesSelected].i = i; + Vertex[NumVerticesSelected].j = j; + NumVerticesSelected++; + } + } else if ((event->state & GDK_SHIFT_MASK) != 0) { + if (NumVerticesSelected) { + NumVerticesSelected = 1; + i0 = min(Vertex[0].i, i); + i1 = max(Vertex[0].i, i); + j0 = min(Vertex[0].j, j); + j1 = max(Vertex[0].j, j); + for (i = i0; i <= i1; i++) { + for (j = j0; j <= j1; j++) { + if (i == 0 && j == 0) { + continue; + } + if (i == NH && j == 0) { + continue; + } + if (i == 0 && j == NV) { + continue; + } + if (i == NH && j == NV) { + continue; + } + if (i != Vertex[0].i || j != Vertex[0].j) { + Vertex[NumVerticesSelected].i = i; + Vertex[NumVerticesSelected].j = j; + NumVerticesSelected++; + } + } + } + } else { + Vertex[0].i = i; + Vertex[0].j = j; + NumVerticesSelected = 1; + } + } else { + Vertex[0].i = i; + Vertex[0].j = j; + NumVerticesSelected = 1; + } + + vertex_selected(); } -static void motion( GtkWidget *widget, GdkEventMotion *event, gpointer data ){ - Point pt = { (long)event->x, widget->allocation.height - (long)event->y }; - - if ( !VertexMode ) { - return; - } - - if ( !g_UIGtkTable.m_pfn_glwidget_make_current( g_pPreviewWidget ) ) { - g_FuncTable.m_pfnSysPrintf( "GtkGenSurf: glMakeCurrent failed\n" ); - return; - } - - g_GLTable.m_pfn_qglEnable( GL_SCISSOR_TEST ); - g_GLTable.m_pfn_qglScissor( rcCoord.left, rcCoord.bottom, rcCoord.right - rcCoord.left, - rcCoord.top - rcCoord.bottom ); - g_GLTable.m_pfn_qglClear( GL_COLOR_BUFFER_BIT ); - - if ( PtInRect( &rcGrid,pt ) ) { - GdkCursor *cursor = gdk_cursor_new( GDK_CROSS ); - gdk_window_set_cursor( g_pWndPreview->window, cursor ); - gdk_cursor_unref( cursor ); - - char Text[32]; - int x, y; - - x = (int)( Hll + ( pt.x - X0G ) / SFG ); - y = (int)( Vur - ( pt.y - Y0G ) / SFG ); - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - sprintf( Text," x=%d, z=%d ",(int)( floor( x - 0.5 ) + 1. ),(int)( floor( y - 0.5 ) + 1. ) ); - break; - case PLANE_YZ0: - case PLANE_YZ1: - sprintf( Text," y=%d, z=%d ",(int)( floor( x - 0.5 ) + 1. ),(int)( floor( y - 0.5 ) + 1. ) ); - break; - default: - sprintf( Text," x=%d, y=%d ",(int)( floor( x - 0.5 ) + 1. ),(int)( floor( y - 0.5 ) + 1. ) ); - } - - texfont_write( Text, rcCoord.left, rcCoord.top ); - } - else - { - gdk_window_set_cursor( g_pWndPreview->window, NULL ); - } - - g_UIGtkTable.m_pfn_glwidget_swap_buffers( g_pPreviewWidget ); - g_GLTable.m_pfn_QE_CheckOpenGLForErrors(); - g_GLTable.m_pfn_qglDisable( GL_SCISSOR_TEST ); +static void motion(GtkWidget *widget, GdkEventMotion *event, gpointer data) +{ + Point pt = {(long) event->x, widget->allocation.height - (long) event->y}; + + if (!VertexMode) { + return; + } + + if (!g_UIGtkTable.m_pfn_glwidget_make_current(g_pPreviewWidget)) { + g_FuncTable.m_pfnSysPrintf("GtkGenSurf: glMakeCurrent failed\n"); + return; + } + + g_GLTable.m_pfn_qglEnable(GL_SCISSOR_TEST); + g_GLTable.m_pfn_qglScissor(rcCoord.left, rcCoord.bottom, rcCoord.right - rcCoord.left, + rcCoord.top - rcCoord.bottom); + g_GLTable.m_pfn_qglClear(GL_COLOR_BUFFER_BIT); + + if (PtInRect(&rcGrid, pt)) { + GdkCursor *cursor = gdk_cursor_new(GDK_CROSS); + gdk_window_set_cursor(g_pWndPreview->window, cursor); + gdk_cursor_unref(cursor); + + char Text[32]; + int x, y; + + x = (int) (Hll + (pt.x - X0G) / SFG); + y = (int) (Vur - (pt.y - Y0G) / SFG); + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + sprintf(Text, " x=%d, z=%d ", (int) (floor(x - 0.5) + 1.), (int) (floor(y - 0.5) + 1.)); + break; + case PLANE_YZ0: + case PLANE_YZ1: + sprintf(Text, " y=%d, z=%d ", (int) (floor(x - 0.5) + 1.), (int) (floor(y - 0.5) + 1.)); + break; + default: + sprintf(Text, " x=%d, y=%d ", (int) (floor(x - 0.5) + 1.), (int) (floor(y - 0.5) + 1.)); + } + + texfont_write(Text, rcCoord.left, rcCoord.top); + } else { + gdk_window_set_cursor(g_pWndPreview->window, NULL); + } + + g_UIGtkTable.m_pfn_glwidget_swap_buffers(g_pPreviewWidget); + g_GLTable.m_pfn_QE_CheckOpenGLForErrors(); + g_GLTable.m_pfn_qglDisable(GL_SCISSOR_TEST); } -static gint preview_close( GtkWidget *widget, gpointer data ){ - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "main_preview" ) ), FALSE ); - return TRUE; +static gint preview_close(GtkWidget *widget, gpointer data) +{ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(g_pWnd), "main_preview")), FALSE); + return TRUE; } -static void preview_focusout( GtkSpinButton *spin, GdkEventFocus *event, double *data ){ - *data = DegreesToRadians( (double)( gtk_spin_button_get_value_as_int( spin ) % 360 ) ); - UpdatePreview( false ); +static void preview_focusout(GtkSpinButton *spin, GdkEventFocus *event, double *data) +{ + *data = DegreesToRadians((double) (gtk_spin_button_get_value_as_int(spin) % 360)); + UpdatePreview(false); } -static gint doublevariable_spinfocusout( GtkWidget* widget, GdkEventFocus* event, gpointer data ){ - preview_focusout( GTK_SPIN_BUTTON( widget ), event, reinterpret_cast( data ) ); - return FALSE; +static gint doublevariable_spinfocusout(GtkWidget *widget, GdkEventFocus *event, gpointer data) +{ + preview_focusout(GTK_SPIN_BUTTON(widget), event, reinterpret_cast( data )); + return FALSE; } -static void preview_spin( GtkAdjustment *adj, double *data ){ - *data = DegreesToRadians( adj->value ); - UpdatePreview( false ); +static void preview_spin(GtkAdjustment *adj, double *data) +{ + *data = DegreesToRadians(adj->value); + UpdatePreview(false); } -void CreateViewWindow(){ - GtkWidget *label, *spin; +void CreateViewWindow() +{ + GtkWidget *label, *spin; #ifndef ISOMETRIC - elevation = PI / 6.; - azimuth = PI / 6.; + elevation = PI / 6.; + azimuth = PI / 6.; #endif - auto dlg = g_pWndPreview = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( dlg, "GtkGenSurf Preview" ); - dlg.connect( "delete_event", G_CALLBACK( preview_close ), NULL ); - dlg.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); - gtk_window_set_transient_for( dlg, g_pWnd ); - gtk_window_set_default_size( dlg, 300, 400 ); + auto dlg = g_pWndPreview = ui::Window(ui::window_type::TOP); + gtk_window_set_title(dlg, "GtkGenSurf Preview"); + dlg.connect("delete_event", G_CALLBACK(preview_close), NULL); + dlg.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_window_set_transient_for(dlg, g_pWnd); + gtk_window_set_default_size(dlg, 300, 400); - auto vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - dlg.add(vbox); + auto vbox = ui::VBox(FALSE, 5); + vbox.show(); + dlg.add(vbox); #ifndef ISOMETRIC - auto hbox = ui::HBox( TRUE, 5 ); - hbox.show(); - vbox.pack_start( hbox, FALSE, TRUE, 0 ); - gtk_container_set_border_width( GTK_CONTAINER( hbox ), 3 ); - - label = ui::Label( "Elevation" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - hbox.pack_start( label, FALSE, TRUE, 0 ); - - auto adj = ui::Adjustment( 30, -90, 90, 1, 10, 0 ); - adj.connect( "value_changed", G_CALLBACK( preview_spin ), &elevation ); - spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); - hbox.pack_start( spin, FALSE, TRUE, 0 ); - spin.connect( "focus_out_event", G_CALLBACK( doublevariable_spinfocusout ), &elevation ); - - adj = ui::Adjustment( 30, 0, 359, 1, 10, 0 ); - adj.connect( "value_changed", G_CALLBACK( preview_spin ), &azimuth ); - spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); - gtk_spin_button_set_wrap( GTK_SPIN_BUTTON( spin ), TRUE ); - hbox.pack_end(spin, FALSE, TRUE, 0); - - label = ui::Label( "Azimuth" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - hbox.pack_end(label, FALSE, TRUE, 0); - spin.connect( "focus_out_event", G_CALLBACK( doublevariable_spinfocusout ), &azimuth ); + auto hbox = ui::HBox(TRUE, 5); + hbox.show(); + vbox.pack_start(hbox, FALSE, TRUE, 0); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 3); + + label = ui::Label("Elevation"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + hbox.pack_start(label, FALSE, TRUE, 0); + + auto adj = ui::Adjustment(30, -90, 90, 1, 10, 0); + adj.connect("value_changed", G_CALLBACK(preview_spin), &elevation); + spin = ui::SpinButton(adj, 1, 0); + spin.show(); + hbox.pack_start(spin, FALSE, TRUE, 0); + spin.connect("focus_out_event", G_CALLBACK(doublevariable_spinfocusout), &elevation); + + adj = ui::Adjustment(30, 0, 359, 1, 10, 0); + adj.connect("value_changed", G_CALLBACK(preview_spin), &azimuth); + spin = ui::SpinButton(adj, 1, 0); + spin.show(); + gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spin), TRUE); + hbox.pack_end(spin, FALSE, TRUE, 0); + + label = ui::Label("Azimuth"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + hbox.pack_end(label, FALSE, TRUE, 0); + spin.connect("focus_out_event", G_CALLBACK(doublevariable_spinfocusout), &azimuth); #endif - auto frame = ui::Frame(ui::null); - frame.show(); - gtk_frame_set_shadow_type( GTK_FRAME( frame ), GTK_SHADOW_IN ); - vbox.pack_start( frame, TRUE, TRUE, 0 ); + auto frame = ui::Frame(ui::null); + frame.show(); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); + vbox.pack_start(frame, TRUE, TRUE, 0); - g_pPreviewWidget = g_UIGtkTable.m_pfn_glwidget_new( FALSE, NULL ); + g_pPreviewWidget = g_UIGtkTable.m_pfn_glwidget_new(FALSE, NULL); - gtk_widget_set_events( g_pPreviewWidget, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK ); - g_pPreviewWidget.connect( "expose_event", G_CALLBACK( expose ), NULL ); - g_pPreviewWidget.connect( "motion_notify_event", G_CALLBACK( motion ), NULL ); - g_pPreviewWidget.connect( "button_press_event", - G_CALLBACK( button_press ), NULL ); + gtk_widget_set_events(g_pPreviewWidget, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); + g_pPreviewWidget.connect("expose_event", G_CALLBACK(expose), NULL); + g_pPreviewWidget.connect("motion_notify_event", G_CALLBACK(motion), NULL); + g_pPreviewWidget.connect("button_press_event", + G_CALLBACK(button_press), NULL); - g_pPreviewWidget.show(); - frame.add(ui::Widget(g_pPreviewWidget)); + g_pPreviewWidget.show(); + frame.add(ui::Widget(g_pPreviewWidget)); - if ( Preview ) { - g_pWndPreview.show(); - } + if (Preview) { + g_pWndPreview.show(); + } - UpdatePreview( true ); + UpdatePreview(true); } //============================================================= /* DrawPreview */ -void DrawPreview( Rect rc ){ +void DrawPreview(Rect rc) +{ #define COSXA 0.8660254037844 #define SINXA 0.5 #define COSYA 0.8660254037844 #define SINYA 0.5 - double L; - double x,y; - int i, j; - Point pt[8]; - XYZ v[8]; - char axis[3][2] = {"X","Y","Z"}; + double L; + double x, y; + int i, j; + Point pt[8]; + XYZ v[8]; + char axis[3][2] = {"X", "Y", "Z"}; #ifndef ISOMETRIC - evaluate(); + evaluate(); #endif - XLo = xmin; - XHi = xmax; - YLo = ymin; - YHi = ymax; - ZLo = zmin; - ZHi = zmax; - switch ( Plane ) - { - case PLANE_XY1: - ZHi = backface; - break; - case PLANE_XZ0: - YLo = backface; - break; - case PLANE_XZ1: - YHi = backface; - break; - case PLANE_YZ0: - XLo = backface; - break; - case PLANE_YZ1: - XHi = backface; - break; - default: - ZLo = backface; - } - - - - GetScaleFactor( rc ); - //PEN_GRID - g_GLTable.m_pfn_qglLineWidth( 1 ); - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); - g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); - - if ( Decimate > 0 && ( Game != QUAKE3 || UsePatches == 0 ) ) { - XYZ *vv; - - vv = (XYZ *) malloc( gNumNodes * sizeof( XYZ ) ); - for ( i = 0; i < gNumNodes; i++ ) - { - for ( j = 0; j < 3; j++ ) - vv[i].p[j] = (double)( gNode[i].p[j] ); - project( &vv[i] ); - } - - for ( i = 0; i < gNumTris; i++ ) - { - for ( j = 0; j < 3; j++ ) - Scale( rc,vv[gTri[i].v[j]],&pt[j] ); - - g_GLTable.m_pfn_qglBegin( GL_LINE_STRIP ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - g_GLTable.m_pfn_qglVertex2i( pt[1].x, pt[1].y ); - g_GLTable.m_pfn_qglVertex2i( pt[2].x, pt[2].y ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - g_GLTable.m_pfn_qglEnd(); - } - free( vv ); - } - else if ( Game == QUAKE3 && UsePatches != 0 ) { - int axis, ii, jj, k; - float u, v; - XYZ uv[3][3]; - XYZ Ctrl[3],out; - - switch ( Plane ) - { - case PLANE_XY0: - case PLANE_XY1: - k = 2; - break; - case PLANE_XZ0: - case PLANE_XZ1: - k = 1; - break; - default: - k = 0; - } - for ( i = 0; i < NH; i += 2 ) - { - for ( j = 0; j < NV; j += 2 ) - { - VectorCopy( xyz[i ][j ].p,uv[0][0].p ); - VectorCopy( xyz[i + 1][j ].p,uv[1][0].p ); - VectorCopy( xyz[i + 2][j ].p,uv[2][0].p ); - VectorCopy( xyz[i ][j + 1].p,uv[0][1].p ); - VectorCopy( xyz[i + 1][j + 1].p,uv[1][1].p ); - VectorCopy( xyz[i + 2][j + 1].p,uv[2][1].p ); - VectorCopy( xyz[i ][j + 2].p,uv[0][2].p ); - VectorCopy( xyz[i + 1][j + 2].p,uv[1][2].p ); - VectorCopy( xyz[i + 2][j + 2].p,uv[2][2].p ); - uv[1][0].p[k] = ( 4 * xyz[i + 1][j ].p[k] - xyz[i ][j ].p[k] - xyz[i + 2][j ].p[k] ) / 2; - uv[0][1].p[k] = ( 4 * xyz[i ][j + 1].p[k] - xyz[i ][j ].p[k] - xyz[i ][j + 2].p[k] ) / 2; - uv[2][1].p[k] = ( 4 * xyz[i + 2][j + 1].p[k] - xyz[i + 2][j ].p[k] - xyz[i + 2][j + 2].p[k] ) / 2; - uv[1][2].p[k] = ( 4 * xyz[i + 1][j + 2].p[k] - xyz[i ][j + 2].p[k] - xyz[i + 2][j + 2].p[k] ) / 2; - uv[1][1].p[k] = ( 16 * xyz[i + 1][j + 1].p[k] - - xyz[i ][j ].p[k] - 2 * xyz[i + 1][j ].p[k] - xyz[i + 2][j ].p[k] - - 2 * xyz[i ][j + 1].p[k] - 2 * xyz[i + 2][j + 1].p[k] - - xyz[i ][j + 2].p[k] - 2 * xyz[i + 1][j + 2].p[k] - xyz[i + 2][j + 2].p[k] ) / 4; - - for ( ii = 0; ii <= SUBDIVS; ii++ ) - { - if ( ii == 0 || ii == SUBDIVS / 2 || ii == SUBDIVS ) { - g_GLTable.m_pfn_qglLineWidth( 1 ); - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); - g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); - // PEN_GRID - } - else - { - g_GLTable.m_pfn_qglLineWidth( 1 ); - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); - g_GLTable.m_pfn_qglLineStipple( 1, 0xF0F0 ); - g_GLTable.m_pfn_qglEnable( GL_LINE_STIPPLE ); - // PEN_DASH - } - - u = (float)( ii ) / (float)( SUBDIVS ); - for ( jj = 0; jj < 3; jj++ ) - { - for ( axis = 0; axis < 3; axis++ ) - { - float a, b, c; - float qA, qB, qC; - a = (float)uv[0][jj].p[axis]; - b = (float)uv[1][jj].p[axis]; - c = (float)uv[2][jj].p[axis]; - qA = a - 2 * b + c; - qB = 2 * b - 2 * a; - qC = a; - Ctrl[jj].p[axis] = qA * u * u + qB * u + qC; - } - } - VectorCopy( Ctrl[0].p,out.p ); - project( &out ); - Scale( rc,out,&pt[0] ); - g_GLTable.m_pfn_qglBegin( GL_LINE_STRIP ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - for ( jj = 1; jj <= SUBDIVS; jj++ ) - { - v = (float)( jj ) / (float)( SUBDIVS ); - for ( axis = 0 ; axis < 3 ; axis++ ) - { - float a, b, c; - float qA, qB, qC; - a = (float)Ctrl[0].p[axis]; - b = (float)Ctrl[1].p[axis]; - c = (float)Ctrl[2].p[axis]; - qA = a - 2 * b + c; - qB = 2 * b - 2 * a; - qC = a; - out.p[axis] = qA * v * v + qB * v + qC; - } - project( &out ); - Scale( rc,out,&pt[0] ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - } - g_GLTable.m_pfn_qglEnd(); - } - for ( jj = 0; jj <= SUBDIVS; jj++ ) - { - if ( jj == 0 || jj == SUBDIVS / 2 || jj == SUBDIVS ) { - g_GLTable.m_pfn_qglLineWidth( 1 ); - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); - g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); - // PEN_GRID - } - else - { - g_GLTable.m_pfn_qglLineWidth( 1 ); - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); - g_GLTable.m_pfn_qglLineStipple( 1, 0xF0F0 ); - g_GLTable.m_pfn_qglEnable( GL_LINE_STIPPLE ); - // PEN_DASH - } - - v = (float)( jj ) / (float)( SUBDIVS ); - for ( ii = 0; ii < 3; ii++ ) - { - for ( axis = 0; axis < 3; axis++ ) - { - float a, b, c; - float qA, qB, qC; - a = (float)uv[ii][0].p[axis]; - b = (float)uv[ii][1].p[axis]; - c = (float)uv[ii][2].p[axis]; - qA = a - 2 * b + c; - qB = 2 * b - 2 * a; - qC = a; - Ctrl[ii].p[axis] = qA * v * v + qB * v + qC; - } - } - VectorCopy( Ctrl[0].p,out.p ); - project( &out ); - Scale( rc,out,&pt[0] ); - g_GLTable.m_pfn_qglBegin( GL_LINE_STRIP ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - for ( ii = 1; ii <= SUBDIVS; ii++ ) - { - u = (float)( ii ) / (float)( SUBDIVS ); - for ( axis = 0 ; axis < 3 ; axis++ ) - { - float a, b, c; - float qA, qB, qC; - a = (float)Ctrl[0].p[axis]; - b = (float)Ctrl[1].p[axis]; - c = (float)Ctrl[2].p[axis]; - qA = a - 2 * b + c; - qB = 2 * b - 2 * a; - qC = a; - out.p[axis] = qA * u * u + qB * u + qC; - } - project( &out ); - Scale( rc,out,&pt[0] ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - } - g_GLTable.m_pfn_qglEnd(); - } - } - } - } - else - { - for ( i = 0; i <= NH; i++ ) - { - Scale( rc,xyz[i][0],&pt[0] ); - g_GLTable.m_pfn_qglBegin( GL_LINE_STRIP ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - for ( j = 1; j <= NV; j++ ) - { - Scale( rc,xyz[i][j],&pt[0] ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - } - g_GLTable.m_pfn_qglEnd(); - } - for ( j = 0; j <= NV; j++ ) - { - Scale( rc,xyz[0][j],&pt[0] ); - g_GLTable.m_pfn_qglBegin( GL_LINE_STRIP ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - for ( i = 1; i <= NH; i++ ) - { - Scale( rc,xyz[i][j],&pt[0] ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - } - g_GLTable.m_pfn_qglEnd(); - } - } - - if ( Game != QUAKE3 || UsePatches == 0 ) { - // Draw lines from corners to base, and lines around base - for ( i = 0; i <= NH; i += NH ) - { - for ( j = 0; j <= NV; j += NV ) - { - VectorCopy( xyz[i][j].p, v[0].p ); - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - v[0].p[1] = backface; - break; - case PLANE_YZ0: - case PLANE_YZ1: - v[0].p[0] = backface; - break; - default: - v[0].p[2] = backface; - } - Scale( rc,xyz[i][j],&pt[0] ); + XLo = xmin; + XHi = xmax; + YLo = ymin; + YHi = ymax; + ZLo = zmin; + ZHi = zmax; + switch (Plane) { + case PLANE_XY1: + ZHi = backface; + break; + case PLANE_XZ0: + YLo = backface; + break; + case PLANE_XZ1: + YHi = backface; + break; + case PLANE_YZ0: + XLo = backface; + break; + case PLANE_YZ1: + XHi = backface; + break; + default: + ZLo = backface; + } + + + GetScaleFactor(rc); + //PEN_GRID + g_GLTable.m_pfn_qglLineWidth(1); + g_GLTable.m_pfn_qglColor3f(0, 1, 0); + g_GLTable.m_pfn_qglDisable(GL_LINE_STIPPLE); + + if (Decimate > 0 && (Game != QUAKE3 || UsePatches == 0)) { + XYZ *vv; + + vv = (XYZ *) malloc(gNumNodes * sizeof(XYZ)); + for (i = 0; i < gNumNodes; i++) { + for (j = 0; j < 3; j++) { + vv[i].p[j] = (double) (gNode[i].p[j]); + } + project(&vv[i]); + } + + for (i = 0; i < gNumTris; i++) { + for (j = 0; j < 3; j++) { + Scale(rc, vv[gTri[i].v[j]], &pt[j]); + } + + g_GLTable.m_pfn_qglBegin(GL_LINE_STRIP); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + g_GLTable.m_pfn_qglVertex2i(pt[1].x, pt[1].y); + g_GLTable.m_pfn_qglVertex2i(pt[2].x, pt[2].y); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + g_GLTable.m_pfn_qglEnd(); + } + free(vv); + } else if (Game == QUAKE3 && UsePatches != 0) { + int axis, ii, jj, k; + float u, v; + XYZ uv[3][3]; + XYZ Ctrl[3], out; + + switch (Plane) { + case PLANE_XY0: + case PLANE_XY1: + k = 2; + break; + case PLANE_XZ0: + case PLANE_XZ1: + k = 1; + break; + default: + k = 0; + } + for (i = 0; i < NH; i += 2) { + for (j = 0; j < NV; j += 2) { + VectorCopy(xyz[i][j].p, uv[0][0].p); + VectorCopy(xyz[i + 1][j].p, uv[1][0].p); + VectorCopy(xyz[i + 2][j].p, uv[2][0].p); + VectorCopy(xyz[i][j + 1].p, uv[0][1].p); + VectorCopy(xyz[i + 1][j + 1].p, uv[1][1].p); + VectorCopy(xyz[i + 2][j + 1].p, uv[2][1].p); + VectorCopy(xyz[i][j + 2].p, uv[0][2].p); + VectorCopy(xyz[i + 1][j + 2].p, uv[1][2].p); + VectorCopy(xyz[i + 2][j + 2].p, uv[2][2].p); + uv[1][0].p[k] = (4 * xyz[i + 1][j].p[k] - xyz[i][j].p[k] - xyz[i + 2][j].p[k]) / 2; + uv[0][1].p[k] = (4 * xyz[i][j + 1].p[k] - xyz[i][j].p[k] - xyz[i][j + 2].p[k]) / 2; + uv[2][1].p[k] = (4 * xyz[i + 2][j + 1].p[k] - xyz[i + 2][j].p[k] - xyz[i + 2][j + 2].p[k]) / 2; + uv[1][2].p[k] = (4 * xyz[i + 1][j + 2].p[k] - xyz[i][j + 2].p[k] - xyz[i + 2][j + 2].p[k]) / 2; + uv[1][1].p[k] = (16 * xyz[i + 1][j + 1].p[k] - + xyz[i][j].p[k] - 2 * xyz[i + 1][j].p[k] - xyz[i + 2][j].p[k] - + 2 * xyz[i][j + 1].p[k] - 2 * xyz[i + 2][j + 1].p[k] - + xyz[i][j + 2].p[k] - 2 * xyz[i + 1][j + 2].p[k] - xyz[i + 2][j + 2].p[k]) / 4; + + for (ii = 0; ii <= SUBDIVS; ii++) { + if (ii == 0 || ii == SUBDIVS / 2 || ii == SUBDIVS) { + g_GLTable.m_pfn_qglLineWidth(1); + g_GLTable.m_pfn_qglColor3f(0, 1, 0); + g_GLTable.m_pfn_qglDisable(GL_LINE_STIPPLE); + // PEN_GRID + } else { + g_GLTable.m_pfn_qglLineWidth(1); + g_GLTable.m_pfn_qglColor3f(0, 1, 0); + g_GLTable.m_pfn_qglLineStipple(1, 0xF0F0); + g_GLTable.m_pfn_qglEnable(GL_LINE_STIPPLE); + // PEN_DASH + } + + u = (float) (ii) / (float) (SUBDIVS); + for (jj = 0; jj < 3; jj++) { + for (axis = 0; axis < 3; axis++) { + float a, b, c; + float qA, qB, qC; + a = (float) uv[0][jj].p[axis]; + b = (float) uv[1][jj].p[axis]; + c = (float) uv[2][jj].p[axis]; + qA = a - 2 * b + c; + qB = 2 * b - 2 * a; + qC = a; + Ctrl[jj].p[axis] = qA * u * u + qB * u + qC; + } + } + VectorCopy(Ctrl[0].p, out.p); + project(&out); + Scale(rc, out, &pt[0]); + g_GLTable.m_pfn_qglBegin(GL_LINE_STRIP); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + for (jj = 1; jj <= SUBDIVS; jj++) { + v = (float) (jj) / (float) (SUBDIVS); + for (axis = 0; axis < 3; axis++) { + float a, b, c; + float qA, qB, qC; + a = (float) Ctrl[0].p[axis]; + b = (float) Ctrl[1].p[axis]; + c = (float) Ctrl[2].p[axis]; + qA = a - 2 * b + c; + qB = 2 * b - 2 * a; + qC = a; + out.p[axis] = qA * v * v + qB * v + qC; + } + project(&out); + Scale(rc, out, &pt[0]); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + } + g_GLTable.m_pfn_qglEnd(); + } + for (jj = 0; jj <= SUBDIVS; jj++) { + if (jj == 0 || jj == SUBDIVS / 2 || jj == SUBDIVS) { + g_GLTable.m_pfn_qglLineWidth(1); + g_GLTable.m_pfn_qglColor3f(0, 1, 0); + g_GLTable.m_pfn_qglDisable(GL_LINE_STIPPLE); + // PEN_GRID + } else { + g_GLTable.m_pfn_qglLineWidth(1); + g_GLTable.m_pfn_qglColor3f(0, 1, 0); + g_GLTable.m_pfn_qglLineStipple(1, 0xF0F0); + g_GLTable.m_pfn_qglEnable(GL_LINE_STIPPLE); + // PEN_DASH + } + + v = (float) (jj) / (float) (SUBDIVS); + for (ii = 0; ii < 3; ii++) { + for (axis = 0; axis < 3; axis++) { + float a, b, c; + float qA, qB, qC; + a = (float) uv[ii][0].p[axis]; + b = (float) uv[ii][1].p[axis]; + c = (float) uv[ii][2].p[axis]; + qA = a - 2 * b + c; + qB = 2 * b - 2 * a; + qC = a; + Ctrl[ii].p[axis] = qA * v * v + qB * v + qC; + } + } + VectorCopy(Ctrl[0].p, out.p); + project(&out); + Scale(rc, out, &pt[0]); + g_GLTable.m_pfn_qglBegin(GL_LINE_STRIP); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + for (ii = 1; ii <= SUBDIVS; ii++) { + u = (float) (ii) / (float) (SUBDIVS); + for (axis = 0; axis < 3; axis++) { + float a, b, c; + float qA, qB, qC; + a = (float) Ctrl[0].p[axis]; + b = (float) Ctrl[1].p[axis]; + c = (float) Ctrl[2].p[axis]; + qA = a - 2 * b + c; + qB = 2 * b - 2 * a; + qC = a; + out.p[axis] = qA * u * u + qB * u + qC; + } + project(&out); + Scale(rc, out, &pt[0]); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + } + g_GLTable.m_pfn_qglEnd(); + } + } + } + } else { + for (i = 0; i <= NH; i++) { + Scale(rc, xyz[i][0], &pt[0]); + g_GLTable.m_pfn_qglBegin(GL_LINE_STRIP); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + for (j = 1; j <= NV; j++) { + Scale(rc, xyz[i][j], &pt[0]); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + } + g_GLTable.m_pfn_qglEnd(); + } + for (j = 0; j <= NV; j++) { + Scale(rc, xyz[0][j], &pt[0]); + g_GLTable.m_pfn_qglBegin(GL_LINE_STRIP); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + for (i = 1; i <= NH; i++) { + Scale(rc, xyz[i][j], &pt[0]); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + } + g_GLTable.m_pfn_qglEnd(); + } + } + + if (Game != QUAKE3 || UsePatches == 0) { + // Draw lines from corners to base, and lines around base + for (i = 0; i <= NH; i += NH) { + for (j = 0; j <= NV; j += NV) { + VectorCopy(xyz[i][j].p, v[0].p); + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + v[0].p[1] = backface; + break; + case PLANE_YZ0: + case PLANE_YZ1: + v[0].p[0] = backface; + break; + default: + v[0].p[2] = backface; + } + Scale(rc, xyz[i][j], &pt[0]); #ifndef ISOMETRIC - project( &v[0] ); + project(&v[0]); #endif - Scale( rc,v[0],&pt[1] ); - g_GLTable.m_pfn_qglBegin( GL_LINE_STRIP ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - g_GLTable.m_pfn_qglVertex2i( pt[1].x, pt[1].y ); - g_GLTable.m_pfn_qglEnd(); - } - } - VectorCopy( xyz[ 0][ 0].p, v[0].p ); - VectorCopy( xyz[NH][ 0].p, v[1].p ); - VectorCopy( xyz[NH][NV].p, v[2].p ); - VectorCopy( xyz[ 0][NV].p, v[3].p ); - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - v[0].p[1] = backface;; - v[1].p[1] = v[0].p[1]; - v[2].p[1] = v[0].p[1]; - v[3].p[1] = v[0].p[1]; - break; - case PLANE_YZ0: - case PLANE_YZ1: - v[0].p[0] = backface; - v[1].p[0] = v[0].p[0]; - v[2].p[0] = v[0].p[0]; - v[3].p[0] = v[0].p[0]; - break; - default: - v[0].p[2] = backface; - v[1].p[2] = v[0].p[2]; - v[2].p[2] = v[0].p[2]; - v[3].p[2] = v[0].p[2]; - } + Scale(rc, v[0], &pt[1]); + g_GLTable.m_pfn_qglBegin(GL_LINE_STRIP); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + g_GLTable.m_pfn_qglVertex2i(pt[1].x, pt[1].y); + g_GLTable.m_pfn_qglEnd(); + } + } + VectorCopy(xyz[0][0].p, v[0].p); + VectorCopy(xyz[NH][0].p, v[1].p); + VectorCopy(xyz[NH][NV].p, v[2].p); + VectorCopy(xyz[0][NV].p, v[3].p); + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + v[0].p[1] = backface;; + v[1].p[1] = v[0].p[1]; + v[2].p[1] = v[0].p[1]; + v[3].p[1] = v[0].p[1]; + break; + case PLANE_YZ0: + case PLANE_YZ1: + v[0].p[0] = backface; + v[1].p[0] = v[0].p[0]; + v[2].p[0] = v[0].p[0]; + v[3].p[0] = v[0].p[0]; + break; + default: + v[0].p[2] = backface; + v[1].p[2] = v[0].p[2]; + v[2].p[2] = v[0].p[2]; + v[3].p[2] = v[0].p[2]; + } #ifndef ISOMETRIC - project( &v[3] ); + project(&v[3]); #endif - Scale( rc,v[3],&pt[0] ); - g_GLTable.m_pfn_qglBegin( GL_LINE_STRIP ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - for ( i = 0; i < 3; i++ ) - { + Scale(rc, v[3], &pt[0]); + g_GLTable.m_pfn_qglBegin(GL_LINE_STRIP); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + for (i = 0; i < 3; i++) { #ifndef ISOMETRIC - project( &v[i] ); + project(&v[i]); #endif - Scale( rc,v[i],&pt[1] ); - g_GLTable.m_pfn_qglVertex2i( pt[1].x, pt[1].y ); - } - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - g_GLTable.m_pfn_qglEnd(); - } + Scale(rc, v[i], &pt[1]); + g_GLTable.m_pfn_qglVertex2i(pt[1].x, pt[1].y); + } + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + g_GLTable.m_pfn_qglEnd(); + } - g_GLTable.m_pfn_qglLineWidth( 1 ); - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); - g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); + g_GLTable.m_pfn_qglLineWidth(1); + g_GLTable.m_pfn_qglColor3f(0, 1, 0); + g_GLTable.m_pfn_qglDisable(GL_LINE_STIPPLE); #ifdef ISOMETRIC - // Draw small depiction of coordinate axes - pt[0].x = rc.right - cxChar - cxChar / 2 - cyChar; - pt[0].y = rc.bottom - cyChar / 2 - cxChar / 2; - pt[1].x = pt[0].x + (int)( cyChar * COSXA ); - pt[1].y = pt[0].y - (int)( cyChar * SINXA ); - MoveToEx( hdc,pt[0].x,pt[0].y,NULL ); - LineTo( hdc,pt[1].x,pt[1].y ); - SetTextAlign( hdc,TA_LEFT | TA_TOP ); - TextOut( hdc,pt[1].x,pt[1].y - cyChar / 2,"X",1 ); - pt[1].x = pt[0].x - (int)( cyChar * COSYA ); - pt[1].y = pt[0].y - (int)( cyChar * SINYA ); - MoveToEx( hdc,pt[0].x,pt[0].y,NULL ); - LineTo( hdc,pt[1].x,pt[1].y ); - SetTextAlign( hdc,TA_RIGHT | TA_TOP ); - TextOut( hdc,pt[1].x,pt[1].y - cyChar / 2,"Y",1 ); - pt[1].x = pt[0].x; - pt[1].y = pt[0].y - cyChar; - MoveToEx( hdc,pt[0].x,pt[0].y,NULL ); - LineTo( hdc,pt[1].x,pt[1].y ); - SetTextAlign( hdc,TA_CENTER | TA_BOTTOM ); - TextOut( hdc,pt[1].x,pt[1].y,"Z",1 ); + // Draw small depiction of coordinate axes + pt[0].x = rc.right - cxChar - cxChar / 2 - cyChar; + pt[0].y = rc.bottom - cyChar / 2 - cxChar / 2; + pt[1].x = pt[0].x + (int)( cyChar * COSXA ); + pt[1].y = pt[0].y - (int)( cyChar * SINXA ); + MoveToEx( hdc,pt[0].x,pt[0].y,NULL ); + LineTo( hdc,pt[1].x,pt[1].y ); + SetTextAlign( hdc,TA_LEFT | TA_TOP ); + TextOut( hdc,pt[1].x,pt[1].y - cyChar / 2,"X",1 ); + pt[1].x = pt[0].x - (int)( cyChar * COSYA ); + pt[1].y = pt[0].y - (int)( cyChar * SINYA ); + MoveToEx( hdc,pt[0].x,pt[0].y,NULL ); + LineTo( hdc,pt[1].x,pt[1].y ); + SetTextAlign( hdc,TA_RIGHT | TA_TOP ); + TextOut( hdc,pt[1].x,pt[1].y - cyChar / 2,"Y",1 ); + pt[1].x = pt[0].x; + pt[1].y = pt[0].y - cyChar; + MoveToEx( hdc,pt[0].x,pt[0].y,NULL ); + LineTo( hdc,pt[1].x,pt[1].y ); + SetTextAlign( hdc,TA_CENTER | TA_BOTTOM ); + TextOut( hdc,pt[1].x,pt[1].y,"Z",1 ); #else - L = 2 * (double)cyChar / SF; - v[0].p[0] = 0.; - v[0].p[1] = 0.; - v[0].p[2] = 0.; - v[1].p[0] = L; - v[1].p[1] = 0.; - v[1].p[2] = 0.; - v[2].p[0] = 0.; - v[2].p[1] = L; - v[2].p[2] = 0.; - v[3].p[0] = 0.; - v[3].p[1] = 0.; - v[3].p[2] = L; - for ( i = 0; i <= 3; i++ ) - { - project( &v[i] ); - Scale( rc,v[i],&pt[i] ); - } - for ( i = 1; i <= 3; i++ ) - { - pt[i].x += -pt[0].x + rc.right - 2 * cyChar; - pt[i].y += -pt[0].y + rc.bottom + 2 * cyChar; - } - pt[0].x = rc.right - 2 * cyChar; - pt[0].y = rc.bottom + 2 * cyChar; - - for ( i = 1; i <= 3; i++ ) - { - g_GLTable.m_pfn_qglBegin( GL_LINES ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - g_GLTable.m_pfn_qglVertex2i( pt[i].x, pt[i].y ); - g_GLTable.m_pfn_qglEnd(); - texfont_write( axis[i - 1], pt[i].x - cxChar / 2,pt[i].y + cyChar / 2 ); - } + L = 2 * (double) cyChar / SF; + v[0].p[0] = 0.; + v[0].p[1] = 0.; + v[0].p[2] = 0.; + v[1].p[0] = L; + v[1].p[1] = 0.; + v[1].p[2] = 0.; + v[2].p[0] = 0.; + v[2].p[1] = L; + v[2].p[2] = 0.; + v[3].p[0] = 0.; + v[3].p[1] = 0.; + v[3].p[2] = L; + for (i = 0; i <= 3; i++) { + project(&v[i]); + Scale(rc, v[i], &pt[i]); + } + for (i = 1; i <= 3; i++) { + pt[i].x += -pt[0].x + rc.right - 2 * cyChar; + pt[i].y += -pt[0].y + rc.bottom + 2 * cyChar; + } + pt[0].x = rc.right - 2 * cyChar; + pt[0].y = rc.bottom + 2 * cyChar; + + for (i = 1; i <= 3; i++) { + g_GLTable.m_pfn_qglBegin(GL_LINES); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + g_GLTable.m_pfn_qglVertex2i(pt[i].x, pt[i].y); + g_GLTable.m_pfn_qglEnd(); + texfont_write(axis[i - 1], pt[i].x - cxChar / 2, pt[i].y + cyChar / 2); + } #endif - // Draw player model's bounding box in red to give a sense of scale - // PEN_RED - g_GLTable.m_pfn_qglLineWidth( 2 ); - g_GLTable.m_pfn_qglColor3f( 1, 0, 0 ); - g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); - - switch ( Plane ) - { - case PLANE_XY1: - v[0].p[0] = xyz[NH / 2][NV / 2].p[0] + PlayerBox[Game].x[0]; - v[0].p[1] = xyz[NH / 2][NV / 2].p[1] + PlayerBox[Game].y[0]; - v[0].p[2] = zmin - PlayerBox[Game].z[0] - 32; - break; - case PLANE_XZ0: - v[0].p[0] = ( xmax + xmin ) / 2 + PlayerBox[Game].x[0]; - v[0].p[1] = ymax + 64; - v[0].p[2] = zmin; - break; - case PLANE_XZ1: - v[0].p[0] = ( xmax + xmin ) / 2 + PlayerBox[Game].x[0]; - v[0].p[1] = ymin - 64; - v[0].p[2] = zmin; - break; - case PLANE_YZ0: - v[0].p[0] = xmax + 64; - v[0].p[1] = ( ymax + ymin ) / 2 + PlayerBox[Game].y[0]; - v[0].p[2] = zmin; - break; - case PLANE_YZ1: - v[0].p[0] = xmin - 64; - v[0].p[1] = ( ymax + ymin ) / 2 + PlayerBox[Game].y[0]; - v[0].p[2] = zmin; - break; - default: - // Put player on a node. For patches, put on an even numbered node. - if ( Game == QUAKE3 && UsePatches != 0 ) { - if ( NH > 2 ) { - x = Hll + dh * (int)( NH / 2 + 1 ); - } - else{ - x = Hll + dh * (int)( NH / 2 ); - } - if ( NV > 2 ) { - y = Vll + dv * (int)( NV / 2 + 1 ); - } - else{ - y = Vll + dv * (int)( NV / 2 ); - } - } - else - { - if ( NH > 1 ) { - x = Hll + dh * (int)( NH / 2 ); - } - else{ - x = Hll + dh / 2; - } - if ( NV > 1 ) { - y = Vll + dv * (int)( NV / 2 ); - } - else{ - y = Vll + dv / 2; - } - } + // Draw player model's bounding box in red to give a sense of scale + // PEN_RED + g_GLTable.m_pfn_qglLineWidth(2); + g_GLTable.m_pfn_qglColor3f(1, 0, 0); + g_GLTable.m_pfn_qglDisable(GL_LINE_STIPPLE); + + switch (Plane) { + case PLANE_XY1: + v[0].p[0] = xyz[NH / 2][NV / 2].p[0] + PlayerBox[Game].x[0]; + v[0].p[1] = xyz[NH / 2][NV / 2].p[1] + PlayerBox[Game].y[0]; + v[0].p[2] = zmin - PlayerBox[Game].z[0] - 32; + break; + case PLANE_XZ0: + v[0].p[0] = (xmax + xmin) / 2 + PlayerBox[Game].x[0]; + v[0].p[1] = ymax + 64; + v[0].p[2] = zmin; + break; + case PLANE_XZ1: + v[0].p[0] = (xmax + xmin) / 2 + PlayerBox[Game].x[0]; + v[0].p[1] = ymin - 64; + v[0].p[2] = zmin; + break; + case PLANE_YZ0: + v[0].p[0] = xmax + 64; + v[0].p[1] = (ymax + ymin) / 2 + PlayerBox[Game].y[0]; + v[0].p[2] = zmin; + break; + case PLANE_YZ1: + v[0].p[0] = xmin - 64; + v[0].p[1] = (ymax + ymin) / 2 + PlayerBox[Game].y[0]; + v[0].p[2] = zmin; + break; + default: + // Put player on a node. For patches, put on an even numbered node. + if (Game == QUAKE3 && UsePatches != 0) { + if (NH > 2) { + x = Hll + dh * (int) (NH / 2 + 1); + } else { + x = Hll + dh * (int) (NH / 2); + } + if (NV > 2) { + y = Vll + dv * (int) (NV / 2 + 1); + } else { + y = Vll + dv * (int) (NV / 2); + } + } else { + if (NH > 1) { + x = Hll + dh * (int) (NH / 2); + } else { + x = Hll + dh / 2; + } + if (NV > 1) { + y = Vll + dv * (int) (NV / 2); + } else { + y = Vll + dv / 2; + } + } // x = (Hll+Hur)/2.; // y = (Vll+Vur)/2.; - v[0].p[0] = x + PlayerBox[Game].x[0]; - v[0].p[1] = y + PlayerBox[Game].y[0]; - v[0].p[2] = PlayerStartZ( x,y ) + PlayerBox[Game].z[0] + 8; // add 8 cuz I'm a pessimist - } - v[1].p[0] = v[0].p[0] + PlayerBox[Game].x[1] - PlayerBox[Game].x[0]; - v[1].p[1] = v[0].p[1]; - v[1].p[2] = v[0].p[2]; - v[2].p[0] = v[1].p[0]; - v[2].p[1] = v[1].p[1] + PlayerBox[Game].y[1] - PlayerBox[Game].y[0]; - v[2].p[2] = v[0].p[2]; - v[3].p[0] = v[0].p[0]; - v[3].p[1] = v[2].p[1]; - v[3].p[2] = v[0].p[2]; - VectorCopy( v[0].p,v[4].p ); - VectorCopy( v[1].p,v[5].p ); - VectorCopy( v[2].p,v[6].p ); - VectorCopy( v[3].p,v[7].p ); - v[4].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0]; - v[5].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0]; - v[6].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0]; - v[7].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0]; - for ( i = 0; i <= 7; i++ ) - { + v[0].p[0] = x + PlayerBox[Game].x[0]; + v[0].p[1] = y + PlayerBox[Game].y[0]; + v[0].p[2] = PlayerStartZ(x, y) + PlayerBox[Game].z[0] + 8; // add 8 cuz I'm a pessimist + } + v[1].p[0] = v[0].p[0] + PlayerBox[Game].x[1] - PlayerBox[Game].x[0]; + v[1].p[1] = v[0].p[1]; + v[1].p[2] = v[0].p[2]; + v[2].p[0] = v[1].p[0]; + v[2].p[1] = v[1].p[1] + PlayerBox[Game].y[1] - PlayerBox[Game].y[0]; + v[2].p[2] = v[0].p[2]; + v[3].p[0] = v[0].p[0]; + v[3].p[1] = v[2].p[1]; + v[3].p[2] = v[0].p[2]; + VectorCopy(v[0].p, v[4].p); + VectorCopy(v[1].p, v[5].p); + VectorCopy(v[2].p, v[6].p); + VectorCopy(v[3].p, v[7].p); + v[4].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0]; + v[5].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0]; + v[6].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0]; + v[7].p[2] += PlayerBox[Game].z[1] - PlayerBox[Game].z[0]; + for (i = 0; i <= 7; i++) { #ifndef ISOMETRIC - project( &v[i] ); + project(&v[i]); #endif - Scale( rc,v[i],&pt[i] ); - } - g_GLTable.m_pfn_qglBegin( GL_LINE_STRIP ); - g_GLTable.m_pfn_qglVertex2i( pt[3].x, pt[3].y ); - for ( i = 0; i <= 3; i++ ) - g_GLTable.m_pfn_qglVertex2i( pt[i].x, pt[i].y ); - g_GLTable.m_pfn_qglEnd(); - g_GLTable.m_pfn_qglBegin( GL_LINE_STRIP ); - g_GLTable.m_pfn_qglVertex2i( pt[7].x, pt[7].y ); - for ( i = 4; i <= 7; i++ ) - g_GLTable.m_pfn_qglVertex2i( pt[i].x, pt[i].y ); - g_GLTable.m_pfn_qglEnd(); - g_GLTable.m_pfn_qglBegin( GL_LINES ); - for ( i = 0; i <= 3; i++ ) - { - g_GLTable.m_pfn_qglVertex2i( pt[i].x,pt[i].y ); - g_GLTable.m_pfn_qglVertex2i( pt[i + 4].x,pt[i + 4].y ); - } - g_GLTable.m_pfn_qglEnd(); - - g_GLTable.m_pfn_qglLineWidth( 1 ); - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); - g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); + Scale(rc, v[i], &pt[i]); + } + g_GLTable.m_pfn_qglBegin(GL_LINE_STRIP); + g_GLTable.m_pfn_qglVertex2i(pt[3].x, pt[3].y); + for (i = 0; i <= 3; i++) { + g_GLTable.m_pfn_qglVertex2i(pt[i].x, pt[i].y); + } + g_GLTable.m_pfn_qglEnd(); + g_GLTable.m_pfn_qglBegin(GL_LINE_STRIP); + g_GLTable.m_pfn_qglVertex2i(pt[7].x, pt[7].y); + for (i = 4; i <= 7; i++) { + g_GLTable.m_pfn_qglVertex2i(pt[i].x, pt[i].y); + } + g_GLTable.m_pfn_qglEnd(); + g_GLTable.m_pfn_qglBegin(GL_LINES); + for (i = 0; i <= 3; i++) { + g_GLTable.m_pfn_qglVertex2i(pt[i].x, pt[i].y); + g_GLTable.m_pfn_qglVertex2i(pt[i + 4].x, pt[i + 4].y); + } + g_GLTable.m_pfn_qglEnd(); + + g_GLTable.m_pfn_qglLineWidth(1); + g_GLTable.m_pfn_qglColor3f(0, 1, 0); + g_GLTable.m_pfn_qglDisable(GL_LINE_STIPPLE); } + //============================================================= -void DrawGrid( Rect rc ){ - int i, j, k; - double h,w,x,y; - Point pt[2]; - Rect rcBox; - - w = (double)( rc.right - rc.left + 1 ) - cxChar; - h = (double)( rc.top - rc.bottom + 1 ) - cxChar - cyChar; - - SFG = w / ( Hur - Hll ); - SFG = min( SFG, h / ( Vur - Vll ) ); - - // Center drawing - X0G = (int)( rc.left + rc.right - (int)( SFG * ( Hur - Hll ) ) ) / 2; - Y0G = (int)( rc.top + rc.bottom + cyChar - (int)( SFG * ( Vur - Vll ) ) ) / 2; - - g_GLTable.m_pfn_qglLineWidth( 2 ); - g_GLTable.m_pfn_qglColor3f( 0, 1, 0 ); - g_GLTable.m_pfn_qglDisable( GL_LINE_STIPPLE ); - - pt[0].y = Y0G; - pt[1].y = Y0G + (int)( SFG * ( Vur - Vll ) ); - g_GLTable.m_pfn_qglBegin( GL_LINES ); - for ( i = 0; i <= NH; i++ ) - { - x = Hll + i * dh; - pt[0].x = X0G + (int)( SFG * ( x - Hll ) ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[0].y ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x, pt[1].y ); - } - g_GLTable.m_pfn_qglEnd(); - pt[0].x = X0G; - pt[1].x = X0G + (int)( SFG * ( Hur - Hll ) ); - g_GLTable.m_pfn_qglBegin( GL_LINES ); - for ( i = 0; i <= NV; i++ ) - { - y = Vll + i * dv; - pt[0].y = Y0G + (int)( SFG * ( Vur - y ) ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x,pt[0].y ); - g_GLTable.m_pfn_qglVertex2i( pt[1].x,pt[0].y ); - } - g_GLTable.m_pfn_qglEnd(); - - g_GLTable.m_pfn_qglLineWidth( 1 ); - - // Draw axes - pt[0].x = rc.right - cyChar - cxChar - cyChar / 2; - pt[0].y = rc.bottom + cyChar / 2; - pt[1].x = pt[0].x + cyChar; - pt[1].y = pt[0].y; - g_GLTable.m_pfn_qglBegin( GL_LINES ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x,pt[0].y ); - g_GLTable.m_pfn_qglVertex2i( pt[1].x,pt[1].y ); - g_GLTable.m_pfn_qglEnd(); - switch ( Plane ) - { - case PLANE_YZ0: - case PLANE_YZ1: - texfont_write( "Y", pt[1].x, pt[1].y + cyChar / 2 ); - break; - default: - texfont_write( "X", pt[1].x, pt[1].y + cyChar / 2 ); - } - pt[1].x = pt[0].x; - pt[1].y = pt[0].y + cyChar; - g_GLTable.m_pfn_qglBegin( GL_LINES ); - g_GLTable.m_pfn_qglVertex2i( pt[0].x,pt[0].y ); - g_GLTable.m_pfn_qglVertex2i( pt[1].x,pt[1].y ); - g_GLTable.m_pfn_qglEnd(); - switch ( Plane ) - { - case PLANE_XY0: - case PLANE_XY1: - texfont_write( "Y", pt[1].x - cyChar / 2, pt[1].y + cyChar ); - break; - default: - texfont_write( "Z", pt[1].x - cyChar / 2, pt[1].y + cyChar ); - } - - // Denote fixed points with a 5x5 red rectangle - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - if ( xyz[i][j].fixed ) { - x = Hll + i * dh; - y = Vll + j * dv; - rcBox.left = X0G + (int)( SFG * ( x - Hll ) ) - 2; - rcBox.top = Y0G + (int)( SFG * ( Vur - y ) ) + 2; - rcBox.right = rcBox.left + 5; - rcBox.bottom = rcBox.top - 5; - - DRAW_QUAD( rcBox, 1,0,0 ); - } - } - } - - // Denote currently selected point with a 5x5 green rectangle - if ( NumVerticesSelected ) { - for ( k = 0; k < NumVerticesSelected; k++ ) - { - x = Hll + Vertex[k].i * dh; - y = Vll + Vertex[k].j * dv; - rcBox.left = X0G + (int)( SFG * ( x - Hll ) ) - 2; - rcBox.top = Y0G + (int)( SFG * ( Vur - y ) ) + 2; - rcBox.right = rcBox.left + 5; - rcBox.bottom = rcBox.top - 5; - - DRAW_QUAD( rcBox, 0,1,0 ); - } - } - - // Unmovable vertices - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - if ( !CanEdit( i,j ) ) { - x = Hll + i * dh; - y = Vll + j * dv; - rcBox.left = X0G + (int)( SFG * ( x - Hll ) ) - 2; - rcBox.top = Y0G + (int)( SFG * ( Vur - y ) ) + 2; - rcBox.right = rcBox.left + 5; - rcBox.bottom = rcBox.top - 5; - - DRAW_QUAD( rcBox, 1,1,0 ); - } - } - } - - // Legend - rcBox.left = rc.left + cxChar / 2 - 2; - rcBox.top = rc.top - cyChar / 2 - 2; - rcBox.right = rcBox.left + 5; - rcBox.bottom = rcBox.top - 5; - DRAW_QUAD( rcBox, 1,0,0 ); - texfont_write( "Fixed points", rcBox.right + cxChar,rcBox.top - 4 + cyChar / 2 ); - - rcBox.top -= cyChar; - rcBox.bottom -= cyChar; - DRAW_QUAD( rcBox, 1,1,0 ); - texfont_write( "Not movable", rcBox.right + cxChar, rcBox.top - 4 + cyChar / 2 ); - - rcBox.top -= cyChar; - rcBox.bottom -= cyChar; - DRAW_QUAD( rcBox, 0,1,0 ); - texfont_write( "Selected", rcBox.right + cxChar, rcBox.top - 4 + cyChar / 2 ); +void DrawGrid(Rect rc) +{ + int i, j, k; + double h, w, x, y; + Point pt[2]; + Rect rcBox; + + w = (double) (rc.right - rc.left + 1) - cxChar; + h = (double) (rc.top - rc.bottom + 1) - cxChar - cyChar; + + SFG = w / (Hur - Hll); + SFG = min(SFG, h / (Vur - Vll)); + + // Center drawing + X0G = (int) (rc.left + rc.right - (int) (SFG * (Hur - Hll))) / 2; + Y0G = (int) (rc.top + rc.bottom + cyChar - (int) (SFG * (Vur - Vll))) / 2; + + g_GLTable.m_pfn_qglLineWidth(2); + g_GLTable.m_pfn_qglColor3f(0, 1, 0); + g_GLTable.m_pfn_qglDisable(GL_LINE_STIPPLE); + + pt[0].y = Y0G; + pt[1].y = Y0G + (int) (SFG * (Vur - Vll)); + g_GLTable.m_pfn_qglBegin(GL_LINES); + for (i = 0; i <= NH; i++) { + x = Hll + i * dh; + pt[0].x = X0G + (int) (SFG * (x - Hll)); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[1].y); + } + g_GLTable.m_pfn_qglEnd(); + pt[0].x = X0G; + pt[1].x = X0G + (int) (SFG * (Hur - Hll)); + g_GLTable.m_pfn_qglBegin(GL_LINES); + for (i = 0; i <= NV; i++) { + y = Vll + i * dv; + pt[0].y = Y0G + (int) (SFG * (Vur - y)); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + g_GLTable.m_pfn_qglVertex2i(pt[1].x, pt[0].y); + } + g_GLTable.m_pfn_qglEnd(); + + g_GLTable.m_pfn_qglLineWidth(1); + + // Draw axes + pt[0].x = rc.right - cyChar - cxChar - cyChar / 2; + pt[0].y = rc.bottom + cyChar / 2; + pt[1].x = pt[0].x + cyChar; + pt[1].y = pt[0].y; + g_GLTable.m_pfn_qglBegin(GL_LINES); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + g_GLTable.m_pfn_qglVertex2i(pt[1].x, pt[1].y); + g_GLTable.m_pfn_qglEnd(); + switch (Plane) { + case PLANE_YZ0: + case PLANE_YZ1: + texfont_write("Y", pt[1].x, pt[1].y + cyChar / 2); + break; + default: + texfont_write("X", pt[1].x, pt[1].y + cyChar / 2); + } + pt[1].x = pt[0].x; + pt[1].y = pt[0].y + cyChar; + g_GLTable.m_pfn_qglBegin(GL_LINES); + g_GLTable.m_pfn_qglVertex2i(pt[0].x, pt[0].y); + g_GLTable.m_pfn_qglVertex2i(pt[1].x, pt[1].y); + g_GLTable.m_pfn_qglEnd(); + switch (Plane) { + case PLANE_XY0: + case PLANE_XY1: + texfont_write("Y", pt[1].x - cyChar / 2, pt[1].y + cyChar); + break; + default: + texfont_write("Z", pt[1].x - cyChar / 2, pt[1].y + cyChar); + } + + // Denote fixed points with a 5x5 red rectangle + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + if (xyz[i][j].fixed) { + x = Hll + i * dh; + y = Vll + j * dv; + rcBox.left = X0G + (int) (SFG * (x - Hll)) - 2; + rcBox.top = Y0G + (int) (SFG * (Vur - y)) + 2; + rcBox.right = rcBox.left + 5; + rcBox.bottom = rcBox.top - 5; + + DRAW_QUAD(rcBox, 1, 0, 0); + } + } + } + + // Denote currently selected point with a 5x5 green rectangle + if (NumVerticesSelected) { + for (k = 0; k < NumVerticesSelected; k++) { + x = Hll + Vertex[k].i * dh; + y = Vll + Vertex[k].j * dv; + rcBox.left = X0G + (int) (SFG * (x - Hll)) - 2; + rcBox.top = Y0G + (int) (SFG * (Vur - y)) + 2; + rcBox.right = rcBox.left + 5; + rcBox.bottom = rcBox.top - 5; + + DRAW_QUAD(rcBox, 0, 1, 0); + } + } + + // Unmovable vertices + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + if (!CanEdit(i, j)) { + x = Hll + i * dh; + y = Vll + j * dv; + rcBox.left = X0G + (int) (SFG * (x - Hll)) - 2; + rcBox.top = Y0G + (int) (SFG * (Vur - y)) + 2; + rcBox.right = rcBox.left + 5; + rcBox.bottom = rcBox.top - 5; + + DRAW_QUAD(rcBox, 1, 1, 0); + } + } + } + + // Legend + rcBox.left = rc.left + cxChar / 2 - 2; + rcBox.top = rc.top - cyChar / 2 - 2; + rcBox.right = rcBox.left + 5; + rcBox.bottom = rcBox.top - 5; + DRAW_QUAD(rcBox, 1, 0, 0); + texfont_write("Fixed points", rcBox.right + cxChar, rcBox.top - 4 + cyChar / 2); + + rcBox.top -= cyChar; + rcBox.bottom -= cyChar; + DRAW_QUAD(rcBox, 1, 1, 0); + texfont_write("Not movable", rcBox.right + cxChar, rcBox.top - 4 + cyChar / 2); + + rcBox.top -= cyChar; + rcBox.bottom -= cyChar; + DRAW_QUAD(rcBox, 0, 1, 0); + texfont_write("Selected", rcBox.right + cxChar, rcBox.top - 4 + cyChar / 2); } //============================================================= -void GetScaleFactor( Rect rc ){ +void GetScaleFactor(Rect rc) +{ #ifdef ISOMETRIC - double h, w; + double h, w; - w = (double)( rc.right - rc.left + 1 ) - cxChar; - h = (double)( rc.top - rc.bottom + 1 ) - cxChar; + w = (double)( rc.right - rc.left + 1 ) - cxChar; + h = (double)( rc.top - rc.bottom + 1 ) - cxChar; - SF = w / ( ( XHi - XLo ) * COSXA + ( YHi - YLo ) * COSYA ); - SF = min( SF, h / ( ( XHi - XLo ) * SINXA + ( YHi - YLo ) * SINYA + ZHi - ZLo ) ); - // Center drawing - X0 = (int)( rc.left + rc.right - (int)( SF * ( ( XHi - XLo ) * COSXA + ( YHi - YLo ) * COSYA ) ) ) / 2; - Y0 = (int)( rc.top + rc.bottom - (int)( SF * ( ( XHi - XLo ) * SINXA + ( YHi - YLo ) * SINYA + ZHi - ZLo ) ) ) / 2; + SF = w / ( ( XHi - XLo ) * COSXA + ( YHi - YLo ) * COSYA ); + SF = min( SF, h / ( ( XHi - XLo ) * SINXA + ( YHi - YLo ) * SINYA + ZHi - ZLo ) ); + // Center drawing + X0 = (int)( rc.left + rc.right - (int)( SF * ( ( XHi - XLo ) * COSXA + ( YHi - YLo ) * COSYA ) ) ) / 2; + Y0 = (int)( rc.top + rc.bottom - (int)( SF * ( ( XHi - XLo ) * SINXA + ( YHi - YLo ) * SINYA + ZHi - ZLo ) ) ) / 2; #else - double h, w; + double h, w; - w = (double)( rc.right - rc.left + 1 ) - cxChar; - h = (double)( rc.top - rc.bottom + 1 ) - cxChar; + w = (double) (rc.right - rc.left + 1) - cxChar; + h = (double) (rc.top - rc.bottom + 1) - cxChar; - SF = w / ( Hhi - Hlo ); - SF = min( SF, h / ( Vhi - Vlo ) ); - X0 = (int)( rc.left + rc.right - (int)( SF * ( Hhi - Hlo ) ) ) / 2; - Y0 = (int)( rc.top + rc.bottom + (int)( SF * ( Vhi - Vlo ) ) ) / 2; + SF = w / (Hhi - Hlo); + SF = min(SF, h / (Vhi - Vlo)); + X0 = (int) (rc.left + rc.right - (int) (SF * (Hhi - Hlo))) / 2; + Y0 = (int) (rc.top + rc.bottom + (int) (SF * (Vhi - Vlo))) / 2; #endif } //============================================================= -void Scale( Rect rc,XYZ xyz,Point *pt ){ +void Scale(Rect rc, XYZ xyz, Point *pt) +{ #ifdef ISOMETRIC - pt[0].x = X0 + (int)( SF * ( ( xyz.p[0] - XLo ) * COSXA + - ( YHi - xyz.p[1] ) * COSYA ) ); - pt[0].y = Y0 + (int)( SF * ( ZHi - xyz.p[2] + - ( YHi - xyz.p[1] ) * SINYA + - ( XHi - xyz.p[0] ) * SINXA ) ); + pt[0].x = X0 + (int)( SF * ( ( xyz.p[0] - XLo ) * COSXA + + ( YHi - xyz.p[1] ) * COSYA ) ); + pt[0].y = Y0 + (int)( SF * ( ZHi - xyz.p[2] + + ( YHi - xyz.p[1] ) * SINYA + + ( XHi - xyz.p[0] ) * SINXA ) ); #else - pt[0].x = X0 + (int)( SF * ( xyz.pp[0] - Hlo ) ); - pt[0].y = Y0 - (int)( SF * ( Vhi - xyz.pp[1] ) ); + pt[0].x = X0 + (int) (SF * (xyz.pp[0] - Hlo)); + pt[0].y = Y0 - (int) (SF * (Vhi - xyz.pp[1])); #endif } #ifndef ISOMETRIC + /* ======================================================================= */ -void project( XYZ *v ){ - // project a 3D point (x,y,z) onto view plane - double x, y, z, xa, ya, za; +void project(XYZ *v) +{ + // project a 3D point (x,y,z) onto view plane + double x, y, z, xa, ya, za; - x = v->p[0]; - y = v->p[1]; - z = v->p[2]; + x = v->p[0]; + y = v->p[1]; + z = v->p[2]; - // yaw - xa = ct[0] * x - st[0] * z; - za = st[0] * x + ct[0] * z; + // yaw + xa = ct[0] * x - st[0] * z; + za = st[0] * x + ct[0] * z; - // roll - x = ct[1] * xa + st[1] * y; - ya = ct[1] * y - st[1] * xa; + // roll + x = ct[1] * xa + st[1] * y; + ya = ct[1] * y - st[1] * xa; - // azimuth - z = ct[2] * za - st[2] * ya; - y = ct[2] * ya + st[2] * za; + // azimuth + z = ct[2] * za - st[2] * ya; + y = ct[2] * ya + st[2] * za; - // horizontal and vertical projections: + // horizontal and vertical projections: // v->pp[0] = D*x/z; // v->pp[1] = D*y/z; - v->pp[0] = -y; - v->pp[1] = x; - v->pp[2] = z; - - // NOTE: if perspective transformation is desired, - // set "persp" to the range from the surface, - // then: - // v->projected_h = -v->projected_h * persp/(v->projected_z-persp); - // v->projected_v = -v->projected_v * persp/(v->projected_z-persp); + v->pp[0] = -y; + v->pp[1] = x; + v->pp[2] = z; + + // NOTE: if perspective transformation is desired, + // set "persp" to the range from the surface, + // then: + // v->projected_h = -v->projected_h * persp/(v->projected_z-persp); + // v->projected_v = -v->projected_v * persp/(v->projected_z-persp); } + /*=======================================================================*/ -void evaluate(){ - int i, j; - XYZ v[4]; - - if ( elevation > PI ) { - elevation -= 2. * PI; - } - roll = elevation * sin( azimuth ); - yaw = 1.5 * PI + elevation*cos( azimuth ); - - // Find angles from midpoint to viewpoint: - st[0] = sin( yaw ); - st[1] = sin( roll ); - st[2] = sin( azimuth ); - ct[0] = cos( yaw ); - ct[1] = cos( roll ); - ct[2] = cos( azimuth ); - - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - project( &xyz[i][j] ); - } - } - - Hhi = xyz[0][0].pp[0]; - Hlo = Hhi; - Vhi = xyz[0][0].pp[1]; - Vlo = Vhi; - for ( i = 0; i <= NH; i++ ) - { - for ( j = 0; j <= NV; j++ ) - { - Hlo = min( Hlo,xyz[i][j].pp[0] ); - Hhi = max( Hhi,xyz[i][j].pp[0] ); - Vlo = min( Vlo,xyz[i][j].pp[1] ); - Vhi = max( Vhi,xyz[i][j].pp[1] ); - } - } - - // Include backface in min-max - VectorCopy( xyz[ 0][ 0].p,v[0].p ); - VectorCopy( xyz[NH][ 0].p,v[1].p ); - VectorCopy( xyz[NH][NV].p,v[2].p ); - VectorCopy( xyz[ 0][NV].p,v[3].p ); - switch ( Plane ) - { - case PLANE_XZ0: - case PLANE_XZ1: - v[0].p[1] = backface; - v[1].p[1] = v[0].p[1]; - v[2].p[1] = v[0].p[1]; - v[3].p[1] = v[0].p[1]; - break; - case PLANE_YZ0: - case PLANE_YZ1: - v[0].p[0] = backface; - v[1].p[0] = v[0].p[0]; - v[2].p[0] = v[0].p[0]; - v[3].p[0] = v[0].p[0]; - break; - default: - v[0].p[2] = backface; - v[1].p[2] = v[0].p[2]; - v[2].p[2] = v[0].p[2]; - v[3].p[2] = v[0].p[2]; - } - for ( i = 0; i <= 3; i++ ) - { - project( &v[i] ); - Hlo = min( Hlo,v[i].pp[0] ); - Hhi = max( Hhi,v[i].pp[0] ); - Vlo = min( Vlo,v[i].pp[1] ); - Vhi = max( Vhi,v[i].pp[1] ); - } +void evaluate() +{ + int i, j; + XYZ v[4]; + + if (elevation > PI) { + elevation -= 2. * PI; + } + roll = elevation * sin(azimuth); + yaw = 1.5 * PI + elevation * cos(azimuth); + + // Find angles from midpoint to viewpoint: + st[0] = sin(yaw); + st[1] = sin(roll); + st[2] = sin(azimuth); + ct[0] = cos(yaw); + ct[1] = cos(roll); + ct[2] = cos(azimuth); + + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + project(&xyz[i][j]); + } + } + + Hhi = xyz[0][0].pp[0]; + Hlo = Hhi; + Vhi = xyz[0][0].pp[1]; + Vlo = Vhi; + for (i = 0; i <= NH; i++) { + for (j = 0; j <= NV; j++) { + Hlo = min(Hlo, xyz[i][j].pp[0]); + Hhi = max(Hhi, xyz[i][j].pp[0]); + Vlo = min(Vlo, xyz[i][j].pp[1]); + Vhi = max(Vhi, xyz[i][j].pp[1]); + } + } + + // Include backface in min-max + VectorCopy(xyz[0][0].p, v[0].p); + VectorCopy(xyz[NH][0].p, v[1].p); + VectorCopy(xyz[NH][NV].p, v[2].p); + VectorCopy(xyz[0][NV].p, v[3].p); + switch (Plane) { + case PLANE_XZ0: + case PLANE_XZ1: + v[0].p[1] = backface; + v[1].p[1] = v[0].p[1]; + v[2].p[1] = v[0].p[1]; + v[3].p[1] = v[0].p[1]; + break; + case PLANE_YZ0: + case PLANE_YZ1: + v[0].p[0] = backface; + v[1].p[0] = v[0].p[0]; + v[2].p[0] = v[0].p[0]; + v[3].p[0] = v[0].p[0]; + break; + default: + v[0].p[2] = backface; + v[1].p[2] = v[0].p[2]; + v[2].p[2] = v[0].p[2]; + v[3].p[2] = v[0].p[2]; + } + for (i = 0; i <= 3; i++) { + project(&v[i]); + Hlo = min(Hlo, v[i].pp[0]); + Hhi = max(Hhi, v[i].pp[0]); + Vlo = min(Vlo, v[i].pp[1]); + Vhi = max(Vhi, v[i].pp[1]); + } } + #endif diff --git a/contrib/hydratoolz/plugin.cpp b/contrib/hydratoolz/plugin.cpp index 14f2c4b8..1753c785 100644 --- a/contrib/hydratoolz/plugin.cpp +++ b/contrib/hydratoolz/plugin.cpp @@ -58,135 +58,136 @@ void *g_pMainWnd; // ============================================================================= // Ripped from TexTool.cpp -static void dialog_button_callback( ui::Widget widget, gpointer data ){ - int *loop, *ret; +static void dialog_button_callback(ui::Widget widget, gpointer data) +{ + int *loop, *ret; - auto parent = widget.window(); - loop = (int*)gtk_object_get_data( GTK_OBJECT( parent ), "loop" ); - ret = (int*)gtk_object_get_data( GTK_OBJECT( parent ), "ret" ); + auto parent = widget.window(); + loop = (int *) gtk_object_get_data(GTK_OBJECT(parent), "loop"); + ret = (int *) gtk_object_get_data(GTK_OBJECT(parent), "ret"); - *loop = 0; - *ret = gpointer_to_int( data ); + *loop = 0; + *ret = gpointer_to_int(data); } -static gint dialog_delete_callback( GtkWidget *widget, GdkEvent* event, gpointer data ){ - int *loop; +static gint dialog_delete_callback(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + int *loop; - gtk_widget_hide( widget ); - loop = (int*)gtk_object_get_data( GTK_OBJECT( widget ), "loop" ); - *loop = 0; + gtk_widget_hide(widget); + loop = (int *) gtk_object_get_data(GTK_OBJECT(widget), "loop"); + *loop = 0; - return TRUE; + return TRUE; } -int DoMessageBox( const char* lpText, const char* lpCaption, guint32 uType ){ - GtkWidget *w, *hbox; - int mode = ( uType & MB_TYPEMASK ), ret, loop = 1; - - auto window = ui::Window( ui::window_type::TOP ); - window.connect( "delete_event", - G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", - G_CALLBACK( gtk_widget_destroy ), NULL ); - gtk_window_set_title( window, lpCaption ); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); - gtk_object_set_data( GTK_OBJECT( window ), "loop", &loop ); - gtk_object_set_data( GTK_OBJECT( window ), "ret", &ret ); - gtk_widget_realize( window ); - - auto vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); - - w = ui::Label( lpText ); - vbox.pack_start( w, FALSE, FALSE, 2 ); - gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT ); - w.show(); - - w = gtk_hseparator_new(); - vbox.pack_start( w, FALSE, FALSE, 2 ); - w.show(); - - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); - - if ( mode == MB_OK ) { - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDOK ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - ret = IDOK; - } - else if ( mode == MB_OKCANCEL ) { - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDOK ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) ); - w.show(); - ret = IDCANCEL; - } - else if ( mode == MB_YESNOCANCEL ) { - w = ui::Button( "Yes" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDYES ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "No" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDNO ) ); - w.show(); - - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) ); - w.show(); - ret = IDCANCEL; - } - else /* if (mode == MB_YESNO) */ - { - w = ui::Button( "Yes" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDYES ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "No" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDNO ) ); - w.show(); - ret = IDNO; - } - - window.show(); - gtk_grab_add( window ); - - while ( loop ) - gtk_main_iteration(); - - gtk_grab_remove( window ); - window.destroy(); - - return ret; +int DoMessageBox(const char *lpText, const char *lpCaption, guint32 uType) +{ + GtkWidget *w, *hbox; + int mode = (uType & MB_TYPEMASK), ret, loop = 1; + + auto window = ui::Window(ui::window_type::TOP); + window.connect("delete_event", + G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", + G_CALLBACK(gtk_widget_destroy), NULL); + gtk_window_set_title(window, lpCaption); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); + gtk_object_set_data(GTK_OBJECT(window), "loop", &loop); + gtk_object_set_data(GTK_OBJECT(window), "ret", &ret); + gtk_widget_realize(window); + + auto vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); + + w = ui::Label(lpText); + vbox.pack_start(w, FALSE, FALSE, 2); + gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT); + w.show(); + + w = gtk_hseparator_new(); + vbox.pack_start(w, FALSE, FALSE, 2); + w.show(); + + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); + + if (mode == MB_OK) { + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + ret = IDOK; + } else if (mode == MB_OKCANCEL) { + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDCANCEL)); + w.show(); + ret = IDCANCEL; + } else if (mode == MB_YESNOCANCEL) { + w = ui::Button("Yes"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDYES)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("No"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDNO)); + w.show(); + + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDCANCEL)); + w.show(); + ret = IDCANCEL; + } else /* if (mode == MB_YESNO) */ + { + w = ui::Button("Yes"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDYES)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("No"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDNO)); + w.show(); + ret = IDNO; + } + + window.show(); + gtk_grab_add(window); + + while (loop) { + gtk_main_iteration(); + } + + gtk_grab_remove(window); + window.destroy(); + + return ret; } // End of rip from TexTool.cpp @@ -199,52 +200,55 @@ int DoMessageBox( const char* lpText, const char* lpCaption, guint32 uType ){ Extract file parts ==================== */ -void ExtractFilePath( const char *path, char *dest ){ - const char *src; +void ExtractFilePath(const char *path, char *dest) +{ + const char *src; - src = path + strlen( path ) - 1; + src = path + strlen(path) - 1; // // back up until a \ or the start // - while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' ) - src--; + while (src != path && *(src - 1) != '/' && *(src - 1) != '\\') { + src--; + } - memcpy( dest, path, src - path ); - dest[src - path] = 0; + memcpy(dest, path, src - path); + dest[src - path] = 0; } -void ExtractFileName( const char *path, char *dest ){ - const char *src; +void ExtractFileName(const char *path, char *dest) +{ + const char *src; - src = path + strlen( path ) - 1; + src = path + strlen(path) - 1; // // back up until a \ or the start // - while ( src != path && *( src - 1 ) != '/' - && *( src - 1 ) != '\\' ) - src--; - - while ( *src ) - { - *dest++ = *src++; - } - *dest = 0; + while (src != path && *(src - 1) != '/' + && *(src - 1) != '\\') { + src--; + } + + while (*src) { + *dest++ = *src++; + } + *dest = 0; } -void ConvertDOSToUnixName( char *dst, const char *src ){ - while ( *src ) - { - if ( *src == '\\' ) { - *dst = '/'; - } - else{ - *dst = *src; - } - dst++; src++; - } - *dst = 0; +void ConvertDOSToUnixName(char *dst, const char *src) +{ + while (*src) { + if (*src == '\\') { + *dst = '/'; + } else { + *dst = *src; + } + dst++; + src++; + } + *dst = 0; } // End of rip from cmdlib.cpp @@ -255,192 +259,170 @@ void ConvertDOSToUnixName( char *dst, const char *src ){ // get the wad name from the shader name (or an actual wadname) and add to a list of wad names making // sure we don't add duplicates. -GSList *AddToWadList( GSList *wadlist, const char *shadername, const char *wad ){ - char tmpstr[QER_MAX_NAMELEN]; - char *wadname; - if ( !shadername && !wad ) { - return wadlist; - } - - if ( shadername ) { - if ( strcmp( shadername,"color" ) == 0 ) { - return wadlist; - } - ExtractFilePath( shadername,tmpstr ); - // Sys_Printf("checking: %s\n",shadername); - - int l = strlen( tmpstr ) - 1; - - if ( tmpstr[l] == '/' || tmpstr[l] == '\\' ) { - tmpstr[l] = 0; - } - else - { - Sys_Printf( "WARNING: Unknown wad file for shader %s\n",shadername ); - return wadlist; - } - - ExtractFileName( tmpstr,tmpstr ); - - wadname = (char *)malloc( strlen( tmpstr ) + 5 ); - sprintf( wadname,"%s.wad",tmpstr ); - } - else - { - wadname = strdup( wad ); - } - - for ( GSList *l = wadlist; l != NULL ; l = l->next ) - { - if ( string_equal_nocase( (char *)l->data,wadname ) ) { - free( wadname ); - return wadlist; - } - } - - Sys_Printf( "Adding Wad File to WAD list: %s (reason: ",wadname ); - if ( shadername ) { - Sys_Printf( "see shader \"%s\")\n", shadername ); - } - else{ - Sys_Printf( "already in WAD key. )\n" ); - } - return ( g_slist_append( wadlist, wadname ) ); +GSList *AddToWadList(GSList *wadlist, const char *shadername, const char *wad) +{ + char tmpstr[QER_MAX_NAMELEN]; + char *wadname; + if (!shadername && !wad) { + return wadlist; + } + + if (shadername) { + if (strcmp(shadername, "color") == 0) { + return wadlist; + } + ExtractFilePath(shadername, tmpstr); + // Sys_Printf("checking: %s\n",shadername); + + int l = strlen(tmpstr) - 1; + + if (tmpstr[l] == '/' || tmpstr[l] == '\\') { + tmpstr[l] = 0; + } else { + Sys_Printf("WARNING: Unknown wad file for shader %s\n", shadername); + return wadlist; + } + + ExtractFileName(tmpstr, tmpstr); + + wadname = (char *) malloc(strlen(tmpstr) + 5); + sprintf(wadname, "%s.wad", tmpstr); + } else { + wadname = strdup(wad); + } + + for (GSList *l = wadlist; l != NULL; l = l->next) { + if (string_equal_nocase((char *) l->data, wadname)) { + free(wadname); + return wadlist; + } + } + + Sys_Printf("Adding Wad File to WAD list: %s (reason: ", wadname); + if (shadername) { + Sys_Printf("see shader \"%s\")\n", shadername); + } else { + Sys_Printf("already in WAD key. )\n"); + } + return (g_slist_append(wadlist, wadname)); } -void UpdateWadKeyPair( void ){ - int i,nb; - - char wads[2048]; // change to CString usage ? - wads[0] = 0; - char *p1,*p2; - entity_t *pEntity; - epair_t *pEpair; - GSList *wadlist = NULL; - face_t *f; - brush_t *b; - char cleanwadname[QER_MAX_NAMELEN]; - const char *actualwad; - - - pEntity = (entity_t *)g_FuncTable.m_pfnGetEntityHandle( 0 ); // get the worldspawn ent - - Sys_Printf( "Searching for in-use wad files...\n" ); - for ( pEpair = pEntity->epairs; pEpair != NULL; pEpair = pEpair->next ) - { - if ( string_equal_nocase( pEpair->key,"wad" ) ) { - strcpy( wads,pEpair->value ); - ConvertDOSToUnixName( wads,wads ); - - // ok, we got the list of ; delimited wads, now split it into a GSList that contains - // just the wad names themselves. - - p1 = wads; - - do - { - p2 = strchr( p1,';' ); - if ( p2 ) { - *p2 = 0; // swap the ; with a null terminator - - } - if ( strchr( p1,'/' ) || strchr( p1,'\\' ) ) { - ExtractFileName( p1,cleanwadname ); - wadlist = AddToWadList( wadlist, NULL, cleanwadname ); - } - else - { - wadlist = AddToWadList( wadlist, NULL, p1 ); - } - if ( p2 ) { - p1 = p2 + 1; // point back to the remainder of the string - } - else{ - p1 = NULL; // make it so we exit the loop. - - } - } while ( p1 ); - - // ok, now we have a list of wads in GSList. - // now we need to add any new wadfiles (with their paths) to this list - // so scan all brushes and see what wads are in use - // FIXME: scan brushes only in the region ? - - break; // we don't need to process any more key/pairs. - } - } - - nb = g_FuncTable.m_pfnAllocateActiveBrushHandles(); - for ( i = 0; i < nb; i++ ) - { - b = (brush_t *)g_FuncTable.m_pfnGetActiveBrushHandle( i ); - if ( b->patchBrush ) { // patches in halflife ? - wadlist = AddToWadList( wadlist, b->pPatch->pShader->getName(),NULL ); - } - else - { - for ( f = b->brush_faces ; f ; f = f->next ) - { - wadlist = AddToWadList( wadlist, f->pShader->getName(),NULL ); - } - } - } - g_FuncTable.m_pfnReleaseActiveBrushHandles(); - - nb = g_FuncTable.m_pfnAllocateSelectedBrushHandles(); - for ( i = 0; i < nb; i++ ) - { - b = (brush_t *)g_FuncTable.m_pfnGetSelectedBrushHandle( i ); - if ( b->patchBrush ) { // patches in halflife ? - wadlist = AddToWadList( wadlist, b->pPatch->pShader->getName(),NULL ); - } - else - { - for ( f = b->brush_faces ; f ; f = f->next ) - { - wadlist = AddToWadList( wadlist, f->pShader->getName(),NULL ); - } - } - } - g_FuncTable.m_pfnReleaseSelectedBrushHandles(); - - // Now we have a complete list of wadnames (without paths) so we just have to turn this - // back to a ; delimited list. - - wads[0] = 0; - while ( wadlist ) - { - if ( string_equal_nocase( (char *)wadlist->data,"common-hydra.wad" ) ) { - Sys_Printf( "Skipping radiant-supplied wad file %s\n",(char *)wadlist->data ); - } - else - { - if ( wads[0] ) { - strcat( wads,";" ); - } - - actualwad = vfsGetFullPath( (char *)wadlist->data ); - - if ( actualwad ) { - strcat( wads, actualwad ); - } - else - { - Sys_Printf( "WARNING: could not locate wad file %s\n",(char *)wadlist->data ); - strcat( wads, (char *)wadlist->data ); - } - } - - free( wadlist->data ); - wadlist = g_slist_remove( wadlist, wadlist->data ); - } - - // store the wad list back in the worldspawn. - if ( wads[0] ) { - //free(pEpair->value); - //pEpair->value = strdup(wads); - SetKeyValue( pEntity, "wad", wads ); - } +void UpdateWadKeyPair(void) +{ + int i, nb; + + char wads[2048]; // change to CString usage ? + wads[0] = 0; + char *p1, *p2; + entity_t *pEntity; + epair_t *pEpair; + GSList *wadlist = NULL; + face_t *f; + brush_t *b; + char cleanwadname[QER_MAX_NAMELEN]; + const char *actualwad; + + + pEntity = (entity_t *) g_FuncTable.m_pfnGetEntityHandle(0); // get the worldspawn ent + + Sys_Printf("Searching for in-use wad files...\n"); + for (pEpair = pEntity->epairs; pEpair != NULL; pEpair = pEpair->next) { + if (string_equal_nocase(pEpair->key, "wad")) { + strcpy(wads, pEpair->value); + ConvertDOSToUnixName(wads, wads); + + // ok, we got the list of ; delimited wads, now split it into a GSList that contains + // just the wad names themselves. + + p1 = wads; + + do { + p2 = strchr(p1, ';'); + if (p2) { + *p2 = 0; // swap the ; with a null terminator + + } + if (strchr(p1, '/') || strchr(p1, '\\')) { + ExtractFileName(p1, cleanwadname); + wadlist = AddToWadList(wadlist, NULL, cleanwadname); + } else { + wadlist = AddToWadList(wadlist, NULL, p1); + } + if (p2) { + p1 = p2 + 1; // point back to the remainder of the string + } else { + p1 = NULL; // make it so we exit the loop. + + } + } while (p1); + + // ok, now we have a list of wads in GSList. + // now we need to add any new wadfiles (with their paths) to this list + // so scan all brushes and see what wads are in use + // FIXME: scan brushes only in the region ? + + break; // we don't need to process any more key/pairs. + } + } + + nb = g_FuncTable.m_pfnAllocateActiveBrushHandles(); + for (i = 0; i < nb; i++) { + b = (brush_t *) g_FuncTable.m_pfnGetActiveBrushHandle(i); + if (b->patchBrush) { // patches in halflife ? + wadlist = AddToWadList(wadlist, b->pPatch->pShader->getName(), NULL); + } else { + for (f = b->brush_faces; f; f = f->next) { + wadlist = AddToWadList(wadlist, f->pShader->getName(), NULL); + } + } + } + g_FuncTable.m_pfnReleaseActiveBrushHandles(); + + nb = g_FuncTable.m_pfnAllocateSelectedBrushHandles(); + for (i = 0; i < nb; i++) { + b = (brush_t *) g_FuncTable.m_pfnGetSelectedBrushHandle(i); + if (b->patchBrush) { // patches in halflife ? + wadlist = AddToWadList(wadlist, b->pPatch->pShader->getName(), NULL); + } else { + for (f = b->brush_faces; f; f = f->next) { + wadlist = AddToWadList(wadlist, f->pShader->getName(), NULL); + } + } + } + g_FuncTable.m_pfnReleaseSelectedBrushHandles(); + + // Now we have a complete list of wadnames (without paths) so we just have to turn this + // back to a ; delimited list. + + wads[0] = 0; + while (wadlist) { + if (string_equal_nocase((char *) wadlist->data, "common-hydra.wad")) { + Sys_Printf("Skipping radiant-supplied wad file %s\n", (char *) wadlist->data); + } else { + if (wads[0]) { + strcat(wads, ";"); + } + + actualwad = vfsGetFullPath((char *) wadlist->data); + + if (actualwad) { + strcat(wads, actualwad); + } else { + Sys_Printf("WARNING: could not locate wad file %s\n", (char *) wadlist->data); + strcat(wads, (char *) wadlist->data); + } + } + + free(wadlist->data); + wadlist = g_slist_remove(wadlist, wadlist->data); + } + + // store the wad list back in the worldspawn. + if (wads[0]) { + //free(pEpair->value); + //pEpair->value = strdup(wads); + SetKeyValue(pEntity, "wad", wads); + } } @@ -454,74 +436,88 @@ const char *PLUGIN_NAME = "Q3 Texture Tools"; const char *PLUGIN_COMMANDS = "About...;Create/Update WAD keypair"; const char *PLUGIN_ABOUT = "HydraToolz for GTKRadiant\n\n" - "By Hydra!"; + "By Hydra!"; -extern "C" void* WINAPI QERPlug_GetFuncTable(){ - return &g_FuncTable; +extern "C" void *WINAPI + +QERPlug_GetFuncTable() +{ + return &g_FuncTable; } -const char* QERPlug_Init( void* hApp, void *pWidget ){ - GtkWidget* pMainWidget = static_cast( pWidget ); +const char *QERPlug_Init(void *hApp, void *pWidget) +{ + GtkWidget *pMainWidget = static_cast( pWidget ); - g_pMainWnd = pMainWidget; - memset( &g_FuncTable, 0, sizeof( _QERFuncTable_1 ) ); - g_FuncTable.m_nSize = sizeof( _QERFuncTable_1 ); - return "HydraToolz for GTKRadiant"; // do we need this ? hmmm + g_pMainWnd = pMainWidget; + memset(&g_FuncTable, 0, sizeof(_QERFuncTable_1)); + g_FuncTable.m_nSize = sizeof(_QERFuncTable_1); + return "HydraToolz for GTKRadiant"; // do we need this ? hmmm } -const char* QERPlug_GetName(){ - return (char*)PLUGIN_NAME; +const char *QERPlug_GetName() +{ + return (char *) PLUGIN_NAME; } -const char* QERPlug_GetCommandList(){ - return PLUGIN_COMMANDS; +const char *QERPlug_GetCommandList() +{ + return PLUGIN_COMMANDS; } -extern "C" void QERPlug_Dispatch( const char* p, vec3_t vMin, vec3_t vMax, bool bSingleBrush ){ - if ( !strcmp( p, "Create/Update WAD keypair" ) ) { - UpdateWadKeyPair(); - } - else if ( !strcmp( p, "About..." ) ) { - g_FuncTable.m_pfnMessageBox( (GtkWidget*)NULL, PLUGIN_ABOUT, "About", eMB_OK ); - } +extern "C" void QERPlug_Dispatch(const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush) +{ + if (!strcmp(p, "Create/Update WAD keypair")) { + UpdateWadKeyPair(); + } else if (!strcmp(p, "About...")) { + g_FuncTable.m_pfnMessageBox((GtkWidget *) NULL, PLUGIN_ABOUT, "About", eMB_OK); + } } // ============================================================================= // SYNAPSE -CSynapseServer* g_pSynapseServer = NULL; +CSynapseServer *g_pSynapseServer = NULL; CSynapseClientHydraToolz g_SynapseClient; -extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ){ - if ( strcmp( version, SYNAPSE_VERSION ) ) { - Syn_Printf( "ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version ); - return NULL; - } - g_pSynapseServer = pServer; - g_pSynapseServer->IncRef(); - Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() ); - - g_SynapseClient.AddAPI( PLUGIN_MAJOR, "HydraToolz", sizeof( _QERPluginTable ) ); - g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( g_FuncTable ), SYN_REQUIRE, &g_FuncTable ); - g_SynapseClient.AddAPI( VFS_MAJOR, "wad", sizeof( g_FileSystemTable ), SYN_REQUIRE, &g_FileSystemTable ); - g_SynapseClient.AddAPI( ENTITY_MAJOR, NULL, sizeof( g_EntityTable ), SYN_REQUIRE, &g_EntityTable ); - return &g_SynapseClient; +extern "C" CSynapseClient *SYNAPSE_DLL_EXPORT + +Synapse_EnumerateInterfaces(const char *version, CSynapseServer *pServer) +{ + if (strcmp(version, SYNAPSE_VERSION)) { + Syn_Printf("ERROR: synapse API version mismatch: should be '" + SYNAPSE_VERSION + "', got '%s'\n", version ); + return NULL; + } + g_pSynapseServer = pServer; + g_pSynapseServer->IncRef(); + Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf()); + + g_SynapseClient.AddAPI(PLUGIN_MAJOR, "HydraToolz", sizeof(_QERPluginTable)); + g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable); + g_SynapseClient.AddAPI(VFS_MAJOR, "wad", sizeof(g_FileSystemTable), SYN_REQUIRE, &g_FileSystemTable); + g_SynapseClient.AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable); + return &g_SynapseClient; } -bool CSynapseClientHydraToolz::RequestAPI( APIDescriptor_t *pAPI ){ - if ( !strcmp( pAPI->major_name, PLUGIN_MAJOR ) ) { - _QERPluginTable *pTable = static_cast<_QERPluginTable*>( pAPI->mpTable ); - pTable->m_pfnQERPlug_Init = QERPlug_Init; - pTable->m_pfnQERPlug_GetName = QERPlug_GetName; - pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; - pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; - return true; - } - - Syn_Printf( "ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo() ); - return false; +bool CSynapseClientHydraToolz::RequestAPI(APIDescriptor_t *pAPI) +{ + if (!strcmp(pAPI->major_name, PLUGIN_MAJOR)) { + _QERPluginTable *pTable = static_cast<_QERPluginTable *>( pAPI->mpTable ); + pTable->m_pfnQERPlug_Init = QERPlug_Init; + pTable->m_pfnQERPlug_GetName = QERPlug_GetName; + pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; + pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; + return true; + } + + Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo()); + return false; } -const char* CSynapseClientHydraToolz::GetInfo(){ - return "HydraToolz plugin built " __DATE__ " " RADIANT_VERSION; +const char *CSynapseClientHydraToolz::GetInfo() +{ + return "HydraToolz plugin built " __DATE__ " " + RADIANT_VERSION; } diff --git a/contrib/hydratoolz/plugin.h b/contrib/hydratoolz/plugin.h index 055cf991..06b527c3 100644 --- a/contrib/hydratoolz/plugin.h +++ b/contrib/hydratoolz/plugin.h @@ -28,11 +28,14 @@ #include #define USE_QERTABLE_DEFINE + #include "iscenegraph.h" #include "qerplugin.h" #include "ifilesystem.h" + #define USE_ENTITYTABLE_DEFINE + #include "ientity.h" #include @@ -42,15 +45,18 @@ #include "synapse.h" -class CSynapseClientHydraToolz : public CSynapseClient -{ +class CSynapseClientHydraToolz : public CSynapseClient { public: // CSynapseClient API -bool RequestAPI( APIDescriptor_t *pAPI ); -const char* GetInfo(); + bool RequestAPI(APIDescriptor_t *pAPI); + + const char *GetInfo(); + + CSynapseClientHydraToolz() + {} -CSynapseClientHydraToolz() { } -virtual ~CSynapseClientHydraToolz() { } + virtual ~CSynapseClientHydraToolz() + {} }; #endif // _PLUGIN_H_ diff --git a/contrib/prtview/AboutDialog.cpp b/contrib/prtview/AboutDialog.cpp index f320de22..599614f5 100644 --- a/contrib/prtview/AboutDialog.cpp +++ b/contrib/prtview/AboutDialog.cpp @@ -27,67 +27,71 @@ #include "prtview.h" #include "ConfigDialog.h" -static void dialog_button_callback( ui::Widget widget, gpointer data ){ - int *loop, *ret; +static void dialog_button_callback(ui::Widget widget, gpointer data) +{ + int *loop, *ret; - auto parent = widget.window(); - loop = (int*)g_object_get_data( G_OBJECT( parent ), "loop" ); - ret = (int*)g_object_get_data( G_OBJECT( parent ), "ret" ); + auto parent = widget.window(); + loop = (int *) g_object_get_data(G_OBJECT(parent), "loop"); + ret = (int *) g_object_get_data(G_OBJECT(parent), "ret"); - *loop = 0; - *ret = gpointer_to_int( data ); + *loop = 0; + *ret = gpointer_to_int(data); } -static gint dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){ - widget.hide(); - int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); - *loop = 0; - return TRUE; +static gint dialog_delete_callback(ui::Widget widget, GdkEvent *event, gpointer data) +{ + widget.hide(); + int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); + *loop = 0; + return TRUE; } -void DoAboutDlg(){ - int loop = 1, ret = IDCANCEL; - - auto dlg = ui::Window(ui::window_type::TOP); - gtk_window_set_title(dlg, "About Portal Viewer"); - dlg.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); - dlg.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - g_object_set_data(G_OBJECT(dlg), "loop", &loop); - g_object_set_data(G_OBJECT(dlg), "ret", &ret); - - auto hbox = ui::HBox(FALSE, 10); - hbox.show(); - dlg.add(hbox); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 10); - - char const *label_text = "Version 1.000\n\n" - "Gtk port by Leonardo Zide\nleo@lokigames.com\n\n" - "Written by Geoffrey DeWan\ngdewan@prairienet.org\n\n" - "Built against NetRadiant " RADIANT_VERSION "\n" - __DATE__; - auto label = ui::Label(label_text); - label.show(); - hbox.pack_start( label, TRUE, TRUE, 0); - gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); - - auto vbox = ui::VBox(FALSE, 0); - vbox.show(); - hbox.pack_start( vbox, FALSE, FALSE, 0); - - auto button = ui::Button("OK"); - button.show(); - vbox.pack_start( button, FALSE, FALSE, 0); - button.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK)); - button.dimensions(60, -1); - - gtk_grab_add(dlg); - dlg.show(); - - while (loop) - gtk_main_iteration(); - - gtk_grab_remove(dlg); - dlg.destroy(); +void DoAboutDlg() +{ + int loop = 1, ret = IDCANCEL; + + auto dlg = ui::Window(ui::window_type::TOP); + gtk_window_set_title(dlg, "About Portal Viewer"); + dlg.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + dlg.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); + g_object_set_data(G_OBJECT(dlg), "loop", &loop); + g_object_set_data(G_OBJECT(dlg), "ret", &ret); + + auto hbox = ui::HBox(FALSE, 10); + hbox.show(); + dlg.add(hbox); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 10); + + char const *label_text = "Version 1.000\n\n" + "Gtk port by Leonardo Zide\nleo@lokigames.com\n\n" + "Written by Geoffrey DeWan\ngdewan@prairienet.org\n\n" + "Built against NetRadiant " RADIANT_VERSION "\n" + __DATE__; + auto label = ui::Label(label_text); + label.show(); + hbox.pack_start(label, TRUE, TRUE, 0); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); + + auto vbox = ui::VBox(FALSE, 0); + vbox.show(); + hbox.pack_start(vbox, FALSE, FALSE, 0); + + auto button = ui::Button("OK"); + button.show(); + vbox.pack_start(button, FALSE, FALSE, 0); + button.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK)); + button.dimensions(60, -1); + + gtk_grab_add(dlg); + dlg.show(); + + while (loop) { + gtk_main_iteration(); + } + + gtk_grab_remove(dlg); + dlg.destroy(); } diff --git a/contrib/prtview/ConfigDialog.cpp b/contrib/prtview/ConfigDialog.cpp index 1d7f2743..7784beec 100644 --- a/contrib/prtview/ConfigDialog.cpp +++ b/contrib/prtview/ConfigDialog.cpp @@ -28,426 +28,454 @@ #include "prtview.h" #include "portals.h" -static void dialog_button_callback( ui::Widget widget, gpointer data ){ - int *loop, *ret; +static void dialog_button_callback(ui::Widget widget, gpointer data) +{ + int *loop, *ret; - auto parent = widget.window(); - loop = (int*)g_object_get_data( G_OBJECT( parent ), "loop" ); - ret = (int*)g_object_get_data( G_OBJECT( parent ), "ret" ); + auto parent = widget.window(); + loop = (int *) g_object_get_data(G_OBJECT(parent), "loop"); + ret = (int *) g_object_get_data(G_OBJECT(parent), "ret"); - *loop = 0; - *ret = gpointer_to_int( data ); + *loop = 0; + *ret = gpointer_to_int(data); } -static gint dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){ - widget.hide(); - int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); - *loop = 0; - return TRUE; +static gint dialog_delete_callback(ui::Widget widget, GdkEvent *event, gpointer data) +{ + widget.hide(); + int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); + *loop = 0; + return TRUE; } // ============================================================================= // Color selection dialog -static int DoColor( PackedColour *c ){ - GdkColor clr; - int loop = 1, ret = IDCANCEL; +static int DoColor(PackedColour *c) +{ + GdkColor clr; + int loop = 1, ret = IDCANCEL; - clr.red = (guint16) (GetRValue(*c) * (65535 / 255)); - clr.blue = (guint16) (GetGValue(*c) * (65535 / 255)); - clr.green = (guint16) (GetBValue(*c) * (65535 / 255)); + clr.red = (guint16) (GetRValue(*c) * (65535 / 255)); + clr.blue = (guint16) (GetGValue(*c) * (65535 / 255)); + clr.green = (guint16) (GetBValue(*c) * (65535 / 255)); - auto dlg = ui::Widget::from(gtk_color_selection_dialog_new( "Choose Color" )); - gtk_color_selection_set_current_color( GTK_COLOR_SELECTION( gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dlg)) ), &clr ); - dlg.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL ); - dlg.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL ); + auto dlg = ui::Widget::from(gtk_color_selection_dialog_new("Choose Color")); + gtk_color_selection_set_current_color( + GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dlg))), &clr); + dlg.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL); + dlg.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL); - GtkWidget *ok_button, *cancel_button; - g_object_get(dlg, "ok-button", &ok_button, "cancel-button", &cancel_button, nullptr); + GtkWidget *ok_button, *cancel_button; + g_object_get(dlg, "ok-button", &ok_button, "cancel-button", &cancel_button, nullptr); - ui::Widget::from(ok_button).connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDOK ) ); - ui::Widget::from(cancel_button).connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) ); - g_object_set_data( G_OBJECT( dlg ), "loop", &loop ); - g_object_set_data( G_OBJECT( dlg ), "ret", &ret ); + ui::Widget::from(ok_button).connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK)); + ui::Widget::from(cancel_button).connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDCANCEL)); + g_object_set_data(G_OBJECT(dlg), "loop", &loop); + g_object_set_data(G_OBJECT(dlg), "ret", &ret); - dlg.show(); - gtk_grab_add( dlg ); + dlg.show(); + gtk_grab_add(dlg); - while ( loop ) - gtk_main_iteration(); + while (loop) { + gtk_main_iteration(); + } - gtk_color_selection_get_current_color( GTK_COLOR_SELECTION( gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dlg)) ), &clr ); + gtk_color_selection_get_current_color( + GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dlg))), &clr); - gtk_grab_remove( dlg ); - dlg.destroy(); + gtk_grab_remove(dlg); + dlg.destroy(); - if ( ret == IDOK ) { - *c = RGB( clr.red / (65535 / 255), clr.green / (65535 / 255), clr.blue / (65535 / 255)); - } + if (ret == IDOK) { + *c = RGB(clr.red / (65535 / 255), clr.green / (65535 / 255), clr.blue / (65535 / 255)); + } - return ret; + return ret; } -static void Set2DText(ui::Widget label ){ - char s[40]; +static void Set2DText(ui::Widget label) +{ + char s[40]; - sprintf( s, "Line Width = %6.3f", portals.width_2d * 0.5f ); + sprintf(s, "Line Width = %6.3f", portals.width_2d * 0.5f); - gtk_label_set_text( GTK_LABEL( label ), s ); + gtk_label_set_text(GTK_LABEL(label), s); } -static void Set3DText(ui::Widget label ){ - char s[40]; +static void Set3DText(ui::Widget label) +{ + char s[40]; - sprintf( s, "Line Width = %6.3f", portals.width_3d * 0.5f ); + sprintf(s, "Line Width = %6.3f", portals.width_3d * 0.5f); - gtk_label_set_text( GTK_LABEL( label ), s ); + gtk_label_set_text(GTK_LABEL(label), s); } -static void Set3DTransText(ui::Widget label ){ - char s[40]; +static void Set3DTransText(ui::Widget label) +{ + char s[40]; - sprintf( s, "Polygon transparency = %d%%", (int)portals.trans_3d ); + sprintf(s, "Polygon transparency = %d%%", (int) portals.trans_3d); - gtk_label_set_text( GTK_LABEL( label ), s ); + gtk_label_set_text(GTK_LABEL(label), s); } -static void SetClipText(ui::Widget label ){ - char s[40]; +static void SetClipText(ui::Widget label) +{ + char s[40]; - sprintf( s, "Cubic clip range = %d", (int)portals.clip_range * 64 ); + sprintf(s, "Cubic clip range = %d", (int) portals.clip_range * 64); - gtk_label_set_text( GTK_LABEL( label ), s ); + gtk_label_set_text(GTK_LABEL(label), s); } -static void OnScroll2d(ui::Adjustment adj, gpointer data ){ - portals.width_2d = static_cast( gtk_adjustment_get_value(adj) ); - Set2DText( ui::Widget::from(data) ); +static void OnScroll2d(ui::Adjustment adj, gpointer data) +{ + portals.width_2d = static_cast( gtk_adjustment_get_value(adj)); + Set2DText(ui::Widget::from(data)); - Portals_shadersChanged(); - SceneChangeNotify(); + Portals_shadersChanged(); + SceneChangeNotify(); } -static void OnScroll3d(ui::Adjustment adj, gpointer data ){ - portals.width_3d = static_cast( gtk_adjustment_get_value(adj) ); - Set3DText( ui::Widget::from( data ) ); +static void OnScroll3d(ui::Adjustment adj, gpointer data) +{ + portals.width_3d = static_cast( gtk_adjustment_get_value(adj)); + Set3DText(ui::Widget::from(data)); - SceneChangeNotify(); + SceneChangeNotify(); } -static void OnScrollTrans(ui::Adjustment adj, gpointer data ){ - portals.trans_3d = static_cast( gtk_adjustment_get_value(adj) ); - Set3DTransText( ui::Widget::from( data ) ); +static void OnScrollTrans(ui::Adjustment adj, gpointer data) +{ + portals.trans_3d = static_cast( gtk_adjustment_get_value(adj)); + Set3DTransText(ui::Widget::from(data)); - SceneChangeNotify(); + SceneChangeNotify(); } -static void OnScrollClip(ui::Adjustment adj, gpointer data ){ - portals.clip_range = static_cast( gtk_adjustment_get_value(adj) ); - SetClipText( ui::Widget::from( data ) ); +static void OnScrollClip(ui::Adjustment adj, gpointer data) +{ + portals.clip_range = static_cast( gtk_adjustment_get_value(adj)); + SetClipText(ui::Widget::from(data)); - SceneChangeNotify(); + SceneChangeNotify(); } -static void OnAntiAlias2d(ui::Widget widget, gpointer data ){ - portals.aa_2d = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ) ? true : false; +static void OnAntiAlias2d(ui::Widget widget, gpointer data) +{ + portals.aa_2d = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ? true : false; - Portals_shadersChanged(); + Portals_shadersChanged(); - SceneChangeNotify(); + SceneChangeNotify(); } -static void OnConfig2d(ui::Widget widget, gpointer data ){ - portals.show_2d = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ) ? true : false; +static void OnConfig2d(ui::Widget widget, gpointer data) +{ + portals.show_2d = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ? true : false; - SceneChangeNotify(); + SceneChangeNotify(); } -static void OnColor2d(ui::Widget widget, gpointer data ){ - if ( DoColor( &portals.color_2d ) == IDOK ) { - Portals_shadersChanged(); +static void OnColor2d(ui::Widget widget, gpointer data) +{ + if (DoColor(&portals.color_2d) == IDOK) { + Portals_shadersChanged(); - SceneChangeNotify(); - } + SceneChangeNotify(); + } } -static void OnConfig3d(ui::Widget widget, gpointer data ){ - portals.show_3d = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ) ? true : false; +static void OnConfig3d(ui::Widget widget, gpointer data) +{ + portals.show_3d = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ? true : false; - SceneChangeNotify(); + SceneChangeNotify(); } -static void OnAntiAlias3d(ui::Widget widget, gpointer data ){ - portals.aa_3d = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ) ? true : false; +static void OnAntiAlias3d(ui::Widget widget, gpointer data) +{ + portals.aa_3d = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ? true : false; - Portals_shadersChanged(); - SceneChangeNotify(); + Portals_shadersChanged(); + SceneChangeNotify(); } -static void OnColor3d(ui::Widget widget, gpointer data ){ - if ( DoColor( &portals.color_3d ) == IDOK ) { - Portals_shadersChanged(); +static void OnColor3d(ui::Widget widget, gpointer data) +{ + if (DoColor(&portals.color_3d) == IDOK) { + Portals_shadersChanged(); - SceneChangeNotify(); - } + SceneChangeNotify(); + } } -static void OnColorFog(ui::Widget widget, gpointer data ){ - if ( DoColor( &portals.color_fog ) == IDOK ) { - Portals_shadersChanged(); +static void OnColorFog(ui::Widget widget, gpointer data) +{ + if (DoColor(&portals.color_fog) == IDOK) { + Portals_shadersChanged(); - SceneChangeNotify(); - } + SceneChangeNotify(); + } } -static void OnFog(ui::Widget widget, gpointer data ){ - portals.fog = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ) ? true : false; +static void OnFog(ui::Widget widget, gpointer data) +{ + portals.fog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ? true : false; - Portals_shadersChanged(); - SceneChangeNotify(); + Portals_shadersChanged(); + SceneChangeNotify(); } -static void OnSelchangeZbuffer(ui::Widget widget, gpointer data ){ - portals.zbuffer = gpointer_to_int( data ); +static void OnSelchangeZbuffer(ui::Widget widget, gpointer data) +{ + portals.zbuffer = gpointer_to_int(data); - Portals_shadersChanged(); - SceneChangeNotify(); + Portals_shadersChanged(); + SceneChangeNotify(); } -static void OnPoly(ui::Widget widget, gpointer data ){ - portals.polygons = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ); +static void OnPoly(ui::Widget widget, gpointer data) +{ + portals.polygons = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - SceneChangeNotify(); + SceneChangeNotify(); } -static void OnLines(ui::Widget widget, gpointer data ){ - portals.lines = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ); +static void OnLines(ui::Widget widget, gpointer data) +{ + portals.lines = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - SceneChangeNotify(); + SceneChangeNotify(); } -static void OnClip(ui::Widget widget, gpointer data ){ - portals.clip = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ) ? true : false; +static void OnClip(ui::Widget widget, gpointer data) +{ + portals.clip = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ? true : false; - SceneChangeNotify(); + SceneChangeNotify(); } -void DoConfigDialog(){ - int loop = 1, ret = IDCANCEL; - - auto dlg = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( dlg, "Portal Viewer Configuration" ); - dlg.connect( "delete_event", - G_CALLBACK( dialog_delete_callback ), NULL ); - dlg.connect( "destroy", - G_CALLBACK( gtk_widget_destroy ), NULL ); - g_object_set_data( G_OBJECT( dlg ), "loop", &loop ); - g_object_set_data( G_OBJECT( dlg ), "ret", &ret ); - - auto vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - dlg.add(vbox); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - auto frame = ui::Frame( "3D View" ); - frame.show(); - vbox.pack_start( frame, TRUE, TRUE, 0 ); - - auto vbox2 = ui::VBox( FALSE, 5 ); - vbox2.show(); - frame.add(vbox2); - gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 5 ); - - auto hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox2.pack_start( hbox, TRUE, TRUE, 0 ); - - auto adj = ui::Adjustment( portals.width_3d, 2, 40, 1, 1, 0 ); - auto lw3slider = ui::HScale( adj ); - lw3slider.show(); - hbox.pack_start( lw3slider, TRUE, TRUE, 0 ); - gtk_scale_set_draw_value( GTK_SCALE( lw3slider ), FALSE ); - - auto lw3label = ui::Label( "" ); - lw3label.show(); - hbox.pack_start( lw3label, FALSE, TRUE, 0 ); - adj.connect( "value_changed", G_CALLBACK( OnScroll3d ), lw3label ); - - auto table = ui::Table( 2, 4, FALSE ); - table.show(); - vbox2.pack_start( table, TRUE, TRUE, 0 ); +void DoConfigDialog() +{ + int loop = 1, ret = IDCANCEL; + + auto dlg = ui::Window(ui::window_type::TOP); + gtk_window_set_title(dlg, "Portal Viewer Configuration"); + dlg.connect("delete_event", + G_CALLBACK(dialog_delete_callback), NULL); + dlg.connect("destroy", + G_CALLBACK(gtk_widget_destroy), NULL); + g_object_set_data(G_OBJECT(dlg), "loop", &loop); + g_object_set_data(G_OBJECT(dlg), "ret", &ret); + + auto vbox = ui::VBox(FALSE, 5); + vbox.show(); + dlg.add(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + auto frame = ui::Frame("3D View"); + frame.show(); + vbox.pack_start(frame, TRUE, TRUE, 0); + + auto vbox2 = ui::VBox(FALSE, 5); + vbox2.show(); + frame.add(vbox2); + gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); + + auto hbox = ui::HBox(FALSE, 5); + hbox.show(); + vbox2.pack_start(hbox, TRUE, TRUE, 0); + + auto adj = ui::Adjustment(portals.width_3d, 2, 40, 1, 1, 0); + auto lw3slider = ui::HScale(adj); + lw3slider.show(); + hbox.pack_start(lw3slider, TRUE, TRUE, 0); + gtk_scale_set_draw_value(GTK_SCALE(lw3slider), FALSE); + + auto lw3label = ui::Label(""); + lw3label.show(); + hbox.pack_start(lw3label, FALSE, TRUE, 0); + adj.connect("value_changed", G_CALLBACK(OnScroll3d), lw3label); + + auto table = ui::Table(2, 4, FALSE); + table.show(); + vbox2.pack_start(table, TRUE, TRUE, 0); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - auto button = ui::Button( "Color" ); - button.show(); + auto button = ui::Button("Color"); + button.show(); table.attach(button, {0, 1, 0, 1}, {GTK_FILL, 0}); - button.connect( "clicked", G_CALLBACK( OnColor3d ), NULL ); + button.connect("clicked", G_CALLBACK(OnColor3d), NULL); - button = ui::Button( "Depth Color" ); - button.show(); + button = ui::Button("Depth Color"); + button.show(); table.attach(button, {0, 1, 1, 2}, {GTK_FILL, 0}); - button.connect( "clicked", G_CALLBACK( OnColorFog ), NULL ); + button.connect("clicked", G_CALLBACK(OnColorFog), NULL); - auto aa3check = ui::CheckButton( "Anti-Alias (May not work on some video cards)" ); - aa3check.show(); + auto aa3check = ui::CheckButton("Anti-Alias (May not work on some video cards)"); + aa3check.show(); table.attach(aa3check, {1, 4, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - aa3check.connect( "toggled", G_CALLBACK( OnAntiAlias3d ), NULL ); + aa3check.connect("toggled", G_CALLBACK(OnAntiAlias3d), NULL); - auto depthcheck = ui::CheckButton( "Depth Cue" ); - depthcheck.show(); + auto depthcheck = ui::CheckButton("Depth Cue"); + depthcheck.show(); table.attach(depthcheck, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - depthcheck.connect( "toggled", G_CALLBACK( OnFog ), NULL ); + depthcheck.connect("toggled", G_CALLBACK(OnFog), NULL); - auto linescheck = ui::CheckButton( "Lines" ); - linescheck.show(); + auto linescheck = ui::CheckButton("Lines"); + linescheck.show(); table.attach(linescheck, {2, 3, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - linescheck.connect( "toggled", G_CALLBACK( OnLines ), NULL ); + linescheck.connect("toggled", G_CALLBACK(OnLines), NULL); - auto polyscheck = ui::CheckButton( "Polygons" ); - polyscheck.show(); + auto polyscheck = ui::CheckButton("Polygons"); + polyscheck.show(); table.attach(polyscheck, {3, 4, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - polyscheck.connect( "toggled", G_CALLBACK( OnPoly ), NULL ); + polyscheck.connect("toggled", G_CALLBACK(OnPoly), NULL); - auto zlist = ui::ComboBoxText(ui::New); - zlist.show(); - vbox2.pack_start( zlist, TRUE, FALSE, 0 ); + auto zlist = ui::ComboBoxText(ui::New); + zlist.show(); + vbox2.pack_start(zlist, TRUE, FALSE, 0); - gtk_combo_box_text_append_text(zlist, "Z-Buffer Test and Write (recommended for solid or no polygons)"); - gtk_combo_box_text_append_text(zlist, "Z-Buffer Test Only (recommended for transparent polygons)"); - gtk_combo_box_text_append_text(zlist, "Z-Buffer Off"); + gtk_combo_box_text_append_text(zlist, "Z-Buffer Test and Write (recommended for solid or no polygons)"); + gtk_combo_box_text_append_text(zlist, "Z-Buffer Test Only (recommended for transparent polygons)"); + gtk_combo_box_text_append_text(zlist, "Z-Buffer Off"); - zlist.connect("changed", G_CALLBACK(+[](ui::ComboBox self, void *) { - OnSelchangeZbuffer(self, GINT_TO_POINTER(gtk_combo_box_get_active(self))); - }), nullptr); + zlist.connect("changed", G_CALLBACK(+[](ui::ComboBox self, void *) { + OnSelchangeZbuffer(self, GINT_TO_POINTER(gtk_combo_box_get_active(self))); + }), nullptr); - table = ui::Table( 2, 2, FALSE ); - table.show(); - vbox2.pack_start( table, TRUE, TRUE, 0 ); + table = ui::Table(2, 2, FALSE); + table.show(); + vbox2.pack_start(table, TRUE, TRUE, 0); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - adj = ui::Adjustment( portals.trans_3d, 0, 100, 1, 1, 0 ); - auto transslider = ui::HScale( adj ); - transslider.show(); + adj = ui::Adjustment(portals.trans_3d, 0, 100, 1, 1, 0); + auto transslider = ui::HScale(adj); + transslider.show(); table.attach(transslider, {0, 1, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_scale_set_draw_value( GTK_SCALE( transslider ), FALSE ); + gtk_scale_set_draw_value(GTK_SCALE(transslider), FALSE); - auto translabel = ui::Label( "" ); - translabel.show(); + auto translabel = ui::Label(""); + translabel.show(); table.attach(translabel, {1, 2, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( translabel ), 0.0, 0.0 ); - adj.connect( "value_changed", G_CALLBACK( OnScrollTrans ), translabel ); + gtk_misc_set_alignment(GTK_MISC(translabel), 0.0, 0.0); + adj.connect("value_changed", G_CALLBACK(OnScrollTrans), translabel); - adj = ui::Adjustment( portals.clip_range, 1, 128, 1, 1, 0 ); - auto clipslider = ui::HScale( adj ); - clipslider.show(); + adj = ui::Adjustment(portals.clip_range, 1, 128, 1, 1, 0); + auto clipslider = ui::HScale(adj); + clipslider.show(); table.attach(clipslider, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_scale_set_draw_value( GTK_SCALE( clipslider ), FALSE ); + gtk_scale_set_draw_value(GTK_SCALE(clipslider), FALSE); - auto cliplabel = ui::Label( "" ); - cliplabel.show(); + auto cliplabel = ui::Label(""); + cliplabel.show(); table.attach(cliplabel, {1, 2, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( cliplabel ), 0.0, 0.0 ); - adj.connect( "value_changed", G_CALLBACK( OnScrollClip ), cliplabel ); - - hbox = ui::HBox( TRUE, 5 ); - hbox.show(); - vbox2.pack_start( hbox, TRUE, FALSE, 0 ); - - auto show3check = ui::CheckButton( "Show" ); - show3check.show(); - hbox.pack_start( show3check, TRUE, TRUE, 0 ); - show3check.connect( "toggled", G_CALLBACK( OnConfig3d ), NULL ); - - auto portalcheck = ui::CheckButton( "Portal cubic clipper" ); - portalcheck.show(); - hbox.pack_start( portalcheck, TRUE, TRUE, 0 ); - portalcheck.connect( "toggled", G_CALLBACK( OnClip ), NULL ); - - frame = ui::Frame( "2D View" ); - frame.show(); - vbox.pack_start( frame, TRUE, TRUE, 0 ); - - vbox2 = ui::VBox( FALSE, 5 ); - vbox2.show(); - frame.add(vbox2); - gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 5 ); - - hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox2.pack_start( hbox, TRUE, FALSE, 0 ); - - adj = ui::Adjustment( portals.width_2d, 2, 40, 1, 1, 0 ); - auto lw2slider = ui::HScale( adj ); - lw2slider.show(); - hbox.pack_start( lw2slider, TRUE, TRUE, 0 ); - gtk_scale_set_draw_value( GTK_SCALE( lw2slider ), FALSE ); - - auto lw2label = ui::Label( "" ); - lw2label.show(); - hbox.pack_start( lw2label, FALSE, TRUE, 0 ); - adj.connect( "value_changed", G_CALLBACK( OnScroll2d ), lw2label ); - - hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox2.pack_start( hbox, TRUE, FALSE, 0 ); - - button = ui::Button( "Color" ); - button.show(); - hbox.pack_start( button, FALSE, FALSE, 0 ); - button.connect( "clicked", G_CALLBACK( OnColor2d ), NULL ); - button.dimensions(60, -1); - - auto aa2check = ui::CheckButton( "Anti-Alias (May not work on some video cards)" ); - aa2check.show(); - hbox.pack_start( aa2check, TRUE, TRUE, 0 ); - aa2check.connect( "toggled", G_CALLBACK( OnAntiAlias2d ), NULL ); - - hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox2.pack_start( hbox, TRUE, FALSE, 0 ); - - auto show2check = ui::CheckButton( "Show" ); - show2check.show(); - hbox.pack_start( show2check, FALSE, FALSE, 0 ); - show2check.connect( "toggled", G_CALLBACK( OnConfig2d ), NULL ); - - hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - - button = ui::Button( "OK" ); - button.show(); - hbox.pack_end(button, FALSE, FALSE, 0); - button.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDOK ) ); - button.dimensions(60, -1); - - // initialize dialog - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( show2check ), portals.show_2d ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( aa2check ), portals.aa_2d ); - Set2DText( lw2label ); - - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( show3check ), portals.show_3d ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( depthcheck ), portals.fog ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( polyscheck ), portals.polygons ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( linescheck ), portals.lines ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( aa3check ), portals.aa_3d ); - gtk_combo_box_set_active(zlist, portals.zbuffer); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( portalcheck ), portals.clip ); - - Set3DText( lw3label ); - Set3DTransText( translabel ); - SetClipText( cliplabel ); - - gtk_grab_add( dlg ); - dlg.show(); - - while ( loop ) - gtk_main_iteration(); - - gtk_grab_remove( dlg ); - dlg.destroy(); + gtk_misc_set_alignment(GTK_MISC(cliplabel), 0.0, 0.0); + adj.connect("value_changed", G_CALLBACK(OnScrollClip), cliplabel); + + hbox = ui::HBox(TRUE, 5); + hbox.show(); + vbox2.pack_start(hbox, TRUE, FALSE, 0); + + auto show3check = ui::CheckButton("Show"); + show3check.show(); + hbox.pack_start(show3check, TRUE, TRUE, 0); + show3check.connect("toggled", G_CALLBACK(OnConfig3d), NULL); + + auto portalcheck = ui::CheckButton("Portal cubic clipper"); + portalcheck.show(); + hbox.pack_start(portalcheck, TRUE, TRUE, 0); + portalcheck.connect("toggled", G_CALLBACK(OnClip), NULL); + + frame = ui::Frame("2D View"); + frame.show(); + vbox.pack_start(frame, TRUE, TRUE, 0); + + vbox2 = ui::VBox(FALSE, 5); + vbox2.show(); + frame.add(vbox2); + gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); + + hbox = ui::HBox(FALSE, 5); + hbox.show(); + vbox2.pack_start(hbox, TRUE, FALSE, 0); + + adj = ui::Adjustment(portals.width_2d, 2, 40, 1, 1, 0); + auto lw2slider = ui::HScale(adj); + lw2slider.show(); + hbox.pack_start(lw2slider, TRUE, TRUE, 0); + gtk_scale_set_draw_value(GTK_SCALE(lw2slider), FALSE); + + auto lw2label = ui::Label(""); + lw2label.show(); + hbox.pack_start(lw2label, FALSE, TRUE, 0); + adj.connect("value_changed", G_CALLBACK(OnScroll2d), lw2label); + + hbox = ui::HBox(FALSE, 5); + hbox.show(); + vbox2.pack_start(hbox, TRUE, FALSE, 0); + + button = ui::Button("Color"); + button.show(); + hbox.pack_start(button, FALSE, FALSE, 0); + button.connect("clicked", G_CALLBACK(OnColor2d), NULL); + button.dimensions(60, -1); + + auto aa2check = ui::CheckButton("Anti-Alias (May not work on some video cards)"); + aa2check.show(); + hbox.pack_start(aa2check, TRUE, TRUE, 0); + aa2check.connect("toggled", G_CALLBACK(OnAntiAlias2d), NULL); + + hbox = ui::HBox(FALSE, 5); + hbox.show(); + vbox2.pack_start(hbox, TRUE, FALSE, 0); + + auto show2check = ui::CheckButton("Show"); + show2check.show(); + hbox.pack_start(show2check, FALSE, FALSE, 0); + show2check.connect("toggled", G_CALLBACK(OnConfig2d), NULL); + + hbox = ui::HBox(FALSE, 5); + hbox.show(); + vbox.pack_start(hbox, FALSE, FALSE, 0); + + button = ui::Button("OK"); + button.show(); + hbox.pack_end(button, FALSE, FALSE, 0); + button.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK)); + button.dimensions(60, -1); + + // initialize dialog + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show2check), portals.show_2d); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(aa2check), portals.aa_2d); + Set2DText(lw2label); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show3check), portals.show_3d); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(depthcheck), portals.fog); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(polyscheck), portals.polygons); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linescheck), portals.lines); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(aa3check), portals.aa_3d); + gtk_combo_box_set_active(zlist, portals.zbuffer); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(portalcheck), portals.clip); + + Set3DText(lw3label); + Set3DTransText(translabel); + SetClipText(cliplabel); + + gtk_grab_add(dlg); + dlg.show(); + + while (loop) { + gtk_main_iteration(); + } + + gtk_grab_remove(dlg); + dlg.destroy(); } diff --git a/contrib/prtview/LoadPortalFileDialog.cpp b/contrib/prtview/LoadPortalFileDialog.cpp index 9ebcd69b..f83b34ff 100644 --- a/contrib/prtview/LoadPortalFileDialog.cpp +++ b/contrib/prtview/LoadPortalFileDialog.cpp @@ -33,132 +33,137 @@ #include "prtview.h" #include "portals.h" -static void dialog_button_callback( ui::Widget widget, gpointer data ){ - int *loop, *ret; +static void dialog_button_callback(ui::Widget widget, gpointer data) +{ + int *loop, *ret; - auto parent = widget.window(); - loop = (int*)g_object_get_data( G_OBJECT( parent ), "loop" ); - ret = (int*)g_object_get_data( G_OBJECT( parent ), "ret" ); + auto parent = widget.window(); + loop = (int *) g_object_get_data(G_OBJECT(parent), "loop"); + ret = (int *) g_object_get_data(G_OBJECT(parent), "ret"); - *loop = 0; - *ret = gpointer_to_int( data ); + *loop = 0; + *ret = gpointer_to_int(data); } -static gint dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){ - widget.hide(); - int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); - *loop = 0; - return TRUE; +static gint dialog_delete_callback(ui::Widget widget, GdkEvent *event, gpointer data) +{ + widget.hide(); + int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); + *loop = 0; + return TRUE; } -static void change_clicked(ui::Widget widget, gpointer data ){ - char* filename = NULL; +static void change_clicked(ui::Widget widget, gpointer data) +{ + char *filename = NULL; - auto file_sel = ui::Widget::from(gtk_file_chooser_dialog_new ( "Locate portal (.prt) file", nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - nullptr)); + auto file_sel = ui::Widget::from( + gtk_file_chooser_dialog_new("Locate portal (.prt) file", nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + nullptr)); - gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(file_sel), portals.fn ); + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(file_sel), portals.fn); - if (gtk_dialog_run (GTK_DIALOG (file_sel)) == GTK_RESPONSE_ACCEPT) - { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_sel)); - } - ui::Widget(file_sel).destroy(); + if (gtk_dialog_run(GTK_DIALOG (file_sel)) == GTK_RESPONSE_ACCEPT) { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (file_sel)); + } + ui::Widget(file_sel).destroy(); - if ( filename != NULL ) { - strcpy( portals.fn, filename ); - gtk_entry_set_text( GTK_ENTRY( data ), filename ); - g_free( filename ); - } + if (filename != NULL) { + strcpy(portals.fn, filename); + gtk_entry_set_text(GTK_ENTRY(data), filename); + g_free(filename); + } } -int DoLoadPortalFileDialog(){ - int loop = 1, ret = IDCANCEL; - - auto dlg = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( dlg, "Load .prt" ); - dlg.connect( "delete_event", - G_CALLBACK( dialog_delete_callback ), NULL ); - dlg.connect( "destroy", - G_CALLBACK( gtk_widget_destroy ), NULL ); - g_object_set_data( G_OBJECT( dlg ), "loop", &loop ); - g_object_set_data( G_OBJECT( dlg ), "ret", &ret ); - - auto vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - dlg.add(vbox); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - auto entry = ui::Entry(ui::New); - entry.show(); - gtk_editable_set_editable( GTK_EDITABLE( entry ), FALSE ); - vbox.pack_start( entry, FALSE, FALSE, 0 ); - - auto hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - - auto check3d = ui::CheckButton( "Show 3D" ); - check3d.show(); - hbox.pack_start( check3d, FALSE, FALSE, 0 ); - - auto check2d = ui::CheckButton( "Show 2D" ); - check2d.show(); - hbox.pack_start( check2d, FALSE, FALSE, 0 ); - - auto button = ui::Button( "Change" ); - button.show(); - hbox.pack_end(button, FALSE, FALSE, 0); - button.connect( "clicked", G_CALLBACK( change_clicked ), entry ); - button.dimensions(60, -1); - - hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox.pack_start( hbox, FALSE, FALSE, 0 ); - - button = ui::Button( "Cancel" ); - button.show(); - hbox.pack_end(button, FALSE, FALSE, 0); - button.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) ); - button.dimensions(60, -1); - - button = ui::Button( "OK" ); - button.show(); - hbox.pack_end(button, FALSE, FALSE, 0); - button.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDOK ) ); - button.dimensions(60, -1); - - strcpy( portals.fn, GlobalRadiant().getMapName() ); - char* fn = strrchr( portals.fn, '.' ); - if ( fn != NULL ) { - strcpy( fn, ".prt" ); - } - - StringOutputStream value( 256 ); - value << portals.fn; - gtk_entry_set_text( GTK_ENTRY( entry ), value.c_str() ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( check2d ), portals.show_2d ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( check3d ), portals.show_3d ); - - gtk_grab_add( dlg ); - dlg.show(); - - while ( loop ) - gtk_main_iteration(); - - if ( ret == IDOK ) { - portals.Purge(); - - portals.show_3d = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check3d ) ) ? true : false; - portals.show_2d = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check2d ) ) ? true : false; - } - - gtk_grab_remove( dlg ); - dlg.destroy(); - - return ret; +int DoLoadPortalFileDialog() +{ + int loop = 1, ret = IDCANCEL; + + auto dlg = ui::Window(ui::window_type::TOP); + gtk_window_set_title(dlg, "Load .prt"); + dlg.connect("delete_event", + G_CALLBACK(dialog_delete_callback), NULL); + dlg.connect("destroy", + G_CALLBACK(gtk_widget_destroy), NULL); + g_object_set_data(G_OBJECT(dlg), "loop", &loop); + g_object_set_data(G_OBJECT(dlg), "ret", &ret); + + auto vbox = ui::VBox(FALSE, 5); + vbox.show(); + dlg.add(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + auto entry = ui::Entry(ui::New); + entry.show(); + gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE); + vbox.pack_start(entry, FALSE, FALSE, 0); + + auto hbox = ui::HBox(FALSE, 5); + hbox.show(); + vbox.pack_start(hbox, FALSE, FALSE, 0); + + auto check3d = ui::CheckButton("Show 3D"); + check3d.show(); + hbox.pack_start(check3d, FALSE, FALSE, 0); + + auto check2d = ui::CheckButton("Show 2D"); + check2d.show(); + hbox.pack_start(check2d, FALSE, FALSE, 0); + + auto button = ui::Button("Change"); + button.show(); + hbox.pack_end(button, FALSE, FALSE, 0); + button.connect("clicked", G_CALLBACK(change_clicked), entry); + button.dimensions(60, -1); + + hbox = ui::HBox(FALSE, 5); + hbox.show(); + vbox.pack_start(hbox, FALSE, FALSE, 0); + + button = ui::Button("Cancel"); + button.show(); + hbox.pack_end(button, FALSE, FALSE, 0); + button.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDCANCEL)); + button.dimensions(60, -1); + + button = ui::Button("OK"); + button.show(); + hbox.pack_end(button, FALSE, FALSE, 0); + button.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK)); + button.dimensions(60, -1); + + strcpy(portals.fn, GlobalRadiant().getMapName()); + char *fn = strrchr(portals.fn, '.'); + if (fn != NULL) { + strcpy(fn, ".prt"); + } + + StringOutputStream value(256); + value << portals.fn; + gtk_entry_set_text(GTK_ENTRY(entry), value.c_str()); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check2d), portals.show_2d); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check3d), portals.show_3d); + + gtk_grab_add(dlg); + dlg.show(); + + while (loop) { + gtk_main_iteration(); + } + + if (ret == IDOK) { + portals.Purge(); + + portals.show_3d = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check3d)) ? true : false; + portals.show_2d = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check2d)) ? true : false; + } + + gtk_grab_remove(dlg); + dlg.destroy(); + + return ret; } diff --git a/contrib/prtview/portals.cpp b/contrib/prtview/portals.cpp index 7a2d99d1..c4d3b04d 100644 --- a/contrib/prtview/portals.cpp +++ b/contrib/prtview/portals.cpp @@ -21,9 +21,13 @@ #include "globaldefs.h" #include #include + #if !GDEF_OS_MACOS + #include + #endif + #include #include "iglrender.h" @@ -36,172 +40,171 @@ const int LINE_BUF = 1000; CPortals portals; CPortalsRender render; -int compare( const void *arg1, const void *arg2 ){ +int compare(const void *arg1, const void *arg2) +{ - if ( portals.portal[*( (int *)arg1 )].dist > portals.portal[*( (int *)arg2 )].dist ) { - return -1; - } - else if ( portals.portal[*( (int *)arg1 )].dist < portals.portal[*( (int *)arg2 )].dist ) { - return 1; - } + if (portals.portal[*((int *) arg1)].dist > portals.portal[*((int *) arg2)].dist) { + return -1; + } else if (portals.portal[*((int *) arg1)].dist < portals.portal[*((int *) arg2)].dist) { + return 1; + } - return 0; + return 0; } -CBspPortal::CBspPortal(){ - memset( this, 0, sizeof( CBspPortal ) ); +CBspPortal::CBspPortal() +{ + memset(this, 0, sizeof(CBspPortal)); } -CBspPortal::~CBspPortal(){ - delete[] point; - delete[] inner_point; +CBspPortal::~CBspPortal() +{ + delete[] point; + delete[] inner_point; } -bool CBspPortal::Build( char *def ){ - char *c = def; - unsigned int n; - int dummy1, dummy2; - int res_cnt, i; - - if ( portals.hint_flags ) { - res_cnt = sscanf( def, "%u %d %d %d", &point_count, &dummy1, &dummy2, (int *)&hint ); - } - else - { - sscanf( def, "%u", &point_count ); - hint = false; - } - - if ( point_count < 3 || ( portals.hint_flags && res_cnt < 4 ) ) { - return false; - } - - point = new CBspPoint[point_count]; - inner_point = new CBspPoint[point_count]; - - for ( n = 0; n < point_count; n++ ) - { - for (; *c != 0 && *c != '('; c++ ) ; - - if ( *c == 0 ) { - return false; - } - - c++; - - sscanf( c, "%f %f %f", point[n].p, point[n].p + 1, point[n].p + 2 ); - - center.p[0] += point[n].p[0]; - center.p[1] += point[n].p[1]; - center.p[2] += point[n].p[2]; - - if ( n == 0 ) { - for ( i = 0; i < 3; i++ ) - { - min[i] = point[n].p[i]; - max[i] = point[n].p[i]; - } - } - else - { - for ( i = 0; i < 3; i++ ) - { - if ( min[i] > point[n].p[i] ) { - min[i] = point[n].p[i]; - } - if ( max[i] < point[n].p[i] ) { - max[i] = point[n].p[i]; - } - } - } - } - - center.p[0] /= (float)point_count; - center.p[1] /= (float)point_count; - center.p[2] /= (float)point_count; - - for ( n = 0; n < point_count; n++ ) - { - inner_point[n].p[0] = ( 0.01f * center.p[0] ) + ( 0.99f * point[n].p[0] ); - inner_point[n].p[1] = ( 0.01f * center.p[1] ) + ( 0.99f * point[n].p[1] ); - inner_point[n].p[2] = ( 0.01f * center.p[2] ) + ( 0.99f * point[n].p[2] ); - } - - fp_color_random[0] = (float)( rand() & 0xff ) / 255.0f; - fp_color_random[1] = (float)( rand() & 0xff ) / 255.0f; - fp_color_random[2] = (float)( rand() & 0xff ) / 255.0f; - fp_color_random[3] = 1.0f; - - return true; +bool CBspPortal::Build(char *def) +{ + char *c = def; + unsigned int n; + int dummy1, dummy2; + int res_cnt, i; + + if (portals.hint_flags) { + res_cnt = sscanf(def, "%u %d %d %d", &point_count, &dummy1, &dummy2, (int *) &hint); + } else { + sscanf(def, "%u", &point_count); + hint = false; + } + + if (point_count < 3 || (portals.hint_flags && res_cnt < 4)) { + return false; + } + + point = new CBspPoint[point_count]; + inner_point = new CBspPoint[point_count]; + + for (n = 0; n < point_count; n++) { + for (; *c != 0 && *c != '('; c++) {} + + if (*c == 0) { + return false; + } + + c++; + + sscanf(c, "%f %f %f", point[n].p, point[n].p + 1, point[n].p + 2); + + center.p[0] += point[n].p[0]; + center.p[1] += point[n].p[1]; + center.p[2] += point[n].p[2]; + + if (n == 0) { + for (i = 0; i < 3; i++) { + min[i] = point[n].p[i]; + max[i] = point[n].p[i]; + } + } else { + for (i = 0; i < 3; i++) { + if (min[i] > point[n].p[i]) { + min[i] = point[n].p[i]; + } + if (max[i] < point[n].p[i]) { + max[i] = point[n].p[i]; + } + } + } + } + + center.p[0] /= (float) point_count; + center.p[1] /= (float) point_count; + center.p[2] /= (float) point_count; + + for (n = 0; n < point_count; n++) { + inner_point[n].p[0] = (0.01f * center.p[0]) + (0.99f * point[n].p[0]); + inner_point[n].p[1] = (0.01f * center.p[1]) + (0.99f * point[n].p[1]); + inner_point[n].p[2] = (0.01f * center.p[2]) + (0.99f * point[n].p[2]); + } + + fp_color_random[0] = (float) (rand() & 0xff) / 255.0f; + fp_color_random[1] = (float) (rand() & 0xff) / 255.0f; + fp_color_random[2] = (float) (rand() & 0xff) / 255.0f; + fp_color_random[3] = 1.0f; + + return true; } -CPortals::CPortals(){ - memset( this, 0, sizeof( CPortals ) ); +CPortals::CPortals() +{ + memset(this, 0, sizeof(CPortals)); } -CPortals::~CPortals(){ - Purge(); +CPortals::~CPortals() +{ + Purge(); } -void CPortals::Purge(){ - delete[] portal; - delete[] portal_sort; - portal = NULL; - portal_sort = NULL; - portal_count = 0; - - /* - delete[] node; - node = NULL; - node_count = 0; - */ +void CPortals::Purge() +{ + delete[] portal; + delete[] portal_sort; + portal = NULL; + portal_sort = NULL; + portal_count = 0; + + /* + delete[] node; + node = NULL; + node_count = 0; + */ } -void CPortals::Load(){ - char buf[LINE_BUF + 1]; +void CPortals::Load() +{ + char buf[LINE_BUF + 1]; - memset( buf, 0, LINE_BUF + 1 ); + memset(buf, 0, LINE_BUF + 1); - Purge(); + Purge(); - globalOutputStream() << MSG_PREFIX "Loading portal file " << fn << ".\n"; + globalOutputStream() << MSG_PREFIX "Loading portal file " << fn << ".\n"; - FILE *in; + FILE *in; - in = fopen( fn, "rt" ); + in = fopen(fn, "rt"); - if ( in == NULL ) { - globalOutputStream() << " ERROR - could not open file.\n"; + if (in == NULL) { + globalOutputStream() << " ERROR - could not open file.\n"; - return; - } + return; + } - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - globalOutputStream() << " ERROR - File ended prematurely.\n"; + globalOutputStream() << " ERROR - File ended prematurely.\n"; - return; - } + return; + } - if ( strncmp( "PRT1", buf, 4 ) != 0 ) { - fclose( in ); + if (strncmp("PRT1", buf, 4) != 0) { + fclose(in); - globalOutputStream() << " ERROR - File header indicates wrong file type (should be \"PRT1\").\n"; + globalOutputStream() << " ERROR - File header indicates wrong file type (should be \"PRT1\").\n"; - return; - } + return; + } - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - globalOutputStream() << " ERROR - File ended prematurely.\n"; + globalOutputStream() << " ERROR - File ended prematurely.\n"; - return; - } + return; + } - sscanf( buf, "%u", &node_count ); + sscanf(buf, "%u", &node_count); /* if(node_count > 0xFFFF) { @@ -215,427 +218,422 @@ void CPortals::Load(){ } */ - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - node_count = 0; + node_count = 0; - globalOutputStream() << " ERROR - File ended prematurely.\n"; + globalOutputStream() << " ERROR - File ended prematurely.\n"; - return; - } + return; + } - sscanf( buf, "%u", &portal_count ); + sscanf(buf, "%u", &portal_count); - if ( portal_count > 0xFFFF ) { - fclose( in ); + if (portal_count > 0xFFFF) { + fclose(in); - portal_count = 0; - node_count = 0; + portal_count = 0; + node_count = 0; - globalOutputStream() << " ERROR - Extreme number of portals, aborting.\n"; + globalOutputStream() << " ERROR - Extreme number of portals, aborting.\n"; - return; - } + return; + } - if ( portal_count == 0 ) { - fclose( in ); + if (portal_count == 0) { + fclose(in); - portal_count = 0; - node_count = 0; + portal_count = 0; + node_count = 0; - globalOutputStream() << " ERROR - number of portals equals 0, aborting.\n"; + globalOutputStream() << " ERROR - number of portals equals 0, aborting.\n"; - return; - } + return; + } // node = new CBspNode[node_count]; - portal = new CBspPortal[portal_count]; - portal_sort = new int[portal_count]; + portal = new CBspPortal[portal_count]; + portal_sort = new int[portal_count]; - unsigned int n; - bool first = true; - unsigned test_vals_1, test_vals_2; + unsigned int n; + bool first = true; + unsigned test_vals_1, test_vals_2; - hint_flags = false; + hint_flags = false; - for ( n = 0; n < portal_count; ) - { - if ( !fgets( buf, LINE_BUF, in ) ) { - fclose( in ); + for (n = 0; n < portal_count;) { + if (!fgets(buf, LINE_BUF, in)) { + fclose(in); - Purge(); + Purge(); - globalOutputStream() << " ERROR - Could not find information for portal number " << n + 1 << " of " << portal_count << ".\n"; + globalOutputStream() << " ERROR - Could not find information for portal number " << n + 1 << " of " + << portal_count << ".\n"; - return; - } + return; + } - if ( !portal[n].Build( buf ) ) { - if ( first && sscanf( buf, "%d %d", (int *) &test_vals_1, (int *) &test_vals_2 ) == 1 ) { // skip additional counts of later data, not needed - // We can count on hint flags being in the file - hint_flags = true; - continue; - } + if (!portal[n].Build(buf)) { + if (first && sscanf(buf, "%d %d", (int *) &test_vals_1, (int *) &test_vals_2) == + 1) { // skip additional counts of later data, not needed + // We can count on hint flags being in the file + hint_flags = true; + continue; + } - first = false; + first = false; - fclose( in ); + fclose(in); - Purge(); + Purge(); - globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << portal_count << " is not formatted correctly.\n"; + globalOutputStream() << " ERROR - Information for portal number " << n + 1 << " of " << portal_count + << " is not formatted correctly.\n"; - return; - } + return; + } - n++; - } + n++; + } - fclose( in ); + fclose(in); - globalOutputStream() << " " << node_count << " portals read in.\n"; + globalOutputStream() << " " << node_count << " portals read in.\n"; } #include "math/matrix.h" -const char* g_state_solid = "$plugins/prtview/solid"; -const char* g_state_solid_outline = "$plugins/prtview/solid_outline"; -const char* g_state_wireframe = "$plugins/prtview/wireframe"; -Shader* g_shader_solid = 0; -Shader* g_shader_solid_outline = 0; -Shader* g_shader_wireframe = 0; - -void Portals_constructShaders(){ - OpenGLState state; - GlobalOpenGLStateLibrary().getDefaultState( state ); - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortOverlayFirst; - state.m_linewidth = portals.width_2d * 0.5f; - state.m_colour[0] = portals.fp_color_2d[0]; - state.m_colour[1] = portals.fp_color_2d[1]; - state.m_colour[2] = portals.fp_color_2d[2]; - state.m_colour[3] = portals.fp_color_2d[3]; - if ( portals.aa_2d ) { - state.m_state |= RENDER_BLEND | RENDER_LINESMOOTH; - } - GlobalOpenGLStateLibrary().insert( g_state_wireframe, state ); - - GlobalOpenGLStateLibrary().getDefaultState( state ); - state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_COLOURCHANGE | RENDER_SMOOTH; - - if ( portals.aa_3d ) { - state.m_state |= RENDER_POLYGONSMOOTH; - } - - switch ( portals.zbuffer ) - { - case 1: - state.m_state |= RENDER_DEPTHTEST; - break; - case 2: - break; - default: - state.m_state |= RENDER_DEPTHTEST; - state.m_state |= RENDER_DEPTHWRITE; - } - - if ( portals.fog ) { - state.m_state |= RENDER_FOG; - - state.m_fog.mode = GL_EXP; - state.m_fog.density = 0.001f; - state.m_fog.start = 10.0f; - state.m_fog.end = 10000.0f; - state.m_fog.index = 0; - state.m_fog.colour[0] = portals.fp_color_fog[0]; - state.m_fog.colour[1] = portals.fp_color_fog[1]; - state.m_fog.colour[2] = portals.fp_color_fog[2]; - state.m_fog.colour[3] = portals.fp_color_fog[3]; - } - - GlobalOpenGLStateLibrary().insert( g_state_solid, state ); - - GlobalOpenGLStateLibrary().getDefaultState( state ); - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortOverlayFirst; - state.m_linewidth = portals.width_3d * 0.5f; - state.m_colour[0] = portals.fp_color_3d[0]; - state.m_colour[1] = portals.fp_color_3d[1]; - state.m_colour[2] = portals.fp_color_3d[2]; - state.m_colour[3] = portals.fp_color_3d[3]; - - if ( portals.aa_3d ) { - state.m_state |= RENDER_LINESMOOTH; - } - - switch ( portals.zbuffer ) - { - case 1: - state.m_state |= RENDER_DEPTHTEST; - break; - case 2: - break; - default: - state.m_state |= RENDER_DEPTHTEST; - state.m_state |= RENDER_DEPTHWRITE; - } - - if ( portals.fog ) { - state.m_state |= RENDER_FOG; - - state.m_fog.mode = GL_EXP; - state.m_fog.density = 0.001f; - state.m_fog.start = 10.0f; - state.m_fog.end = 10000.0f; - state.m_fog.index = 0; - state.m_fog.colour[0] = portals.fp_color_fog[0]; - state.m_fog.colour[1] = portals.fp_color_fog[1]; - state.m_fog.colour[2] = portals.fp_color_fog[2]; - state.m_fog.colour[3] = portals.fp_color_fog[3]; - } - - GlobalOpenGLStateLibrary().insert( g_state_solid_outline, state ); - - g_shader_solid = GlobalShaderCache().capture( g_state_solid ); - g_shader_solid_outline = GlobalShaderCache().capture( g_state_solid_outline ); - g_shader_wireframe = GlobalShaderCache().capture( g_state_wireframe ); +const char *g_state_solid = "$plugins/prtview/solid"; +const char *g_state_solid_outline = "$plugins/prtview/solid_outline"; +const char *g_state_wireframe = "$plugins/prtview/wireframe"; +Shader *g_shader_solid = 0; +Shader *g_shader_solid_outline = 0; +Shader *g_shader_wireframe = 0; + +void Portals_constructShaders() +{ + OpenGLState state; + GlobalOpenGLStateLibrary().getDefaultState(state); + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortOverlayFirst; + state.m_linewidth = portals.width_2d * 0.5f; + state.m_colour[0] = portals.fp_color_2d[0]; + state.m_colour[1] = portals.fp_color_2d[1]; + state.m_colour[2] = portals.fp_color_2d[2]; + state.m_colour[3] = portals.fp_color_2d[3]; + if (portals.aa_2d) { + state.m_state |= RENDER_BLEND | RENDER_LINESMOOTH; + } + GlobalOpenGLStateLibrary().insert(g_state_wireframe, state); + + GlobalOpenGLStateLibrary().getDefaultState(state); + state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_COLOURCHANGE | RENDER_SMOOTH; + + if (portals.aa_3d) { + state.m_state |= RENDER_POLYGONSMOOTH; + } + + switch (portals.zbuffer) { + case 1: + state.m_state |= RENDER_DEPTHTEST; + break; + case 2: + break; + default: + state.m_state |= RENDER_DEPTHTEST; + state.m_state |= RENDER_DEPTHWRITE; + } + + if (portals.fog) { + state.m_state |= RENDER_FOG; + + state.m_fog.mode = GL_EXP; + state.m_fog.density = 0.001f; + state.m_fog.start = 10.0f; + state.m_fog.end = 10000.0f; + state.m_fog.index = 0; + state.m_fog.colour[0] = portals.fp_color_fog[0]; + state.m_fog.colour[1] = portals.fp_color_fog[1]; + state.m_fog.colour[2] = portals.fp_color_fog[2]; + state.m_fog.colour[3] = portals.fp_color_fog[3]; + } + + GlobalOpenGLStateLibrary().insert(g_state_solid, state); + + GlobalOpenGLStateLibrary().getDefaultState(state); + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortOverlayFirst; + state.m_linewidth = portals.width_3d * 0.5f; + state.m_colour[0] = portals.fp_color_3d[0]; + state.m_colour[1] = portals.fp_color_3d[1]; + state.m_colour[2] = portals.fp_color_3d[2]; + state.m_colour[3] = portals.fp_color_3d[3]; + + if (portals.aa_3d) { + state.m_state |= RENDER_LINESMOOTH; + } + + switch (portals.zbuffer) { + case 1: + state.m_state |= RENDER_DEPTHTEST; + break; + case 2: + break; + default: + state.m_state |= RENDER_DEPTHTEST; + state.m_state |= RENDER_DEPTHWRITE; + } + + if (portals.fog) { + state.m_state |= RENDER_FOG; + + state.m_fog.mode = GL_EXP; + state.m_fog.density = 0.001f; + state.m_fog.start = 10.0f; + state.m_fog.end = 10000.0f; + state.m_fog.index = 0; + state.m_fog.colour[0] = portals.fp_color_fog[0]; + state.m_fog.colour[1] = portals.fp_color_fog[1]; + state.m_fog.colour[2] = portals.fp_color_fog[2]; + state.m_fog.colour[3] = portals.fp_color_fog[3]; + } + + GlobalOpenGLStateLibrary().insert(g_state_solid_outline, state); + + g_shader_solid = GlobalShaderCache().capture(g_state_solid); + g_shader_solid_outline = GlobalShaderCache().capture(g_state_solid_outline); + g_shader_wireframe = GlobalShaderCache().capture(g_state_wireframe); } -void Portals_destroyShaders(){ - GlobalShaderCache().release( g_state_solid ); - GlobalShaderCache().release( g_state_solid_outline ); - GlobalShaderCache().release( g_state_wireframe ); - GlobalOpenGLStateLibrary().erase( g_state_solid ); - GlobalOpenGLStateLibrary().erase( g_state_solid_outline ); - GlobalOpenGLStateLibrary().erase( g_state_wireframe ); +void Portals_destroyShaders() +{ + GlobalShaderCache().release(g_state_solid); + GlobalShaderCache().release(g_state_solid_outline); + GlobalShaderCache().release(g_state_wireframe); + GlobalOpenGLStateLibrary().erase(g_state_solid); + GlobalOpenGLStateLibrary().erase(g_state_solid_outline); + GlobalOpenGLStateLibrary().erase(g_state_wireframe); } -void Portals_shadersChanged(){ - Portals_destroyShaders(); - portals.FixColors(); - Portals_constructShaders(); +void Portals_shadersChanged() +{ + Portals_destroyShaders(); + portals.FixColors(); + Portals_constructShaders(); } -void CPortals::FixColors(){ - fp_color_2d[0] = (float)GetRValue( color_2d ) / 255.0f; - fp_color_2d[1] = (float)GetGValue( color_2d ) / 255.0f; - fp_color_2d[2] = (float)GetBValue( color_2d ) / 255.0f; - fp_color_2d[3] = 1.0f; - - fp_color_3d[0] = (float)GetRValue( color_3d ) / 255.0f; - fp_color_3d[1] = (float)GetGValue( color_3d ) / 255.0f; - fp_color_3d[2] = (float)GetBValue( color_3d ) / 255.0f; - fp_color_3d[3] = 1.0f; - - fp_color_fog[0] = 0.0f; //(float)GetRValue(color_fog) / 255.0f; - fp_color_fog[1] = 0.0f; //(float)GetGValue(color_fog) / 255.0f; - fp_color_fog[2] = 0.0f; //(float)GetBValue(color_fog) / 255.0f; - fp_color_fog[3] = 1.0f; +void CPortals::FixColors() +{ + fp_color_2d[0] = (float) GetRValue(color_2d) / 255.0f; + fp_color_2d[1] = (float) GetGValue(color_2d) / 255.0f; + fp_color_2d[2] = (float) GetBValue(color_2d) / 255.0f; + fp_color_2d[3] = 1.0f; + + fp_color_3d[0] = (float) GetRValue(color_3d) / 255.0f; + fp_color_3d[1] = (float) GetGValue(color_3d) / 255.0f; + fp_color_3d[2] = (float) GetBValue(color_3d) / 255.0f; + fp_color_3d[3] = 1.0f; + + fp_color_fog[0] = 0.0f; //(float)GetRValue(color_fog) / 255.0f; + fp_color_fog[1] = 0.0f; //(float)GetGValue(color_fog) / 255.0f; + fp_color_fog[2] = 0.0f; //(float)GetBValue(color_fog) / 255.0f; + fp_color_fog[3] = 1.0f; } -void CPortalsRender::renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - if ( !portals.show_2d || portals.portal_count < 1 ) { - return; - } +void CPortalsRender::renderWireframe(Renderer &renderer, const VolumeTest &volume) const +{ + if (!portals.show_2d || portals.portal_count < 1) { + return; + } - renderer.SetState( g_shader_wireframe, Renderer::eWireframeOnly ); + renderer.SetState(g_shader_wireframe, Renderer::eWireframeOnly); - renderer.addRenderable( m_drawWireframe, g_matrix4_identity ); + renderer.addRenderable(m_drawWireframe, g_matrix4_identity); } -void CPortalsDrawWireframe::render( RenderStateFlags state ) const { - unsigned int n, p; +void CPortalsDrawWireframe::render(RenderStateFlags state) const +{ + unsigned int n, p; - for ( n = 0; n < portals.portal_count; n++ ) - { - glBegin( GL_LINE_LOOP ); + for (n = 0; n < portals.portal_count; n++) { + glBegin(GL_LINE_LOOP); - for ( p = 0; p < portals.portal[n].point_count; p++ ) - glVertex3fv( portals.portal[n].point[p].p ); + for (p = 0; p < portals.portal[n].point_count; p++) + glVertex3fv(portals.portal[n].point[p].p); - glEnd(); - } + glEnd(); + } } -CubicClipVolume calculateCubicClipVolume( const Matrix4& viewproj ){ - CubicClipVolume clip; - clip.cam = vector4_projected( - matrix4_transformed_vector4( - matrix4_full_inverse( viewproj ), - Vector4( 0, 0, -1, 1 ) - ) - ); - clip.min[0] = clip.cam[0] + ( portals.clip_range * 64.0f ); - clip.min[1] = clip.cam[1] + ( portals.clip_range * 64.0f ); - clip.min[2] = clip.cam[2] + ( portals.clip_range * 64.0f ); - clip.max[0] = clip.cam[0] - ( portals.clip_range * 64.0f ); - clip.max[1] = clip.cam[1] - ( portals.clip_range * 64.0f ); - clip.max[2] = clip.cam[2] - ( portals.clip_range * 64.0f ); - return clip; +CubicClipVolume calculateCubicClipVolume(const Matrix4 &viewproj) +{ + CubicClipVolume clip; + clip.cam = vector4_projected( + matrix4_transformed_vector4( + matrix4_full_inverse(viewproj), + Vector4(0, 0, -1, 1) + ) + ); + clip.min[0] = clip.cam[0] + (portals.clip_range * 64.0f); + clip.min[1] = clip.cam[1] + (portals.clip_range * 64.0f); + clip.min[2] = clip.cam[2] + (portals.clip_range * 64.0f); + clip.max[0] = clip.cam[0] - (portals.clip_range * 64.0f); + clip.max[1] = clip.cam[1] - (portals.clip_range * 64.0f); + clip.max[2] = clip.cam[2] - (portals.clip_range * 64.0f); + return clip; } -void CPortalsRender::renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - if ( !portals.show_3d || portals.portal_count < 1 ) { - return; - } +void CPortalsRender::renderSolid(Renderer &renderer, const VolumeTest &volume) const +{ + if (!portals.show_3d || portals.portal_count < 1) { + return; + } - CubicClipVolume clip = calculateCubicClipVolume( matrix4_multiplied_by_matrix4( volume.GetProjection(), volume.GetModelview() ) ); + CubicClipVolume clip = calculateCubicClipVolume( + matrix4_multiplied_by_matrix4(volume.GetProjection(), volume.GetModelview())); - if ( portals.polygons ) { - renderer.SetState( g_shader_solid, Renderer::eWireframeOnly ); - renderer.SetState( g_shader_solid, Renderer::eFullMaterials ); + if (portals.polygons) { + renderer.SetState(g_shader_solid, Renderer::eWireframeOnly); + renderer.SetState(g_shader_solid, Renderer::eFullMaterials); - m_drawSolid.clip = clip; - renderer.addRenderable( m_drawSolid, g_matrix4_identity ); - } + m_drawSolid.clip = clip; + renderer.addRenderable(m_drawSolid, g_matrix4_identity); + } - if ( portals.lines ) { - renderer.SetState( g_shader_solid_outline, Renderer::eWireframeOnly ); - renderer.SetState( g_shader_solid_outline, Renderer::eFullMaterials ); + if (portals.lines) { + renderer.SetState(g_shader_solid_outline, Renderer::eWireframeOnly); + renderer.SetState(g_shader_solid_outline, Renderer::eFullMaterials); - m_drawSolidOutline.clip = clip; - renderer.addRenderable( m_drawSolidOutline, g_matrix4_identity ); - } + m_drawSolidOutline.clip = clip; + renderer.addRenderable(m_drawSolidOutline, g_matrix4_identity); + } } -void CPortalsDrawSolid::render( RenderStateFlags state ) const { - float trans = ( 100.0f - portals.trans_3d ) / 100.0f; - - unsigned int n, p; - - if ( portals.zbuffer != 0 ) { - float d; - - for ( n = 0; n < portals.portal_count; n++ ) - { - d = (float)clip.cam[0] - portals.portal[n].center.p[0]; - portals.portal[n].dist = d * d; - - d = (float)clip.cam[1] - portals.portal[n].center.p[1]; - portals.portal[n].dist += d * d; - - d = (float)clip.cam[2] - portals.portal[n].center.p[2]; - portals.portal[n].dist += d * d; - - portals.portal_sort[n] = n; - } - - qsort( portals.portal_sort, portals.portal_count, 4, compare ); - - for ( n = 0; n < portals.portal_count; n++ ) - { - if ( portals.polygons == 2 && !portals.portal[portals.portal_sort[n]].hint ) { - continue; - } - - if ( portals.clip ) { - if ( clip.min[0] < portals.portal[portals.portal_sort[n]].min[0] ) { - continue; - } - else if ( clip.min[1] < portals.portal[portals.portal_sort[n]].min[1] ) { - continue; - } - else if ( clip.min[2] < portals.portal[portals.portal_sort[n]].min[2] ) { - continue; - } - else if ( clip.max[0] > portals.portal[portals.portal_sort[n]].max[0] ) { - continue; - } - else if ( clip.max[1] > portals.portal[portals.portal_sort[n]].max[1] ) { - continue; - } - else if ( clip.max[2] > portals.portal[portals.portal_sort[n]].max[2] ) { - continue; - } - } - - glColor4f( portals.portal[portals.portal_sort[n]].fp_color_random[0], portals.portal[portals.portal_sort[n]].fp_color_random[1], - portals.portal[portals.portal_sort[n]].fp_color_random[2], trans ); - - glBegin( GL_POLYGON ); - - for ( p = 0; p < portals.portal[portals.portal_sort[n]].point_count; p++ ) - glVertex3fv( portals.portal[portals.portal_sort[n]].point[p].p ); - - glEnd(); - } - } - else - { - for ( n = 0; n < portals.portal_count; n++ ) - { - if ( portals.polygons == 2 && !portals.portal[n].hint ) { - continue; - } - - if ( portals.clip ) { - if ( clip.min[0] < portals.portal[n].min[0] ) { - continue; - } - else if ( clip.min[1] < portals.portal[n].min[1] ) { - continue; - } - else if ( clip.min[2] < portals.portal[n].min[2] ) { - continue; - } - else if ( clip.max[0] > portals.portal[n].max[0] ) { - continue; - } - else if ( clip.max[1] > portals.portal[n].max[1] ) { - continue; - } - else if ( clip.max[2] > portals.portal[n].max[2] ) { - continue; - } - } - - glColor4f( portals.portal[n].fp_color_random[0], portals.portal[n].fp_color_random[1], - portals.portal[n].fp_color_random[2], trans ); - - glBegin( GL_POLYGON ); - - for ( p = 0; p < portals.portal[n].point_count; p++ ) - glVertex3fv( portals.portal[n].point[p].p ); - - glEnd(); - } - } +void CPortalsDrawSolid::render(RenderStateFlags state) const +{ + float trans = (100.0f - portals.trans_3d) / 100.0f; + + unsigned int n, p; + + if (portals.zbuffer != 0) { + float d; + + for (n = 0; n < portals.portal_count; n++) { + d = (float) clip.cam[0] - portals.portal[n].center.p[0]; + portals.portal[n].dist = d * d; + + d = (float) clip.cam[1] - portals.portal[n].center.p[1]; + portals.portal[n].dist += d * d; + + d = (float) clip.cam[2] - portals.portal[n].center.p[2]; + portals.portal[n].dist += d * d; + + portals.portal_sort[n] = n; + } + + qsort(portals.portal_sort, portals.portal_count, 4, compare); + + for (n = 0; n < portals.portal_count; n++) { + if (portals.polygons == 2 && !portals.portal[portals.portal_sort[n]].hint) { + continue; + } + + if (portals.clip) { + if (clip.min[0] < portals.portal[portals.portal_sort[n]].min[0]) { + continue; + } else if (clip.min[1] < portals.portal[portals.portal_sort[n]].min[1]) { + continue; + } else if (clip.min[2] < portals.portal[portals.portal_sort[n]].min[2]) { + continue; + } else if (clip.max[0] > portals.portal[portals.portal_sort[n]].max[0]) { + continue; + } else if (clip.max[1] > portals.portal[portals.portal_sort[n]].max[1]) { + continue; + } else if (clip.max[2] > portals.portal[portals.portal_sort[n]].max[2]) { + continue; + } + } + + glColor4f(portals.portal[portals.portal_sort[n]].fp_color_random[0], + portals.portal[portals.portal_sort[n]].fp_color_random[1], + portals.portal[portals.portal_sort[n]].fp_color_random[2], trans); + + glBegin(GL_POLYGON); + + for (p = 0; p < portals.portal[portals.portal_sort[n]].point_count; p++) + glVertex3fv(portals.portal[portals.portal_sort[n]].point[p].p); + + glEnd(); + } + } else { + for (n = 0; n < portals.portal_count; n++) { + if (portals.polygons == 2 && !portals.portal[n].hint) { + continue; + } + + if (portals.clip) { + if (clip.min[0] < portals.portal[n].min[0]) { + continue; + } else if (clip.min[1] < portals.portal[n].min[1]) { + continue; + } else if (clip.min[2] < portals.portal[n].min[2]) { + continue; + } else if (clip.max[0] > portals.portal[n].max[0]) { + continue; + } else if (clip.max[1] > portals.portal[n].max[1]) { + continue; + } else if (clip.max[2] > portals.portal[n].max[2]) { + continue; + } + } + + glColor4f(portals.portal[n].fp_color_random[0], portals.portal[n].fp_color_random[1], + portals.portal[n].fp_color_random[2], trans); + + glBegin(GL_POLYGON); + + for (p = 0; p < portals.portal[n].point_count; p++) + glVertex3fv(portals.portal[n].point[p].p); + + glEnd(); + } + } } -void CPortalsDrawSolidOutline::render( RenderStateFlags state ) const { - for ( unsigned int n = 0; n < portals.portal_count; n++ ) - { - if ( portals.lines == 2 && !portals.portal[n].hint ) { - continue; - } - - if ( portals.clip ) { - if ( clip.min[0] < portals.portal[n].min[0] ) { - continue; - } - if ( clip.min[1] < portals.portal[n].min[1] ) { - continue; - } - if ( clip.min[2] < portals.portal[n].min[2] ) { - continue; - } - if ( clip.max[0] > portals.portal[n].max[0] ) { - continue; - } - if ( clip.max[1] > portals.portal[n].max[1] ) { - continue; - } - if ( clip.max[2] > portals.portal[n].max[2] ) { - continue; - } - } - - glBegin( GL_LINE_LOOP ); - - for ( unsigned int p = 0; p < portals.portal[n].point_count; p++ ) - glVertex3fv( portals.portal[n].inner_point[p].p ); - - glEnd(); - } +void CPortalsDrawSolidOutline::render(RenderStateFlags state) const +{ + for (unsigned int n = 0; n < portals.portal_count; n++) { + if (portals.lines == 2 && !portals.portal[n].hint) { + continue; + } + + if (portals.clip) { + if (clip.min[0] < portals.portal[n].min[0]) { + continue; + } + if (clip.min[1] < portals.portal[n].min[1]) { + continue; + } + if (clip.min[2] < portals.portal[n].min[2]) { + continue; + } + if (clip.max[0] > portals.portal[n].max[0]) { + continue; + } + if (clip.max[1] > portals.portal[n].max[1]) { + continue; + } + if (clip.max[2] > portals.portal[n].max[2]) { + continue; + } + } + + glBegin(GL_LINE_LOOP); + + for (unsigned int p = 0; p < portals.portal[n].point_count; p++) + glVertex3fv(portals.portal[n].inner_point[p].p); + + glEnd(); + } } diff --git a/contrib/prtview/portals.h b/contrib/prtview/portals.h index 48651088..b3d29052 100644 --- a/contrib/prtview/portals.h +++ b/contrib/prtview/portals.h @@ -28,28 +28,29 @@ class CBspPoint { public: -float p[3]; + float p[3]; }; class CBspPortal { public: -CBspPortal(); -~CBspPortal(); + CBspPortal(); + + ~CBspPortal(); protected: public: -CBspPoint center; -unsigned point_count; -CBspPoint *point; -CBspPoint *inner_point; -float fp_color_random[4]; -float min[3]; -float max[3]; -float dist; -bool hint; - -bool Build( char *def ); + CBspPoint center; + unsigned point_count; + CBspPoint *point; + CBspPoint *inner_point; + float fp_color_random[4]; + float min[3]; + float max[3]; + float dist; + bool hint; + + bool Build(char *def); }; #ifdef PATH_MAX @@ -58,101 +59,101 @@ const int PRTVIEW_PATH_MAX = PATH_MAX; const int PRTVIEW_PATH_MAX = 260; #endif typedef guint32 PackedColour; -#define RGB( r, g, b ) ( (guint32)( ( (guint8) ( r ) | ( (guint16) ( g ) << 8 ) ) | ( ( (guint32) (guint8) ( b ) ) << 16 ) ) ) -#define GetRValue( rgb ) ( (guint8)( rgb ) ) -#define GetGValue( rgb ) ( (guint8)( ( (guint16)( rgb ) ) >> 8 ) ) -#define GetBValue( rgb ) ( (guint8)( ( rgb ) >> 16 ) ) +#define RGB(r, g, b) ( (guint32)( ( (guint8) ( r ) | ( (guint16) ( g ) << 8 ) ) | ( ( (guint32) (guint8) ( b ) ) << 16 ) ) ) +#define GetRValue(rgb) ( (guint8)( rgb ) ) +#define GetGValue(rgb) ( (guint8)( ( (guint16)( rgb ) ) >> 8 ) ) +#define GetBValue(rgb) ( (guint8)( ( rgb ) >> 16 ) ) class CPortals { public: -CPortals(); -~CPortals(); + CPortals(); + + ~CPortals(); protected: public: -void Load(); // use filename in fn -void Purge(); - -void FixColors(); - -char fn[PRTVIEW_PATH_MAX]; - -int zbuffer; -int polygons; -int lines; -bool show_3d; -bool aa_3d; -bool fog; -PackedColour color_3d; -float width_3d; // in 8'ths -float fp_color_3d[4]; -PackedColour color_fog; -float fp_color_fog[4]; -float trans_3d; -float clip_range; -bool clip; - -bool show_2d; -bool aa_2d; -PackedColour color_2d; -float width_2d; // in 8'ths -float fp_color_2d[4]; - -CBspPortal *portal; -int *portal_sort; -bool hint_flags; + void Load(); // use filename in fn + void Purge(); + + void FixColors(); + + char fn[PRTVIEW_PATH_MAX]; + + int zbuffer; + int polygons; + int lines; + bool show_3d; + bool aa_3d; + bool fog; + PackedColour color_3d; + float width_3d; // in 8'ths + float fp_color_3d[4]; + PackedColour color_fog; + float fp_color_fog[4]; + float trans_3d; + float clip_range; + bool clip; + + bool show_2d; + bool aa_2d; + PackedColour color_2d; + float width_2d; // in 8'ths + float fp_color_2d[4]; + + CBspPortal *portal; + int *portal_sort; + bool hint_flags; // CBspNode *node; -unsigned int node_count; -unsigned int portal_count; + unsigned int node_count; + unsigned int portal_count; }; -class CubicClipVolume -{ +class CubicClipVolume { public: -Vector3 cam, min, max; + Vector3 cam, min, max; }; -class CPortalsDrawSolid : public OpenGLRenderable -{ +class CPortalsDrawSolid : public OpenGLRenderable { public: -mutable CubicClipVolume clip; -void render( RenderStateFlags state ) const; + mutable CubicClipVolume clip; + + void render(RenderStateFlags state) const; }; -class CPortalsDrawSolidOutline : public OpenGLRenderable -{ +class CPortalsDrawSolidOutline : public OpenGLRenderable { public: -mutable CubicClipVolume clip; -void render( RenderStateFlags state ) const; + mutable CubicClipVolume clip; + + void render(RenderStateFlags state) const; }; -class CPortalsDrawWireframe : public OpenGLRenderable -{ +class CPortalsDrawWireframe : public OpenGLRenderable { public: -void render( RenderStateFlags state ) const; + void render(RenderStateFlags state) const; }; -class CPortalsRender : public Renderable -{ +class CPortalsRender : public Renderable { public: -CPortalsDrawSolid m_drawSolid; -CPortalsDrawSolidOutline m_drawSolidOutline; -CPortalsDrawWireframe m_drawWireframe; + CPortalsDrawSolid m_drawSolid; + CPortalsDrawSolidOutline m_drawSolidOutline; + CPortalsDrawWireframe m_drawWireframe; + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const; -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const; -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const; + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const; }; extern CPortals portals; extern CPortalsRender render; void Portals_constructShaders(); + void Portals_destroyShaders(); void Portals_shadersChanged(); diff --git a/contrib/prtview/prtview.cpp b/contrib/prtview/prtview.cpp index 080af13a..0f6195b2 100644 --- a/contrib/prtview/prtview.cpp +++ b/contrib/prtview/prtview.cpp @@ -67,122 +67,120 @@ const char *CLIP_RANGE = "ClipRange"; const char *CLIP = "Clip"; -void PrtView_construct(){ - StringOutputStream tmp( 64 ); - tmp << GlobalRadiant().getSettingsPath() << "prtview.ini"; - INIfn = tmp.c_str(); - - portals.show_2d = INIGetInt( RENDER_2D, FALSE ) ? true : false; - portals.aa_2d = INIGetInt( AA_2D, FALSE ) ? true : false; - portals.width_2d = (float)INIGetInt( WIDTH_2D, 10 ); - portals.color_2d = (PackedColour)INIGetInt( COLOR_2D, RGB( 0, 0, 255 ) ) & 0xFFFFFF; - - if ( portals.width_2d > 40.0f ) { - portals.width_2d = 40.0f; - } - else if ( portals.width_2d < 2.0f ) { - portals.width_2d = 2.0f; - } - - portals.show_3d = INIGetInt( RENDER_3D, TRUE ) ? true : false; - - portals.zbuffer = INIGetInt( ZBUFFER, 1 ); - portals.fog = INIGetInt( FOG, FALSE ) ? true : false; - portals.polygons = INIGetInt( POLYGON, TRUE ); - portals.lines = INIGetInt( LINE, TRUE ); - portals.aa_3d = INIGetInt( AA_3D, FALSE ) ? true : false; - portals.width_3d = (float)INIGetInt( WIDTH_3D, 4 ); - portals.color_3d = (PackedColour)INIGetInt( COLOR_3D, RGB( 255, 255, 0 ) ) & 0xFFFFFF; - portals.color_fog = (PackedColour)INIGetInt( COLOR_FOG, RGB( 127, 127, 127 ) ) & 0xFFFFFF; - portals.trans_3d = (float)INIGetInt( TRANS_3D, 50 ); - portals.clip = INIGetInt( CLIP, FALSE ) ? true : false; - portals.clip_range = (float)INIGetInt( CLIP_RANGE, 16 ); - - if ( portals.clip_range < 1 ) { - portals.clip_range = 1; - } - else if ( portals.clip_range > 128 ) { - portals.clip_range = 128; - } - - if ( portals.zbuffer < 0 ) { - portals.zbuffer = 0; - } - else if ( portals.zbuffer > 2 ) { - portals.zbuffer = 0; - } - - if ( portals.width_3d > 40.0f ) { - portals.width_3d = 40.0f; - } - else if ( portals.width_3d < 2.0f ) { - portals.width_3d = 2.0f; - } - - if ( portals.trans_3d > 100.0f ) { - portals.trans_3d = 100.0f; - } - else if ( portals.trans_3d < 0.0f ) { - portals.trans_3d = 0.0f; - } - - SaveConfig(); - - portals.FixColors(); - - Portals_constructShaders(); - GlobalShaderCache().attachRenderable( render ); +void PrtView_construct() +{ + StringOutputStream tmp(64); + tmp << GlobalRadiant().getSettingsPath() << "prtview.ini"; + INIfn = tmp.c_str(); + + portals.show_2d = INIGetInt(RENDER_2D, FALSE) ? true : false; + portals.aa_2d = INIGetInt(AA_2D, FALSE) ? true : false; + portals.width_2d = (float) INIGetInt(WIDTH_2D, 10); + portals.color_2d = (PackedColour) INIGetInt(COLOR_2D, RGB(0, 0, 255)) & 0xFFFFFF; + + if (portals.width_2d > 40.0f) { + portals.width_2d = 40.0f; + } else if (portals.width_2d < 2.0f) { + portals.width_2d = 2.0f; + } + + portals.show_3d = INIGetInt(RENDER_3D, TRUE) ? true : false; + + portals.zbuffer = INIGetInt(ZBUFFER, 1); + portals.fog = INIGetInt(FOG, FALSE) ? true : false; + portals.polygons = INIGetInt(POLYGON, TRUE); + portals.lines = INIGetInt(LINE, TRUE); + portals.aa_3d = INIGetInt(AA_3D, FALSE) ? true : false; + portals.width_3d = (float) INIGetInt(WIDTH_3D, 4); + portals.color_3d = (PackedColour) INIGetInt(COLOR_3D, RGB(255, 255, 0)) & 0xFFFFFF; + portals.color_fog = (PackedColour) INIGetInt(COLOR_FOG, RGB(127, 127, 127)) & 0xFFFFFF; + portals.trans_3d = (float) INIGetInt(TRANS_3D, 50); + portals.clip = INIGetInt(CLIP, FALSE) ? true : false; + portals.clip_range = (float) INIGetInt(CLIP_RANGE, 16); + + if (portals.clip_range < 1) { + portals.clip_range = 1; + } else if (portals.clip_range > 128) { + portals.clip_range = 128; + } + + if (portals.zbuffer < 0) { + portals.zbuffer = 0; + } else if (portals.zbuffer > 2) { + portals.zbuffer = 0; + } + + if (portals.width_3d > 40.0f) { + portals.width_3d = 40.0f; + } else if (portals.width_3d < 2.0f) { + portals.width_3d = 2.0f; + } + + if (portals.trans_3d > 100.0f) { + portals.trans_3d = 100.0f; + } else if (portals.trans_3d < 0.0f) { + portals.trans_3d = 0.0f; + } + + SaveConfig(); + + portals.FixColors(); + + Portals_constructShaders(); + GlobalShaderCache().attachRenderable(render); } -void PrtView_destroy(){ - GlobalShaderCache().detachRenderable( render ); - Portals_destroyShaders(); +void PrtView_destroy() +{ + GlobalShaderCache().detachRenderable(render); + Portals_destroyShaders(); } -void SaveConfig(){ - INISetInt( RENDER_2D, portals.show_2d, "Draw in 2D windows" ); - INISetInt( WIDTH_2D, (int)portals.width_2d, "Width of lines in 2D windows (in units of 1/2)" ); - INISetInt( COLOR_2D, (int)portals.color_2d, "Color of lines in 2D windows" ); - INISetInt( AA_2D, portals.aa_2d, "Draw lines in 2D window anti-aliased" ); - - INISetInt( ZBUFFER, portals.zbuffer, "ZBuffer level in 3D window" ); - INISetInt( FOG, portals.fog, "Use depth cueing in 3D window" ); - INISetInt( POLYGON, portals.polygons, "Render using polygons polygons in 3D window" ); - INISetInt( LINE, portals.polygons, "Render using lines in 3D window" ); - INISetInt( RENDER_3D, portals.show_3d, "Draw in 3D windows" ); - INISetInt( WIDTH_3D, (int)portals.width_3d, "Width of lines in 3D window (in units of 1/2)" ); - INISetInt( COLOR_3D, (int)portals.color_3d, "Color of lines/polygons in 3D window" ); - INISetInt( COLOR_FOG, (int)portals.color_fog, "Color of distant lines/polygons in 3D window" ); - INISetInt( AA_3D, portals.aa_3d, "Draw lines in 3D window anti-aliased" ); - INISetInt( TRANS_3D, (int)portals.trans_3d, "Transparency in 3d view (0 = solid, 100 = invisible)" ); - INISetInt( CLIP, portals.clip, "Cubic clipper active for portal viewer" ); - INISetInt( CLIP_RANGE, (int)portals.clip_range, "Portal viewer cubic clip distance (in units of 64)" ); +void SaveConfig() +{ + INISetInt(RENDER_2D, portals.show_2d, "Draw in 2D windows"); + INISetInt(WIDTH_2D, (int) portals.width_2d, "Width of lines in 2D windows (in units of 1/2)"); + INISetInt(COLOR_2D, (int) portals.color_2d, "Color of lines in 2D windows"); + INISetInt(AA_2D, portals.aa_2d, "Draw lines in 2D window anti-aliased"); + + INISetInt(ZBUFFER, portals.zbuffer, "ZBuffer level in 3D window"); + INISetInt(FOG, portals.fog, "Use depth cueing in 3D window"); + INISetInt(POLYGON, portals.polygons, "Render using polygons polygons in 3D window"); + INISetInt(LINE, portals.polygons, "Render using lines in 3D window"); + INISetInt(RENDER_3D, portals.show_3d, "Draw in 3D windows"); + INISetInt(WIDTH_3D, (int) portals.width_3d, "Width of lines in 3D window (in units of 1/2)"); + INISetInt(COLOR_3D, (int) portals.color_3d, "Color of lines/polygons in 3D window"); + INISetInt(COLOR_FOG, (int) portals.color_fog, "Color of distant lines/polygons in 3D window"); + INISetInt(AA_3D, portals.aa_3d, "Draw lines in 3D window anti-aliased"); + INISetInt(TRANS_3D, (int) portals.trans_3d, "Transparency in 3d view (0 = solid, 100 = invisible)"); + INISetInt(CLIP, portals.clip, "Cubic clipper active for portal viewer"); + INISetInt(CLIP_RANGE, (int) portals.clip_range, "Portal viewer cubic clip distance (in units of 64)"); } const char *CONFIG_SECTION = "Configuration"; -int INIGetInt( const char *key, int def ){ - char value[1024]; +int INIGetInt(const char *key, int def) +{ + char value[1024]; - if ( read_var( INIfn.c_str(), CONFIG_SECTION, key, value ) ) { - return atoi( value ); - } - else{ - return def; - } + if (read_var(INIfn.c_str(), CONFIG_SECTION, key, value)) { + return atoi(value); + } else { + return def; + } } -void INISetInt( const char *key, int val, const char *comment /* = NULL */ ){ - char s[1000]; - - if ( comment ) { - sprintf( s, "%d ; %s", val, comment ); - } - else{ - sprintf( s, "%d", val ); - } - save_var( INIfn.c_str(), CONFIG_SECTION, key, s ); +void INISetInt(const char *key, int val, const char *comment /* = NULL */ ) +{ + char s[1000]; + + if (comment) { + sprintf(s, "%d ; %s", val, comment); + } else { + sprintf(s, "%d", val); + } + save_var(INIfn.c_str(), CONFIG_SECTION, key, s); } @@ -190,127 +188,126 @@ void INISetInt( const char *key, int val, const char *comment /* = NULL */ ){ static const char *PLUGIN_NAME = "Portal Viewer"; // commands in the menu static const char *PLUGIN_COMMANDS = - Q3R_CMD_ABOUT ";" - Q3R_CMD_SPLITTER ";" - Q3R_CMD_OPTIONS ";" - Q3R_CMD_SPLITTER ";" - Q3R_CMD_SHOW_2D ";" - Q3R_CMD_SHOW_3D ";" - Q3R_CMD_SPLITTER ";" - Q3R_CMD_RELEASE ";" - Q3R_CMD_LOAD; - - - -const char* QERPlug_Init( void *hApp, void* pMainWidget ){ - return "Portal Viewer for Q3Radiant"; + Q3R_CMD_ABOUT ";" + Q3R_CMD_SPLITTER ";" + Q3R_CMD_OPTIONS ";" + Q3R_CMD_SPLITTER ";" + Q3R_CMD_SHOW_2D ";" + Q3R_CMD_SHOW_3D ";" + Q3R_CMD_SPLITTER ";" + Q3R_CMD_RELEASE ";" + Q3R_CMD_LOAD; + + +const char *QERPlug_Init(void *hApp, void *pMainWidget) +{ + return "Portal Viewer for Q3Radiant"; } -const char* QERPlug_GetName(){ - return PLUGIN_NAME; +const char *QERPlug_GetName() +{ + return PLUGIN_NAME; } -const char* QERPlug_GetCommandList(){ - return PLUGIN_COMMANDS; +const char *QERPlug_GetCommandList() +{ + return PLUGIN_COMMANDS; } -const char* QERPlug_GetCommandTitleList(){ - return ""; +const char *QERPlug_GetCommandTitleList() +{ + return ""; } -void QERPlug_Dispatch( const char* p, float* vMin, float* vMax, bool bSingleBrush ){ - globalOutputStream() << MSG_PREFIX "Command \"" << p << "\"\n"; - - if ( !strcmp( p,Q3R_CMD_ABOUT ) ) { - DoAboutDlg(); - } - else if ( !strcmp( p,Q3R_CMD_LOAD ) ) { - if ( DoLoadPortalFileDialog() == IDOK ) { - portals.Load(); - SceneChangeNotify(); - } - else - { - globalOutputStream() << MSG_PREFIX "Portal file load aborted.\n"; - } - } - else if ( !strcmp( p,Q3R_CMD_RELEASE ) ) { - portals.Purge(); - - SceneChangeNotify(); - - globalOutputStream() << MSG_PREFIX "Portals unloaded.\n"; - } - else if ( !strcmp( p,Q3R_CMD_SHOW_2D ) ) { - portals.show_2d = !portals.show_2d; - - SceneChangeNotify(); - SaveConfig(); - - if ( portals.show_2d ) { - globalOutputStream() << MSG_PREFIX "Portals will be rendered in 2D view.\n"; - } - else{ - globalOutputStream() << MSG_PREFIX "Portals will NOT be rendered in 2D view.\n"; - } - } - else if ( !strcmp( p,Q3R_CMD_SHOW_3D ) ) { - portals.show_3d = !portals.show_3d; - SaveConfig(); - - SceneChangeNotify(); - - if ( portals.show_3d ) { - globalOutputStream() << MSG_PREFIX "Portals will be rendered in 3D view.\n"; - } - else{ - globalOutputStream() << MSG_PREFIX "Portals will NOT be rendered in 3D view.\n"; - } - } - else if ( !strcmp( p,Q3R_CMD_OPTIONS ) ) { - DoConfigDialog(); - SaveConfig(); - - SceneChangeNotify(); - } +void QERPlug_Dispatch(const char *p, float *vMin, float *vMax, bool bSingleBrush) +{ + globalOutputStream() << MSG_PREFIX "Command \"" << p << "\"\n"; + + if (!strcmp(p, Q3R_CMD_ABOUT)) { + DoAboutDlg(); + } else if (!strcmp(p, Q3R_CMD_LOAD)) { + if (DoLoadPortalFileDialog() == IDOK) { + portals.Load(); + SceneChangeNotify(); + } else { + globalOutputStream() << MSG_PREFIX "Portal file load aborted.\n"; + } + } else if (!strcmp(p, Q3R_CMD_RELEASE)) { + portals.Purge(); + + SceneChangeNotify(); + + globalOutputStream() << MSG_PREFIX "Portals unloaded.\n"; + } else if (!strcmp(p, Q3R_CMD_SHOW_2D)) { + portals.show_2d = !portals.show_2d; + + SceneChangeNotify(); + SaveConfig(); + + if (portals.show_2d) { + globalOutputStream() << MSG_PREFIX "Portals will be rendered in 2D view.\n"; + } else { + globalOutputStream() << MSG_PREFIX "Portals will NOT be rendered in 2D view.\n"; + } + } else if (!strcmp(p, Q3R_CMD_SHOW_3D)) { + portals.show_3d = !portals.show_3d; + SaveConfig(); + + SceneChangeNotify(); + + if (portals.show_3d) { + globalOutputStream() << MSG_PREFIX "Portals will be rendered in 3D view.\n"; + } else { + globalOutputStream() << MSG_PREFIX "Portals will NOT be rendered in 3D view.\n"; + } + } else if (!strcmp(p, Q3R_CMD_OPTIONS)) { + DoConfigDialog(); + SaveConfig(); + + SceneChangeNotify(); + } } #include "modulesystem/singletonmodule.h" class PrtViewPluginDependencies : - public GlobalSceneGraphModuleRef, - public GlobalRadiantModuleRef, - public GlobalShaderCacheModuleRef, - public GlobalOpenGLModuleRef, - public GlobalOpenGLStateLibraryModuleRef -{ + public GlobalSceneGraphModuleRef, + public GlobalRadiantModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalOpenGLModuleRef, + public GlobalOpenGLStateLibraryModuleRef { }; -class PrtViewPluginModule -{ -_QERPluginTable m_plugin; +class PrtViewPluginModule { + _QERPluginTable m_plugin; public: -typedef _QERPluginTable Type; -STRING_CONSTANT( Name, "prtview" ); - -PrtViewPluginModule(){ - m_plugin.m_pfnQERPlug_Init = QERPlug_Init; - m_plugin.m_pfnQERPlug_GetName = QERPlug_GetName; - m_plugin.m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; - m_plugin.m_pfnQERPlug_GetCommandTitleList = QERPlug_GetCommandTitleList; - m_plugin.m_pfnQERPlug_Dispatch = QERPlug_Dispatch; - - PrtView_construct(); -} -~PrtViewPluginModule(){ - PrtView_destroy(); -} -_QERPluginTable* getTable(){ - return &m_plugin; -} + typedef _QERPluginTable Type; + + STRING_CONSTANT(Name, "prtview"); + + PrtViewPluginModule() + { + m_plugin.m_pfnQERPlug_Init = QERPlug_Init; + m_plugin.m_pfnQERPlug_GetName = QERPlug_GetName; + m_plugin.m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; + m_plugin.m_pfnQERPlug_GetCommandTitleList = QERPlug_GetCommandTitleList; + m_plugin.m_pfnQERPlug_Dispatch = QERPlug_Dispatch; + + PrtView_construct(); + } + + ~PrtViewPluginModule() + { + PrtView_destroy(); + } + + _QERPluginTable *getTable() + { + return &m_plugin; + } }; typedef SingletonModule SingletonPrtViewPluginModule; @@ -318,8 +315,9 @@ typedef SingletonModule Singleto SingletonPrtViewPluginModule g_PrtViewPluginModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_PrtViewPluginModule.selfRegister(); + g_PrtViewPluginModule.selfRegister(); } diff --git a/contrib/prtview/prtview.h b/contrib/prtview/prtview.h index 6b048782..2253474d 100644 --- a/contrib/prtview/prtview.h +++ b/contrib/prtview/prtview.h @@ -23,13 +23,15 @@ #define MSG_PREFIX "Portal Viewer plugin: " void InitInstance(); + void SaveConfig(); -int INIGetInt( const char *key, int def ); -void INISetInt( const char *key, int val, const char *comment = 0 ); +int INIGetInt(const char *key, int def); + +void INISetInt(const char *key, int val, const char *comment = 0); -const int IDOK = 1; -const int IDCANCEL = 2; +const int IDOK = 1; +const int IDCANCEL = 2; #endif diff --git a/contrib/prtview/res/PrtView.rc2 b/contrib/prtview/res/PrtView.rc2 index a534b6a2..14acdde2 100644 --- a/contrib/prtview/res/PrtView.rc2 +++ b/contrib/prtview/res/PrtView.rc2 @@ -3,7 +3,7 @@ // #ifdef APSTUDIO_INVOKED - #error this file is not editable by Microsoft Visual C++ +#error this file is not editable by Microsoft Visual C++ #endif //APSTUDIO_INVOKED diff --git a/contrib/shaderplug/shaderplug.cpp b/contrib/shaderplug/shaderplug.cpp index 9d7bc4c5..489cceac 100644 --- a/contrib/shaderplug/shaderplug.cpp +++ b/contrib/shaderplug/shaderplug.cpp @@ -42,190 +42,207 @@ #include "generic/callback.h" namespace { -const char SHADERTAG_FILE[] = "shadertags.xml"; + const char SHADERTAG_FILE[] = "shadertags.xml"; } class ShaderPlugPluginDependencies : public GlobalRadiantModuleRef, - public GlobalFileSystemModuleRef, - public GlobalShadersModuleRef -{ + public GlobalFileSystemModuleRef, + public GlobalShadersModuleRef { public: -ShaderPlugPluginDependencies() : - GlobalShadersModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "shaders" ) ){ -} + ShaderPlugPluginDependencies() : + GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders")) + { + } }; -namespace Shaderplug -{ -ui::Window g_window{ui::null}; - -std::vector archives; -std::set shaders; -std::set textures; - -XmlTagBuilder TagBuilder; -void CreateTagFile(); - -const char* init( void* hApp, void* pMainWidget ){ - g_window = ui::Window::from(pMainWidget); - return ""; -} -const char* getName(){ - return "ShaderPlug"; -} -const char* getCommandList(){ - return "About;Create tag file"; -} -const char* getCommandTitleList(){ - return ""; -} -void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){ - if ( string_equal( command, "About" ) ) { - GlobalRadiant().m_pfnMessageBox( g_window, "Shaderplug (1.0)\n\n" - "by Shaderman (shaderman@gmx.net)", - "About", - eMB_OK, - eMB_ICONDEFAULT ); - } - if ( string_equal( command, "Create tag file" ) ) { - CreateTagFile(); - } -} - -void loadArchiveFile( const char* filename ){ - archives.push_back( filename ); -} - -void LoadTextureFile( const char* filename ){ - std::string s_filename = filename; - - char buffer[256]; - strcpy( buffer, "textures/" ); - - // append filename without trailing file extension (.tga or .jpg for example) - strncat( buffer, filename, s_filename.length() - 4 ); - - std::set::iterator iter; - iter = shaders.find( buffer ); - - // a shader with this name already exists - if ( iter == shaders.end() ) { - textures.insert( buffer ); - } -} - -void GetTextures( const char* extension ){ - GlobalFileSystem().forEachFile("textures/", extension, makeCallbackF(LoadTextureFile), 0); -} - -void LoadShaderList( const char* filename ){ - if ( string_equal_prefix( filename, "textures/" ) ) { - shaders.insert( filename ); - } -} - -void GetAllShaders(){ - GlobalShaderSystem().foreachShaderName(makeCallbackF(LoadShaderList)); -} - -void GetArchiveList(){ - GlobalFileSystem().forEachArchive(makeCallbackF(loadArchiveFile)); - globalOutputStream() << "Shaderplug: " << (const Unsigned)Shaderplug::archives.size() << " archives found.\n"; -} - -void CreateTagFile(){ - const char* shader_type = GlobalRadiant().getGameDescriptionKeyValue( "shaders" ); - - GetAllShaders(); - globalOutputStream() << "Shaderplug: " << (const Unsigned)shaders.size() << " shaders found.\n"; - - if ( string_equal( shader_type, "quake3" ) ) { - GetTextures( "jpg" ); - GetTextures( "tga" ); - GetTextures( "png" ); - - globalOutputStream() << "Shaderplug: " << (const Unsigned)textures.size() << " textures found.\n"; - } - - if ( shaders.size() || textures.size() != 0 ) { - globalOutputStream() << "Shaderplug: Creating XML tag file.\n"; - - TagBuilder.CreateXmlDocument(); - - std::set::reverse_iterator r_iter; - - for ( r_iter = textures.rbegin(); r_iter != textures.rend(); ++r_iter ) - { - TagBuilder.AddShaderNode( const_cast( ( *r_iter ).c_str() ), STOCK, TEXTURE ); - } - - for ( r_iter = shaders.rbegin(); r_iter != shaders.rend(); ++r_iter ) - { - TagBuilder.AddShaderNode( const_cast( ( *r_iter ).c_str() ), STOCK, SHADER ); - } - - // Get the tag file - StringOutputStream tagFileStream( 256 ); - tagFileStream << GlobalRadiant().getLocalRcPath() << SHADERTAG_FILE; - char* tagFile = tagFileStream.c_str(); - - char message[256]; - strcpy( message, "Tag file saved to\n" ); - strcat( message, tagFile ); - strcat( message, "\nPlease restart Radiant now.\n" ); - - if ( file_exists( tagFile ) ) { - EMessageBoxReturn result = GlobalRadiant().m_pfnMessageBox( g_window , - "WARNING! A tag file already exists! Overwrite it?", "Overwrite tag file?", - eMB_NOYES, - eMB_ICONWARNING ); - - if ( result == eIDYES ) { - TagBuilder.SaveXmlDoc( tagFile ); - GlobalRadiant().m_pfnMessageBox( g_window, message, "INFO", eMB_OK, eMB_ICONASTERISK ); - } - } - else { - TagBuilder.SaveXmlDoc( tagFile ); - GlobalRadiant().m_pfnMessageBox( g_window, message, "INFO", eMB_OK, eMB_ICONASTERISK ); - } - } - else { - GlobalRadiant().m_pfnMessageBox( g_window, - "No shaders or textures found. No XML tag file created!\n" - "", - "ERROR", - eMB_OK, - eMB_ICONERROR ); - } -} +namespace Shaderplug { + ui::Window g_window{ui::null}; + + std::vector archives; + std::set shaders; + std::set textures; + + XmlTagBuilder TagBuilder; + + void CreateTagFile(); + + const char *init(void *hApp, void *pMainWidget) + { + g_window = ui::Window::from(pMainWidget); + return ""; + } + + const char *getName() + { + return "ShaderPlug"; + } + + const char *getCommandList() + { + return "About;Create tag file"; + } + + const char *getCommandTitleList() + { + return ""; + } + + void dispatch(const char *command, float *vMin, float *vMax, bool bSingleBrush) + { + if (string_equal(command, "About")) { + GlobalRadiant().m_pfnMessageBox(g_window, "Shaderplug (1.0)\n\n" + "by Shaderman (shaderman@gmx.net)", + "About", + eMB_OK, + eMB_ICONDEFAULT); + } + if (string_equal(command, "Create tag file")) { + CreateTagFile(); + } + } + + void loadArchiveFile(const char *filename) + { + archives.push_back(filename); + } + + void LoadTextureFile(const char *filename) + { + std::string s_filename = filename; + + char buffer[256]; + strcpy(buffer, "textures/"); + + // append filename without trailing file extension (.tga or .jpg for example) + strncat(buffer, filename, s_filename.length() - 4); + + std::set::iterator iter; + iter = shaders.find(buffer); + + // a shader with this name already exists + if (iter == shaders.end()) { + textures.insert(buffer); + } + } + + void GetTextures(const char *extension) + { + GlobalFileSystem().forEachFile("textures/", extension, makeCallbackF(LoadTextureFile), 0); + } + + void LoadShaderList(const char *filename) + { + if (string_equal_prefix(filename, "textures/")) { + shaders.insert(filename); + } + } + + void GetAllShaders() + { + GlobalShaderSystem().foreachShaderName(makeCallbackF(LoadShaderList)); + } + + void GetArchiveList() + { + GlobalFileSystem().forEachArchive(makeCallbackF(loadArchiveFile)); + globalOutputStream() << "Shaderplug: " << (const Unsigned) Shaderplug::archives.size() << " archives found.\n"; + } + + void CreateTagFile() + { + const char *shader_type = GlobalRadiant().getGameDescriptionKeyValue("shaders"); + + GetAllShaders(); + globalOutputStream() << "Shaderplug: " << (const Unsigned) shaders.size() << " shaders found.\n"; + + if (string_equal(shader_type, "quake3")) { + GetTextures("jpg"); + GetTextures("tga"); + GetTextures("png"); + + globalOutputStream() << "Shaderplug: " << (const Unsigned) textures.size() << " textures found.\n"; + } + + if (shaders.size() || textures.size() != 0) { + globalOutputStream() << "Shaderplug: Creating XML tag file.\n"; + + TagBuilder.CreateXmlDocument(); + + std::set::reverse_iterator r_iter; + + for (r_iter = textures.rbegin(); r_iter != textures.rend(); ++r_iter) { + TagBuilder.AddShaderNode(const_cast((*r_iter).c_str()), STOCK, TEXTURE); + } + + for (r_iter = shaders.rbegin(); r_iter != shaders.rend(); ++r_iter) { + TagBuilder.AddShaderNode(const_cast((*r_iter).c_str()), STOCK, SHADER); + } + + // Get the tag file + StringOutputStream tagFileStream(256); + tagFileStream << GlobalRadiant().getLocalRcPath() << SHADERTAG_FILE; + char *tagFile = tagFileStream.c_str(); + + char message[256]; + strcpy(message, "Tag file saved to\n"); + strcat(message, tagFile); + strcat(message, "\nPlease restart Radiant now.\n"); + + if (file_exists(tagFile)) { + EMessageBoxReturn result = GlobalRadiant().m_pfnMessageBox(g_window, + "WARNING! A tag file already exists! Overwrite it?", + "Overwrite tag file?", + eMB_NOYES, + eMB_ICONWARNING); + + if (result == eIDYES) { + TagBuilder.SaveXmlDoc(tagFile); + GlobalRadiant().m_pfnMessageBox(g_window, message, "INFO", eMB_OK, eMB_ICONASTERISK); + } + } else { + TagBuilder.SaveXmlDoc(tagFile); + GlobalRadiant().m_pfnMessageBox(g_window, message, "INFO", eMB_OK, eMB_ICONASTERISK); + } + } else { + GlobalRadiant().m_pfnMessageBox(g_window, + "No shaders or textures found. No XML tag file created!\n" + "", + "ERROR", + eMB_OK, + eMB_ICONERROR); + } + } } // namespace -class ShaderPluginModule -{ -_QERPluginTable m_plugin; +class ShaderPluginModule { + _QERPluginTable m_plugin; public: -typedef _QERPluginTable Type; -STRING_CONSTANT( Name, "ShaderPlug" ); - -ShaderPluginModule(){ - m_plugin.m_pfnQERPlug_Init = &Shaderplug::init; - m_plugin.m_pfnQERPlug_GetName = &Shaderplug::getName; - m_plugin.m_pfnQERPlug_GetCommandList = &Shaderplug::getCommandList; - m_plugin.m_pfnQERPlug_GetCommandTitleList = &Shaderplug::getCommandTitleList; - m_plugin.m_pfnQERPlug_Dispatch = &Shaderplug::dispatch; -} -_QERPluginTable* getTable(){ - return &m_plugin; -} + typedef _QERPluginTable Type; + + STRING_CONSTANT(Name, "ShaderPlug"); + + ShaderPluginModule() + { + m_plugin.m_pfnQERPlug_Init = &Shaderplug::init; + m_plugin.m_pfnQERPlug_GetName = &Shaderplug::getName; + m_plugin.m_pfnQERPlug_GetCommandList = &Shaderplug::getCommandList; + m_plugin.m_pfnQERPlug_GetCommandTitleList = &Shaderplug::getCommandTitleList; + m_plugin.m_pfnQERPlug_Dispatch = &Shaderplug::dispatch; + } + + _QERPluginTable *getTable() + { + return &m_plugin; + } }; typedef SingletonModule SingletonShaderPluginModule; SingletonShaderPluginModule g_ShaderPluginModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_ShaderPluginModule.selfRegister(); + g_ShaderPluginModule.selfRegister(); } diff --git a/contrib/sunplug/sunplug.cpp b/contrib/sunplug/sunplug.cpp index ac8233d1..5aa06e87 100644 --- a/contrib/sunplug/sunplug.cpp +++ b/contrib/sunplug/sunplug.cpp @@ -38,43 +38,46 @@ #include // to display something with gtk (windows, buttons etc.), the whole package might not be necessary void about_plugin_window(); + void MapCoordinator(); #if !GDEF_OS_WINDOWS + // linux itoa implementation -char* itoa( int value, char* result, int base ){ - // check that the base if valid - if ( base < 2 || base > 16 ) { - *result = 0; - return result; - } +char *itoa(int value, char *result, int base) +{ + // check that the base if valid + if (base < 2 || base > 16) { + *result = 0; + return result; + } - char* out = result; - int quotient = value; + char *out = result; + int quotient = value; - do - { - *out = "0123456789abcdef"[abs( quotient % base )]; - ++out; + do { + *out = "0123456789abcdef"[abs(quotient % base)]; + ++out; - quotient /= base; - } while ( quotient ); + quotient /= base; + } while (quotient); - // Only apply negative sign for base 10 - if ( value < 0 && base == 10 ) { - *out++ = '-'; - } + // Only apply negative sign for base 10 + if (value < 0 && base == 10) { + *out++ = '-'; + } - std::reverse( result, out ); + std::reverse(result, out); - *out = 0; - return result; + *out = 0; + return result; } + #endif typedef struct _mapcoord_setting_packet { ui::SpinButton spinner1{ui::null}, spinner2{ui::null}, spinner3{ui::null}, spinner4{ui::null}; - Entity* worldspawn; + Entity *worldspawn; } mapcoord_setting_packet; static int map_minX, map_maxX, map_minY, map_maxY; @@ -84,157 +87,178 @@ mapcoord_setting_packet msp; // ************************** // ** find entities by class ** from radiant/map.cpp // ************************** -class EntityFindByClassname : public scene::Graph::Walker -{ -const char* m_name; -Entity*& m_entity; +class EntityFindByClassname : public scene::Graph::Walker { + const char *m_name; + Entity *&m_entity; public: -EntityFindByClassname( const char* name, Entity*& entity ) : m_name( name ), m_entity( entity ){ - m_entity = 0; -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( m_entity == 0 ) { - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 - && string_equal( m_name, entity->getKeyValue( "classname" ) ) ) { - m_entity = entity; - } - } - return true; -} + EntityFindByClassname(const char *name, Entity *&entity) : m_name(name), m_entity(entity) + { + m_entity = 0; + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (m_entity == 0) { + Entity *entity = Node_getEntity(path.top()); + if (entity != 0 + && string_equal(m_name, entity->getKeyValue("classname"))) { + m_entity = entity; + } + } + return true; + } }; -Entity* Scene_FindEntityByClass( const char* name ){ - Entity* entity; - GlobalSceneGraph().traverse( EntityFindByClassname( name, entity ) ); - return entity; +Entity *Scene_FindEntityByClass(const char *name) +{ + Entity *entity; + GlobalSceneGraph().traverse(EntityFindByClassname(name, entity)); + return entity; } // ************************** // ** GTK callback functions ** // ************************** -static gboolean delete_event(ui::Widget widget, GdkEvent *event, gpointer data ){ - /* If you return FALSE in the "delete_event" signal handler, - * GTK will emit the "destroy" signal. Returning TRUE means - * you don't want the window to be destroyed. - * This is useful for popping up 'are you sure you want to quit?' - * type dialogs. */ +static gboolean delete_event(ui::Widget widget, GdkEvent *event, gpointer data) +{ + /* If you return FALSE in the "delete_event" signal handler, + * GTK will emit the "destroy" signal. Returning TRUE means + * you don't want the window to be destroyed. + * This is useful for popping up 'are you sure you want to quit?' + * type dialogs. */ - return FALSE; + return FALSE; } // destroy widget if destroy signal is passed to widget -static void destroy( ui::Widget widget, gpointer data ){ - widget.destroy(); +static void destroy(ui::Widget widget, gpointer data) +{ + widget.destroy(); } // function for close button to destroy the toplevel widget -static void close_window( ui::Widget widget, gpointer data ){ - widget.window().destroy(); +static void close_window(ui::Widget widget, gpointer data) +{ + widget.window().destroy(); } // callback function to assign the optimal mapcoords to the spinboxes -static void input_optimal(ui::Widget widget, gpointer data ){ - gtk_spin_button_set_value( msp.spinner1, minX ); - gtk_spin_button_set_value( msp.spinner2, maxY ); - gtk_spin_button_set_value( msp.spinner3, maxX ); - gtk_spin_button_set_value( msp.spinner4, minY ); +static void input_optimal(ui::Widget widget, gpointer data) +{ + gtk_spin_button_set_value(msp.spinner1, minX); + gtk_spin_button_set_value(msp.spinner2, maxY); + gtk_spin_button_set_value(msp.spinner3, maxX); + gtk_spin_button_set_value(msp.spinner4, minY); } // Spinner return value function -gint grab_int_value(ui::SpinButton a_spinner, gpointer user_data ) { - return gtk_spin_button_get_value_as_int( a_spinner ); +gint grab_int_value(ui::SpinButton a_spinner, gpointer user_data) +{ + return gtk_spin_button_get_value_as_int(a_spinner); } // write the values of the Spinner-Boxes to the worldspawn -static void set_coordinates( ui::Widget widget, gpointer data ){ - //Str str_min, str_max; - char buffer[10], str_min[20], str_max[20]; - - itoa( gtk_spin_button_get_value_as_int( msp.spinner1 ), str_min, 10 ); - itoa( gtk_spin_button_get_value_as_int( msp.spinner2 ), buffer, 10 ); - strcat( str_min, " " ); - strcat( str_min, buffer ); - msp.worldspawn->setKeyValue( "mapcoordsmins", str_min ); - - itoa( gtk_spin_button_get_value_as_int( msp.spinner3 ), str_max, 10 ); - itoa( gtk_spin_button_get_value_as_int( msp.spinner4 ), buffer, 10 ); - strcat( str_max, " " ); - strcat( str_max, buffer ); - UndoableCommand undo( "SunPlug.entitySetMapcoords" ); - msp.worldspawn->setKeyValue( "mapcoordsmaxs", str_max ); - - close_window( widget, NULL ); +static void set_coordinates(ui::Widget widget, gpointer data) +{ + //Str str_min, str_max; + char buffer[10], str_min[20], str_max[20]; + + itoa(gtk_spin_button_get_value_as_int(msp.spinner1), str_min, 10); + itoa(gtk_spin_button_get_value_as_int(msp.spinner2), buffer, 10); + strcat(str_min, " "); + strcat(str_min, buffer); + msp.worldspawn->setKeyValue("mapcoordsmins", str_min); + + itoa(gtk_spin_button_get_value_as_int(msp.spinner3), str_max, 10); + itoa(gtk_spin_button_get_value_as_int(msp.spinner4), buffer, 10); + strcat(str_max, " "); + strcat(str_max, buffer); + UndoableCommand undo("SunPlug.entitySetMapcoords"); + msp.worldspawn->setKeyValue("mapcoordsmaxs", str_max); + + close_window(widget, NULL); } class SunPlugPluginDependencies : - public GlobalRadiantModuleRef, // basic class for all other module refs - public GlobalUndoModuleRef, // used to say radiant that something has changed and to undo that - public GlobalSceneGraphModuleRef, // necessary to handle data in the mapfile (change, retrieve data) - public GlobalEntityModuleRef // to access and modify the entities + public GlobalRadiantModuleRef, // basic class for all other module refs + public GlobalUndoModuleRef, // used to say radiant that something has changed and to undo that + public GlobalSceneGraphModuleRef, // necessary to handle data in the mapfile (change, retrieve data) + public GlobalEntityModuleRef // to access and modify the entities { public: -SunPlugPluginDependencies() : - GlobalEntityModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entities" ) ){ //, -} + SunPlugPluginDependencies() : + GlobalEntityModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entities")) + { //, + } }; // ************************* // ** standard plugin stuff ** // ************************* -namespace SunPlug -{ -ui::Window main_window{ui::null}; -char MenuList[100] = ""; - -const char* init( void* hApp, void* pMainWidget ){ - main_window = ui::Window::from(pMainWidget); - return "Initializing SunPlug for GTKRadiant"; -} -const char* getName(){ - return "SunPlug"; // name that is shown in the menue -} -const char* getCommandList(){ - const char about[] = "About..."; - const char etMapCoordinator[] = ";ET-MapCoordinator"; - - strcat( MenuList, about ); - if ( strncmp( GlobalRadiant().getGameName(), "etmain", 6 ) == 0 ) { - strcat( MenuList, etMapCoordinator ); - } - return (const char*)MenuList; -} -const char* getCommandTitleList(){ - return ""; -} -void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){ // message processing - if ( string_equal( command, "About..." ) ) { - about_plugin_window(); - } - if ( string_equal( command, "ET-MapCoordinator" ) ) { - MapCoordinator(); - } -} +namespace SunPlug { + ui::Window main_window{ui::null}; + char MenuList[100] = ""; + + const char *init(void *hApp, void *pMainWidget) + { + main_window = ui::Window::from(pMainWidget); + return "Initializing SunPlug for GTKRadiant"; + } + + const char *getName() + { + return "SunPlug"; // name that is shown in the menue + } + + const char *getCommandList() + { + const char about[] = "About..."; + const char etMapCoordinator[] = ";ET-MapCoordinator"; + + strcat(MenuList, about); + if (strncmp(GlobalRadiant().getGameName(), "etmain", 6) == 0) { + strcat(MenuList, etMapCoordinator); + } + return (const char *) MenuList; + } + + const char *getCommandTitleList() + { + return ""; + } + + void dispatch(const char *command, float *vMin, float *vMax, bool bSingleBrush) + { // message processing + if (string_equal(command, "About...")) { + about_plugin_window(); + } + if (string_equal(command, "ET-MapCoordinator")) { + MapCoordinator(); + } + } } // namespace -class SunPlugModule : public TypeSystemRef -{ -_QERPluginTable m_plugin; +class SunPlugModule : public TypeSystemRef { + _QERPluginTable m_plugin; public: -typedef _QERPluginTable Type; -STRING_CONSTANT( Name, "SunPlug" ); - -SunPlugModule(){ - m_plugin.m_pfnQERPlug_Init = &SunPlug::init; - m_plugin.m_pfnQERPlug_GetName = &SunPlug::getName; - m_plugin.m_pfnQERPlug_GetCommandList = &SunPlug::getCommandList; - m_plugin.m_pfnQERPlug_GetCommandTitleList = &SunPlug::getCommandTitleList; - m_plugin.m_pfnQERPlug_Dispatch = &SunPlug::dispatch; -} -_QERPluginTable* getTable(){ - return &m_plugin; -} + typedef _QERPluginTable Type; + + STRING_CONSTANT(Name, "SunPlug"); + + SunPlugModule() + { + m_plugin.m_pfnQERPlug_Init = &SunPlug::init; + m_plugin.m_pfnQERPlug_GetName = &SunPlug::getName; + m_plugin.m_pfnQERPlug_GetCommandList = &SunPlug::getCommandList; + m_plugin.m_pfnQERPlug_GetCommandTitleList = &SunPlug::getCommandTitleList; + m_plugin.m_pfnQERPlug_Dispatch = &SunPlug::dispatch; + } + + _QERPluginTable *getTable() + { + return &m_plugin; + } }; typedef SingletonModule SingletonSunPlugModule; @@ -242,10 +266,11 @@ typedef SingletonModule SingletonSunPl SingletonSunPlugModule g_SunPlugModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_SunPlugModule.selfRegister(); + g_SunPlugModule.selfRegister(); } // ************ @@ -253,187 +278,199 @@ extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server // ************ // About dialog -void about_plugin_window(){ - auto window = ui::Window( ui::window_type::TOP ); // create a window - gtk_window_set_transient_for( window, SunPlug::main_window ); // make the window to stay in front of the main window - window.connect( "delete_event", G_CALLBACK( delete_event ), NULL ); // connect the delete event - window.connect( "destroy", G_CALLBACK( destroy ), NULL ); // connect the destroy event for the window - gtk_window_set_title( window, "About SunPlug" ); // set the title of the window for the window - gtk_window_set_resizable( window, FALSE ); // don't let the user resize the window - gtk_window_set_modal( window, TRUE ); // force the user not to do something with the other windows - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); // set the border of the window - - auto vbox = ui::VBox( FALSE, 10 ); // create a box to arrange new objects vertically - window.add(vbox); - - auto label = ui::Label( "SunPlug v1.0 for NetRadiant 1.5\nby Topsun" ); // create a label - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); // text align left - vbox.pack_start( label, FALSE, FALSE, 2 ); // insert the label in the box - - auto button = ui::Button( "OK" ); // create a button with text - g_signal_connect_swapped( G_OBJECT( button ), "clicked", G_CALLBACK( gtk_widget_destroy ), (void *) window ); // connect the click event to close the window - vbox.pack_start( button, FALSE, FALSE, 2 ); // insert the button in the box - - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); // center the window on screen - - gtk_widget_show_all( window ); // show the window and all subelements +void about_plugin_window() +{ + auto window = ui::Window(ui::window_type::TOP); // create a window + gtk_window_set_transient_for(window, SunPlug::main_window); // make the window to stay in front of the main window + window.connect("delete_event", G_CALLBACK(delete_event), NULL); // connect the delete event + window.connect("destroy", G_CALLBACK(destroy), NULL); // connect the destroy event for the window + gtk_window_set_title(window, "About SunPlug"); // set the title of the window for the window + gtk_window_set_resizable(window, FALSE); // don't let the user resize the window + gtk_window_set_modal(window, TRUE); // force the user not to do something with the other windows + gtk_container_set_border_width(GTK_CONTAINER(window), 10); // set the border of the window + + auto vbox = ui::VBox(FALSE, 10); // create a box to arrange new objects vertically + window.add(vbox); + + auto label = ui::Label("SunPlug v1.0 for NetRadiant 1.5\nby Topsun"); // create a label + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); // text align left + vbox.pack_start(label, FALSE, FALSE, 2); // insert the label in the box + + auto button = ui::Button("OK"); // create a button with text + g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_destroy), + (void *) window); // connect the click event to close the window + vbox.pack_start(button, FALSE, FALSE, 2); // insert the button in the box + + gtk_window_set_position(window, GTK_WIN_POS_CENTER); // center the window on screen + + gtk_widget_show_all(window); // show the window and all subelements } // get the current bounding box and return the optimal coordinates -void GetOptimalCoordinates( AABB *levelBoundingBox ){ - int half_width, half_heigth, center_x, center_y; - - half_width = levelBoundingBox->extents.x(); - half_heigth = levelBoundingBox->extents.y(); - center_x = levelBoundingBox->origin.x(); - center_y = levelBoundingBox->origin.y(); - - if ( half_width > 175 || half_heigth > 175 ) { // the square must be at least 350x350 units - // the wider side is the indicator for the square - if ( half_width >= half_heigth ) { - minX = center_x - half_width; - maxX = center_x + half_width; - minY = center_y - half_width; - maxY = center_y + half_width; - } - else { - minX = center_x - half_heigth; - maxX = center_x + half_heigth; - minY = center_y - half_heigth; - maxY = center_y + half_heigth; - } - } - else { - minX = center_x - 175; - maxX = center_x + 175; - minY = center_y - 175; - maxY = center_y + 175; - } +void GetOptimalCoordinates(AABB *levelBoundingBox) +{ + int half_width, half_heigth, center_x, center_y; + + half_width = levelBoundingBox->extents.x(); + half_heigth = levelBoundingBox->extents.y(); + center_x = levelBoundingBox->origin.x(); + center_y = levelBoundingBox->origin.y(); + + if (half_width > 175 || half_heigth > 175) { // the square must be at least 350x350 units + // the wider side is the indicator for the square + if (half_width >= half_heigth) { + minX = center_x - half_width; + maxX = center_x + half_width; + minY = center_y - half_width; + maxY = center_y + half_width; + } else { + minX = center_x - half_heigth; + maxX = center_x + half_heigth; + minY = center_y - half_heigth; + maxY = center_y + half_heigth; + } + } else { + minX = center_x - 175; + maxX = center_x + 175; + minY = center_y - 175; + maxY = center_y + 175; + } } // MapCoordinator dialog window -void MapCoordinator(){ - Entity *theWorldspawn = NULL; - const char *buffer; - char line[20]; - - // in any case we need a window to show the user what to do - auto window = ui::Window( ui::window_type::TOP ); // create the window - gtk_window_set_transient_for( window, SunPlug::main_window ); // make the window to stay in front of the main window - window.connect( "delete_event", G_CALLBACK( delete_event ), NULL ); // connect the delete event for the window - window.connect( "destroy", G_CALLBACK( destroy ), NULL ); // connect the destroy event for the window - gtk_window_set_title( window, "ET-MapCoordinator" ); // set the title of the window for the window - gtk_window_set_resizable( window, FALSE ); // don't let the user resize the window - gtk_window_set_modal( window, TRUE ); // force the user not to do something with the other windows - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); // set the border of the window - - auto vbox = ui::VBox( FALSE, 10 ); // create a box to arrange new objects vertically - window.add(vbox); - - scene::Path path = makeReference( GlobalSceneGraph().root() ); // get the path to the root element of the graph - scene::Instance* instance = GlobalSceneGraph().find( path ); // find the instance to the given path - AABB levelBoundingBox = instance->worldAABB(); // get the bounding box of the level - - theWorldspawn = Scene_FindEntityByClass( "worldspawn" ); // find the entity worldspawn - if ( theWorldspawn != 0 ) { // need to have a worldspawn otherwise setting a value crashes the radiant - // next two if's: get the current values of the mapcoords - buffer = theWorldspawn->getKeyValue( "mapcoordsmins" ); // upper left corner - if ( strlen( buffer ) > 0 ) { - strncpy( line, buffer, 19 ); - map_minX = atoi( strtok( line, " " ) ); // minimum of x value - map_minY = atoi( strtok( NULL, " " ) ); // maximum of y value - } - else { - map_minX = 0; - map_minY = 0; - } - buffer = theWorldspawn->getKeyValue( "mapcoordsmaxs" ); // lower right corner - if ( strlen( buffer ) > 0 ) { - strncpy( line, buffer, 19 ); - map_maxX = atoi( strtok( line, " " ) ); // maximum of x value - map_maxY = atoi( strtok( NULL, " " ) ); // minimum of y value - } - else { - map_maxX = 0; - map_maxY = 0; - } - - globalOutputStream() << "SunPlug: calculating optimal coordinates\n"; // write to console that we are calculating the coordinates - GetOptimalCoordinates( &levelBoundingBox ); // calculate optimal mapcoords with the dimensions of the level bounding box - globalOutputStream() << "SunPlug: adviced mapcoordsmins=" << minX << " " << maxY << "\n"; // console info about mapcoordsmins - globalOutputStream() << "SunPlug: adviced mapcoordsmaxs=" << maxX << " " << minY << "\n"; // console info about mapcoordsmaxs - - auto spinner_adj_MinX = ui::Adjustment( map_minX, -65536.0, 65536.0, 1.0, 5.0, 0 ); // create adjustment for value and range of minimum x value - auto spinner_adj_MinY = ui::Adjustment( map_minY, -65536.0, 65536.0, 1.0, 5.0, 0 ); // create adjustment for value and range of minimum y value - auto spinner_adj_MaxX = ui::Adjustment( map_maxX, -65536.0, 65536.0, 1.0, 5.0, 0 ); // create adjustment for value and range of maximum x value - auto spinner_adj_MaxY = ui::Adjustment( map_maxY, -65536.0, 65536.0, 1.0, 5.0, 0 ); // create adjustment for value and range of maximum y value - - auto button = ui::Button( "Get optimal mapcoords" ); // create button with text - button.connect( "clicked", G_CALLBACK( input_optimal ), NULL ); // connect button with callback function - vbox.pack_start( button, FALSE, FALSE, 2 ); // insert button into vbox - - vbox.pack_start( ui::Widget::from(gtk_hseparator_new()), FALSE, FALSE, 2 ); // insert separator into vbox - - auto table = ui::Table( 4, 3, TRUE ); // create table +void MapCoordinator() +{ + Entity *theWorldspawn = NULL; + const char *buffer; + char line[20]; + + // in any case we need a window to show the user what to do + auto window = ui::Window(ui::window_type::TOP); // create the window + gtk_window_set_transient_for(window, SunPlug::main_window); // make the window to stay in front of the main window + window.connect("delete_event", G_CALLBACK(delete_event), NULL); // connect the delete event for the window + window.connect("destroy", G_CALLBACK(destroy), NULL); // connect the destroy event for the window + gtk_window_set_title(window, "ET-MapCoordinator"); // set the title of the window for the window + gtk_window_set_resizable(window, FALSE); // don't let the user resize the window + gtk_window_set_modal(window, TRUE); // force the user not to do something with the other windows + gtk_container_set_border_width(GTK_CONTAINER(window), 10); // set the border of the window + + auto vbox = ui::VBox(FALSE, 10); // create a box to arrange new objects vertically + window.add(vbox); + + scene::Path path = makeReference(GlobalSceneGraph().root()); // get the path to the root element of the graph + scene::Instance *instance = GlobalSceneGraph().find(path); // find the instance to the given path + AABB levelBoundingBox = instance->worldAABB(); // get the bounding box of the level + + theWorldspawn = Scene_FindEntityByClass("worldspawn"); // find the entity worldspawn + if (theWorldspawn != 0) { // need to have a worldspawn otherwise setting a value crashes the radiant + // next two if's: get the current values of the mapcoords + buffer = theWorldspawn->getKeyValue("mapcoordsmins"); // upper left corner + if (strlen(buffer) > 0) { + strncpy(line, buffer, 19); + map_minX = atoi(strtok(line, " ")); // minimum of x value + map_minY = atoi(strtok(NULL, " ")); // maximum of y value + } else { + map_minX = 0; + map_minY = 0; + } + buffer = theWorldspawn->getKeyValue("mapcoordsmaxs"); // lower right corner + if (strlen(buffer) > 0) { + strncpy(line, buffer, 19); + map_maxX = atoi(strtok(line, " ")); // maximum of x value + map_maxY = atoi(strtok(NULL, " ")); // minimum of y value + } else { + map_maxX = 0; + map_maxY = 0; + } + + globalOutputStream() + << "SunPlug: calculating optimal coordinates\n"; // write to console that we are calculating the coordinates + GetOptimalCoordinates( + &levelBoundingBox); // calculate optimal mapcoords with the dimensions of the level bounding box + globalOutputStream() << "SunPlug: adviced mapcoordsmins=" << minX << " " << maxY + << "\n"; // console info about mapcoordsmins + globalOutputStream() << "SunPlug: adviced mapcoordsmaxs=" << maxX << " " << minY + << "\n"; // console info about mapcoordsmaxs + + auto spinner_adj_MinX = ui::Adjustment(map_minX, -65536.0, 65536.0, 1.0, 5.0, + 0); // create adjustment for value and range of minimum x value + auto spinner_adj_MinY = ui::Adjustment(map_minY, -65536.0, 65536.0, 1.0, 5.0, + 0); // create adjustment for value and range of minimum y value + auto spinner_adj_MaxX = ui::Adjustment(map_maxX, -65536.0, 65536.0, 1.0, 5.0, + 0); // create adjustment for value and range of maximum x value + auto spinner_adj_MaxY = ui::Adjustment(map_maxY, -65536.0, 65536.0, 1.0, 5.0, + 0); // create adjustment for value and range of maximum y value + + auto button = ui::Button("Get optimal mapcoords"); // create button with text + button.connect("clicked", G_CALLBACK(input_optimal), NULL); // connect button with callback function + vbox.pack_start(button, FALSE, FALSE, 2); // insert button into vbox + + vbox.pack_start(ui::Widget::from(gtk_hseparator_new()), FALSE, FALSE, 2); // insert separator into vbox + + auto table = ui::Table(4, 3, TRUE); // create table gtk_table_set_row_spacings(table, 8); // set row spacings gtk_table_set_col_spacings(table, 8); // set column spacings - vbox.pack_start( table, FALSE, FALSE, 2 ); // insert table into vbox + vbox.pack_start(table, FALSE, FALSE, 2); // insert table into vbox - auto label = ui::Label( "x" ); // create label - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); // align text to the left side + auto label = ui::Label("x"); // create label + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); // align text to the left side table.attach(label, {1, 2, 0, 1}); // insert label into table - label = ui::Label( "y" ); // create label - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); // align text to the left side + label = ui::Label("y"); // create label + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); // align text to the left side table.attach(label, {2, 3, 0, 1}); // insert label into table - label = ui::Label( "mapcoordsmins" ); // create label - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); // align text to the left side + label = ui::Label("mapcoordsmins"); // create label + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); // align text to the left side table.attach(label, {0, 1, 1, 2}); // insert label into table - auto spinnerMinX = ui::SpinButton(spinner_adj_MinX, 1.0, 0); // create textbox wiht value spin, value and value range + auto spinnerMinX = ui::SpinButton(spinner_adj_MinX, 1.0, + 0); // create textbox wiht value spin, value and value range table.attach(spinnerMinX, {1, 2, 1, 2}); // insert spinbox into table - auto spinnerMinY = ui::SpinButton(spinner_adj_MinY, 1.0, 0); // create textbox wiht value spin, value and value range + auto spinnerMinY = ui::SpinButton(spinner_adj_MinY, 1.0, + 0); // create textbox wiht value spin, value and value range table.attach(spinnerMinY, {2, 3, 1, 2}); // insert spinbox into table - label = ui::Label( "mapcoordsmaxs" ); // create label - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); // align text to the left side + label = ui::Label("mapcoordsmaxs"); // create label + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); // align text to the left side table.attach(label, {0, 1, 2, 3}); // insert label into table - auto spinnerMaxX = ui::SpinButton(spinner_adj_MaxX, 1.0, 0); // create textbox wiht value spin, value and value range + auto spinnerMaxX = ui::SpinButton(spinner_adj_MaxX, 1.0, + 0); // create textbox wiht value spin, value and value range table.attach(spinnerMaxX, {1, 2, 2, 3}); // insert spinbox into table - auto spinnerMaxY = ui::SpinButton(spinner_adj_MaxY, 1.0, 0); // create textbox wiht value spin, value and value range + auto spinnerMaxY = ui::SpinButton(spinner_adj_MaxY, 1.0, + 0); // create textbox wiht value spin, value and value range table.attach(spinnerMaxY, {2, 3, 2, 3}); // insert spinbox into table - // put the references to the spinboxes and the worldspawn into the global exchange + // put the references to the spinboxes and the worldspawn into the global exchange msp.spinner1 = spinnerMinX; msp.spinner2 = spinnerMinY; msp.spinner3 = spinnerMaxX; msp.spinner4 = spinnerMaxY; - msp.worldspawn = theWorldspawn; + msp.worldspawn = theWorldspawn; - button = ui::Button( "Set" ); // create button with text - button.connect( "clicked", G_CALLBACK( set_coordinates ), NULL ); // connect button with callback function + button = ui::Button("Set"); // create button with text + button.connect("clicked", G_CALLBACK(set_coordinates), NULL); // connect button with callback function table.attach(button, {1, 2, 3, 4}); // insert button into table - button = ui::Button( "Cancel" ); // create button with text - button.connect( "clicked", G_CALLBACK( close_window ), NULL ); // connect button with callback function + button = ui::Button("Cancel"); // create button with text + button.connect("clicked", G_CALLBACK(close_window), NULL); // connect button with callback function table.attach(button, {2, 3, 3, 4}); // insert button into table - } - else { - globalOutputStream() << "SunPlug: no worldspawn found!\n"; // output error to console + } else { + globalOutputStream() << "SunPlug: no worldspawn found!\n"; // output error to console - auto label = ui::Label( "ERROR: No worldspawn was found in the map!\nIn order to use this tool the map must have at least one brush in the worldspawn. " ); // create a label - gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); // text align left - vbox.pack_start( label, FALSE, FALSE, 2 ); // insert the label in the box + auto label = ui::Label( + "ERROR: No worldspawn was found in the map!\nIn order to use this tool the map must have at least one brush in the worldspawn. "); // create a label + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); // text align left + vbox.pack_start(label, FALSE, FALSE, 2); // insert the label in the box - auto button = ui::Button( "OK" ); // create a button with text - button.connect( "clicked", G_CALLBACK( close_window ), NULL ); // connect the click event to close the window - vbox.pack_start( button, FALSE, FALSE, 2 ); // insert the button in the box - } + auto button = ui::Button("OK"); // create a button with text + button.connect("clicked", G_CALLBACK(close_window), NULL); // connect the click event to close the window + vbox.pack_start(button, FALSE, FALSE, 2); // insert the button in the box + } - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); // center the window - gtk_widget_show_all( window ); // show the window and all subelements + gtk_window_set_position(window, GTK_WIN_POS_CENTER); // center the window + gtk_widget_show_all(window); // show the window and all subelements } diff --git a/contrib/sunplug/sunplug.h b/contrib/sunplug/sunplug.h index 8ea4f50c..f21f1980 100644 --- a/contrib/sunplug/sunplug.h +++ b/contrib/sunplug/sunplug.h @@ -19,7 +19,7 @@ */ #ifndef _PLUGIN_SUNPLUG_ - #define _PLUGIN_SUNPLUG_ +#define _PLUGIN_SUNPLUG_ #endif // _PLUGIN_SUNPLUG_ diff --git a/contrib/ufoaiplug/ufoai.cpp b/contrib/ufoaiplug/ufoai.cpp index 99815ab0..853ef5d0 100644 --- a/contrib/ufoaiplug/ufoai.cpp +++ b/contrib/ufoaiplug/ufoai.cpp @@ -44,121 +44,117 @@ #include "ieclass.h" class UFOAIPluginDependencies : - public GlobalRadiantModuleRef, // basic class for all other module refs - public GlobalUndoModuleRef, // used to say radiant that something has changed and to undo that - public GlobalSceneGraphModuleRef, // necessary to handle data in the mapfile (change, retrieve data) - public GlobalEntityModuleRef, // to access and modify the entities - public GlobalEntityClassManagerModuleRef -{ + public GlobalRadiantModuleRef, // basic class for all other module refs + public GlobalUndoModuleRef, // used to say radiant that something has changed and to undo that + public GlobalSceneGraphModuleRef, // necessary to handle data in the mapfile (change, retrieve data) + public GlobalEntityModuleRef, // to access and modify the entities + public GlobalEntityClassManagerModuleRef { public: -UFOAIPluginDependencies( void ) : - GlobalEntityModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entities" ) ), - GlobalEntityClassManagerModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entityclass" ) ){ -} + UFOAIPluginDependencies(void) : + GlobalEntityModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entities")), + GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass")) + { + } }; -namespace UFOAI -{ - ui::Window g_mainwnd{ui::null}; - -const char* init( void* hApp, void* pMainWidget ){ - g_mainwnd = ui::Window::from(pMainWidget); - return "Initializing GTKRadiant UFOAI plugin"; -} -const char* getName(){ - return "UFO:AI"; -} -const char* getCommandList(){ - /*GlobalRadiant().getGameName()*/ - return "About;-;Worldspawn reset;Worldspawn;Perform check;-;Level 1;Level 2;Level 3;Level 4;Level 5;Level 6;Level 7;Level 8;-;StepOn;ActorClip;WeaponClip;Nodraw"; -} -const char* getCommandTitleList(){ - return ""; -} -void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){ - char const *message = NULL; - if ( string_equal( command, "About" ) ) { - char const *version_string = "UFO:AI Plugin (http://ufoai.sf.net)\nBuild: " __DATE__ - "\nRadiant version: " RADIANT_VERSION - "\nPlugin version: " PLUGIN_VERSION - "\nAuthor: Martin Gerhardy (tlh2000/mattn)\n"; - GlobalRadiant().m_pfnMessageBox( g_mainwnd, - version_string, "About", - eMB_OK, eMB_ICONDEFAULT ); - } - else if ( string_equal( command, "Level 1" ) ) { - filter_level( CONTENTS_LEVEL1 ); - } - else if ( string_equal( command, "Level 2" ) ) { - filter_level( CONTENTS_LEVEL2 ); - } - else if ( string_equal( command, "Level 3" ) ) { - filter_level( CONTENTS_LEVEL3 ); - } - else if ( string_equal( command, "Worldspawn" ) ) { - assign_default_values_to_worldspawn( false, &message ); - } - else if ( string_equal( command, "Worldspawn reset" ) ) { - assign_default_values_to_worldspawn( true, &message ); - } - else if ( string_equal( command, "Perform check" ) ) { - check_map_values( &message ); - } - else if ( string_equal( command, "Level 4" ) ) { - filter_level( CONTENTS_LEVEL4 ); - } - else if ( string_equal( command, "Level 5" ) ) { - filter_level( CONTENTS_LEVEL5 ); - } - else if ( string_equal( command, "Level 6" ) ) { - filter_level( CONTENTS_LEVEL6 ); - } - else if ( string_equal( command, "Level 7" ) ) { - filter_level( CONTENTS_LEVEL7 ); - } - else if ( string_equal( command, "Level 8" ) ) { - filter_level( CONTENTS_LEVEL8 ); - } - else if ( string_equal( command, "StepOn" ) ) { - filter_stepon(); - } - else if ( string_equal( command, "ActorClip" ) ) { - filter_actorclip(); - } - else if ( string_equal( command, "WeaponClip" ) ) { - filter_weaponclip(); - } - else if ( string_equal( command, "NoDraw" ) ) { - filter_nodraw(); - } - - if ( message != NULL ) { - GlobalRadiant().m_pfnMessageBox( g_mainwnd, - message, "Note", - eMB_OK, eMB_ICONDEFAULT ); - } - SceneChangeNotify(); -} +namespace UFOAI { + ui::Window g_mainwnd{ui::null}; + + const char *init(void *hApp, void *pMainWidget) + { + g_mainwnd = ui::Window::from(pMainWidget); + return "Initializing GTKRadiant UFOAI plugin"; + } + + const char *getName() + { + return "UFO:AI"; + } + + const char *getCommandList() + { + /*GlobalRadiant().getGameName()*/ + return "About;-;Worldspawn reset;Worldspawn;Perform check;-;Level 1;Level 2;Level 3;Level 4;Level 5;Level 6;Level 7;Level 8;-;StepOn;ActorClip;WeaponClip;Nodraw"; + } + + const char *getCommandTitleList() + { + return ""; + } + + void dispatch(const char *command, float *vMin, float *vMax, bool bSingleBrush) + { + char const *message = NULL; + if (string_equal(command, "About")) { + char const *version_string = "UFO:AI Plugin (http://ufoai.sf.net)\nBuild: " __DATE__ + "\nRadiant version: " RADIANT_VERSION + "\nPlugin version: " PLUGIN_VERSION + "\nAuthor: Martin Gerhardy (tlh2000/mattn)\n"; + GlobalRadiant().m_pfnMessageBox(g_mainwnd, + version_string, "About", + eMB_OK, eMB_ICONDEFAULT); + } else if (string_equal(command, "Level 1")) { + filter_level(CONTENTS_LEVEL1); + } else if (string_equal(command, "Level 2")) { + filter_level(CONTENTS_LEVEL2); + } else if (string_equal(command, "Level 3")) { + filter_level(CONTENTS_LEVEL3); + } else if (string_equal(command, "Worldspawn")) { + assign_default_values_to_worldspawn(false, &message); + } else if (string_equal(command, "Worldspawn reset")) { + assign_default_values_to_worldspawn(true, &message); + } else if (string_equal(command, "Perform check")) { + check_map_values(&message); + } else if (string_equal(command, "Level 4")) { + filter_level(CONTENTS_LEVEL4); + } else if (string_equal(command, "Level 5")) { + filter_level(CONTENTS_LEVEL5); + } else if (string_equal(command, "Level 6")) { + filter_level(CONTENTS_LEVEL6); + } else if (string_equal(command, "Level 7")) { + filter_level(CONTENTS_LEVEL7); + } else if (string_equal(command, "Level 8")) { + filter_level(CONTENTS_LEVEL8); + } else if (string_equal(command, "StepOn")) { + filter_stepon(); + } else if (string_equal(command, "ActorClip")) { + filter_actorclip(); + } else if (string_equal(command, "WeaponClip")) { + filter_weaponclip(); + } else if (string_equal(command, "NoDraw")) { + filter_nodraw(); + } + + if (message != NULL) { + GlobalRadiant().m_pfnMessageBox(g_mainwnd, + message, "Note", + eMB_OK, eMB_ICONDEFAULT); + } + SceneChangeNotify(); + } } // namespace -class UFOAIModule : public TypeSystemRef -{ -_QERPluginTable m_plugin; +class UFOAIModule : public TypeSystemRef { + _QERPluginTable m_plugin; public: -typedef _QERPluginTable Type; -STRING_CONSTANT( Name, "UFO:AI" ); - -UFOAIModule(){ - m_plugin.m_pfnQERPlug_Init = &UFOAI::init; - m_plugin.m_pfnQERPlug_GetName = &UFOAI::getName; - m_plugin.m_pfnQERPlug_GetCommandList = &UFOAI::getCommandList; - m_plugin.m_pfnQERPlug_GetCommandTitleList = &UFOAI::getCommandTitleList; - m_plugin.m_pfnQERPlug_Dispatch = &UFOAI::dispatch; -} -_QERPluginTable* getTable(){ - return &m_plugin; -} + typedef _QERPluginTable Type; + + STRING_CONSTANT(Name, "UFO:AI"); + + UFOAIModule() + { + m_plugin.m_pfnQERPlug_Init = &UFOAI::init; + m_plugin.m_pfnQERPlug_GetName = &UFOAI::getName; + m_plugin.m_pfnQERPlug_GetCommandList = &UFOAI::getCommandList; + m_plugin.m_pfnQERPlug_GetCommandTitleList = &UFOAI::getCommandTitleList; + m_plugin.m_pfnQERPlug_Dispatch = &UFOAI::dispatch; + } + + _QERPluginTable *getTable() + { + return &m_plugin; + } }; typedef SingletonModule SingletonUFOAIModule; @@ -166,34 +162,35 @@ typedef SingletonModule SingletonUFOAIModu SingletonUFOAIModule g_UFOAIModule; -class UFOAIToolbarDependencies : public ModuleRef<_QERPluginTable> -{ +class UFOAIToolbarDependencies : public ModuleRef<_QERPluginTable> { public: -UFOAIToolbarDependencies() : ModuleRef<_QERPluginTable>( "UFO:AI" ){ -} + UFOAIToolbarDependencies() : ModuleRef<_QERPluginTable>("UFO:AI") + { + } }; -class UFOAIToolbarModule : public TypeSystemRef -{ -_QERPlugToolbarTable m_table; +class UFOAIToolbarModule : public TypeSystemRef { + _QERPlugToolbarTable m_table; public: -typedef _QERPlugToolbarTable Type; -STRING_CONSTANT( Name, "UFO:AI" ); - -UFOAIToolbarModule(){ - if ( !strcmp( GlobalRadiant().getGameDescriptionKeyValue( "name" ), "UFO:Alien Invasion" ) ) { - m_table.m_pfnToolbarButtonCount = ToolbarButtonCount; - m_table.m_pfnGetToolbarButton = GetToolbarButton; - } - else - { - m_table.m_pfnToolbarButtonCount = ToolbarNoButtons; - m_table.m_pfnGetToolbarButton = GetToolbarNoButton; - } -} -_QERPlugToolbarTable* getTable(){ - return &m_table; -} + typedef _QERPlugToolbarTable Type; + + STRING_CONSTANT(Name, "UFO:AI"); + + UFOAIToolbarModule() + { + if (!strcmp(GlobalRadiant().getGameDescriptionKeyValue("name"), "UFO:Alien Invasion")) { + m_table.m_pfnToolbarButtonCount = ToolbarButtonCount; + m_table.m_pfnGetToolbarButton = GetToolbarButton; + } else { + m_table.m_pfnToolbarButtonCount = ToolbarNoButtons; + m_table.m_pfnGetToolbarButton = GetToolbarNoButton; + } + } + + _QERPlugToolbarTable *getTable() + { + return &m_table; + } }; typedef SingletonModule SingletonUFOAIToolbarModule; @@ -201,9 +198,10 @@ typedef SingletonModule SingletonU SingletonUFOAIToolbarModule g_UFOAIToolbarModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_UFOAIModule.selfRegister(); - g_UFOAIToolbarModule.selfRegister(); + g_UFOAIModule.selfRegister(); + g_UFOAIToolbarModule.selfRegister(); } diff --git a/contrib/ufoaiplug/ufoai_filters.cpp b/contrib/ufoaiplug/ufoai_filters.cpp index c40de733..de30083a 100644 --- a/contrib/ufoaiplug/ufoai_filters.cpp +++ b/contrib/ufoaiplug/ufoai_filters.cpp @@ -39,143 +39,145 @@ int level_active = 0; // TODO: This should be added to ibrush.h // like already done for Node_getEntity in ientity.h // FIXME: Doesn't belong here -inline Brush* Node_getBrush( scene::Node& node ){ - return NodeTypeCast::cast( node ); +inline Brush *Node_getBrush(scene::Node &node) +{ + return NodeTypeCast::cast(node); } -void hide_node( scene::Node& node, bool hide ){ - hide - ? node.enable( scene::Node::eHidden ) - : node.disable( scene::Node::eHidden ); +void hide_node(scene::Node &node, bool hide) +{ + hide + ? node.enable(scene::Node::eHidden) + : node.disable(scene::Node::eHidden); } -typedef std::list entitylist_t; +typedef std::list entitylist_t; -class EntityFindByName : public scene::Graph::Walker -{ -const char* m_name; -entitylist_t& m_entitylist; +class EntityFindByName : public scene::Graph::Walker { + const char *m_name; + entitylist_t &m_entitylist; /* this starts at 1 << level */ -int m_flag; -int m_hide; + int m_flag; + int m_hide; public: -EntityFindByName( const char* name, entitylist_t& entitylist, int flag, bool hide ) - : m_name( name ), m_entitylist( entitylist ), m_flag( flag ), m_hide( hide ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - int spawnflagsInt; - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 ) { - if ( string_equal( m_name, entity->getKeyValue( "classname" ) ) ) { - const char *spawnflags = entity->getKeyValue( "spawnflags" ); - globalOutputStream() << "spawnflags for " << m_name << ": " << spawnflags << ".\n"; - - if ( !string_empty( spawnflags ) ) { - spawnflagsInt = atoi( spawnflags ); - if ( !( spawnflagsInt & m_flag ) ) { - hide_node( path.top(), m_hide ); // hide/unhide - m_entitylist.push_back( entity ); - } - } - else - { - globalOutputStream() << "UFO:AI: Warning: no spawnflags for " << m_name << ".\n"; - } - } - } - return true; -} + EntityFindByName(const char *name, entitylist_t &entitylist, int flag, bool hide) + : m_name(name), m_entitylist(entitylist), m_flag(flag), m_hide(hide) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + int spawnflagsInt; + Entity *entity = Node_getEntity(path.top()); + if (entity != 0) { + if (string_equal(m_name, entity->getKeyValue("classname"))) { + const char *spawnflags = entity->getKeyValue("spawnflags"); + globalOutputStream() << "spawnflags for " << m_name << ": " << spawnflags << ".\n"; + + if (!string_empty(spawnflags)) { + spawnflagsInt = atoi(spawnflags); + if (!(spawnflagsInt & m_flag)) { + hide_node(path.top(), m_hide); // hide/unhide + m_entitylist.push_back(entity); + } + } else { + globalOutputStream() << "UFO:AI: Warning: no spawnflags for " << m_name << ".\n"; + } + } + } + return true; + } }; -class ForEachFace : public BrushVisitor -{ -Brush &m_brush; +class ForEachFace : public BrushVisitor { + Brush &m_brush; public: -mutable int m_contentFlagsVis; -mutable int m_surfaceFlagsVis; - -ForEachFace( Brush& brush ) - : m_brush( brush ){ - m_contentFlagsVis = -1; - m_surfaceFlagsVis = -1; -} - -void visit( Face& face ) const { + mutable int m_contentFlagsVis; + mutable int m_surfaceFlagsVis; + + ForEachFace(Brush &brush) + : m_brush(brush) + { + m_contentFlagsVis = -1; + m_surfaceFlagsVis = -1; + } + + void visit(Face &face) const + { #if GDEF_DEBUG - if ( m_surfaceFlagsVis < 0 ) { - m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags; - } - else if ( m_surfaceFlagsVis >= 0 && m_surfaceFlagsVis != face.getShader().m_flags.m_surfaceFlags ) { - globalOutputStream() << "Faces with different surfaceflags at brush\n"; - } - if ( m_contentFlagsVis < 0 ) { - m_contentFlagsVis = face.getShader().m_flags.m_contentFlags; - } - else if ( m_contentFlagsVis >= 0 && m_contentFlagsVis != face.getShader().m_flags.m_contentFlags ) { - globalOutputStream() << "Faces with different contentflags at brush\n"; - } + if (m_surfaceFlagsVis < 0) { + m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags; + } else if (m_surfaceFlagsVis >= 0 && m_surfaceFlagsVis != face.getShader().m_flags.m_surfaceFlags) { + globalOutputStream() << "Faces with different surfaceflags at brush\n"; + } + if (m_contentFlagsVis < 0) { + m_contentFlagsVis = face.getShader().m_flags.m_contentFlags; + } else if (m_contentFlagsVis >= 0 && m_contentFlagsVis != face.getShader().m_flags.m_contentFlags) { + globalOutputStream() << "Faces with different contentflags at brush\n"; + } #else - m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags; - m_contentFlagsVis = face.getShader().m_flags.m_contentFlags; + m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags; + m_contentFlagsVis = face.getShader().m_flags.m_contentFlags; #endif -} + } }; -typedef std::list brushlist_t; +typedef std::list brushlist_t; -class BrushGetLevel : public scene::Graph::Walker -{ -brushlist_t& m_brushlist; -int m_flag; -bool m_content; // if true - use m_contentFlags - otherwise m_surfaceFlags -mutable bool m_notset; -mutable bool m_hide; +class BrushGetLevel : public scene::Graph::Walker { + brushlist_t &m_brushlist; + int m_flag; + bool m_content; // if true - use m_contentFlags - otherwise m_surfaceFlags + mutable bool m_notset; + mutable bool m_hide; public: -BrushGetLevel( brushlist_t& brushlist, int flag, bool content, bool notset, bool hide ) - : m_brushlist( brushlist ), m_flag( flag ), m_content( content ), m_notset( notset ), m_hide( hide ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Brush* brush = Node_getBrush( path.top() ); - if ( brush != 0 ) { - ForEachFace faces( *brush ); - brush->forEachFace( faces ); - // contentflags? - if ( m_content ) { - // are any flags set? - if ( faces.m_contentFlagsVis > 0 ) { - // flag should not be set - if ( m_notset && ( !( faces.m_contentFlagsVis & m_flag ) ) ) { - hide_node( path.top(), m_hide ); - m_brushlist.push_back( brush ); - } - // check whether flag is set - else if ( !m_notset && ( ( faces.m_contentFlagsVis & m_flag ) ) ) { - hide_node( path.top(), m_hide ); - m_brushlist.push_back( brush ); - } - } - } - // surfaceflags? - else - { - // are any flags set? - if ( faces.m_surfaceFlagsVis > 0 ) { - // flag should not be set - if ( m_notset && ( !( faces.m_surfaceFlagsVis & m_flag ) ) ) { - hide_node( path.top(), m_hide ); - m_brushlist.push_back( brush ); - } - // check whether flag is set - else if ( !m_notset && ( ( faces.m_surfaceFlagsVis & m_flag ) ) ) { - hide_node( path.top(), m_hide ); - m_brushlist.push_back( brush ); - } - } - } - - } - return true; -} + BrushGetLevel(brushlist_t &brushlist, int flag, bool content, bool notset, bool hide) + : m_brushlist(brushlist), m_flag(flag), m_content(content), m_notset(notset), m_hide(hide) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Brush *brush = Node_getBrush(path.top()); + if (brush != 0) { + ForEachFace faces(*brush); + brush->forEachFace(faces); + // contentflags? + if (m_content) { + // are any flags set? + if (faces.m_contentFlagsVis > 0) { + // flag should not be set + if (m_notset && (!(faces.m_contentFlagsVis & m_flag))) { + hide_node(path.top(), m_hide); + m_brushlist.push_back(brush); + } + // check whether flag is set + else if (!m_notset && ((faces.m_contentFlagsVis & m_flag))) { + hide_node(path.top(), m_hide); + m_brushlist.push_back(brush); + } + } + } + // surfaceflags? + else { + // are any flags set? + if (faces.m_surfaceFlagsVis > 0) { + // flag should not be set + if (m_notset && (!(faces.m_surfaceFlagsVis & m_flag))) { + hide_node(path.top(), m_hide); + m_brushlist.push_back(brush); + } + // check whether flag is set + else if (!m_notset && ((faces.m_surfaceFlagsVis & m_flag))) { + hide_node(path.top(), m_hide); + m_brushlist.push_back(brush); + } + } + } + + } + return true; + } }; /** @@ -183,137 +185,126 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { * @param[in] level Which level to show? * @todo Entities */ -void filter_level( int flag ){ - int level; - brushlist_t brushes; - entitylist_t entities; - - level = ( flag >> 8 ); - - if ( level_active ) { - GlobalSceneGraph().traverse( BrushGetLevel( brushes, ( level_active << 8 ), true, true, false ) ); - GlobalSceneGraph().traverse( EntityFindByName( "func_door", entities, level_active, false ) ); - GlobalSceneGraph().traverse( EntityFindByName( "func_breakable", entities, level_active, false ) ); - GlobalSceneGraph().traverse( EntityFindByName( "misc_model", entities, level_active, false ) ); - GlobalSceneGraph().traverse( EntityFindByName( "misc_particle", entities, level_active, false ) ); - entities.erase( entities.begin(), entities.end() ); - brushes.erase( brushes.begin(), brushes.end() ); - if ( level_active == level ) { - level_active = 0; - // just disabĺe level filter - return; - } - } - level_active = level; - globalOutputStream() << "UFO:AI: level_active: " << level_active << ", flag: " << flag << ".\n"; - - // first all brushes - GlobalSceneGraph().traverse( BrushGetLevel( brushes, flag, true, true, true ) ); - - // now all entities - GlobalSceneGraph().traverse( EntityFindByName( "func_door", entities, level, true ) ); - GlobalSceneGraph().traverse( EntityFindByName( "func_breakable", entities, level, true ) ); - GlobalSceneGraph().traverse( EntityFindByName( "misc_model", entities, level, true ) ); - GlobalSceneGraph().traverse( EntityFindByName( "misc_particle", entities, level, true ) ); +void filter_level(int flag) +{ + int level; + brushlist_t brushes; + entitylist_t entities; + + level = (flag >> 8); + + if (level_active) { + GlobalSceneGraph().traverse(BrushGetLevel(brushes, (level_active << 8), true, true, false)); + GlobalSceneGraph().traverse(EntityFindByName("func_door", entities, level_active, false)); + GlobalSceneGraph().traverse(EntityFindByName("func_breakable", entities, level_active, false)); + GlobalSceneGraph().traverse(EntityFindByName("misc_model", entities, level_active, false)); + GlobalSceneGraph().traverse(EntityFindByName("misc_particle", entities, level_active, false)); + entities.erase(entities.begin(), entities.end()); + brushes.erase(brushes.begin(), brushes.end()); + if (level_active == level) { + level_active = 0; + // just disabĺe level filter + return; + } + } + level_active = level; + globalOutputStream() << "UFO:AI: level_active: " << level_active << ", flag: " << flag << ".\n"; + + // first all brushes + GlobalSceneGraph().traverse(BrushGetLevel(brushes, flag, true, true, true)); + + // now all entities + GlobalSceneGraph().traverse(EntityFindByName("func_door", entities, level, true)); + GlobalSceneGraph().traverse(EntityFindByName("func_breakable", entities, level, true)); + GlobalSceneGraph().traverse(EntityFindByName("misc_model", entities, level, true)); + GlobalSceneGraph().traverse(EntityFindByName("misc_particle", entities, level, true)); #if GDEF_DEBUG - if ( brushes.empty() ) { - globalOutputStream() << "UFO:AI: No brushes.\n"; - } - else - { - globalOutputStream() << "UFO:AI: Found " << Unsigned( brushes.size() ) << " brushes.\n"; - } - - // now let's filter all entities like misc_model, func_breakable and func_door that have the spawnflags set - if ( entities.empty() ) { - globalOutputStream() << "UFO:AI: No entities.\n"; - } - else - { - globalOutputStream() << "UFO:AI: Found " << Unsigned( entities.size() ) << " entities.\n"; - } + if (brushes.empty()) { + globalOutputStream() << "UFO:AI: No brushes.\n"; + } else { + globalOutputStream() << "UFO:AI: Found " << Unsigned(brushes.size()) << " brushes.\n"; + } + + // now let's filter all entities like misc_model, func_breakable and func_door that have the spawnflags set + if (entities.empty()) { + globalOutputStream() << "UFO:AI: No entities.\n"; + } else { + globalOutputStream() << "UFO:AI: Found " << Unsigned(entities.size()) << " entities.\n"; + } #endif } -void filter_stepon( void ){ - if ( stepon_active ) { - stepon_active = false; - } - else { - stepon_active = true; - } - brushlist_t brushes; - GlobalSceneGraph().traverse( BrushGetLevel( brushes, CONTENTS_STEPON, true, false, stepon_active ) ); - - if ( brushes.empty() ) { - globalOutputStream() << "UFO:AI: No brushes.\n"; - } - else - { - globalOutputStream() << "UFO:AI: Hiding " << Unsigned( brushes.size() ) << " stepon brushes.\n"; - } +void filter_stepon(void) +{ + if (stepon_active) { + stepon_active = false; + } else { + stepon_active = true; + } + brushlist_t brushes; + GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_STEPON, true, false, stepon_active)); + + if (brushes.empty()) { + globalOutputStream() << "UFO:AI: No brushes.\n"; + } else { + globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " stepon brushes.\n"; + } } -void filter_nodraw( void ){ - if ( nodraw_active ) { - nodraw_active = false; - } - else { - nodraw_active = true; - } - brushlist_t brushes; - GlobalSceneGraph().traverse( BrushGetLevel( brushes, SURF_NODRAW, false, false, nodraw_active ) ); +void filter_nodraw(void) +{ + if (nodraw_active) { + nodraw_active = false; + } else { + nodraw_active = true; + } + brushlist_t brushes; + GlobalSceneGraph().traverse(BrushGetLevel(brushes, SURF_NODRAW, false, false, nodraw_active)); #if GDEF_DEBUG - if ( brushes.empty() ) { - globalOutputStream() << "UFO:AI: No brushes.\n"; - } - else - { - globalOutputStream() << "UFO:AI: Hiding " << Unsigned( brushes.size() ) << " nodraw brushes.\n"; - } + if (brushes.empty()) { + globalOutputStream() << "UFO:AI: No brushes.\n"; + } else { + globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " nodraw brushes.\n"; + } #endif } -void filter_actorclip( void ){ - if ( actorclip_active ) { - actorclip_active = false; - } - else { - actorclip_active = true; - } - brushlist_t brushes; - GlobalSceneGraph().traverse( BrushGetLevel( brushes, CONTENTS_ACTORCLIP, true, false, actorclip_active ) ); +void filter_actorclip(void) +{ + if (actorclip_active) { + actorclip_active = false; + } else { + actorclip_active = true; + } + brushlist_t brushes; + GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_ACTORCLIP, true, false, actorclip_active)); #if GDEF_DEBUG - if ( brushes.empty() ) { - globalOutputStream() << "UFO:AI: No brushes.\n"; - } - else - { - globalOutputStream() << "UFO:AI: Hiding " << Unsigned( brushes.size() ) << " actorclip brushes.\n"; - } + if (brushes.empty()) { + globalOutputStream() << "UFO:AI: No brushes.\n"; + } else { + globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " actorclip brushes.\n"; + } #endif } -void filter_weaponclip( void ){ - if ( weaponclip_active ) { - weaponclip_active = false; - } - else { - weaponclip_active = true; - } - brushlist_t brushes; - GlobalSceneGraph().traverse( BrushGetLevel( brushes, CONTENTS_WEAPONCLIP, true, false, weaponclip_active ) ); +void filter_weaponclip(void) +{ + if (weaponclip_active) { + weaponclip_active = false; + } else { + weaponclip_active = true; + } + brushlist_t brushes; + GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_WEAPONCLIP, true, false, weaponclip_active)); #if GDEF_DEBUG - if ( brushes.empty() ) { - globalOutputStream() << "UFO:AI: No brushes.\n"; - } - else - { - globalOutputStream() << "UFO:AI: Hiding " << Unsigned( brushes.size() ) << " weaponclip brushes.\n"; - } + if (brushes.empty()) { + globalOutputStream() << "UFO:AI: No brushes.\n"; + } else { + globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " weaponclip brushes.\n"; + } #endif } diff --git a/contrib/ufoaiplug/ufoai_filters.h b/contrib/ufoaiplug/ufoai_filters.h index 99289922..ecf0731f 100644 --- a/contrib/ufoaiplug/ufoai_filters.h +++ b/contrib/ufoaiplug/ufoai_filters.h @@ -19,11 +19,15 @@ #if !defined( INCLUDED_FILTERS_H ) #define INCLUDED_FILTERS_H -void filter_level( int flag ); -void filter_stepon( void ); -void filter_actorclip( void ); -void filter_weaponclip( void ); -void filter_nodraw( void ); +void filter_level(int flag); + +void filter_stepon(void); + +void filter_actorclip(void); + +void filter_weaponclip(void); + +void filter_nodraw(void); const int SURF_NODRAW = 0x80; diff --git a/contrib/ufoaiplug/ufoai_gtk.cpp b/contrib/ufoaiplug/ufoai_gtk.cpp index 39a983b6..fef53076 100644 --- a/contrib/ufoaiplug/ufoai_gtk.cpp +++ b/contrib/ufoaiplug/ufoai_gtk.cpp @@ -32,22 +32,25 @@ * This is useful for popping up 'are you sure you want to quit?' * type dialogs. */ -static gboolean delete_event(ui::Widget widget, GdkEvent *event, gpointer data ){ - return FALSE; +static gboolean delete_event(ui::Widget widget, GdkEvent *event, gpointer data) +{ + return FALSE; } /** * @brief destroy widget if destroy signal is passed to widget */ -static void destroy( ui::Widget widget, gpointer data ){ - widget.destroy(); +static void destroy(ui::Widget widget, gpointer data) +{ + widget.destroy(); } /** * @brief function for close button to destroy the toplevel widget */ -static void close_window( ui::Widget widget, gpointer data ){ - widget.window().destroy(); +static void close_window(ui::Widget widget, gpointer data) +{ + widget.window().destroy(); } /* =============================== */ @@ -57,109 +60,178 @@ const int NUM_TOOLBARBUTTONS = 12; /** * @brief */ -std::size_t ToolbarButtonCount( void ){ - return NUM_TOOLBARBUTTONS; +std::size_t ToolbarButtonCount(void) +{ + return NUM_TOOLBARBUTTONS; } /** * @brief Used if the ufo plugin should not be visible (at least the toolbar stuff) */ -std::size_t ToolbarNoButtons( void ){ - return 0; +std::size_t ToolbarNoButtons(void) +{ + return 0; } /** * @brief */ -class CUFOAIToolbarButton : public IToolbarButton -{ +class CUFOAIToolbarButton : public IToolbarButton { public: -virtual const char* getImage() const { - switch ( mIndex ) - { - case 0: return "ufoai_level1.png"; - case 1: return "ufoai_level2.png"; - case 2: return "ufoai_level3.png"; - case 3: return "ufoai_level4.png"; - case 4: return "ufoai_level5.png"; - case 5: return "ufoai_level6.png"; - case 6: return "ufoai_level7.png"; - case 7: return "ufoai_level8.png"; - case 8: return "ufoai_stepon.png"; - case 9: return "ufoai_actorclip.png"; - case 10: return "ufoai_weaponclip.png"; - case 11: return "ufoai_nodraw.png"; - } - return NULL; -} -virtual EType getType() const { - switch ( mIndex ) - { + virtual const char *getImage() const + { + switch (mIndex) { + case 0: + return "ufoai_level1.png"; + case 1: + return "ufoai_level2.png"; + case 2: + return "ufoai_level3.png"; + case 3: + return "ufoai_level4.png"; + case 4: + return "ufoai_level5.png"; + case 5: + return "ufoai_level6.png"; + case 6: + return "ufoai_level7.png"; + case 7: + return "ufoai_level8.png"; + case 8: + return "ufoai_stepon.png"; + case 9: + return "ufoai_actorclip.png"; + case 10: + return "ufoai_weaponclip.png"; + case 11: + return "ufoai_nodraw.png"; + } + return NULL; + } + + virtual EType getType() const + { + switch (mIndex) { /* case 3: return eButton;*/ - case 8: return eToggleButton; - case 9: return eToggleButton; - case 10: return eToggleButton; - case 11: return eToggleButton; - default: return eButton; - } -} -virtual const char* getText() const { - switch ( mIndex ) - { - case 0: return "Level 1"; - case 1: return "Level 2"; - case 2: return "Level 3"; - case 3: return "Level 4"; - case 4: return "Level 5"; - case 5: return "Level 6"; - case 6: return "Level 7"; - case 7: return "Level 8"; - case 8: return "Stepon"; - case 9: return "Actorclip"; - case 10: return "Weaponclip"; - case 11: return "Nodraw"; - } - return NULL; -} -virtual const char* getTooltip() const { - switch ( mIndex ) - { - case 0: return "Show only level 1"; - case 1: return "Show only level 2"; - case 2: return "Show only level 3"; - case 3: return "Show only level 4"; - case 4: return "Show only level 5"; - case 5: return "Show only level 6"; - case 6: return "Show only level 7"; - case 7: return "Show only level 8"; - case 8: return "Hide stepon brushes"; - case 9: return "Hide actorclip brushes"; - case 10: return "Hide weaponclip brushes"; - case 11: return "Hide nodraw brushes"; - } - return NULL; -} + case 8: + return eToggleButton; + case 9: + return eToggleButton; + case 10: + return eToggleButton; + case 11: + return eToggleButton; + default: + return eButton; + } + } -virtual void activate() const { - switch ( mIndex ) - { - case 0: filter_level( CONTENTS_LEVEL1 ); break; - case 1: filter_level( CONTENTS_LEVEL2 ); break; - case 2: filter_level( CONTENTS_LEVEL3 ); break; - case 3: filter_level( CONTENTS_LEVEL4 ); break; - case 4: filter_level( CONTENTS_LEVEL5 ); break; - case 5: filter_level( CONTENTS_LEVEL6 ); break; - case 6: filter_level( CONTENTS_LEVEL7 ); break; - case 7: filter_level( CONTENTS_LEVEL8 ); break; - case 8: filter_stepon(); break; - case 9: filter_actorclip(); break; - case 10: filter_weaponclip(); break; - case 11: filter_nodraw(); break; - } - SceneChangeNotify(); -} + virtual const char *getText() const + { + switch (mIndex) { + case 0: + return "Level 1"; + case 1: + return "Level 2"; + case 2: + return "Level 3"; + case 3: + return "Level 4"; + case 4: + return "Level 5"; + case 5: + return "Level 6"; + case 6: + return "Level 7"; + case 7: + return "Level 8"; + case 8: + return "Stepon"; + case 9: + return "Actorclip"; + case 10: + return "Weaponclip"; + case 11: + return "Nodraw"; + } + return NULL; + } -std::size_t mIndex; + virtual const char *getTooltip() const + { + switch (mIndex) { + case 0: + return "Show only level 1"; + case 1: + return "Show only level 2"; + case 2: + return "Show only level 3"; + case 3: + return "Show only level 4"; + case 4: + return "Show only level 5"; + case 5: + return "Show only level 6"; + case 6: + return "Show only level 7"; + case 7: + return "Show only level 8"; + case 8: + return "Hide stepon brushes"; + case 9: + return "Hide actorclip brushes"; + case 10: + return "Hide weaponclip brushes"; + case 11: + return "Hide nodraw brushes"; + } + return NULL; + } + + virtual void activate() const + { + switch (mIndex) { + case 0: + filter_level(CONTENTS_LEVEL1); + break; + case 1: + filter_level(CONTENTS_LEVEL2); + break; + case 2: + filter_level(CONTENTS_LEVEL3); + break; + case 3: + filter_level(CONTENTS_LEVEL4); + break; + case 4: + filter_level(CONTENTS_LEVEL5); + break; + case 5: + filter_level(CONTENTS_LEVEL6); + break; + case 6: + filter_level(CONTENTS_LEVEL7); + break; + case 7: + filter_level(CONTENTS_LEVEL8); + break; + case 8: + filter_stepon(); + break; + case 9: + filter_actorclip(); + break; + case 10: + filter_weaponclip(); + break; + case 11: + filter_nodraw(); + break; + } + SceneChangeNotify(); + } + + std::size_t mIndex; }; /** @@ -170,14 +242,16 @@ CUFOAIToolbarButton g_ufoaiToolbarButtons[NUM_TOOLBARBUTTONS]; /** * @brief */ -const IToolbarButton* GetToolbarButton( std::size_t index ){ - g_ufoaiToolbarButtons[index].mIndex = index; - return &g_ufoaiToolbarButtons[index]; +const IToolbarButton *GetToolbarButton(std::size_t index) +{ + g_ufoaiToolbarButtons[index].mIndex = index; + return &g_ufoaiToolbarButtons[index]; } /** * @brief */ -const IToolbarButton* GetToolbarNoButton( std::size_t index ){ - return NULL; +const IToolbarButton *GetToolbarNoButton(std::size_t index) +{ + return NULL; } diff --git a/contrib/ufoaiplug/ufoai_gtk.h b/contrib/ufoaiplug/ufoai_gtk.h index 939c1f6f..8a182bcd 100644 --- a/contrib/ufoaiplug/ufoai_gtk.h +++ b/contrib/ufoaiplug/ufoai_gtk.h @@ -21,9 +21,12 @@ #include "itoolbar.h" -const IToolbarButton* GetToolbarButton( std::size_t index ); -const IToolbarButton* GetToolbarNoButton( std::size_t index ); -std::size_t ToolbarButtonCount( void ); -std::size_t ToolbarNoButtons( void ); +const IToolbarButton *GetToolbarButton(std::size_t index); + +const IToolbarButton *GetToolbarNoButton(std::size_t index); + +std::size_t ToolbarButtonCount(void); + +std::size_t ToolbarNoButtons(void); #endif diff --git a/contrib/ufoaiplug/ufoai_level.cpp b/contrib/ufoaiplug/ufoai_level.cpp index 41a4c62b..b6d99f6c 100644 --- a/contrib/ufoaiplug/ufoai_level.cpp +++ b/contrib/ufoaiplug/ufoai_level.cpp @@ -32,252 +32,274 @@ class Level; * @brief find entities by class * @note from radiant/map.cpp */ -class EntityFindByClassname : public scene::Graph::Walker -{ -const char* m_name; -Entity*& m_entity; +class EntityFindByClassname : public scene::Graph::Walker { + const char *m_name; + Entity *&m_entity; public: -EntityFindByClassname( const char* name, Entity*& entity ) : m_name( name ), m_entity( entity ){ - m_entity = 0; -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( m_entity == 0 ) { - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 && string_equal( m_name, entity->getKeyValue( "classname" ) ) ) { - m_entity = entity; - } - } - return true; -} + EntityFindByClassname(const char *name, Entity *&entity) : m_name(name), m_entity(entity) + { + m_entity = 0; + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (m_entity == 0) { + Entity *entity = Node_getEntity(path.top()); + if (entity != 0 && string_equal(m_name, entity->getKeyValue("classname"))) { + m_entity = entity; + } + } + return true; + } }; /** * @brief */ -Entity* Scene_FindEntityByClass( const char* name ){ - Entity* entity = NULL; - GlobalSceneGraph().traverse( EntityFindByClassname( name, entity ) ); - return entity; +Entity *Scene_FindEntityByClass(const char *name) +{ + Entity *entity = NULL; + GlobalSceneGraph().traverse(EntityFindByClassname(name, entity)); + return entity; } /** * @brief finds start positions */ -class EntityFindFlags : public scene::Graph::Walker -{ -const char *m_classname; -const char *m_flag; -int *m_count; +class EntityFindFlags : public scene::Graph::Walker { + const char *m_classname; + const char *m_flag; + int *m_count; public: -EntityFindFlags( const char *classname, const char *flag, int *count ) : m_classname( classname ), m_flag( flag ), m_count( count ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - const char *str; - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 && string_equal( m_classname, entity->getKeyValue( "classname" ) ) ) { - str = entity->getKeyValue( m_flag ); - if ( string_empty( str ) ) { - ( *m_count )++; - } - } - return true; -} + EntityFindFlags(const char *classname, const char *flag, int *count) : m_classname(classname), m_flag(flag), + m_count(count) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + const char *str; + Entity *entity = Node_getEntity(path.top()); + if (entity != 0 && string_equal(m_classname, entity->getKeyValue("classname"))) { + str = entity->getKeyValue(m_flag); + if (string_empty(str)) { + (*m_count)++; + } + } + return true; + } }; /** * @brief finds start positions */ -class EntityFindTeams : public scene::Graph::Walker -{ -const char *m_classname; -int *m_count; -int *m_team; +class EntityFindTeams : public scene::Graph::Walker { + const char *m_classname; + int *m_count; + int *m_team; public: -EntityFindTeams( const char *classname, int *count, int *team ) : m_classname( classname ), m_count( count ), m_team( team ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - const char *str; - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 && string_equal( m_classname, entity->getKeyValue( "classname" ) ) ) { - if ( m_count ) { - ( *m_count )++; - } - // now get the highest teamnum - if ( m_team ) { - str = entity->getKeyValue( "team" ); - if ( !string_empty( str ) ) { - if ( atoi( str ) > *m_team ) { - ( *m_team ) = atoi( str ); - } - } - } - } - return true; -} + EntityFindTeams(const char *classname, int *count, int *team) : m_classname(classname), m_count(count), m_team(team) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + const char *str; + Entity *entity = Node_getEntity(path.top()); + if (entity != 0 && string_equal(m_classname, entity->getKeyValue("classname"))) { + if (m_count) { + (*m_count)++; + } + // now get the highest teamnum + if (m_team) { + str = entity->getKeyValue("team"); + if (!string_empty(str)) { + if (atoi(str) > *m_team) { + (*m_team) = atoi(str); + } + } + } + } + return true; + } }; /** * @brief */ -void get_team_count( const char *classname, int *count, int *team ){ - GlobalSceneGraph().traverse( EntityFindTeams( classname, count, team ) ); - globalOutputStream() << "UFO:AI: classname: " << classname << ": #" << ( *count ) << "\n"; +void get_team_count(const char *classname, int *count, int *team) +{ + GlobalSceneGraph().traverse(EntityFindTeams(classname, count, team)); + globalOutputStream() << "UFO:AI: classname: " << classname << ": #" << (*count) << "\n"; } /** * @brief Some default values to worldspawn like maxlevel and so on */ -void assign_default_values_to_worldspawn( bool override, const char **returnMsg ){ - static char message[1024]; - Entity* worldspawn; - int teams = 0; - int count = 0; - char str[64]; - - worldspawn = Scene_FindEntityByClass( "worldspawn" ); - if ( !worldspawn ) { - globalOutputStream() << "UFO:AI: Could not find worldspawn.\n"; - *returnMsg = "Could not find worldspawn"; - return; - } - - *message = '\0'; - *str = '\0'; - - if ( override || string_empty( worldspawn->getKeyValue( "maxlevel" ) ) ) { - // TODO: Get highest brush - a level has 64 units - worldspawn->setKeyValue( "maxlevel", "5" ); - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "Set maxlevel to: %s", worldspawn->getKeyValue( "maxlevel" ) ); - } - - if ( override || string_empty( worldspawn->getKeyValue( "maxteams" ) ) ) { - get_team_count( "info_player_start", &count, &teams ); - if ( teams ) { - snprintf( str, sizeof( str ) - 1, "%i", teams ); - worldspawn->setKeyValue( "maxteams", str ); - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "Set maxteams to: %s", worldspawn->getKeyValue( "maxteams" ) ); - } - if ( count < 16 ) { - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "You should at least place 16 info_player_start" ); - } - } - - // no errors - no warnings - if ( !strlen( message ) ) { - return; - } - - *returnMsg = message; +void assign_default_values_to_worldspawn(bool override, const char **returnMsg) +{ + static char message[1024]; + Entity *worldspawn; + int teams = 0; + int count = 0; + char str[64]; + + worldspawn = Scene_FindEntityByClass("worldspawn"); + if (!worldspawn) { + globalOutputStream() << "UFO:AI: Could not find worldspawn.\n"; + *returnMsg = "Could not find worldspawn"; + return; + } + + *message = '\0'; + *str = '\0'; + + if (override || string_empty(worldspawn->getKeyValue("maxlevel"))) { + // TODO: Get highest brush - a level has 64 units + worldspawn->setKeyValue("maxlevel", "5"); + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), "Set maxlevel to: %s", + worldspawn->getKeyValue("maxlevel")); + } + + if (override || string_empty(worldspawn->getKeyValue("maxteams"))) { + get_team_count("info_player_start", &count, &teams); + if (teams) { + snprintf(str, sizeof(str) - 1, "%i", teams); + worldspawn->setKeyValue("maxteams", str); + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), "Set maxteams to: %s", + worldspawn->getKeyValue("maxteams")); + } + if (count < 16) { + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), + "You should at least place 16 info_player_start"); + } + } + + // no errors - no warnings + if (!strlen(message)) { + return; + } + + *returnMsg = message; } /** * @brief */ -int check_entity_flags( const char *classname, const char *flag ){ - int count; +int check_entity_flags(const char *classname, const char *flag) +{ + int count; - /* init this with 0 every time we browse the tree */ - count = 0; + /* init this with 0 every time we browse the tree */ + count = 0; - GlobalSceneGraph().traverse( EntityFindFlags( classname, flag, &count ) ); - return count; + GlobalSceneGraph().traverse(EntityFindFlags(classname, flag, &count)); + return count; } /** * @brief Will check e.g. the map entities for valid values * @todo: check for maxlevel */ -void check_map_values( const char **returnMsg ){ - static char message[1024]; - int count = 0; - int teams = 0; - int ent_flags; - Entity* worldspawn; - char str[64]; - - worldspawn = Scene_FindEntityByClass( "worldspawn" ); - if ( !worldspawn ) { - globalOutputStream() << "UFO:AI: Could not find worldspawn.\n"; - *returnMsg = "Could not find worldspawn"; - return; - } - - *message = '\0'; - *str = '\0'; - - // multiplayer start positions - get_team_count( "info_player_start", &count, &teams ); - if ( !count ) { - strncat( message, "No multiplayer start positions (info_player_start)\n", sizeof( message ) - 1 ); - } - - // singleplayer map? - count = 0; - get_team_count( "info_human_start", &count, NULL ); - if ( !count ) { - strncat( message, "No singleplayer start positions (info_human_start)\n", sizeof( message ) - 1 ); - } - - // singleplayer map? - count = 0; - get_team_count( "info_2x2_start", &count, NULL ); - if ( !count ) { - strncat( message, "No singleplayer start positions for 2x2 units (info_2x2_start)\n", sizeof( message ) - 1 ); - } - - // search for civilians - count = 0; - get_team_count( "info_civilian_start", &count, NULL ); - if ( !count ) { - strncat( message, "No civilian start positions (info_civilian_start)\n", sizeof( message ) - 1 ); - } - - // check maxlevel - if ( string_empty( worldspawn->getKeyValue( "maxlevel" ) ) ) { - strncat( message, "Worldspawn: No maxlevel defined\n", sizeof( message ) - 1 ); - } - else if ( atoi( worldspawn->getKeyValue( "maxlevel" ) ) > 8 ) { - strncat( message, "Worldspawn: Highest maxlevel is 8\n", sizeof( message ) - 1 ); - worldspawn->setKeyValue( "maxlevel", "8" ); - } - - ent_flags = check_entity_flags( "func_door", "spawnflags" ); - if ( ent_flags ) { - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "Found %i func_door with no spawnflags\n", ent_flags ); - } - ent_flags = check_entity_flags( "func_breakable", "spawnflags" ); - if ( ent_flags ) { - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "Found %i func_breakable with no spawnflags\n", ent_flags ); - } - ent_flags = check_entity_flags( "misc_sound", "spawnflags" ); - if ( ent_flags ) { - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "Found %i misc_sound with no spawnflags\n", ent_flags ); - } - ent_flags = check_entity_flags( "misc_model", "spawnflags" ); - if ( ent_flags ) { - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "Found %i misc_model with no spawnflags\n", ent_flags ); - } - ent_flags = check_entity_flags( "misc_particle", "spawnflags" ); - if ( ent_flags ) { - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "Found %i misc_particle with no spawnflags\n", ent_flags ); - } - ent_flags = check_entity_flags( "info_player_start", "team" ); - if ( ent_flags ) { - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "Found %i info_player_start with no team assigned\n!!Teamcount may change after you've fixed this\n", ent_flags ); - } - ent_flags = check_entity_flags( "light", "color" ); - ent_flags = check_entity_flags( "light", "_color" ); - if ( ent_flags ) { - snprintf( &message[strlen( message )], sizeof( message ) - 1 - strlen( message ), "Found %i lights with no color value\n", ent_flags ); - } - - // no errors found - if ( !strlen( message ) ) { - snprintf( message, sizeof( message ) - 1, "No errors found - you are ready to compile the map now\n" ); - } - - *returnMsg = message; +void check_map_values(const char **returnMsg) +{ + static char message[1024]; + int count = 0; + int teams = 0; + int ent_flags; + Entity *worldspawn; + char str[64]; + + worldspawn = Scene_FindEntityByClass("worldspawn"); + if (!worldspawn) { + globalOutputStream() << "UFO:AI: Could not find worldspawn.\n"; + *returnMsg = "Could not find worldspawn"; + return; + } + + *message = '\0'; + *str = '\0'; + + // multiplayer start positions + get_team_count("info_player_start", &count, &teams); + if (!count) { + strncat(message, "No multiplayer start positions (info_player_start)\n", sizeof(message) - 1); + } + + // singleplayer map? + count = 0; + get_team_count("info_human_start", &count, NULL); + if (!count) { + strncat(message, "No singleplayer start positions (info_human_start)\n", sizeof(message) - 1); + } + + // singleplayer map? + count = 0; + get_team_count("info_2x2_start", &count, NULL); + if (!count) { + strncat(message, "No singleplayer start positions for 2x2 units (info_2x2_start)\n", sizeof(message) - 1); + } + + // search for civilians + count = 0; + get_team_count("info_civilian_start", &count, NULL); + if (!count) { + strncat(message, "No civilian start positions (info_civilian_start)\n", sizeof(message) - 1); + } + + // check maxlevel + if (string_empty(worldspawn->getKeyValue("maxlevel"))) { + strncat(message, "Worldspawn: No maxlevel defined\n", sizeof(message) - 1); + } else if (atoi(worldspawn->getKeyValue("maxlevel")) > 8) { + strncat(message, "Worldspawn: Highest maxlevel is 8\n", sizeof(message) - 1); + worldspawn->setKeyValue("maxlevel", "8"); + } + + ent_flags = check_entity_flags("func_door", "spawnflags"); + if (ent_flags) { + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), + "Found %i func_door with no spawnflags\n", ent_flags); + } + ent_flags = check_entity_flags("func_breakable", "spawnflags"); + if (ent_flags) { + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), + "Found %i func_breakable with no spawnflags\n", ent_flags); + } + ent_flags = check_entity_flags("misc_sound", "spawnflags"); + if (ent_flags) { + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), + "Found %i misc_sound with no spawnflags\n", ent_flags); + } + ent_flags = check_entity_flags("misc_model", "spawnflags"); + if (ent_flags) { + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), + "Found %i misc_model with no spawnflags\n", ent_flags); + } + ent_flags = check_entity_flags("misc_particle", "spawnflags"); + if (ent_flags) { + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), + "Found %i misc_particle with no spawnflags\n", ent_flags); + } + ent_flags = check_entity_flags("info_player_start", "team"); + if (ent_flags) { + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), + "Found %i info_player_start with no team assigned\n!!Teamcount may change after you've fixed this\n", + ent_flags); + } + ent_flags = check_entity_flags("light", "color"); + ent_flags = check_entity_flags("light", "_color"); + if (ent_flags) { + snprintf(&message[strlen(message)], sizeof(message) - 1 - strlen(message), + "Found %i lights with no color value\n", ent_flags); + } + + // no errors found + if (!strlen(message)) { + snprintf(message, sizeof(message) - 1, "No errors found - you are ready to compile the map now\n"); + } + + *returnMsg = message; } diff --git a/contrib/ufoaiplug/ufoai_level.h b/contrib/ufoaiplug/ufoai_level.h index 714f05fc..0104b84b 100644 --- a/contrib/ufoaiplug/ufoai_level.h +++ b/contrib/ufoaiplug/ufoai_level.h @@ -20,7 +20,9 @@ #define INCLUDED_UFOAI_LEVEL_H void assign_default_values_to_worldspawn(bool override, char const **returnMsg); + void check_map_values(char const **returnMsg); + void get_team_count(const char *classname, int *count, int *team); #endif diff --git a/libs/gtkutil/accelerator.cpp b/libs/gtkutil/accelerator.cpp index 414a8eac..30d9f66c 100644 --- a/libs/gtkutil/accelerator.cpp +++ b/libs/gtkutil/accelerator.cpp @@ -37,276 +37,292 @@ #include - -const char* global_keys_find( unsigned int key ){ - const char *s; - if ( key == 0 ) { - return ""; - } - s = gdk_keyval_name( key ); - if ( !s ) { - return ""; - } - return s; -} - -unsigned int global_keys_find( const char* name ){ - guint k; - if ( !name || !*name ) { - return 0; - } - k = gdk_keyval_from_name( name ); - if ( k == GDK_KEY_VoidSymbol ) { - return 0; - } - return k; -} - -void accelerator_write( const Accelerator& accelerator, TextOutputStream& ostream ){ +const char *global_keys_find(unsigned int key) +{ + const char *s; + if (key == 0) { + return ""; + } + s = gdk_keyval_name(key); + if (!s) { + return ""; + } + return s; +} + +unsigned int global_keys_find(const char *name) +{ + guint k; + if (!name || !*name) { + return 0; + } + k = gdk_keyval_from_name(name); + if (k == GDK_KEY_VoidSymbol) { + return 0; + } + return k; +} + +void accelerator_write(const Accelerator &accelerator, TextOutputStream &ostream) +{ #if 0 - 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( accelerator.key ); - } + 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( accelerator.key ); + } #endif - ostream << gtk_accelerator_get_label( accelerator.key, accelerator.modifiers ); + ostream << gtk_accelerator_get_label(accelerator.key, accelerator.modifiers); } typedef std::map> AcceleratorMap; typedef std::set AcceleratorSet; -bool accelerator_map_insert( AcceleratorMap& acceleratorMap, Accelerator accelerator, const Callback& callback ){ - if ( accelerator.key != 0 ) { - return acceleratorMap.insert( AcceleratorMap::value_type( accelerator, callback ) ).second; - } - return true; +bool accelerator_map_insert(AcceleratorMap &acceleratorMap, Accelerator accelerator, const Callback &callback) +{ + if (accelerator.key != 0) { + return acceleratorMap.insert(AcceleratorMap::value_type(accelerator, callback)).second; + } + return true; } -bool accelerator_map_erase( AcceleratorMap& acceleratorMap, Accelerator accelerator ){ - if ( accelerator.key != 0 ) { - AcceleratorMap::iterator i = acceleratorMap.find( accelerator ); - if ( i == acceleratorMap.end() ) { - return false; - } - acceleratorMap.erase( i ); - } - return true; +bool accelerator_map_erase(AcceleratorMap &acceleratorMap, Accelerator accelerator) +{ + if (accelerator.key != 0) { + AcceleratorMap::iterator i = acceleratorMap.find(accelerator); + if (i == acceleratorMap.end()) { + return false; + } + acceleratorMap.erase(i); + } + return true; } -Accelerator accelerator_for_event_key( guint keyval, guint state ){ - keyval = gdk_keyval_to_upper( keyval ); - if ( keyval == GDK_KEY_ISO_Left_Tab ) { - keyval = GDK_KEY_Tab; - } - return Accelerator( keyval, (GdkModifierType)( state & gtk_accelerator_get_default_mod_mask() ) ); +Accelerator accelerator_for_event_key(guint keyval, guint state) +{ + keyval = gdk_keyval_to_upper(keyval); + if (keyval == GDK_KEY_ISO_Left_Tab) { + keyval = GDK_KEY_Tab; + } + return Accelerator(keyval, (GdkModifierType) (state & gtk_accelerator_get_default_mod_mask())); } -bool AcceleratorMap_activate( const AcceleratorMap& acceleratorMap, const Accelerator& accelerator ){ - AcceleratorMap::const_iterator i = acceleratorMap.find( accelerator ); - if ( i != acceleratorMap.end() ) { - ( *i ).second(); - return true; - } +bool AcceleratorMap_activate(const AcceleratorMap &acceleratorMap, const Accelerator &accelerator) +{ + AcceleratorMap::const_iterator i = acceleratorMap.find(accelerator); + if (i != acceleratorMap.end()) { + (*i).second(); + return true; + } - return false; + return false; } -static gboolean accelerator_key_event( ui::Window window, GdkEventKey* event, AcceleratorMap* acceleratorMap ){ - return AcceleratorMap_activate( *acceleratorMap, accelerator_for_event_key( event->keyval, event->state ) ); +static gboolean accelerator_key_event(ui::Window window, GdkEventKey *event, AcceleratorMap *acceleratorMap) +{ + return AcceleratorMap_activate(*acceleratorMap, accelerator_for_event_key(event->keyval, event->state)); } AcceleratorMap g_special_accelerators; -namespace MouseButton -{ -enum -{ - Left = 1 << 0, - Right = 1 << 1, - Middle = 1 << 2, -}; +namespace MouseButton { + enum { + Left = 1 << 0, + Right = 1 << 1, + Middle = 1 << 2, + }; } typedef unsigned int ButtonMask; -void print_buttons( ButtonMask mask ){ - globalOutputStream() << "button state: "; - if ( ( mask & MouseButton::Left ) != 0 ) { - globalOutputStream() << "Left "; - } - if ( ( mask & MouseButton::Right ) != 0 ) { - globalOutputStream() << "Right "; - } - if ( ( mask & MouseButton::Middle ) != 0 ) { - globalOutputStream() << "Middle "; - } - globalOutputStream() << "\n"; -} - -ButtonMask ButtonMask_for_event_button( guint button ){ - switch ( button ) - { - case 1: - return MouseButton::Left; - case 2: - return MouseButton::Middle; - case 3: - return MouseButton::Right; - } - return 0; +void print_buttons(ButtonMask mask) +{ + globalOutputStream() << "button state: "; + if ((mask & MouseButton::Left) != 0) { + globalOutputStream() << "Left "; + } + if ((mask & MouseButton::Right) != 0) { + globalOutputStream() << "Right "; + } + if ((mask & MouseButton::Middle) != 0) { + globalOutputStream() << "Middle "; + } + globalOutputStream() << "\n"; +} + +ButtonMask ButtonMask_for_event_button(guint button) +{ + switch (button) { + case 1: + return MouseButton::Left; + case 2: + return MouseButton::Middle; + case 3: + return MouseButton::Right; + } + return 0; +} + +bool window_has_accel(ui::Window toplevel) +{ + return g_slist_length(gtk_accel_groups_from_object(G_OBJECT(toplevel))) != 0; } -bool window_has_accel( ui::Window toplevel ){ - return g_slist_length( gtk_accel_groups_from_object( G_OBJECT( toplevel ) ) ) != 0; +namespace { + bool g_accel_enabled = true; } -namespace +bool global_accel_enabled() { -bool g_accel_enabled = true; + return g_accel_enabled; } -bool global_accel_enabled(){ - return g_accel_enabled; -} +GClosure *accel_group_add_accelerator(ui::AccelGroup group, Accelerator accelerator, const Callback &callback); -GClosure* accel_group_add_accelerator(ui::AccelGroup group, Accelerator accelerator, const Callback& callback ); -void accel_group_remove_accelerator(ui::AccelGroup group, Accelerator accelerator ); +void accel_group_remove_accelerator(ui::AccelGroup group, Accelerator accelerator); AcceleratorMap g_queuedAcceleratorsAdd; AcceleratorSet g_queuedAcceleratorsRemove; -void globalQueuedAccelerators_add( Accelerator accelerator, const Callback& callback ){ - if ( !g_queuedAcceleratorsAdd.insert( AcceleratorMap::value_type( accelerator, callback ) ).second ) { - globalErrorStream() << "globalQueuedAccelerators_add: accelerator already queued: " << accelerator << "\n"; - } +void globalQueuedAccelerators_add(Accelerator accelerator, const Callback &callback) +{ + if (!g_queuedAcceleratorsAdd.insert(AcceleratorMap::value_type(accelerator, callback)).second) { + globalErrorStream() << "globalQueuedAccelerators_add: accelerator already queued: " << accelerator << "\n"; + } } -void globalQueuedAccelerators_remove( Accelerator accelerator ){ - if ( g_queuedAcceleratorsAdd.erase( accelerator ) == 0 ) { - if ( !g_queuedAcceleratorsRemove.insert( accelerator ).second ) { - globalErrorStream() << "globalQueuedAccelerators_remove: accelerator already queued: " << accelerator << "\n"; - } - } +void globalQueuedAccelerators_remove(Accelerator accelerator) +{ + if (g_queuedAcceleratorsAdd.erase(accelerator) == 0) { + if (!g_queuedAcceleratorsRemove.insert(accelerator).second) { + globalErrorStream() << "globalQueuedAccelerators_remove: accelerator already queued: " << accelerator + << "\n"; + } + } } -void globalQueuedAccelerators_commit(){ - for ( AcceleratorSet::const_iterator i = g_queuedAcceleratorsRemove.begin(); i != g_queuedAcceleratorsRemove.end(); ++i ) - { - //globalOutputStream() << "removing: " << (*i).first << "\n"; - accel_group_remove_accelerator( global_accel, *i ); - } - g_queuedAcceleratorsRemove.clear(); - for ( AcceleratorMap::const_iterator i = g_queuedAcceleratorsAdd.begin(); i != g_queuedAcceleratorsAdd.end(); ++i ) - { - //globalOutputStream() << "adding: " << (*i).first << "\n"; - accel_group_add_accelerator( global_accel, ( *i ).first, ( *i ).second ); - } - g_queuedAcceleratorsAdd.clear(); +void globalQueuedAccelerators_commit() +{ + for (AcceleratorSet::const_iterator i = g_queuedAcceleratorsRemove.begin(); + i != g_queuedAcceleratorsRemove.end(); ++i) { + //globalOutputStream() << "removing: " << (*i).first << "\n"; + accel_group_remove_accelerator(global_accel, *i); + } + g_queuedAcceleratorsRemove.clear(); + for (AcceleratorMap::const_iterator i = g_queuedAcceleratorsAdd.begin(); i != g_queuedAcceleratorsAdd.end(); ++i) { + //globalOutputStream() << "adding: " << (*i).first << "\n"; + accel_group_add_accelerator(global_accel, (*i).first, (*i).second); + } + g_queuedAcceleratorsAdd.clear(); } typedef std::set WindowSet; WindowSet g_accel_windows; -bool Buttons_press( ButtonMask& buttons, guint button, guint state ){ - if ( buttons == 0 && bitfield_enable( buttons, ButtonMask_for_event_button( button ) ) != 0 ) { - ASSERT_MESSAGE( g_accel_enabled, "Buttons_press: accelerators not enabled" ); - g_accel_enabled = false; - for ( WindowSet::iterator i = g_accel_windows.begin(); i != g_accel_windows.end(); ++i ) - { - ui::Window toplevel = *i; - ASSERT_MESSAGE( window_has_accel( toplevel ), "ERROR" ); - ASSERT_MESSAGE( gtk_widget_is_toplevel( toplevel ), "disabling accel for non-toplevel window" ); - gtk_window_remove_accel_group( toplevel, global_accel ); +bool Buttons_press(ButtonMask &buttons, guint button, guint state) +{ + if (buttons == 0 && bitfield_enable(buttons, ButtonMask_for_event_button(button)) != 0) { + ASSERT_MESSAGE(g_accel_enabled, "Buttons_press: accelerators not enabled"); + g_accel_enabled = false; + for (WindowSet::iterator i = g_accel_windows.begin(); i != g_accel_windows.end(); ++i) { + ui::Window toplevel = *i; + ASSERT_MESSAGE(window_has_accel(toplevel), "ERROR"); + ASSERT_MESSAGE(gtk_widget_is_toplevel(toplevel), "disabling accel for non-toplevel window"); + gtk_window_remove_accel_group(toplevel, global_accel); #if 0 - globalOutputStream() << reinterpret_cast( toplevel ) << ": disabled global accelerators\n"; + globalOutputStream() << reinterpret_cast( toplevel ) << ": disabled global accelerators\n"; #endif - } - } - buttons = bitfield_enable( buttons, ButtonMask_for_event_button( button ) ); + } + } + buttons = bitfield_enable(buttons, ButtonMask_for_event_button(button)); #if 0 - globalOutputStream() << "Buttons_press: "; - print_buttons( buttons ); + globalOutputStream() << "Buttons_press: "; + print_buttons( buttons ); #endif - return false; -} - -bool Buttons_release( ButtonMask& buttons, guint button, guint state ){ - if ( buttons != 0 && bitfield_disable( buttons, ButtonMask_for_event_button( button ) ) == 0 ) { - ASSERT_MESSAGE( !g_accel_enabled, "Buttons_release: accelerators are enabled" ); - g_accel_enabled = true; - for ( WindowSet::iterator i = g_accel_windows.begin(); i != g_accel_windows.end(); ++i ) - { - ui::Window toplevel = *i; - ASSERT_MESSAGE( !window_has_accel( toplevel ), "ERROR" ); - ASSERT_MESSAGE( gtk_widget_is_toplevel( toplevel ), "enabling accel for non-toplevel window" ); - toplevel.add_accel_group( global_accel ); + return false; +} + +bool Buttons_release(ButtonMask &buttons, guint button, guint state) +{ + if (buttons != 0 && bitfield_disable(buttons, ButtonMask_for_event_button(button)) == 0) { + ASSERT_MESSAGE(!g_accel_enabled, "Buttons_release: accelerators are enabled"); + g_accel_enabled = true; + for (WindowSet::iterator i = g_accel_windows.begin(); i != g_accel_windows.end(); ++i) { + ui::Window toplevel = *i; + ASSERT_MESSAGE(!window_has_accel(toplevel), "ERROR"); + ASSERT_MESSAGE(gtk_widget_is_toplevel(toplevel), "enabling accel for non-toplevel window"); + toplevel.add_accel_group(global_accel); #if 0 - globalOutputStream() << reinterpret_cast( toplevel ) << ": enabled global accelerators\n"; + globalOutputStream() << reinterpret_cast( toplevel ) << ": enabled global accelerators\n"; #endif - } - globalQueuedAccelerators_commit(); - } - buttons = bitfield_disable( buttons, ButtonMask_for_event_button( button ) ); + } + globalQueuedAccelerators_commit(); + } + buttons = bitfield_disable(buttons, ButtonMask_for_event_button(button)); #if 0 - globalOutputStream() << "Buttons_release: "; - print_buttons( buttons ); + globalOutputStream() << "Buttons_release: "; + print_buttons( buttons ); #endif - return false; + return false; } -bool Buttons_releaseAll( ButtonMask& buttons ){ - Buttons_release( buttons, MouseButton::Left | MouseButton::Middle | MouseButton::Right, 0 ); - return false; +bool Buttons_releaseAll(ButtonMask &buttons) +{ + Buttons_release(buttons, MouseButton::Left | MouseButton::Middle | MouseButton::Right, 0); + return false; } -struct PressedButtons -{ - ButtonMask buttons; +struct PressedButtons { + ButtonMask buttons; - PressedButtons() : buttons( 0 ){ - } + PressedButtons() : buttons(0) + { + } }; -gboolean PressedButtons_button_press(ui::Widget widget, GdkEventButton* event, PressedButtons* pressed ){ - if ( event->type == GDK_BUTTON_PRESS ) { - return Buttons_press( pressed->buttons, event->button, event->state ); - } - return FALSE; +gboolean PressedButtons_button_press(ui::Widget widget, GdkEventButton *event, PressedButtons *pressed) +{ + if (event->type == GDK_BUTTON_PRESS) { + return Buttons_press(pressed->buttons, event->button, event->state); + } + return FALSE; } -gboolean PressedButtons_button_release(ui::Widget widget, GdkEventButton* event, PressedButtons* pressed ){ - if ( event->type == GDK_BUTTON_RELEASE ) { - return Buttons_release( pressed->buttons, event->button, event->state ); - } - return FALSE; +gboolean PressedButtons_button_release(ui::Widget widget, GdkEventButton *event, PressedButtons *pressed) +{ + if (event->type == GDK_BUTTON_RELEASE) { + return Buttons_release(pressed->buttons, event->button, event->state); + } + return FALSE; } -gboolean PressedButtons_focus_out(ui::Widget widget, GdkEventFocus* event, PressedButtons* pressed ){ - Buttons_releaseAll( pressed->buttons ); - return FALSE; +gboolean PressedButtons_focus_out(ui::Widget widget, GdkEventFocus *event, PressedButtons *pressed) +{ + Buttons_releaseAll(pressed->buttons); + return FALSE; } -void PressedButtons_connect( PressedButtons& pressedButtons, ui::Widget widget ){ - widget.connect( "button_press_event", G_CALLBACK( PressedButtons_button_press ), &pressedButtons ); - widget.connect( "button_release_event", G_CALLBACK( PressedButtons_button_release ), &pressedButtons ); - widget.connect( "focus_out_event", G_CALLBACK( PressedButtons_focus_out ), &pressedButtons ); +void PressedButtons_connect(PressedButtons &pressedButtons, ui::Widget widget) +{ + widget.connect("button_press_event", G_CALLBACK(PressedButtons_button_press), &pressedButtons); + widget.connect("button_release_event", G_CALLBACK(PressedButtons_button_release), &pressedButtons); + widget.connect("focus_out_event", G_CALLBACK(PressedButtons_focus_out), &pressedButtons); } PressedButtons g_pressedButtons; @@ -315,241 +331,279 @@ PressedButtons g_pressedButtons; #include #include -struct PressedKeys -{ - typedef std::set Keys; - Keys keys; - std::size_t refcount; +struct PressedKeys { + typedef std::set Keys; + Keys keys; + std::size_t refcount; - PressedKeys() : refcount( 0 ){ - } + PressedKeys() : refcount(0) + { + } }; AcceleratorMap g_keydown_accelerators; AcceleratorMap g_keyup_accelerators; -bool Keys_press( PressedKeys::Keys& keys, guint keyval ){ - if ( keys.insert( keyval ).second ) { - return AcceleratorMap_activate( g_keydown_accelerators, accelerator_for_event_key( keyval, 0 ) ); - } - return g_keydown_accelerators.find( accelerator_for_event_key( keyval, 0 ) ) != g_keydown_accelerators.end(); +bool Keys_press(PressedKeys::Keys &keys, guint keyval) +{ + if (keys.insert(keyval).second) { + return AcceleratorMap_activate(g_keydown_accelerators, accelerator_for_event_key(keyval, 0)); + } + return g_keydown_accelerators.find(accelerator_for_event_key(keyval, 0)) != g_keydown_accelerators.end(); } -bool Keys_release( PressedKeys::Keys& keys, guint keyval ){ - if ( keys.erase( keyval ) != 0 ) { - return AcceleratorMap_activate( g_keyup_accelerators, accelerator_for_event_key( keyval, 0 ) ); - } - return g_keyup_accelerators.find( accelerator_for_event_key( keyval, 0 ) ) != g_keyup_accelerators.end(); +bool Keys_release(PressedKeys::Keys &keys, guint keyval) +{ + if (keys.erase(keyval) != 0) { + return AcceleratorMap_activate(g_keyup_accelerators, accelerator_for_event_key(keyval, 0)); + } + return g_keyup_accelerators.find(accelerator_for_event_key(keyval, 0)) != g_keyup_accelerators.end(); } -void Keys_releaseAll( PressedKeys::Keys& keys, guint state ){ - for ( PressedKeys::Keys::iterator i = keys.begin(); i != keys.end(); ++i ) - { - AcceleratorMap_activate( g_keyup_accelerators, accelerator_for_event_key( *i, state ) ); - } - keys.clear(); +void Keys_releaseAll(PressedKeys::Keys &keys, guint state) +{ + for (PressedKeys::Keys::iterator i = keys.begin(); i != keys.end(); ++i) { + AcceleratorMap_activate(g_keyup_accelerators, accelerator_for_event_key(*i, state)); + } + keys.clear(); } -gboolean PressedKeys_key_press(ui::Widget widget, GdkEventKey* event, PressedKeys* pressedKeys ){ - //globalOutputStream() << "pressed: " << event->keyval << "\n"; - return event->state == 0 && Keys_press( pressedKeys->keys, event->keyval ); +gboolean PressedKeys_key_press(ui::Widget widget, GdkEventKey *event, PressedKeys *pressedKeys) +{ + //globalOutputStream() << "pressed: " << event->keyval << "\n"; + return event->state == 0 && Keys_press(pressedKeys->keys, event->keyval); } -gboolean PressedKeys_key_release(ui::Widget widget, GdkEventKey* event, PressedKeys* pressedKeys ){ - //globalOutputStream() << "released: " << event->keyval << "\n"; - return Keys_release( pressedKeys->keys, event->keyval ); +gboolean PressedKeys_key_release(ui::Widget widget, GdkEventKey *event, PressedKeys *pressedKeys) +{ + //globalOutputStream() << "released: " << event->keyval << "\n"; + return Keys_release(pressedKeys->keys, event->keyval); } -gboolean PressedKeys_focus_in(ui::Widget widget, GdkEventFocus* event, PressedKeys* pressedKeys ){ - ++pressedKeys->refcount; - return FALSE; +gboolean PressedKeys_focus_in(ui::Widget widget, GdkEventFocus *event, PressedKeys *pressedKeys) +{ + ++pressedKeys->refcount; + return FALSE; } -gboolean PressedKeys_focus_out(ui::Widget widget, GdkEventFocus* event, PressedKeys* pressedKeys ){ - if ( --pressedKeys->refcount == 0 ) { - Keys_releaseAll( pressedKeys->keys, 0 ); - } - return FALSE; +gboolean PressedKeys_focus_out(ui::Widget widget, GdkEventFocus *event, PressedKeys *pressedKeys) +{ + if (--pressedKeys->refcount == 0) { + Keys_releaseAll(pressedKeys->keys, 0); + } + return FALSE; } PressedKeys g_pressedKeys; -void GlobalPressedKeys_releaseAll(){ - Keys_releaseAll( g_pressedKeys.keys, 0 ); -} - -void GlobalPressedKeys_connect( ui::Window window ){ - unsigned int key_press_handler = window.connect( "key_press_event", G_CALLBACK( PressedKeys_key_press ), &g_pressedKeys ); - unsigned int key_release_handler = window.connect( "key_release_event", G_CALLBACK( PressedKeys_key_release ), &g_pressedKeys ); - g_object_set_data( G_OBJECT( window ), "key_press_handler", gint_to_pointer( key_press_handler ) ); - g_object_set_data( G_OBJECT( window ), "key_release_handler", gint_to_pointer( key_release_handler ) ); - unsigned int focus_in_handler = window.connect( "focus_in_event", G_CALLBACK( PressedKeys_focus_in ), &g_pressedKeys ); - unsigned int focus_out_handler = window.connect( "focus_out_event", G_CALLBACK( PressedKeys_focus_out ), &g_pressedKeys ); - g_object_set_data( G_OBJECT( window ), "focus_in_handler", gint_to_pointer( focus_in_handler ) ); - g_object_set_data( G_OBJECT( window ), "focus_out_handler", gint_to_pointer( focus_out_handler ) ); +void GlobalPressedKeys_releaseAll() +{ + Keys_releaseAll(g_pressedKeys.keys, 0); } -void GlobalPressedKeys_disconnect( ui::Window window ){ - g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "key_press_handler" ) ) ); - g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "key_release_handler" ) ) ); - g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "focus_in_handler" ) ) ); - g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "focus_out_handler" ) ) ); +void GlobalPressedKeys_connect(ui::Window window) +{ + unsigned int key_press_handler = window.connect("key_press_event", G_CALLBACK(PressedKeys_key_press), + &g_pressedKeys); + unsigned int key_release_handler = window.connect("key_release_event", G_CALLBACK(PressedKeys_key_release), + &g_pressedKeys); + g_object_set_data(G_OBJECT(window), "key_press_handler", gint_to_pointer(key_press_handler)); + g_object_set_data(G_OBJECT(window), "key_release_handler", gint_to_pointer(key_release_handler)); + unsigned int focus_in_handler = window.connect("focus_in_event", G_CALLBACK(PressedKeys_focus_in), &g_pressedKeys); + unsigned int focus_out_handler = window.connect("focus_out_event", G_CALLBACK(PressedKeys_focus_out), + &g_pressedKeys); + g_object_set_data(G_OBJECT(window), "focus_in_handler", gint_to_pointer(focus_in_handler)); + g_object_set_data(G_OBJECT(window), "focus_out_handler", gint_to_pointer(focus_out_handler)); +} + +void GlobalPressedKeys_disconnect(ui::Window window) +{ + g_signal_handler_disconnect(G_OBJECT(window), + gpointer_to_int(g_object_get_data(G_OBJECT(window), "key_press_handler"))); + g_signal_handler_disconnect(G_OBJECT(window), + gpointer_to_int(g_object_get_data(G_OBJECT(window), "key_release_handler"))); + g_signal_handler_disconnect(G_OBJECT(window), + gpointer_to_int(g_object_get_data(G_OBJECT(window), "focus_in_handler"))); + g_signal_handler_disconnect(G_OBJECT(window), + gpointer_to_int(g_object_get_data(G_OBJECT(window), "focus_out_handler"))); } - -void special_accelerators_add( Accelerator accelerator, const Callback& callback ){ - //globalOutputStream() << "special_accelerators_add: " << makeQuoted(accelerator) << "\n"; - if ( !accelerator_map_insert( g_special_accelerators, accelerator, callback ) ) { - globalErrorStream() << "special_accelerators_add: already exists: " << makeQuoted( accelerator ) << "\n"; - } -} -void special_accelerators_remove( Accelerator accelerator ){ - //globalOutputStream() << "special_accelerators_remove: " << makeQuoted(accelerator) << "\n"; - if ( !accelerator_map_erase( g_special_accelerators, accelerator ) ) { - globalErrorStream() << "special_accelerators_remove: not found: " << makeQuoted( accelerator ) << "\n"; - } +void special_accelerators_add(Accelerator accelerator, const Callback &callback) +{ + //globalOutputStream() << "special_accelerators_add: " << makeQuoted(accelerator) << "\n"; + if (!accelerator_map_insert(g_special_accelerators, accelerator, callback)) { + globalErrorStream() << "special_accelerators_add: already exists: " << makeQuoted(accelerator) << "\n"; + } } -void keydown_accelerators_add( Accelerator accelerator, const Callback& callback ){ - //globalOutputStream() << "keydown_accelerators_add: " << makeQuoted(accelerator) << "\n"; - if ( !accelerator_map_insert( g_keydown_accelerators, accelerator, callback ) ) { - globalErrorStream() << "keydown_accelerators_add: already exists: " << makeQuoted( accelerator ) << "\n"; - } -} -void keydown_accelerators_remove( Accelerator accelerator ){ - //globalOutputStream() << "keydown_accelerators_remove: " << makeQuoted(accelerator) << "\n"; - if ( !accelerator_map_erase( g_keydown_accelerators, accelerator ) ) { - globalErrorStream() << "keydown_accelerators_remove: not found: " << makeQuoted( accelerator ) << "\n"; - } +void special_accelerators_remove(Accelerator accelerator) +{ + //globalOutputStream() << "special_accelerators_remove: " << makeQuoted(accelerator) << "\n"; + if (!accelerator_map_erase(g_special_accelerators, accelerator)) { + globalErrorStream() << "special_accelerators_remove: not found: " << makeQuoted(accelerator) << "\n"; + } } -void keyup_accelerators_add( Accelerator accelerator, const Callback& callback ){ - //globalOutputStream() << "keyup_accelerators_add: " << makeQuoted(accelerator) << "\n"; - if ( !accelerator_map_insert( g_keyup_accelerators, accelerator, callback ) ) { - globalErrorStream() << "keyup_accelerators_add: already exists: " << makeQuoted( accelerator ) << "\n"; - } +void keydown_accelerators_add(Accelerator accelerator, const Callback &callback) +{ + //globalOutputStream() << "keydown_accelerators_add: " << makeQuoted(accelerator) << "\n"; + if (!accelerator_map_insert(g_keydown_accelerators, accelerator, callback)) { + globalErrorStream() << "keydown_accelerators_add: already exists: " << makeQuoted(accelerator) << "\n"; + } } -void keyup_accelerators_remove( Accelerator accelerator ){ - //globalOutputStream() << "keyup_accelerators_remove: " << makeQuoted(accelerator) << "\n"; - if ( !accelerator_map_erase( g_keyup_accelerators, accelerator ) ) { - globalErrorStream() << "keyup_accelerators_remove: not found: " << makeQuoted( accelerator ) << "\n"; - } + +void keydown_accelerators_remove(Accelerator accelerator) +{ + //globalOutputStream() << "keydown_accelerators_remove: " << makeQuoted(accelerator) << "\n"; + if (!accelerator_map_erase(g_keydown_accelerators, accelerator)) { + globalErrorStream() << "keydown_accelerators_remove: not found: " << makeQuoted(accelerator) << "\n"; + } } +void keyup_accelerators_add(Accelerator accelerator, const Callback &callback) +{ + //globalOutputStream() << "keyup_accelerators_add: " << makeQuoted(accelerator) << "\n"; + if (!accelerator_map_insert(g_keyup_accelerators, accelerator, callback)) { + globalErrorStream() << "keyup_accelerators_add: already exists: " << makeQuoted(accelerator) << "\n"; + } +} -gboolean accel_closure_callback(ui::AccelGroup group, ui::Widget widget, guint key, GdkModifierType modifiers, gpointer data ){ - ( *reinterpret_cast*>( data ) )( ); - return TRUE; +void keyup_accelerators_remove(Accelerator accelerator) +{ + //globalOutputStream() << "keyup_accelerators_remove: " << makeQuoted(accelerator) << "\n"; + if (!accelerator_map_erase(g_keyup_accelerators, accelerator)) { + globalErrorStream() << "keyup_accelerators_remove: not found: " << makeQuoted(accelerator) << "\n"; + } } -GClosure* accel_group_add_accelerator(ui::AccelGroup group, Accelerator accelerator, const Callback& callback ){ - if ( accelerator.key != 0 && gtk_accelerator_valid( accelerator.key, accelerator.modifiers ) ) { - //globalOutputStream() << "global_accel_connect: " << makeQuoted(accelerator) << "\n"; - GClosure* closure = create_cclosure( G_CALLBACK( accel_closure_callback ), callback ); - gtk_accel_group_connect( group, accelerator.key, accelerator.modifiers, GTK_ACCEL_VISIBLE, closure ); - return closure; - } - else - { - special_accelerators_add( accelerator, callback ); - return 0; - } + +gboolean +accel_closure_callback(ui::AccelGroup group, ui::Widget widget, guint key, GdkModifierType modifiers, gpointer data) +{ + (*reinterpret_cast *>( data ))(); + return TRUE; } -void accel_group_remove_accelerator(ui::AccelGroup group, Accelerator accelerator ){ - if ( accelerator.key != 0 && gtk_accelerator_valid( accelerator.key, accelerator.modifiers ) ) { - //globalOutputStream() << "global_accel_disconnect: " << makeQuoted(accelerator) << "\n"; - gtk_accel_group_disconnect_key( group, accelerator.key, accelerator.modifiers ); - } - else - { - special_accelerators_remove( accelerator ); - } +GClosure *accel_group_add_accelerator(ui::AccelGroup group, Accelerator accelerator, const Callback &callback) +{ + if (accelerator.key != 0 && gtk_accelerator_valid(accelerator.key, accelerator.modifiers)) { + //globalOutputStream() << "global_accel_connect: " << makeQuoted(accelerator) << "\n"; + GClosure *closure = create_cclosure(G_CALLBACK(accel_closure_callback), callback); + gtk_accel_group_connect(group, accelerator.key, accelerator.modifiers, GTK_ACCEL_VISIBLE, closure); + return closure; + } else { + special_accelerators_add(accelerator, callback); + return 0; + } +} + +void accel_group_remove_accelerator(ui::AccelGroup group, Accelerator accelerator) +{ + if (accelerator.key != 0 && gtk_accelerator_valid(accelerator.key, accelerator.modifiers)) { + //globalOutputStream() << "global_accel_disconnect: " << makeQuoted(accelerator) << "\n"; + gtk_accel_group_disconnect_key(group, accelerator.key, accelerator.modifiers); + } else { + special_accelerators_remove(accelerator); + } } ui::AccelGroup global_accel{ui::New}; -GClosure* global_accel_group_add_accelerator( Accelerator accelerator, const Callback& callback ){ - if ( !global_accel_enabled() ) { - // workaround: cannot add to GtkAccelGroup while it is disabled - //globalOutputStream() << "queued for add: " << accelerator << "\n"; - globalQueuedAccelerators_add( accelerator, callback ); - return 0; - } - return accel_group_add_accelerator( global_accel, accelerator, callback ); +GClosure *global_accel_group_add_accelerator(Accelerator accelerator, const Callback &callback) +{ + if (!global_accel_enabled()) { + // workaround: cannot add to GtkAccelGroup while it is disabled + //globalOutputStream() << "queued for add: " << accelerator << "\n"; + globalQueuedAccelerators_add(accelerator, callback); + return 0; + } + return accel_group_add_accelerator(global_accel, accelerator, callback); } -void global_accel_group_remove_accelerator( Accelerator accelerator ){ - if ( !global_accel_enabled() ) { - //globalOutputStream() << "queued for remove: " << accelerator << "\n"; - globalQueuedAccelerators_remove( accelerator ); - return; - } - accel_group_remove_accelerator( global_accel, accelerator ); + +void global_accel_group_remove_accelerator(Accelerator accelerator) +{ + if (!global_accel_enabled()) { + //globalOutputStream() << "queued for remove: " << accelerator << "\n"; + globalQueuedAccelerators_remove(accelerator); + return; + } + accel_group_remove_accelerator(global_accel, accelerator); } /// \brief Propagates key events to the focus-widget, overriding global accelerators. -static gboolean override_global_accelerators( ui::Window window, GdkEventKey* event, gpointer data ){ - gboolean b = gtk_window_propagate_key_event( window, event ); - return b; +static gboolean override_global_accelerators(ui::Window window, GdkEventKey *event, gpointer data) +{ + gboolean b = gtk_window_propagate_key_event(window, event); + return b; } -void global_accel_connect_window( ui::Window window ){ +void global_accel_connect_window(ui::Window window) +{ #if 1 - unsigned int override_handler = window.connect( "key_press_event", G_CALLBACK( override_global_accelerators ), 0 ); - g_object_set_data( G_OBJECT( window ), "override_handler", gint_to_pointer( override_handler ) ); + unsigned int override_handler = window.connect("key_press_event", G_CALLBACK(override_global_accelerators), 0); + g_object_set_data(G_OBJECT(window), "override_handler", gint_to_pointer(override_handler)); - unsigned int special_key_press_handler = window.connect( "key_press_event", G_CALLBACK( accelerator_key_event ), &g_special_accelerators ); - g_object_set_data( G_OBJECT( window ), "special_key_press_handler", gint_to_pointer( special_key_press_handler ) ); + unsigned int special_key_press_handler = window.connect("key_press_event", G_CALLBACK(accelerator_key_event), + &g_special_accelerators); + g_object_set_data(G_OBJECT(window), "special_key_press_handler", gint_to_pointer(special_key_press_handler)); - GlobalPressedKeys_connect( window ); + GlobalPressedKeys_connect(window); #else - unsigned int key_press_handler = window.connect( "key_press_event", G_CALLBACK( accelerator_key_event ), &g_keydown_accelerators ); - unsigned int key_release_handler = window.connect( "key_release_event", G_CALLBACK( accelerator_key_event ), &g_keyup_accelerators ); - g_object_set_data( G_OBJECT( window ), "key_press_handler", gint_to_pointer( key_press_handler ) ); - g_object_set_data( G_OBJECT( window ), "key_release_handler", gint_to_pointer( key_release_handler ) ); + unsigned int key_press_handler = window.connect( "key_press_event", G_CALLBACK( accelerator_key_event ), &g_keydown_accelerators ); + unsigned int key_release_handler = window.connect( "key_release_event", G_CALLBACK( accelerator_key_event ), &g_keyup_accelerators ); + g_object_set_data( G_OBJECT( window ), "key_press_handler", gint_to_pointer( key_press_handler ) ); + g_object_set_data( G_OBJECT( window ), "key_release_handler", gint_to_pointer( key_release_handler ) ); #endif - g_accel_windows.insert( window ); - window.add_accel_group( global_accel ); + g_accel_windows.insert(window); + window.add_accel_group(global_accel); } -void global_accel_disconnect_window( ui::Window window ){ + +void global_accel_disconnect_window(ui::Window window) +{ #if 1 - GlobalPressedKeys_disconnect( window ); + GlobalPressedKeys_disconnect(window); - g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "override_handler" ) ) ); - g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "special_key_press_handler" ) ) ); + g_signal_handler_disconnect(G_OBJECT(window), + gpointer_to_int(g_object_get_data(G_OBJECT(window), "override_handler"))); + g_signal_handler_disconnect(G_OBJECT(window), + gpointer_to_int(g_object_get_data(G_OBJECT(window), "special_key_press_handler"))); #else - g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "key_press_handler" ) ) ); - g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "key_release_handler" ) ) ); + g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "key_press_handler" ) ) ); + g_signal_handler_disconnect( G_OBJECT( window ), gpointer_to_int( g_object_get_data( G_OBJECT( window ), "key_release_handler" ) ) ); #endif - gtk_window_remove_accel_group( window, global_accel ); - std::size_t count = g_accel_windows.erase( window ); - ASSERT_MESSAGE( count == 1, "failed to remove accel group\n" ); + gtk_window_remove_accel_group(window, global_accel); + std::size_t count = g_accel_windows.erase(window); + ASSERT_MESSAGE(count == 1, "failed to remove accel group\n"); } -GClosure* global_accel_group_find( Accelerator accelerator ){ - guint numEntries = 0; - GtkAccelGroupEntry* entry = gtk_accel_group_query( global_accel, accelerator.key, accelerator.modifiers, &numEntries ); - if ( numEntries != 0 ) { - if ( numEntries != 1 ) { - char* name = gtk_accelerator_name( accelerator.key, accelerator.modifiers ); - globalErrorStream() << "accelerator already in-use: " << name << "\n"; - g_free( name ); - } - return entry->closure; - } - return 0; -} - -void global_accel_group_connect( const Accelerator& accelerator, const Callback& callback ){ - if ( accelerator.key != 0 ) { - global_accel_group_add_accelerator( accelerator, callback ); - } +GClosure *global_accel_group_find(Accelerator accelerator) +{ + guint numEntries = 0; + GtkAccelGroupEntry *entry = gtk_accel_group_query(global_accel, accelerator.key, accelerator.modifiers, + &numEntries); + if (numEntries != 0) { + if (numEntries != 1) { + char *name = gtk_accelerator_name(accelerator.key, accelerator.modifiers); + globalErrorStream() << "accelerator already in-use: " << name << "\n"; + g_free(name); + } + return entry->closure; + } + return 0; +} + +void global_accel_group_connect(const Accelerator &accelerator, const Callback &callback) +{ + if (accelerator.key != 0) { + global_accel_group_add_accelerator(accelerator, callback); + } } -void global_accel_group_disconnect( const Accelerator& accelerator, const Callback& callback ){ - if ( accelerator.key != 0 ) { - global_accel_group_remove_accelerator( accelerator ); - } +void global_accel_group_disconnect(const Accelerator &accelerator, const Callback &callback) +{ + if (accelerator.key != 0) { + global_accel_group_remove_accelerator(accelerator); + } } diff --git a/libs/gtkutil/accelerator.h b/libs/gtkutil/accelerator.h index 528dd6bb..7228603b 100644 --- a/libs/gtkutil/accelerator.h +++ b/libs/gtkutil/accelerator.h @@ -31,106 +31,133 @@ // ignore numlock #define ALLOWED_MODIFIERS ( ~( GDK_MOD2_MASK | GDK_LOCK_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK ) ) -struct Accelerator -{ - Accelerator( guint _key ) - : key( gdk_keyval_to_upper( _key ) ), modifiers( ( GdkModifierType ) 0 ){ - } - Accelerator( guint _key, GdkModifierType _modifiers ) - : key( gdk_keyval_to_upper( _key ) ), modifiers( ( GdkModifierType )( _modifiers & ALLOWED_MODIFIERS ) ){ - } - Accelerator( const Accelerator &src ) - : key( gdk_keyval_to_upper( src.key ) ), modifiers( ( GdkModifierType )( src.modifiers & ALLOWED_MODIFIERS ) ){ - } - bool operator<( const Accelerator& other ) const { - guint k1 = key; - guint k2 = other.key; - int mod1 = modifiers & ALLOWED_MODIFIERS; - int mod2 = other.modifiers & ALLOWED_MODIFIERS; - return k1 < k2 || ( !( k2 < k1 ) && mod1 < mod2 ); - } - bool operator==( const Accelerator& other ) const { - guint k1 = key; - guint k2 = other.key; - int mod1 = modifiers & ALLOWED_MODIFIERS; - int mod2 = other.modifiers & ALLOWED_MODIFIERS; - return k1 == k2 && mod1 == mod2; - } - Accelerator &operator=( const Accelerator& other ){ - key = other.key; - modifiers = (GdkModifierType) ( other.modifiers & ALLOWED_MODIFIERS ); - return *this; - } - guint key; - GdkModifierType modifiers; +struct Accelerator { + Accelerator(guint _key) + : key(gdk_keyval_to_upper(_key)), modifiers((GdkModifierType) 0) + { + } + + Accelerator(guint _key, GdkModifierType _modifiers) + : key(gdk_keyval_to_upper(_key)), modifiers((GdkModifierType) (_modifiers & ALLOWED_MODIFIERS)) + { + } + + Accelerator(const Accelerator &src) + : key(gdk_keyval_to_upper(src.key)), modifiers((GdkModifierType) (src.modifiers & ALLOWED_MODIFIERS)) + { + } + + bool operator<(const Accelerator &other) const + { + guint k1 = key; + guint k2 = other.key; + int mod1 = modifiers & ALLOWED_MODIFIERS; + int mod2 = other.modifiers & ALLOWED_MODIFIERS; + return k1 < k2 || (!(k2 < k1) && mod1 < mod2); + } + + bool operator==(const Accelerator &other) const + { + guint k1 = key; + guint k2 = other.key; + int mod1 = modifiers & ALLOWED_MODIFIERS; + int mod2 = other.modifiers & ALLOWED_MODIFIERS; + return k1 == k2 && mod1 == mod2; + } + + Accelerator &operator=(const Accelerator &other) + { + key = other.key; + modifiers = (GdkModifierType) (other.modifiers & ALLOWED_MODIFIERS); + return *this; + } + + guint key; + GdkModifierType modifiers; }; -inline Accelerator accelerator_null(){ - return Accelerator( 0, (GdkModifierType)0 ); +inline Accelerator accelerator_null() +{ + return Accelerator(0, (GdkModifierType) 0); } -const char* global_keys_find( unsigned int key ); -unsigned int global_keys_find( const char* name ); +const char *global_keys_find(unsigned int key); + +unsigned int global_keys_find(const char *name); class TextOutputStream; -void accelerator_write( const Accelerator& accelerator, TextOutputStream& ostream ); + +void accelerator_write(const Accelerator &accelerator, TextOutputStream &ostream); template -TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const Accelerator& accelerator ){ - accelerator_write( accelerator, ostream ); - return ostream; +TextOutputStreamType &ostream_write(TextOutputStreamType &ostream, const Accelerator &accelerator) +{ + accelerator_write(accelerator, ostream); + return ostream; } -void keydown_accelerators_add( Accelerator accelerator, const Callback& callback ); -void keydown_accelerators_remove( Accelerator accelerator ); -void keyup_accelerators_add( Accelerator accelerator, const Callback& callback ); -void keyup_accelerators_remove( Accelerator accelerator ); +void keydown_accelerators_add(Accelerator accelerator, const Callback &callback); -void global_accel_connect_window( ui::Window window ); -void global_accel_disconnect_window( ui::Window window ); +void keydown_accelerators_remove(Accelerator accelerator); + +void keyup_accelerators_add(Accelerator accelerator, const Callback &callback); + +void keyup_accelerators_remove(Accelerator accelerator); + +void global_accel_connect_window(ui::Window window); + +void global_accel_disconnect_window(ui::Window window); void GlobalPressedKeys_releaseAll(); extern ui::AccelGroup global_accel; -GClosure* global_accel_group_find( Accelerator accelerator ); +GClosure *global_accel_group_find(Accelerator accelerator); -void global_accel_group_connect( const Accelerator& accelerator, const Callback& callback ); -void global_accel_group_disconnect( const Accelerator& accelerator, const Callback& callback ); +void global_accel_group_connect(const Accelerator &accelerator, const Callback &callback); +void global_accel_group_disconnect(const Accelerator &accelerator, const Callback &callback); -class Command -{ + +class Command { public: -Callback m_callback; -const Accelerator& m_accelerator; -Command( const Callback& callback, const Accelerator& accelerator ) : m_callback( callback ), m_accelerator( accelerator ){ -} + Callback m_callback; + const Accelerator &m_accelerator; + + Command(const Callback &callback, const Accelerator &accelerator) : m_callback(callback), + m_accelerator(accelerator) + { + } }; -class Toggle -{ +class Toggle { public: -Command m_command; -Callback &)> m_exportCallback; -Toggle( const Callback& callback, const Accelerator& accelerator, const Callback &)>& exportCallback ) : m_command( callback, accelerator ), m_exportCallback( exportCallback ){ -} + Command m_command; + Callback &)> m_exportCallback; + + Toggle(const Callback &callback, const Accelerator &accelerator, + const Callback &)> &exportCallback) : m_command(callback, accelerator), + m_exportCallback(exportCallback) + { + } }; -class KeyEvent -{ +class KeyEvent { public: -const Accelerator& m_accelerator; -Callback m_keyDown; -Callback m_keyUp; -KeyEvent( const Accelerator& accelerator, const Callback& keyDown, const Callback& keyUp ) : m_accelerator( accelerator ), m_keyDown( keyDown ), m_keyUp( keyUp ){ -} + const Accelerator &m_accelerator; + Callback m_keyDown; + Callback m_keyUp; + + KeyEvent(const Accelerator &accelerator, const Callback &keyDown, const Callback &keyUp) + : m_accelerator(accelerator), m_keyDown(keyDown), m_keyUp(keyUp) + { + } }; - struct PressedButtons; -void PressedButtons_connect( PressedButtons& pressedButtons, ui::Widget widget ); + +void PressedButtons_connect(PressedButtons &pressedButtons, ui::Widget widget); extern PressedButtons g_pressedButtons; diff --git a/libs/gtkutil/button.cpp b/libs/gtkutil/button.cpp index 9f40f9e9..2a74c4ba 100644 --- a/libs/gtkutil/button.cpp +++ b/libs/gtkutil/button.cpp @@ -30,121 +30,131 @@ #include "image.h" #include "pointer.h" -void clicked_closure_callback( ui::Widget widget, gpointer data ){ - ( *reinterpret_cast*>( data ) )( ); +void clicked_closure_callback(ui::Widget widget, gpointer data) +{ + (*reinterpret_cast *>( data ))(); } -void button_connect_callback( ui::Button button, const Callback& callback ){ +void button_connect_callback(ui::Button button, const Callback &callback) +{ #if 1 - g_signal_connect_swapped( G_OBJECT( button ), "clicked", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() ); + g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(callback.getThunk()), callback.getEnvironment()); #else - g_signal_connect_closure( G_OBJECT( button ), "clicked", create_cclosure( G_CALLBACK( clicked_closure_callback ), callback ), FALSE ); + g_signal_connect_closure( G_OBJECT( button ), "clicked", create_cclosure( G_CALLBACK( clicked_closure_callback ), callback ), FALSE ); #endif } -void button_connect_callback( ui::ToolButton button, const Callback& callback ){ +void button_connect_callback(ui::ToolButton button, const Callback &callback) +{ #if 1 - g_signal_connect_swapped( G_OBJECT( button ), "clicked", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() ); + g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(callback.getThunk()), callback.getEnvironment()); #else - g_signal_connect_closure( G_OBJECT( button ), "clicked", create_cclosure( G_CALLBACK( clicked_closure_callback ), callback ), FALSE ); + g_signal_connect_closure( G_OBJECT( button ), "clicked", create_cclosure( G_CALLBACK( clicked_closure_callback ), callback ), FALSE ); #endif } -guint toggle_button_connect_callback( ui::ToggleButton button, const Callback& callback ){ +guint toggle_button_connect_callback(ui::ToggleButton button, const Callback &callback) +{ #if 1 - guint handler = g_signal_connect_swapped( G_OBJECT( button ), "toggled", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() ); + guint handler = g_signal_connect_swapped(G_OBJECT(button), "toggled", G_CALLBACK(callback.getThunk()), + callback.getEnvironment()); #else - guint handler = g_signal_connect_closure( G_OBJECT( button ), "toggled", create_cclosure( G_CALLBACK( clicked_closure_callback ), callback ), TRUE ); + guint handler = g_signal_connect_closure( G_OBJECT( button ), "toggled", create_cclosure( G_CALLBACK( clicked_closure_callback ), callback ), TRUE ); #endif - g_object_set_data( G_OBJECT( button ), "handler", gint_to_pointer( handler ) ); - return handler; + g_object_set_data(G_OBJECT(button), "handler", gint_to_pointer(handler)); + return handler; } -guint toggle_button_connect_callback( ui::ToggleToolButton button, const Callback& callback ){ +guint toggle_button_connect_callback(ui::ToggleToolButton button, const Callback &callback) +{ #if 1 - guint handler = g_signal_connect_swapped( G_OBJECT( button ), "toggled", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() ); + guint handler = g_signal_connect_swapped(G_OBJECT(button), "toggled", G_CALLBACK(callback.getThunk()), + callback.getEnvironment()); #else - guint handler = g_signal_connect_closure( G_OBJECT( button ), "toggled", create_cclosure( G_CALLBACK( clicked_closure_callback ), callback ), TRUE ); + guint handler = g_signal_connect_closure( G_OBJECT( button ), "toggled", create_cclosure( G_CALLBACK( clicked_closure_callback ), callback ), TRUE ); #endif - g_object_set_data( G_OBJECT( button ), "handler", gint_to_pointer( handler ) ); - return handler; + g_object_set_data(G_OBJECT(button), "handler", gint_to_pointer(handler)); + return handler; } -void button_set_icon( ui::Button button, const char* icon ){ - ui::Image image = ui::Image(new_local_image( icon )); - image.show(); - button.add(image); +void button_set_icon(ui::Button button, const char *icon) +{ + ui::Image image = ui::Image(new_local_image(icon)); + image.show(); + button.add(image); } -void toggle_button_set_active_no_signal( ui::ToggleButton button, gboolean active ){ - //globalOutputStream() << "set active: " << active << "\n"; - guint handler_id = gpointer_to_int( g_object_get_data( G_OBJECT( button ), "handler" ) ); - //guint signal_id = g_signal_lookup("toggled", G_OBJECT_TYPE (button)); - //globalOutputStream() << "signal_id: " << signal_id << "\n"; - //guint found = g_signal_handler_find(G_OBJECT(button), G_SIGNAL_MATCH_ID, signal_id, 0, 0, 0, 0); - //globalOutputStream() << " handler found: " << found << "\n"; - g_signal_handler_block( G_OBJECT( button ), handler_id ); - gtk_toggle_button_set_active( button, active ); - g_signal_handler_unblock( G_OBJECT( button ), handler_id ); +void toggle_button_set_active_no_signal(ui::ToggleButton button, gboolean active) +{ + //globalOutputStream() << "set active: " << active << "\n"; + guint handler_id = gpointer_to_int(g_object_get_data(G_OBJECT(button), "handler")); + //guint signal_id = g_signal_lookup("toggled", G_OBJECT_TYPE (button)); + //globalOutputStream() << "signal_id: " << signal_id << "\n"; + //guint found = g_signal_handler_find(G_OBJECT(button), G_SIGNAL_MATCH_ID, signal_id, 0, 0, 0, 0); + //globalOutputStream() << " handler found: " << found << "\n"; + g_signal_handler_block(G_OBJECT(button), handler_id); + gtk_toggle_button_set_active(button, active); + g_signal_handler_unblock(G_OBJECT(button), handler_id); } -void toggle_button_set_active_no_signal( ui::ToggleToolButton button, gboolean active ){ - guint handler_id = gpointer_to_int( g_object_get_data( G_OBJECT( button ), "handler" ) ); - g_signal_handler_block( G_OBJECT( button ), handler_id ); - gtk_toggle_tool_button_set_active( button, active ); - g_signal_handler_unblock( G_OBJECT( button ), handler_id ); +void toggle_button_set_active_no_signal(ui::ToggleToolButton button, gboolean active) +{ + guint handler_id = gpointer_to_int(g_object_get_data(G_OBJECT(button), "handler")); + g_signal_handler_block(G_OBJECT(button), handler_id); + gtk_toggle_tool_button_set_active(button, active); + g_signal_handler_unblock(G_OBJECT(button), handler_id); } -void radio_button_print_state( ui::RadioButton button ){ - globalOutputStream() << "toggle button: "; - for ( GSList* radio = gtk_radio_button_get_group( button ); radio != 0; radio = g_slist_next( radio ) ) - { - globalOutputStream() << gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radio->data ) ); - } - globalOutputStream() << "\n"; +void radio_button_print_state(ui::RadioButton button) +{ + globalOutputStream() << "toggle button: "; + for (GSList *radio = gtk_radio_button_get_group(button); radio != 0; radio = g_slist_next(radio)) { + globalOutputStream() << gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio->data)); + } + globalOutputStream() << "\n"; } -ui::ToggleButton radio_button_get_nth( ui::RadioButton radio, int index ){ - GSList *group = gtk_radio_button_get_group( radio ); - return ui::ToggleButton::from( g_slist_nth_data( group, g_slist_length( group ) - index - 1 ) ); +ui::ToggleButton radio_button_get_nth(ui::RadioButton radio, int index) +{ + GSList *group = gtk_radio_button_get_group(radio); + return ui::ToggleButton::from(g_slist_nth_data(group, g_slist_length(group) - index - 1)); } -void radio_button_set_active( ui::RadioButton radio, int index ){ - //radio_button_print_state(radio); - gtk_toggle_button_set_active( radio_button_get_nth( radio, index ), TRUE ); - //radio_button_print_state(radio); +void radio_button_set_active(ui::RadioButton radio, int index) +{ + //radio_button_print_state(radio); + gtk_toggle_button_set_active(radio_button_get_nth(radio, index), TRUE); + //radio_button_print_state(radio); } -void radio_button_set_active_no_signal( ui::RadioButton radio, int index ){ - { - for ( GSList* l = gtk_radio_button_get_group( radio ); l != 0; l = g_slist_next( l ) ) - { - g_signal_handler_block( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) ); - } - } - radio_button_set_active( radio, index ); - { - for ( GSList* l = gtk_radio_button_get_group( radio ); l != 0; l = g_slist_next( l ) ) - { - g_signal_handler_unblock( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) ); - } - } +void radio_button_set_active_no_signal(ui::RadioButton radio, int index) +{ + { + for (GSList *l = gtk_radio_button_get_group(radio); l != 0; l = g_slist_next(l)) { + g_signal_handler_block(G_OBJECT(l->data), gpointer_to_int(g_object_get_data(G_OBJECT(l->data), "handler"))); + } + } + radio_button_set_active(radio, index); + { + for (GSList *l = gtk_radio_button_get_group(radio); l != 0; l = g_slist_next(l)) { + g_signal_handler_unblock(G_OBJECT(l->data), + gpointer_to_int(g_object_get_data(G_OBJECT(l->data), "handler"))); + } + } } -int radio_button_get_active( ui::RadioButton radio ){ - //radio_button_print_state(radio); - GSList *group = gtk_radio_button_get_group( radio ); - int index = g_slist_length( group ) - 1; - for (; group != 0; group = g_slist_next( group ) ) - { - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( group->data ) ) ) { - break; - } - else - { - index--; - } - } - return index; +int radio_button_get_active(ui::RadioButton radio) +{ + //radio_button_print_state(radio); + GSList *group = gtk_radio_button_get_group(radio); + int index = g_slist_length(group) - 1; + for (; group != 0; group = g_slist_next(group)) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group->data))) { + break; + } else { + index--; + } + } + return index; } diff --git a/libs/gtkutil/button.h b/libs/gtkutil/button.h index 238b207c..908f6a07 100644 --- a/libs/gtkutil/button.h +++ b/libs/gtkutil/button.h @@ -29,17 +29,24 @@ typedef int gint; typedef gint gboolean; typedef unsigned int guint; -void button_connect_callback( ui::Button button, const Callback& callback ); -void button_connect_callback( ui::ToolButton button, const Callback& callback ); -guint toggle_button_connect_callback( ui::ToggleButton button, const Callback& callback ); -guint toggle_button_connect_callback( ui::ToggleToolButton button, const Callback& callback ); - -void button_set_icon( ui::Button button, const char* icon ); -void toggle_button_set_active_no_signal( ui::ToggleButton item, gboolean active ); -void toggle_button_set_active_no_signal( ui::ToggleToolButton item, gboolean active ); - -void radio_button_set_active( ui::RadioButton radio, int index ); -void radio_button_set_active_no_signal( ui::RadioButton radio, int index ); -int radio_button_get_active( ui::RadioButton radio ); +void button_connect_callback(ui::Button button, const Callback &callback); + +void button_connect_callback(ui::ToolButton button, const Callback &callback); + +guint toggle_button_connect_callback(ui::ToggleButton button, const Callback &callback); + +guint toggle_button_connect_callback(ui::ToggleToolButton button, const Callback &callback); + +void button_set_icon(ui::Button button, const char *icon); + +void toggle_button_set_active_no_signal(ui::ToggleButton item, gboolean active); + +void toggle_button_set_active_no_signal(ui::ToggleToolButton item, gboolean active); + +void radio_button_set_active(ui::RadioButton radio, int index); + +void radio_button_set_active_no_signal(ui::RadioButton radio, int index); + +int radio_button_get_active(ui::RadioButton radio); #endif diff --git a/libs/gtkutil/clipboard.cpp b/libs/gtkutil/clipboard.cpp index fd36f39e..26c35924 100644 --- a/libs/gtkutil/clipboard.cpp +++ b/libs/gtkutil/clipboard.cpp @@ -36,112 +36,119 @@ const char* c_clipboard_format = "RadiantClippings"; #include void clipboard_copy( ClipboardCopyFunc copy ){ - BufferOutputStream ostream; - copy( ostream ); - - bool bClipped = false; - UINT nClipboard = ::RegisterClipboardFormat( c_clipboard_format ); - if ( nClipboard > 0 ) { - if ( ::OpenClipboard( 0 ) ) { - EmptyClipboard(); - std::size_t length = ostream.size(); - HANDLE h = ::GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, length + sizeof( std::size_t ) ); - if ( h != 0 ) { - char *buffer = reinterpret_cast( ::GlobalLock( h ) ); - *reinterpret_cast( buffer ) = length; - buffer += sizeof( std::size_t ); - memcpy( buffer, ostream.data(), length ); - ::GlobalUnlock( h ); - ::SetClipboardData( nClipboard, h ); - ::CloseClipboard(); - bClipped = true; - } - } - } - - if ( !bClipped ) { - globalOutputStream() << "Unable to register Windows clipboard formats, copy/paste between editors will not be possible\n"; - } + BufferOutputStream ostream; + copy( ostream ); + + bool bClipped = false; + UINT nClipboard = ::RegisterClipboardFormat( c_clipboard_format ); + if ( nClipboard > 0 ) { + if ( ::OpenClipboard( 0 ) ) { + EmptyClipboard(); + std::size_t length = ostream.size(); + HANDLE h = ::GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, length + sizeof( std::size_t ) ); + if ( h != 0 ) { + char *buffer = reinterpret_cast( ::GlobalLock( h ) ); + *reinterpret_cast( buffer ) = length; + buffer += sizeof( std::size_t ); + memcpy( buffer, ostream.data(), length ); + ::GlobalUnlock( h ); + ::SetClipboardData( nClipboard, h ); + ::CloseClipboard(); + bClipped = true; + } + } + } + + if ( !bClipped ) { + globalOutputStream() << "Unable to register Windows clipboard formats, copy/paste between editors will not be possible\n"; + } } void clipboard_paste( ClipboardPasteFunc paste ){ - UINT nClipboard = ::RegisterClipboardFormat( c_clipboard_format ); - if ( nClipboard > 0 && ::OpenClipboard( 0 ) ) { - if ( IsClipboardFormatAvailable( nClipboard ) ) { - HANDLE h = ::GetClipboardData( nClipboard ); - if ( h ) { - const char *buffer = reinterpret_cast( ::GlobalLock( h ) ); - std::size_t length = *reinterpret_cast( buffer ); - buffer += sizeof( std::size_t ); - BufferInputStream istream( buffer, length ); - paste( istream ); - ::GlobalUnlock( h ); - } - } - ::CloseClipboard(); - } + UINT nClipboard = ::RegisterClipboardFormat( c_clipboard_format ); + if ( nClipboard > 0 && ::OpenClipboard( 0 ) ) { + if ( IsClipboardFormatAvailable( nClipboard ) ) { + HANDLE h = ::GetClipboardData( nClipboard ); + if ( h ) { + const char *buffer = reinterpret_cast( ::GlobalLock( h ) ); + std::size_t length = *reinterpret_cast( buffer ); + buffer += sizeof( std::size_t ); + BufferInputStream istream( buffer, length ); + paste( istream ); + ::GlobalUnlock( h ); + } + } + ::CloseClipboard(); + } } #else #include -enum -{ - RADIANT_CLIPPINGS = 23, +enum { + RADIANT_CLIPPINGS = 23, }; static char RADIANT_CLIPPINGS_STR[] = "RADIANT_CLIPPINGS"; static const GtkTargetEntry clipboard_targets[] = { - {RADIANT_CLIPPINGS_STR, 0, RADIANT_CLIPPINGS, }, + {RADIANT_CLIPPINGS_STR, 0, RADIANT_CLIPPINGS,}, }; -static void clipboard_get( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data ){ - std::size_t len = *reinterpret_cast( data ); - const char* buffer = ( len != 0 ) ? reinterpret_cast( data ) + sizeof( std::size_t ) : 0; +static void clipboard_get(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data) +{ + std::size_t len = *reinterpret_cast( data ); + const char *buffer = (len != 0) ? reinterpret_cast( data ) + sizeof(std::size_t) : 0; - GdkAtom type = GDK_NONE; - if ( info == clipboard_targets[0].info ) { - type = gdk_atom_intern( clipboard_targets[0].target, FALSE ); - } + GdkAtom type = GDK_NONE; + if (info == clipboard_targets[0].info) { + type = gdk_atom_intern(clipboard_targets[0].target, FALSE); + } - gtk_selection_data_set( selection_data, type, 8, reinterpret_cast( buffer ), static_cast( len ) ); + gtk_selection_data_set(selection_data, type, 8, reinterpret_cast( buffer ), + static_cast( len )); } -static void clipboard_clear( GtkClipboard *clipboard, gpointer data ){ - delete [] reinterpret_cast( data ); +static void clipboard_clear(GtkClipboard *clipboard, gpointer data) +{ + delete[] reinterpret_cast( data ); } -static void clipboard_received( GtkClipboard *clipboard, GtkSelectionData *data, gpointer user_data ){ - if ( gtk_selection_data_get_length(data) < 0 ) { - globalErrorStream() << "Error retrieving selection\n"; - } - else if ( strcmp( gdk_atom_name( gtk_selection_data_get_data_type(data) ), clipboard_targets[0].target ) == 0 ) { - BufferInputStream istream( reinterpret_cast( gtk_selection_data_get_data(data) ), gtk_selection_data_get_length(data) ); - ( *reinterpret_cast( user_data ) )( istream ); - } +static void clipboard_received(GtkClipboard *clipboard, GtkSelectionData *data, gpointer user_data) +{ + if (gtk_selection_data_get_length(data) < 0) { + globalErrorStream() << "Error retrieving selection\n"; + } else if (strcmp(gdk_atom_name(gtk_selection_data_get_data_type(data)), clipboard_targets[0].target) == 0) { + BufferInputStream istream(reinterpret_cast( gtk_selection_data_get_data(data)), + gtk_selection_data_get_length(data)); + (*reinterpret_cast( user_data ))(istream); + } } -void clipboard_copy( ClipboardCopyFunc copy ){ - GtkClipboard* clipboard = gtk_clipboard_get( GDK_SELECTION_CLIPBOARD ); +void clipboard_copy(ClipboardCopyFunc copy) +{ + GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); - BufferOutputStream ostream; - copy( ostream ); - std::size_t length = ostream.size(); - char* data = new char[length + sizeof( std::size_t )]; - *reinterpret_cast( data ) = length; - memcpy( data + sizeof( std::size_t ), ostream.data(), length ); + BufferOutputStream ostream; + copy(ostream); + std::size_t length = ostream.size(); + char *data = new char[length + sizeof(std::size_t)]; + *reinterpret_cast( data ) = length; + memcpy(data + sizeof(std::size_t), ostream.data(), length); - gtk_clipboard_set_with_data( clipboard, clipboard_targets, 1, clipboard_get, clipboard_clear, data ); + gtk_clipboard_set_with_data(clipboard, clipboard_targets, 1, clipboard_get, clipboard_clear, data); } ClipboardPasteFunc g_clipboardPasteFunc = 0; -void clipboard_paste( ClipboardPasteFunc paste ){ - GtkClipboard* clipboard = gtk_clipboard_get( GDK_SELECTION_CLIPBOARD ); - g_clipboardPasteFunc = paste; - gtk_clipboard_request_contents( clipboard, gdk_atom_intern( clipboard_targets[0].target, FALSE ), clipboard_received, &g_clipboardPasteFunc ); +void clipboard_paste(ClipboardPasteFunc paste) +{ + GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + + g_clipboardPasteFunc = paste; + gtk_clipboard_request_contents(clipboard, gdk_atom_intern(clipboard_targets[0].target, FALSE), clipboard_received, + &g_clipboardPasteFunc); } diff --git a/libs/gtkutil/clipboard.h b/libs/gtkutil/clipboard.h index 69b64d70..ab8d48cb 100644 --- a/libs/gtkutil/clipboard.h +++ b/libs/gtkutil/clipboard.h @@ -23,11 +23,15 @@ #define INCLUDED_GTKUTIL_CLIPBOARD_H class TextOutputStream; -typedef void ( *ClipboardCopyFunc )( TextOutputStream& ); -void clipboard_copy( ClipboardCopyFunc copy ); + +typedef void ( *ClipboardCopyFunc )(TextOutputStream &); + +void clipboard_copy(ClipboardCopyFunc copy); class TextInputStream; -typedef void ( *ClipboardPasteFunc )( TextInputStream& ); -void clipboard_paste( ClipboardPasteFunc paste ); + +typedef void ( *ClipboardPasteFunc )(TextInputStream &); + +void clipboard_paste(ClipboardPasteFunc paste); #endif diff --git a/libs/gtkutil/closure.h b/libs/gtkutil/closure.h index 39945827..3993d392 100644 --- a/libs/gtkutil/closure.h +++ b/libs/gtkutil/closure.h @@ -25,46 +25,53 @@ #include #include "generic/callback.h" -inline void closure_destroy( gpointer data, GClosure* closure ){ - delete reinterpret_cast*>( data ); +inline void closure_destroy(gpointer data, GClosure *closure) +{ + delete reinterpret_cast *>( data ); } -inline GClosure* create_cclosure( GCallback func, const Callback& callback ){ - return g_cclosure_new( func, new Callback( callback ), closure_destroy ); +inline GClosure *create_cclosure(GCallback func, const Callback &callback) +{ + return g_cclosure_new(func, new Callback(callback), closure_destroy); } -inline GValue GValue_default(){ - GValue value; - value.g_type = 0; - return value; +inline GValue GValue_default() +{ + GValue value; + value.g_type = 0; + return value; } -inline gint object_get_int_property( GObject* object, const char* property ){ - GValue gvalue = GValue_default(); - g_value_init( &gvalue, G_TYPE_INT ); - g_object_get_property( object, property, &gvalue ); - return g_value_get_int( &gvalue ); +inline gint object_get_int_property(GObject *object, const char *property) +{ + GValue gvalue = GValue_default(); + g_value_init(&gvalue, G_TYPE_INT); + g_object_get_property(object, property, &gvalue); + return g_value_get_int(&gvalue); } -inline void object_set_int_property( GObject* object, const char* property, gint value ){ - GValue gvalue = GValue_default(); - g_value_init( &gvalue, G_TYPE_INT ); - g_value_set_int( &gvalue, value ); - g_object_set_property( object, property, &gvalue ); +inline void object_set_int_property(GObject *object, const char *property, gint value) +{ + GValue gvalue = GValue_default(); + g_value_init(&gvalue, G_TYPE_INT); + g_value_set_int(&gvalue, value); + g_object_set_property(object, property, &gvalue); } -inline gboolean object_get_boolean_property( GObject* object, const char* property ){ - GValue gvalue = GValue_default(); - g_value_init( &gvalue, G_TYPE_BOOLEAN ); - g_object_get_property( object, property, &gvalue ); - return g_value_get_boolean( &gvalue ); +inline gboolean object_get_boolean_property(GObject *object, const char *property) +{ + GValue gvalue = GValue_default(); + g_value_init(&gvalue, G_TYPE_BOOLEAN); + g_object_get_property(object, property, &gvalue); + return g_value_get_boolean(&gvalue); } -inline void object_set_boolean_property( GObject* object, const char* property, gboolean value ){ - GValue gvalue = GValue_default(); - g_value_init( &gvalue, G_TYPE_BOOLEAN ); - g_value_set_boolean( &gvalue, value ); - g_object_set_property( object, property, &gvalue ); +inline void object_set_boolean_property(GObject *object, const char *property, gboolean value) +{ + GValue gvalue = GValue_default(); + g_value_init(&gvalue, G_TYPE_BOOLEAN); + g_value_set_boolean(&gvalue, value); + g_object_set_property(object, property, &gvalue); } #endif diff --git a/libs/gtkutil/cursor.cpp b/libs/gtkutil/cursor.cpp index 999621f1..67177571 100644 --- a/libs/gtkutil/cursor.cpp +++ b/libs/gtkutil/cursor.cpp @@ -28,99 +28,104 @@ #include -GdkCursor* create_blank_cursor(){ - return gdk_cursor_new(GDK_BLANK_CURSOR); +GdkCursor *create_blank_cursor() +{ + return gdk_cursor_new(GDK_BLANK_CURSOR); } -void blank_cursor( ui::Widget widget ){ - GdkCursor* cursor = create_blank_cursor(); - gdk_window_set_cursor( gtk_widget_get_window(widget), cursor ); - gdk_cursor_unref( cursor ); +void blank_cursor(ui::Widget widget) +{ + GdkCursor *cursor = create_blank_cursor(); + gdk_window_set_cursor(gtk_widget_get_window(widget), cursor); + gdk_cursor_unref(cursor); } -void default_cursor( ui::Widget widget ){ - gdk_window_set_cursor( gtk_widget_get_window(widget), 0 ); +void default_cursor(ui::Widget widget) +{ + gdk_window_set_cursor(gtk_widget_get_window(widget), 0); } -void Sys_GetCursorPos( ui::Window window, int *x, int *y ){ - gdk_display_get_pointer( gdk_display_get_default(), 0, x, y, 0 ); +void Sys_GetCursorPos(ui::Window window, int *x, int *y) +{ + gdk_display_get_pointer(gdk_display_get_default(), 0, x, y, 0); } -void Sys_SetCursorPos( ui::Window window, int x, int y ){ - GdkScreen *screen; - gdk_display_get_pointer( gdk_display_get_default(), &screen, 0, 0, 0 ); - gdk_display_warp_pointer( gdk_display_get_default(), screen, x, y ); +void Sys_SetCursorPos(ui::Window window, int x, int y) +{ + GdkScreen *screen; + gdk_display_get_pointer(gdk_display_get_default(), &screen, 0, 0, 0); + gdk_display_warp_pointer(gdk_display_get_default(), screen, x, y); } gboolean DeferredMotion::gtk_motion(ui::Widget widget, GdkEventMotion *event, DeferredMotion *self) { - self->motion( event->x, event->y, event->state ); + self->motion(event->x, event->y, event->state); return FALSE; } gboolean FreezePointer::motion_delta(ui::Window widget, GdkEventMotion *event, FreezePointer *self) { - int current_x, current_y; - Sys_GetCursorPos( widget, ¤t_x, ¤t_y ); - int dx = current_x - self->last_x; - int dy = current_y - self->last_y; - int ddx = current_x - self->recorded_x; - int ddy = current_y - self->recorded_y; - self->last_x = current_x; - self->last_y = current_y; - if ( dx != 0 || dy != 0 ) { - //globalOutputStream() << "motion x: " << dx << ", y: " << dy << "\n"; - if (ddx < -32 || ddx > 32 || ddy < -32 || ddy > 32) { - Sys_SetCursorPos( widget, self->recorded_x, self->recorded_y ); - self->last_x = self->recorded_x; - self->last_y = self->recorded_y; - } - self->m_function( dx, dy, event->state, self->m_data ); - } - return FALSE; + int current_x, current_y; + Sys_GetCursorPos(widget, ¤t_x, ¤t_y); + int dx = current_x - self->last_x; + int dy = current_y - self->last_y; + int ddx = current_x - self->recorded_x; + int ddy = current_y - self->recorded_y; + self->last_x = current_x; + self->last_y = current_y; + if (dx != 0 || dy != 0) { + //globalOutputStream() << "motion x: " << dx << ", y: " << dy << "\n"; + if (ddx < -32 || ddx > 32 || ddy < -32 || ddy > 32) { + Sys_SetCursorPos(widget, self->recorded_x, self->recorded_y); + self->last_x = self->recorded_x; + self->last_y = self->recorded_y; + } + self->m_function(dx, dy, event->state, self->m_data); + } + return FALSE; } void FreezePointer::freeze_pointer(ui::Window window, FreezePointer::MotionDeltaFunction function, void *data) { - ASSERT_MESSAGE( m_function == 0, "can't freeze pointer" ); + ASSERT_MESSAGE(m_function == 0, "can't freeze pointer"); - const GdkEventMask mask = static_cast( GDK_POINTER_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK - | GDK_BUTTON_MOTION_MASK - | GDK_BUTTON1_MOTION_MASK - | GDK_BUTTON2_MOTION_MASK - | GDK_BUTTON3_MOTION_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK - | GDK_VISIBILITY_NOTIFY_MASK ); + const GdkEventMask mask = static_cast( GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK + | GDK_BUTTON_MOTION_MASK + | GDK_BUTTON1_MOTION_MASK + | GDK_BUTTON2_MOTION_MASK + | GDK_BUTTON3_MOTION_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_VISIBILITY_NOTIFY_MASK ); - GdkCursor* cursor = create_blank_cursor(); - //GdkGrabStatus status = - gdk_pointer_grab( gtk_widget_get_window(window), TRUE, mask, 0, cursor, GDK_CURRENT_TIME ); - gdk_cursor_unref( cursor ); + GdkCursor *cursor = create_blank_cursor(); + //GdkGrabStatus status = + gdk_pointer_grab(gtk_widget_get_window(window), TRUE, mask, 0, cursor, GDK_CURRENT_TIME); + gdk_cursor_unref(cursor); - Sys_GetCursorPos( window, &recorded_x, &recorded_y ); + Sys_GetCursorPos(window, &recorded_x, &recorded_y); - Sys_SetCursorPos( window, recorded_x, recorded_y ); + Sys_SetCursorPos(window, recorded_x, recorded_y); - last_x = recorded_x; - last_y = recorded_y; + last_x = recorded_x; + last_y = recorded_y; - m_function = function; - m_data = data; + m_function = function; + m_data = data; - handle_motion = window.connect( "motion_notify_event", G_CALLBACK( motion_delta ), this ); + handle_motion = window.connect("motion_notify_event", G_CALLBACK(motion_delta), this); } void FreezePointer::unfreeze_pointer(ui::Window window) { - g_signal_handler_disconnect( G_OBJECT( window ), handle_motion ); + g_signal_handler_disconnect(G_OBJECT(window), handle_motion); - m_function = 0; - m_data = 0; + m_function = 0; + m_data = 0; - Sys_SetCursorPos( window, recorded_x, recorded_y ); + Sys_SetCursorPos(window, recorded_x, recorded_y); - gdk_pointer_ungrab( GDK_CURRENT_TIME ); + gdk_pointer_ungrab(GDK_CURRENT_TIME); } diff --git a/libs/gtkutil/cursor.h b/libs/gtkutil/cursor.h index 2d16142e..20e38408 100644 --- a/libs/gtkutil/cursor.h +++ b/libs/gtkutil/cursor.h @@ -29,96 +29,118 @@ typedef struct _GdkCursor GdkCursor; typedef struct _GdkEventMotion GdkEventMotion; -GdkCursor* create_blank_cursor(); -void blank_cursor( ui::Widget widget ); -void default_cursor( ui::Widget widget ); -void Sys_GetCursorPos( ui::Window window, int *x, int *y ); -void Sys_SetCursorPos( ui::Window window, int x, int y ); - - - -class DeferredMotion -{ -guint m_handler; -typedef void ( *MotionFunction )( gdouble x, gdouble y, guint state, void* data ); -MotionFunction m_function; -void* m_data; -gdouble m_x; -gdouble m_y; -guint m_state; - -static gboolean deferred( DeferredMotion* self ){ - self->m_handler = 0; - self->m_function( self->m_x, self->m_y, self->m_state, self->m_data ); - return FALSE; -} +GdkCursor *create_blank_cursor(); + +void blank_cursor(ui::Widget widget); + +void default_cursor(ui::Widget widget); + +void Sys_GetCursorPos(ui::Window window, int *x, int *y); + +void Sys_SetCursorPos(ui::Window window, int x, int y); + + +class DeferredMotion { + guint m_handler; + + typedef void ( *MotionFunction )(gdouble x, gdouble y, guint state, void *data); + + MotionFunction m_function; + void *m_data; + gdouble m_x; + gdouble m_y; + guint m_state; + + static gboolean deferred(DeferredMotion *self) + { + self->m_handler = 0; + self->m_function(self->m_x, self->m_y, self->m_state, self->m_data); + return FALSE; + } + public: -DeferredMotion( MotionFunction function, void* data ) : m_handler( 0 ), m_function( function ), m_data( data ){ -} -void motion( gdouble x, gdouble y, guint state ){ - m_x = x; - m_y = y; - m_state = state; - if ( m_handler == 0 ) { - m_handler = g_idle_add( (GSourceFunc)deferred, this ); - } -} -static gboolean gtk_motion( ui::Widget widget, GdkEventMotion *event, DeferredMotion* self ); + DeferredMotion(MotionFunction function, void *data) : m_handler(0), m_function(function), m_data(data) + { + } + + void motion(gdouble x, gdouble y, guint state) + { + m_x = x; + m_y = y; + m_state = state; + if (m_handler == 0) { + m_handler = g_idle_add((GSourceFunc) deferred, this); + } + } + + static gboolean gtk_motion(ui::Widget widget, GdkEventMotion *event, DeferredMotion *self); }; -class DeferredMotionDelta -{ -int m_delta_x; -int m_delta_y; -guint m_motion_handler; -typedef void ( *MotionDeltaFunction )( int x, int y, void* data ); -MotionDeltaFunction m_function; -void* m_data; - -static gboolean deferred_motion( gpointer data ){ - reinterpret_cast( data )->m_function( - reinterpret_cast( data )->m_delta_x, - reinterpret_cast( data )->m_delta_y, - reinterpret_cast( data )->m_data - ); - reinterpret_cast( data )->m_motion_handler = 0; - reinterpret_cast( data )->m_delta_x = 0; - reinterpret_cast( data )->m_delta_y = 0; - return FALSE; -} +class DeferredMotionDelta { + int m_delta_x; + int m_delta_y; + guint m_motion_handler; + + typedef void ( *MotionDeltaFunction )(int x, int y, void *data); + + MotionDeltaFunction m_function; + void *m_data; + + static gboolean deferred_motion(gpointer data) + { + reinterpret_cast( data )->m_function( + reinterpret_cast( data )->m_delta_x, + reinterpret_cast( data )->m_delta_y, + reinterpret_cast( data )->m_data + ); + reinterpret_cast( data )->m_motion_handler = 0; + reinterpret_cast( data )->m_delta_x = 0; + reinterpret_cast( data )->m_delta_y = 0; + return FALSE; + } + public: -DeferredMotionDelta( MotionDeltaFunction function, void* data ) : m_delta_x( 0 ), m_delta_y( 0 ), m_motion_handler( 0 ), m_function( function ), m_data( data ){ -} -void flush(){ - if ( m_motion_handler != 0 ) { - g_source_remove( m_motion_handler ); - deferred_motion( this ); - } -} -void motion_delta( int x, int y, unsigned int state ){ - m_delta_x += x; - m_delta_y += y; - if ( m_motion_handler == 0 ) { - m_motion_handler = g_idle_add( deferred_motion, this ); - } -} + DeferredMotionDelta(MotionDeltaFunction function, void *data) : m_delta_x(0), m_delta_y(0), m_motion_handler(0), + m_function(function), m_data(data) + { + } + + void flush() + { + if (m_motion_handler != 0) { + g_source_remove(m_motion_handler); + deferred_motion(this); + } + } + + void motion_delta(int x, int y, unsigned int state) + { + m_delta_x += x; + m_delta_y += y; + if (m_motion_handler == 0) { + m_motion_handler = g_idle_add(deferred_motion, this); + } + } }; -class FreezePointer -{ -unsigned int handle_motion; -int recorded_x, recorded_y, last_x, last_y; -typedef void ( *MotionDeltaFunction )( int x, int y, unsigned int state, void* data ); -MotionDeltaFunction m_function; -void* m_data; +class FreezePointer { + unsigned int handle_motion; + int recorded_x, recorded_y, last_x, last_y; + + typedef void ( *MotionDeltaFunction )(int x, int y, unsigned int state, void *data); + + MotionDeltaFunction m_function; + void *m_data; public: -FreezePointer() : handle_motion( 0 ), m_function( 0 ), m_data( 0 ){ -} -static gboolean motion_delta( ui::Window widget, GdkEventMotion *event, FreezePointer* self ); + FreezePointer() : handle_motion(0), m_function(0), m_data(0) + { + } + + static gboolean motion_delta(ui::Window widget, GdkEventMotion *event, FreezePointer *self); -void freeze_pointer( ui::Window window, MotionDeltaFunction function, void* data ); + void freeze_pointer(ui::Window window, MotionDeltaFunction function, void *data); -void unfreeze_pointer( ui::Window window ); + void unfreeze_pointer(ui::Window window); }; #endif diff --git a/libs/gtkutil/dialog.cpp b/libs/gtkutil/dialog.cpp index fddf060e..9024e287 100644 --- a/libs/gtkutil/dialog.cpp +++ b/libs/gtkutil/dialog.cpp @@ -26,238 +26,268 @@ #include "button.h" #include "window.h" -ui::VBox create_dialog_vbox( int spacing, int border ){ - auto vbox = ui::VBox( FALSE, spacing ); - vbox.show(); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), border ); - return vbox; +ui::VBox create_dialog_vbox(int spacing, int border) +{ + auto vbox = ui::VBox(FALSE, spacing); + vbox.show(); + gtk_container_set_border_width(GTK_CONTAINER(vbox), border); + return vbox; } -ui::HBox create_dialog_hbox( int spacing, int border ){ - auto hbox = ui::HBox( FALSE, spacing ); - hbox.show(); - gtk_container_set_border_width( GTK_CONTAINER( hbox ), border ); - return hbox; +ui::HBox create_dialog_hbox(int spacing, int border) +{ + auto hbox = ui::HBox(FALSE, spacing); + hbox.show(); + gtk_container_set_border_width(GTK_CONTAINER(hbox), border); + return hbox; } -ui::Frame create_dialog_frame( const char* label, ui::Shadow shadow ){ - auto frame = ui::Frame( label ); - frame.show(); - gtk_frame_set_shadow_type( frame, (GtkShadowType) shadow ); - return frame; +ui::Frame create_dialog_frame(const char *label, ui::Shadow shadow) +{ + auto frame = ui::Frame(label); + frame.show(); + gtk_frame_set_shadow_type(frame, (GtkShadowType) shadow); + return frame; } -ui::Table create_dialog_table( unsigned int rows, unsigned int columns, unsigned int row_spacing, unsigned int col_spacing, int border ){ - auto table = ui::Table( rows, columns, FALSE ); - table.show(); - gtk_table_set_row_spacings( table, row_spacing ); - gtk_table_set_col_spacings( table, col_spacing ); - gtk_container_set_border_width( GTK_CONTAINER( table ), border ); - return table; +ui::Table +create_dialog_table(unsigned int rows, unsigned int columns, unsigned int row_spacing, unsigned int col_spacing, + int border) +{ + auto table = ui::Table(rows, columns, FALSE); + table.show(); + gtk_table_set_row_spacings(table, row_spacing); + gtk_table_set_col_spacings(table, col_spacing); + gtk_container_set_border_width(GTK_CONTAINER(table), border); + return table; } -ui::Button create_dialog_button( const char* label, GCallback func, gpointer data ){ - auto button = ui::Button( label ); - button.dimensions(64, -1); - button.show(); - button.connect( "clicked", func, data ); - return button; +ui::Button create_dialog_button(const char *label, GCallback func, gpointer data) +{ + auto button = ui::Button(label); + button.dimensions(64, -1); + button.show(); + button.connect("clicked", func, data); + return button; } -ui::Window create_dialog_window( ui::Window parent, const char* title, GCallback func, gpointer data, int default_w, int default_h ){ - ui::Window window = create_floating_window( title, parent ); - gtk_window_set_default_size( window, default_w, default_h ); - gtk_window_set_position( window, GTK_WIN_POS_CENTER_ON_PARENT ); - window.connect( "delete_event", func, data ); +ui::Window +create_dialog_window(ui::Window parent, const char *title, GCallback func, gpointer data, int default_w, int default_h) +{ + ui::Window window = create_floating_window(title, parent); + gtk_window_set_default_size(window, default_w, default_h); + gtk_window_set_position(window, GTK_WIN_POS_CENTER_ON_PARENT); + window.connect("delete_event", func, data); - return window; + return window; } -gboolean modal_dialog_button_clicked( ui::Widget widget, ModalDialogButton* button ){ - button->m_dialog.loop = false; - button->m_dialog.ret = button->m_value; - return TRUE; +gboolean modal_dialog_button_clicked(ui::Widget widget, ModalDialogButton *button) +{ + button->m_dialog.loop = false; + button->m_dialog.ret = button->m_value; + return TRUE; } -gboolean modal_dialog_delete( ui::Widget widget, GdkEvent* event, ModalDialog* dialog ){ - dialog->loop = 0; - dialog->ret = eIDCANCEL; - return TRUE; +gboolean modal_dialog_delete(ui::Widget widget, GdkEvent *event, ModalDialog *dialog) +{ + dialog->loop = 0; + dialog->ret = eIDCANCEL; + return TRUE; } -EMessageBoxReturn modal_dialog_show( ui::Window window, ModalDialog& dialog ){ - gtk_grab_add( window ); - window.show(); +EMessageBoxReturn modal_dialog_show(ui::Window window, ModalDialog &dialog) +{ + gtk_grab_add(window); + window.show(); - dialog.loop = true; - while ( dialog.loop ) - { - gtk_main_iteration(); - } + dialog.loop = true; + while (dialog.loop) { + gtk_main_iteration(); + } - window.hide(); - gtk_grab_remove( window ); + window.hide(); + gtk_grab_remove(window); - return dialog.ret; + return dialog.ret; } -ui::Button create_modal_dialog_button( const char* label, ModalDialogButton& button ){ - return create_dialog_button( label, G_CALLBACK( modal_dialog_button_clicked ), &button ); +ui::Button create_modal_dialog_button(const char *label, ModalDialogButton &button) +{ + return create_dialog_button(label, G_CALLBACK(modal_dialog_button_clicked), &button); } -ui::Window create_modal_dialog_window( ui::Window parent, const char* title, ModalDialog& dialog, int default_w, int default_h ){ - return create_dialog_window( parent, title, G_CALLBACK( modal_dialog_delete ), &dialog, default_w, default_h ); +ui::Window +create_modal_dialog_window(ui::Window parent, const char *title, ModalDialog &dialog, int default_w, int default_h) +{ + return create_dialog_window(parent, title, G_CALLBACK(modal_dialog_delete), &dialog, default_w, default_h); } -ui::Window create_fixedsize_modal_dialog_window( ui::Window parent, const char* title, ModalDialog& dialog, int width, int height ){ - auto window = create_modal_dialog_window( parent, title, dialog, width, height ); +ui::Window +create_fixedsize_modal_dialog_window(ui::Window parent, const char *title, ModalDialog &dialog, int width, int height) +{ + auto window = create_modal_dialog_window(parent, title, dialog, width, height); - gtk_window_set_resizable( window, FALSE ); - gtk_window_set_modal( window, TRUE ); - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); + gtk_window_set_resizable(window, FALSE); + gtk_window_set_modal(window, TRUE); + gtk_window_set_position(window, GTK_WIN_POS_CENTER); - window_remove_minmax( window ); + window_remove_minmax(window); - //window.dimensions(width, height); - //gtk_window_set_default_size(window, width, height); - //gtk_window_resize(window, width, height); - //GdkGeometry geometry = { width, height, -1, -1, width, height, -1, -1, -1, -1, GDK_GRAVITY_STATIC, }; - //gtk_window_set_geometry_hints(window, window, &geometry, (GdkWindowHints)(GDK_HINT_POS|GDK_HINT_MIN_SIZE|GDK_HINT_BASE_SIZE)); + //window.dimensions(width, height); + //gtk_window_set_default_size(window, width, height); + //gtk_window_resize(window, width, height); + //GdkGeometry geometry = { width, height, -1, -1, width, height, -1, -1, -1, -1, GDK_GRAVITY_STATIC, }; + //gtk_window_set_geometry_hints(window, window, &geometry, (GdkWindowHints)(GDK_HINT_POS|GDK_HINT_MIN_SIZE|GDK_HINT_BASE_SIZE)); - return window; + return window; } -gboolean dialog_button_ok( ui::Widget widget, ModalDialog* data ){ - data->loop = false; - data->ret = eIDOK; - return TRUE; +gboolean dialog_button_ok(ui::Widget widget, ModalDialog *data) +{ + data->loop = false; + data->ret = eIDOK; + return TRUE; } -gboolean dialog_button_cancel( ui::Widget widget, ModalDialog* data ){ - data->loop = false; - data->ret = eIDCANCEL; - return TRUE; +gboolean dialog_button_cancel(ui::Widget widget, ModalDialog *data) +{ + data->loop = false; + data->ret = eIDCANCEL; + return TRUE; } -gboolean dialog_button_yes( ui::Widget widget, ModalDialog* data ){ - data->loop = false; - data->ret = eIDYES; - return TRUE; +gboolean dialog_button_yes(ui::Widget widget, ModalDialog *data) +{ + data->loop = false; + data->ret = eIDYES; + return TRUE; } -gboolean dialog_button_no( ui::Widget widget, ModalDialog* data ){ - data->loop = false; - data->ret = eIDNO; - return TRUE; +gboolean dialog_button_no(ui::Widget widget, ModalDialog *data) +{ + data->loop = false; + data->ret = eIDNO; + return TRUE; } -gboolean dialog_delete_callback( ui::Widget widget, GdkEventAny* event, ModalDialog* data ){ - widget.hide(); - data->loop = false; - return TRUE; +gboolean dialog_delete_callback(ui::Widget widget, GdkEventAny *event, ModalDialog *data) +{ + widget.hide(); + data->loop = false; + return TRUE; } -ui::Window create_simple_modal_dialog_window( const char* title, ModalDialog& dialog, ui::Widget contents ){ - ui::Window window = create_fixedsize_modal_dialog_window(ui::Window{ui::null}, title, dialog ); +ui::Window create_simple_modal_dialog_window(const char *title, ModalDialog &dialog, ui::Widget contents) +{ + ui::Window window = create_fixedsize_modal_dialog_window(ui::Window{ui::null}, title, dialog); - auto vbox1 = create_dialog_vbox( 8, 4 ); - window.add(vbox1); + auto vbox1 = create_dialog_vbox(8, 4); + window.add(vbox1); - vbox1.add(contents); + vbox1.add(contents); - ui::Alignment alignment = ui::Alignment( 0.5, 0.0, 0.0, 0.0 ); - alignment.show(); - vbox1.pack_start( alignment, FALSE, FALSE, 0 ); + ui::Alignment alignment = ui::Alignment(0.5, 0.0, 0.0, 0.0); + alignment.show(); + vbox1.pack_start(alignment, FALSE, FALSE, 0); - auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &dialog ); - alignment.add(button); + auto button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &dialog); + alignment.add(button); - return window; + return window; } -RadioHBox RadioHBox_new( StringArrayRange names ){ - auto hbox = ui::HBox( TRUE, 4 ); - hbox.show(); +RadioHBox RadioHBox_new(StringArrayRange names) +{ + auto hbox = ui::HBox(TRUE, 4); + hbox.show(); - GSList* group = 0; - auto radio = ui::RadioButton(ui::null); - for ( StringArrayRange::Iterator i = names.first; i != names.last; ++i ) - { - radio = ui::RadioButton::from( gtk_radio_button_new_with_label( group, *i ) ); - radio.show(); - hbox.pack_start( radio, FALSE, FALSE, 0 ); + GSList *group = 0; + auto radio = ui::RadioButton(ui::null); + for (StringArrayRange::Iterator i = names.first; i != names.last; ++i) { + radio = ui::RadioButton::from(gtk_radio_button_new_with_label(group, *i)); + radio.show(); + hbox.pack_start(radio, FALSE, FALSE, 0); - group = gtk_radio_button_get_group( radio ); - } + group = gtk_radio_button_get_group(radio); + } - return RadioHBox( hbox, radio ); + return RadioHBox(hbox, radio); } -PathEntry PathEntry_new(){ - auto frame = ui::Frame(); - frame.show(); - gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN ); +PathEntry PathEntry_new() +{ + auto frame = ui::Frame(); + frame.show(); + gtk_frame_set_shadow_type(frame, GTK_SHADOW_IN); - // path entry - auto hbox = ui::HBox( FALSE, 0 ); - hbox.show(); + // path entry + auto hbox = ui::HBox(FALSE, 0); + hbox.show(); - auto entry = ui::Entry(ui::New); - gtk_entry_set_has_frame( entry, FALSE ); - entry.show(); - hbox.pack_start( entry, TRUE, TRUE, 0 ); + auto entry = ui::Entry(ui::New); + gtk_entry_set_has_frame(entry, FALSE); + entry.show(); + hbox.pack_start(entry, TRUE, TRUE, 0); - // browse button - auto button = ui::Button(ui::New); - button_set_icon( button, "ellipsis.bmp" ); - button.show(); - hbox.pack_end(button, FALSE, FALSE, 0); + // browse button + auto button = ui::Button(ui::New); + button_set_icon(button, "ellipsis.bmp"); + button.show(); + hbox.pack_end(button, FALSE, FALSE, 0); - frame.add(hbox); + frame.add(hbox); - return PathEntry( frame, entry, button ); + return PathEntry(frame, entry, button); } -void PathEntry_setPath( PathEntry& self, const char* path ){ - gtk_entry_set_text( self.m_entry, path ); +void PathEntry_setPath(PathEntry &self, const char *path) +{ + gtk_entry_set_text(self.m_entry, path); } -typedef ReferenceCaller PathEntrySetPathCaller; -void BrowsedPathEntry_clicked( ui::Widget widget, BrowsedPathEntry* self ){ - self->m_browse( PathEntrySetPathCaller( self->m_entry ) ); +typedef ReferenceCaller PathEntrySetPathCaller; + +void BrowsedPathEntry_clicked(ui::Widget widget, BrowsedPathEntry *self) +{ + self->m_browse(PathEntrySetPathCaller(self->m_entry)); } -BrowsedPathEntry::BrowsedPathEntry( const BrowseCallback& browse ) : - m_entry( PathEntry_new() ), - m_browse( browse ){ - m_entry.m_button.connect( "clicked", G_CALLBACK( BrowsedPathEntry_clicked ), this ); +BrowsedPathEntry::BrowsedPathEntry(const BrowseCallback &browse) : + m_entry(PathEntry_new()), + m_browse(browse) +{ + m_entry.m_button.connect("clicked", G_CALLBACK(BrowsedPathEntry_clicked), this); } -ui::Label DialogLabel_new( const char* name ){ - auto label = ui::Label( name ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - gtk_label_set_justify( label, GTK_JUSTIFY_LEFT ); +ui::Label DialogLabel_new(const char *name) +{ + auto label = ui::Label(name); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_label_set_justify(label, GTK_JUSTIFY_LEFT); - return label; + return label; } -ui::Table DialogRow_new( const char* name, ui::Widget widget ){ - auto table = ui::Table( 1, 3, TRUE ); - table.show(); +ui::Table DialogRow_new(const char *name, ui::Widget widget) +{ + auto table = ui::Table(1, 3, TRUE); + table.show(); - gtk_table_set_col_spacings( table, 4 ); - gtk_table_set_row_spacings( table, 0 ); + gtk_table_set_col_spacings(table, 4); + gtk_table_set_row_spacings(table, 0); table.attach(DialogLabel_new(name), {0, 1, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); table.attach(widget, {1, 3, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - return table; + return table; } -void DialogVBox_packRow( ui::Box vbox, ui::Widget row ){ - vbox.pack_start( row, FALSE, FALSE, 0 ); +void DialogVBox_packRow(ui::Box vbox, ui::Widget row) +{ + vbox.pack_start(row, FALSE, FALSE, 0); } diff --git a/libs/gtkutil/dialog.h b/libs/gtkutil/dialog.h index 79330143..b359bc17 100644 --- a/libs/gtkutil/dialog.h +++ b/libs/gtkutil/dialog.h @@ -31,94 +31,118 @@ typedef gint gboolean; typedef struct _GdkEventAny GdkEventAny; -struct ModalDialog -{ - ModalDialog() - : loop( true ), ret( eIDCANCEL ){ - } - bool loop; - EMessageBoxReturn ret; +struct ModalDialog { + ModalDialog() + : loop(true), ret(eIDCANCEL) + { + } + + bool loop; + EMessageBoxReturn ret; }; -struct ModalDialogButton -{ - ModalDialogButton( ModalDialog& dialog, EMessageBoxReturn value ) - : m_dialog( dialog ), m_value( value ){ - } - ModalDialog& m_dialog; - EMessageBoxReturn m_value; +struct ModalDialogButton { + ModalDialogButton(ModalDialog &dialog, EMessageBoxReturn value) + : m_dialog(dialog), m_value(value) + { + } + + ModalDialog &m_dialog; + EMessageBoxReturn m_value; }; -typedef void ( *GCallback )( void ); -typedef void* gpointer; +typedef void ( *GCallback )(void); + +typedef void *gpointer; + +ui::Window create_fixedsize_modal_window(ui::Window parent, const char *title, int width, int height); + +ui::Window create_dialog_window(ui::Window parent, const char *title, GCallback func, gpointer data, int default_w = -1, + int default_h = -1); + +ui::Table +create_dialog_table(unsigned int rows, unsigned int columns, unsigned int row_spacing, unsigned int col_spacing, + int border = 0); + +ui::Button create_dialog_button(const char *label, GCallback func, gpointer data); + +ui::VBox create_dialog_vbox(int spacing, int border = 0); + +ui::HBox create_dialog_hbox(int spacing, int border = 0); -ui::Window create_fixedsize_modal_window( ui::Window parent, const char* title, int width, int height ); +ui::Frame create_dialog_frame(const char *label, ui::Shadow shadow = ui::Shadow::ETCHED_IN); -ui::Window create_dialog_window( ui::Window parent, const char* title, GCallback func, gpointer data, int default_w = -1, int default_h = -1 ); -ui::Table create_dialog_table( unsigned int rows, unsigned int columns, unsigned int row_spacing, unsigned int col_spacing, int border = 0 ); -ui::Button create_dialog_button( const char* label, GCallback func, gpointer data ); -ui::VBox create_dialog_vbox( int spacing, int border = 0 ); -ui::HBox create_dialog_hbox( int spacing, int border = 0 ); -ui::Frame create_dialog_frame( const char* label, ui::Shadow shadow = ui::Shadow::ETCHED_IN ); +ui::Button create_modal_dialog_button(const char *label, ModalDialogButton &button); -ui::Button create_modal_dialog_button( const char* label, ModalDialogButton& button ); -ui::Window create_modal_dialog_window( ui::Window parent, const char* title, ModalDialog& dialog, int default_w = -1, int default_h = -1 ); -ui::Window create_fixedsize_modal_dialog_window( ui::Window parent, const char* title, ModalDialog& dialog, int width = -1, int height = -1 ); -EMessageBoxReturn modal_dialog_show( ui::Window window, ModalDialog& dialog ); +ui::Window create_modal_dialog_window(ui::Window parent, const char *title, ModalDialog &dialog, int default_w = -1, + int default_h = -1); +ui::Window +create_fixedsize_modal_dialog_window(ui::Window parent, const char *title, ModalDialog &dialog, int width = -1, + int height = -1); -gboolean dialog_button_ok( ui::Widget widget, ModalDialog* data ); -gboolean dialog_button_cancel( ui::Widget widget, ModalDialog* data ); -gboolean dialog_button_yes( ui::Widget widget, ModalDialog* data ); -gboolean dialog_button_no( ui::Widget widget, ModalDialog* data ); -gboolean dialog_delete_callback( ui::Widget widget, GdkEventAny* event, ModalDialog* data ); +EMessageBoxReturn modal_dialog_show(ui::Window window, ModalDialog &dialog); -ui::Window create_simple_modal_dialog_window( const char* title, ModalDialog& dialog, ui::Widget contents ); -class RadioHBox -{ +gboolean dialog_button_ok(ui::Widget widget, ModalDialog *data); + +gboolean dialog_button_cancel(ui::Widget widget, ModalDialog *data); + +gboolean dialog_button_yes(ui::Widget widget, ModalDialog *data); + +gboolean dialog_button_no(ui::Widget widget, ModalDialog *data); + +gboolean dialog_delete_callback(ui::Widget widget, GdkEventAny *event, ModalDialog *data); + +ui::Window create_simple_modal_dialog_window(const char *title, ModalDialog &dialog, ui::Widget contents); + +class RadioHBox { public: -ui::HBox m_hbox; -ui::RadioButton m_radio; -RadioHBox( ui::HBox hbox, ui::RadioButton radio ) : - m_hbox( hbox ), - m_radio( radio ){ -} + ui::HBox m_hbox; + ui::RadioButton m_radio; + + RadioHBox(ui::HBox hbox, ui::RadioButton radio) : + m_hbox(hbox), + m_radio(radio) + { + } }; -RadioHBox RadioHBox_new( StringArrayRange names ); +RadioHBox RadioHBox_new(StringArrayRange names); -class PathEntry -{ +class PathEntry { public: -ui::Frame m_frame; -ui::Entry m_entry; -ui::Button m_button; -PathEntry( ui::Frame frame, ui::Entry entry, ui::Button button ) : - m_frame( frame ), - m_entry( entry ), - m_button( button ){ -} + ui::Frame m_frame; + ui::Entry m_entry; + ui::Button m_button; + + PathEntry(ui::Frame frame, ui::Entry entry, ui::Button button) : + m_frame(frame), + m_entry(entry), + m_button(button) + { + } }; PathEntry PathEntry_new(); -class BrowsedPathEntry -{ +class BrowsedPathEntry { public: -typedef Callback SetPathCallback; -typedef Callback BrowseCallback; + typedef Callback SetPathCallback; + typedef Callback BrowseCallback; -PathEntry m_entry; -BrowseCallback m_browse; + PathEntry m_entry; + BrowseCallback m_browse; -BrowsedPathEntry( const BrowseCallback& browse ); + BrowsedPathEntry(const BrowseCallback &browse); }; -ui::Label DialogLabel_new( const char* name ); -ui::Table DialogRow_new( const char* name, ui::Widget widget ); -void DialogVBox_packRow( ui::Box vbox, ui::Widget row ); +ui::Label DialogLabel_new(const char *name); + +ui::Table DialogRow_new(const char *name, ui::Widget widget); + +void DialogVBox_packRow(ui::Box vbox, ui::Widget row); #endif diff --git a/libs/gtkutil/filechooser.cpp b/libs/gtkutil/filechooser.cpp index 2e7a921a..03106b13 100644 --- a/libs/gtkutil/filechooser.cpp +++ b/libs/gtkutil/filechooser.cpp @@ -37,244 +37,251 @@ #include "messagebox.h" -struct filetype_pair_t -{ - filetype_pair_t() - : m_moduleName( "" ){ - } - filetype_pair_t( const char* moduleName, filetype_t type ) - : m_moduleName( moduleName ), m_type( type ){ - } - const char* m_moduleName; - filetype_t m_type; +struct filetype_pair_t { + filetype_pair_t() + : m_moduleName("") + { + } + + filetype_pair_t(const char *moduleName, filetype_t type) + : m_moduleName(moduleName), m_type(type) + { + } + + const char *m_moduleName; + filetype_t m_type; }; -class FileTypeList : public IFileTypeList -{ -struct filetype_copy_t -{ - filetype_copy_t( const filetype_pair_t& other ) - : m_moduleName( other.m_moduleName ), m_name( other.m_type.name ), m_pattern( other.m_type.pattern ){ - } - CopiedString m_moduleName; - CopiedString m_name; - CopiedString m_pattern; -}; +class FileTypeList : public IFileTypeList { + struct filetype_copy_t { + filetype_copy_t(const filetype_pair_t &other) + : m_moduleName(other.m_moduleName), m_name(other.m_type.name), m_pattern(other.m_type.pattern) + { + } + + CopiedString m_moduleName; + CopiedString m_name; + CopiedString m_pattern; + }; -typedef std::list Types; -Types m_types; + typedef std::list Types; + Types m_types; public: -typedef Types::const_iterator const_iterator; -const_iterator begin() const { - return m_types.begin(); -} -const_iterator end() const { - return m_types.end(); -} + typedef Types::const_iterator const_iterator; -std::size_t size() const { - return m_types.size(); -} + const_iterator begin() const + { + return m_types.begin(); + } -void addType( const char* moduleName, filetype_t type ){ - m_types.push_back( filetype_pair_t( moduleName, type ) ); -} + const_iterator end() const + { + return m_types.end(); + } + + std::size_t size() const + { + return m_types.size(); + } + + void addType(const char *moduleName, filetype_t type) + { + m_types.push_back(filetype_pair_t(moduleName, type)); + } }; -class GTKMasks -{ -const FileTypeList& m_types; +class GTKMasks { + const FileTypeList &m_types; public: -std::vector m_filters; -std::vector m_masks; - -GTKMasks( const FileTypeList& types ) : m_types( types ){ - m_masks.reserve( m_types.size() ); - for ( FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i ) - { - std::size_t len = strlen( ( *i ).m_name.c_str() ) + strlen( ( *i ).m_pattern.c_str() ) + 3; - StringOutputStream buffer( len + 1 ); // length + null char - - buffer << ( *i ).m_name.c_str() << " <" << ( *i ).m_pattern.c_str() << ">"; - - m_masks.push_back( buffer.c_str() ); - } - - m_filters.reserve( m_types.size() ); - for ( FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i ) - { - m_filters.push_back( ( *i ).m_pattern ); - } -} - -filetype_pair_t GetTypeForGTKMask( const char *mask ) const { - std::vector::const_iterator j = m_masks.begin(); - for ( FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i, ++j ) - { - if ( string_equal( ( *j ).c_str(), mask ) ) { - return filetype_pair_t( ( *i ).m_moduleName.c_str(), filetype_t( ( *i ).m_name.c_str(), ( *i ).m_pattern.c_str() ) ); - } - } - return filetype_pair_t(); -} + std::vector m_filters; + std::vector m_masks; + + GTKMasks(const FileTypeList &types) : m_types(types) + { + m_masks.reserve(m_types.size()); + for (FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i) { + std::size_t len = strlen((*i).m_name.c_str()) + strlen((*i).m_pattern.c_str()) + 3; + StringOutputStream buffer(len + 1); // length + null char + + buffer << (*i).m_name.c_str() << " <" << (*i).m_pattern.c_str() << ">"; + + m_masks.push_back(buffer.c_str()); + } + + m_filters.reserve(m_types.size()); + for (FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i) { + m_filters.push_back((*i).m_pattern); + } + } + + filetype_pair_t GetTypeForGTKMask(const char *mask) const + { + std::vector::const_iterator j = m_masks.begin(); + for (FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i, ++j) { + if (string_equal((*j).c_str(), mask)) { + return filetype_pair_t((*i).m_moduleName.c_str(), + filetype_t((*i).m_name.c_str(), (*i).m_pattern.c_str())); + } + } + return filetype_pair_t(); + } }; static char g_file_dialog_file[1024]; -const char* file_dialog_show( ui::Window parent, bool open, const char* title, const char* path, const char* pattern, bool want_load, bool want_import, bool want_save ){ - filetype_t type; - - if ( pattern == 0 ) { - pattern = "*"; - } - - FileTypeList typelist; - GlobalFiletypes().getTypeList( pattern, &typelist, want_load, want_import, want_save ); - - GTKMasks masks( typelist ); - - if ( title == 0 ) { - title = open ? "Open File" : "Save File"; - } - - ui::Dialog dialog{ui::null}; - if ( open ) { - dialog = ui::Dialog::from(gtk_file_chooser_dialog_new( title, - parent, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL )); - } - else - { - dialog = ui::Dialog::from(gtk_file_chooser_dialog_new( title, - parent, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL )); - gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER( dialog ), "unnamed" ); - } - - gtk_window_set_modal( dialog, TRUE ); - gtk_window_set_position( dialog, GTK_WIN_POS_CENTER_ON_PARENT ); - - // we expect an actual path below, if the path is 0 we might crash - if ( path != 0 && !string_empty( path ) ) { - ASSERT_MESSAGE( path_is_absolute( path ), "file_dialog_show: path not absolute: " << makeQuoted( path ) ); - - Array new_path( strlen( path ) + 1 ); - - // copy path, replacing dir separators as appropriate - Array::iterator w = new_path.begin(); - for ( const char* r = path; *r != '\0'; ++r ) - { - *w++ = ( *r == '/' ) ? G_DIR_SEPARATOR : *r; - } - // remove separator from end of path if required - if ( *( w - 1 ) == G_DIR_SEPARATOR ) { - --w; - } - // terminate string - *w = '\0'; - - gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( dialog ), new_path.data() ); - } - - // we should add all important paths as shortcut folder... - // gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(dialog), "/tmp/", NULL); - - - for ( std::size_t i = 0; i < masks.m_filters.size(); ++i ) - { - GtkFileFilter* filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern( filter, masks.m_filters[i].c_str() ); - gtk_file_filter_set_name( filter, masks.m_masks[i].c_str() ); - gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( dialog ), filter ); - } - - if ( gtk_dialog_run( GTK_DIALOG( dialog ) ) == GTK_RESPONSE_ACCEPT ) { - strcpy( g_file_dialog_file, gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ) ) ); - - if ( !string_equal( pattern, "*" ) ) { - GtkFileFilter* filter = gtk_file_chooser_get_filter( GTK_FILE_CHOOSER( dialog ) ); - if ( filter != 0 ) { // no filter set? some file-chooser implementations may allow the user to set no filter, which we treat as 'all files' - type = masks.GetTypeForGTKMask( gtk_file_filter_get_name( filter ) ).m_type; - // last ext separator - const char* extension = path_get_extension( g_file_dialog_file ); - // no extension - if ( string_empty( extension ) ) { - strcat( g_file_dialog_file, type.pattern + 1 ); - } - else - { - strcpy( g_file_dialog_file + ( extension - g_file_dialog_file ), type.pattern + 2 ); - } - } - } - - // convert back to unix format - for ( char* w = g_file_dialog_file; *w != '\0'; w++ ) - { - if ( *w == '\\' ) { - *w = '/'; - } - } - } - else - { - g_file_dialog_file[0] = '\0'; - } - - ui::Widget(dialog).destroy(); - - // don't return an empty filename - if ( g_file_dialog_file[0] == '\0' ) { - return NULL; - } - - return g_file_dialog_file; +const char * +file_dialog_show(ui::Window parent, bool open, const char *title, const char *path, const char *pattern, bool want_load, + bool want_import, bool want_save) +{ + filetype_t type; + + if (pattern == 0) { + pattern = "*"; + } + + FileTypeList typelist; + GlobalFiletypes().getTypeList(pattern, &typelist, want_load, want_import, want_save); + + GTKMasks masks(typelist); + + if (title == 0) { + title = open ? "Open File" : "Save File"; + } + + ui::Dialog dialog{ui::null}; + if (open) { + dialog = ui::Dialog::from(gtk_file_chooser_dialog_new(title, + parent, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL)); + } else { + dialog = ui::Dialog::from(gtk_file_chooser_dialog_new(title, + parent, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL)); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "unnamed"); + } + + gtk_window_set_modal(dialog, TRUE); + gtk_window_set_position(dialog, GTK_WIN_POS_CENTER_ON_PARENT); + + // we expect an actual path below, if the path is 0 we might crash + if (path != 0 && !string_empty(path)) { + ASSERT_MESSAGE(path_is_absolute(path), "file_dialog_show: path not absolute: " << makeQuoted(path)); + + Array new_path(strlen(path) + 1); + + // copy path, replacing dir separators as appropriate + Array::iterator w = new_path.begin(); + for (const char *r = path; *r != '\0'; ++r) { + *w++ = (*r == '/') ? G_DIR_SEPARATOR : *r; + } + // remove separator from end of path if required + if (*(w - 1) == G_DIR_SEPARATOR) { + --w; + } + // terminate string + *w = '\0'; + + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), new_path.data()); + } + + // we should add all important paths as shortcut folder... + // gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(dialog), "/tmp/", NULL); + + + for (std::size_t i = 0; i < masks.m_filters.size(); ++i) { + GtkFileFilter *filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(filter, masks.m_filters[i].c_str()); + gtk_file_filter_set_name(filter, masks.m_masks[i].c_str()); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + } + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + strcpy(g_file_dialog_file, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog))); + + if (!string_equal(pattern, "*")) { + GtkFileFilter *filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog)); + if (filter != + 0) { // no filter set? some file-chooser implementations may allow the user to set no filter, which we treat as 'all files' + type = masks.GetTypeForGTKMask(gtk_file_filter_get_name(filter)).m_type; + // last ext separator + const char *extension = path_get_extension(g_file_dialog_file); + // no extension + if (string_empty(extension)) { + strcat(g_file_dialog_file, type.pattern + 1); + } else { + strcpy(g_file_dialog_file + (extension - g_file_dialog_file), type.pattern + 2); + } + } + } + + // convert back to unix format + for (char *w = g_file_dialog_file; *w != '\0'; w++) { + if (*w == '\\') { + *w = '/'; + } + } + } else { + g_file_dialog_file[0] = '\0'; + } + + ui::Widget(dialog).destroy(); + + // don't return an empty filename + if (g_file_dialog_file[0] == '\0') { + return NULL; + } + + return g_file_dialog_file; } -char* dir_dialog( ui::Window parent, const char* title, const char* path ){ - auto dialog = ui::Dialog::from(gtk_file_chooser_dialog_new( title, - parent, - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL )); +char *dir_dialog(ui::Window parent, const char *title, const char *path) +{ + auto dialog = ui::Dialog::from(gtk_file_chooser_dialog_new(title, + parent, + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL)); - gtk_window_set_modal( dialog, TRUE ); - gtk_window_set_position( dialog, GTK_WIN_POS_CENTER_ON_PARENT ); + gtk_window_set_modal(dialog, TRUE); + gtk_window_set_position(dialog, GTK_WIN_POS_CENTER_ON_PARENT); - if ( !string_empty( path ) ) { - gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( dialog ), path ); - } + if (!string_empty(path)) { + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path); + } - char* filename = 0; - if ( gtk_dialog_run( GTK_DIALOG( dialog ) ) == GTK_RESPONSE_ACCEPT ) { - filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ) ); - } + char *filename = 0; + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + } - dialog.destroy(); + dialog.destroy(); - return filename; + return filename; } -const char* file_dialog( ui::Window parent, bool open, const char* title, const char* path, const char* pattern, bool want_load, bool want_import, bool want_save ){ - for (;; ) - { - const char* file = file_dialog_show( parent, open, title, path, pattern, want_load, want_import, want_save ); - - if ( open - || !file - || !file_exists( file ) - || ui::alert(parent, "The file specified already exists.\nDo you want to replace it?", title, ui::alert_type::NOYES, ui::alert_icon::Question ) == ui::alert_response::YES ) { - return file; - } - } +const char * +file_dialog(ui::Window parent, bool open, const char *title, const char *path, const char *pattern, bool want_load, + bool want_import, bool want_save) +{ + for (;;) { + const char *file = file_dialog_show(parent, open, title, path, pattern, want_load, want_import, want_save); + + if (open + || !file + || !file_exists(file) + || ui::alert(parent, "The file specified already exists.\nDo you want to replace it?", title, + ui::alert_type::NOYES, ui::alert_icon::Question) == ui::alert_response::YES) { + return file; + } + } } diff --git a/libs/gtkutil/filechooser.h b/libs/gtkutil/filechooser.h index cdad28b7..e2b2b25b 100644 --- a/libs/gtkutil/filechooser.h +++ b/libs/gtkutil/filechooser.h @@ -27,13 +27,14 @@ /// \file /// GTK+ file-chooser dialogs. -const char* file_dialog( ui::Window parent, bool open, const char* title, const char* path = 0, const char* pattern = 0, bool want_load = false, bool want_import = false, bool want_save = false ); +const char *file_dialog(ui::Window parent, bool open, const char *title, const char *path = 0, const char *pattern = 0, + bool want_load = false, bool want_import = false, bool want_save = false); /// \brief Prompts the user to browse for a directory. /// The prompt window will be transient to \p parent. /// The directory will initially default to \p path, which must be an absolute path. /// The returned string is allocated with \c g_malloc and must be freed with \c g_free. -char* dir_dialog( ui::Window parent, const char* title = "Choose Directory", const char* path = "" ); +char *dir_dialog(ui::Window parent, const char *title = "Choose Directory", const char *path = ""); #endif diff --git a/libs/gtkutil/frame.cpp b/libs/gtkutil/frame.cpp index 6baab763..c32db754 100644 --- a/libs/gtkutil/frame.cpp +++ b/libs/gtkutil/frame.cpp @@ -24,11 +24,12 @@ #include #include -ui::Frame create_framed_widget( ui::Widget widget ){ - auto frame = ui::Frame(); - frame.show(); - gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN ); - frame.add(widget); - widget.show(); - return frame; +ui::Frame create_framed_widget(ui::Widget widget) +{ + auto frame = ui::Frame(); + frame.show(); + gtk_frame_set_shadow_type(frame, GTK_SHADOW_IN); + frame.add(widget); + widget.show(); + return frame; } diff --git a/libs/gtkutil/frame.h b/libs/gtkutil/frame.h index ecdd7fcc..f35f9dc0 100644 --- a/libs/gtkutil/frame.h +++ b/libs/gtkutil/frame.h @@ -24,6 +24,6 @@ #if !defined( INCLUDED_GTKUTIL_FRAME_H ) #define INCLUDED_GTKUTIL_FRAME_H -ui::Frame create_framed_widget( ui::Widget widget ); +ui::Frame create_framed_widget(ui::Widget widget); #endif diff --git a/libs/gtkutil/glfont.cpp b/libs/gtkutil/glfont.cpp index afe8546e..8307f245 100644 --- a/libs/gtkutil/glfont.cpp +++ b/libs/gtkutil/glfont.cpp @@ -24,36 +24,49 @@ #include "igl.h" // generic string printing with call lists -class GLFontCallList : public GLFont -{ -GLuint m_displayList; -int m_pixelHeight; -int m_pixelAscent; -int m_pixelDescent; +class GLFontCallList : public GLFont { + GLuint m_displayList; + int m_pixelHeight; + int m_pixelAscent; + int m_pixelDescent; public: -GLFontCallList( GLuint displayList, int asc, int desc, int pixelHeight ) : m_displayList( displayList ), m_pixelHeight( pixelHeight ), m_pixelAscent( asc ), m_pixelDescent( desc ){ -} -virtual ~GLFontCallList(){ - glDeleteLists( m_displayList, 256 ); -} -void printString( const char *s ){ - GlobalOpenGL().m_glListBase( m_displayList ); - GlobalOpenGL().m_glCallLists( GLsizei( strlen( s ) ), GL_UNSIGNED_BYTE, reinterpret_cast( s ) ); -} -virtual int getPixelAscent() const { - return m_pixelAscent; -} -virtual int getPixelDescent() const { - return m_pixelDescent; -} -virtual int getPixelHeight() const { - return m_pixelHeight; -} + GLFontCallList(GLuint displayList, int asc, int desc, int pixelHeight) : m_displayList(displayList), + m_pixelHeight(pixelHeight), + m_pixelAscent(asc), m_pixelDescent(desc) + { + } + + virtual ~GLFontCallList() + { + glDeleteLists(m_displayList, 256); + } + + void printString(const char *s) + { + GlobalOpenGL().m_glListBase(m_displayList); + GlobalOpenGL().m_glCallLists(GLsizei(strlen(s)), GL_UNSIGNED_BYTE, reinterpret_cast( s )); + } + + virtual int getPixelAscent() const + { + return m_pixelAscent; + } + + virtual int getPixelDescent() const + { + return m_pixelDescent; + } + + virtual int getPixelHeight() const + { + return m_pixelHeight; + } }; #if GDEF_OS_WINDOWS - #include +#include #endif + #include "debugging/debugging.h" // LordHavoc: this is code for direct Xlib bitmap character fetching, as an @@ -69,58 +82,58 @@ virtual int getPixelHeight() const { #include GLFont *glfont_create( const char* font_string ){ - GLuint font_list_base; - XFontStruct *fontInfo; - Display *dpy = GDK_DISPLAY(); - unsigned int i, first, last, firstrow, lastrow; - int maxchars; - int firstbitmap; - - fontInfo = XLoadQueryFont( dpy, "-*-fixed-*-*-*-*-8-*-*-*-*-*-*-*" ); - if ( fontInfo == NULL ) { - // try to load other fonts - fontInfo = XLoadQueryFont( dpy, "-*-fixed-*-*-*-*-*-*-*-*-*-*-*-*" ); - - // any font will do ! - if ( fontInfo == NULL ) { - fontInfo = XLoadQueryFont( dpy, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" ); - } - - if ( fontInfo == NULL ) { - ERROR_MESSAGE( "couldn't create font" ); - } - } - - first = (int)fontInfo->min_char_or_byte2; - last = (int)fontInfo->max_char_or_byte2; - firstrow = (int)fontInfo->min_byte1; - lastrow = (int)fontInfo->max_byte1; - /* - * How many chars in the charset - */ - maxchars = 256 * lastrow + last; - font_list_base = glGenLists( maxchars + 1 ); - if ( font_list_base == 0 ) { - ERROR_MESSAGE( "couldn't create font" ); - } - - /* - * Get offset to first char in the charset - */ - firstbitmap = 256 * firstrow + first; - /* - * for each row of chars, call glXUseXFont to build the bitmaps. - */ - - for ( i = firstrow; i <= lastrow; i++ ) - { - glXUseXFont( fontInfo->fid, firstbitmap, last - first + 1, font_list_base + firstbitmap ); - firstbitmap += 256; - } + GLuint font_list_base; + XFontStruct *fontInfo; + Display *dpy = GDK_DISPLAY(); + unsigned int i, first, last, firstrow, lastrow; + int maxchars; + int firstbitmap; + + fontInfo = XLoadQueryFont( dpy, "-*-fixed-*-*-*-*-8-*-*-*-*-*-*-*" ); + if ( fontInfo == NULL ) { + // try to load other fonts + fontInfo = XLoadQueryFont( dpy, "-*-fixed-*-*-*-*-*-*-*-*-*-*-*-*" ); + + // any font will do ! + if ( fontInfo == NULL ) { + fontInfo = XLoadQueryFont( dpy, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" ); + } + + if ( fontInfo == NULL ) { + ERROR_MESSAGE( "couldn't create font" ); + } + } + + first = (int)fontInfo->min_char_or_byte2; + last = (int)fontInfo->max_char_or_byte2; + firstrow = (int)fontInfo->min_byte1; + lastrow = (int)fontInfo->max_byte1; + /* + * How many chars in the charset + */ + maxchars = 256 * lastrow + last; + font_list_base = glGenLists( maxchars + 1 ); + if ( font_list_base == 0 ) { + ERROR_MESSAGE( "couldn't create font" ); + } + + /* + * Get offset to first char in the charset + */ + firstbitmap = 256 * firstrow + first; + /* + * for each row of chars, call glXUseXFont to build the bitmaps. + */ + + for ( i = firstrow; i <= lastrow; i++ ) + { + glXUseXFont( fontInfo->fid, firstbitmap, last - first + 1, font_list_base + firstbitmap ); + firstbitmap += 256; + } /* *height = fontInfo->ascent + fontInfo->descent; *width = fontInfo->max_bounds.width; */ - return new GLFontCallList( font_list_base, fontInfo->ascent, fontInfo->descent, fontInfo->ascent + fontInfo->descent ); + return new GLFontCallList( font_list_base, fontInfo->ascent, fontInfo->descent, fontInfo->ascent + fontInfo->descent ); } #elif 0 @@ -128,47 +141,47 @@ GLFont *glfont_create( const char* font_string ){ #include GLFont *glfont_create( const char* font_string ){ - GLuint font_list_base = glGenLists( 256 ); - gint font_height = 0, font_ascent = 0, font_descent = 0; + GLuint font_list_base = glGenLists( 256 ); + gint font_height = 0, font_ascent = 0, font_descent = 0; - PangoFontDescription* font_desc = pango_font_description_from_string( font_string ); + PangoFontDescription* font_desc = pango_font_description_from_string( font_string ); - PangoFont* font = gdk_gl_font_use_pango_font( font_desc, 0, 256, font_list_base ); + PangoFont* font = gdk_gl_font_use_pango_font( font_desc, 0, 256, font_list_base ); - if ( font == 0 ) { - pango_font_description_free( font_desc ); - font_desc = pango_font_description_from_string( "fixed 8" ); - font = gdk_gl_font_use_pango_font( font_desc, 0, 256, font_list_base ); - } + if ( font == 0 ) { + pango_font_description_free( font_desc ); + font_desc = pango_font_description_from_string( "fixed 8" ); + font = gdk_gl_font_use_pango_font( font_desc, 0, 256, font_list_base ); + } - if ( font == 0 ) { - pango_font_description_free( font_desc ); - font_desc = pango_font_description_from_string( "courier new 8" ); - font = gdk_gl_font_use_pango_font( font_desc, 0, 256, font_list_base ); - } + if ( font == 0 ) { + pango_font_description_free( font_desc ); + font_desc = pango_font_description_from_string( "courier new 8" ); + font = gdk_gl_font_use_pango_font( font_desc, 0, 256, font_list_base ); + } - if ( font != 0 ) { - PangoFontMetrics* font_metrics = pango_font_get_metrics( font, 0 ); + if ( font != 0 ) { + PangoFontMetrics* font_metrics = pango_font_get_metrics( font, 0 ); - font_ascent = pango_font_metrics_get_ascent( font_metrics ); - font_descent = pango_font_metrics_get_descent( font_metrics ); - font_height = font_ascent + font_descent; + font_ascent = pango_font_metrics_get_ascent( font_metrics ); + font_descent = pango_font_metrics_get_descent( font_metrics ); + font_height = font_ascent + font_descent; - font_ascent = PANGO_PIXELS( font_ascent ); - font_descent = PANGO_PIXELS( font_descent ); - font_height = PANGO_PIXELS( font_height ); + font_ascent = PANGO_PIXELS( font_ascent ); + font_descent = PANGO_PIXELS( font_descent ); + font_height = PANGO_PIXELS( font_height ); - pango_font_metrics_unref( font_metrics ); - } + pango_font_metrics_unref( font_metrics ); + } - pango_font_description_free( font_desc ); + pango_font_description_free( font_desc ); - // fix for pango/gtkglext metrix bug - if ( font_height > 256 ) { - font_height = 16; - } + // fix for pango/gtkglext metrix bug + if ( font_height > 256 ) { + font_height = 16; + } - return new GLFontCallList( font_list_base, font_ascent, font_descent, font_height ); + return new GLFontCallList( font_list_base, font_ascent, font_descent, font_height ); } #else @@ -178,67 +191,68 @@ GLFont *glfont_create( const char* font_string ){ #include #include -class GLFontInternal : public GLFont -{ -const char *font_string; -int font_height; -int font_ascent; -int font_descent; -int y_offset_bitmap_render_pango_units; -PangoContext *ft2_context; -PangoFontMap *fontmap; +class GLFontInternal : public GLFont { + const char *font_string; + int font_height; + int font_ascent; + int font_descent; + int y_offset_bitmap_render_pango_units; + PangoContext *ft2_context; + PangoFontMap *fontmap; public: -GLFontInternal( const char *_font_string ) : font_string( _font_string ){ - PangoFontDescription *font_desc; - PangoLayout *layout; - PangoRectangle log_rect; - int font_ascent_pango_units; - int font_descent_pango_units; - -#if !PANGO_VERSION_CHECK( 1,22,0 ) - ft2_context = pango_ft2_get_context( 72, 72 ); + GLFontInternal(const char *_font_string) : font_string(_font_string) + { + PangoFontDescription *font_desc; + PangoLayout *layout; + PangoRectangle log_rect; + int font_ascent_pango_units; + int font_descent_pango_units; + +#if !PANGO_VERSION_CHECK(1, 22, 0) + ft2_context = pango_ft2_get_context( 72, 72 ); #else - fontmap = pango_ft2_font_map_new(); - pango_ft2_font_map_set_resolution( PANGO_FT2_FONT_MAP( fontmap ), 72, 72 ); - ft2_context = pango_font_map_create_context( fontmap ); + fontmap = pango_ft2_font_map_new(); + pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontmap), 72, 72); + ft2_context = pango_font_map_create_context(fontmap); #endif - font_desc = pango_font_description_from_string( font_string ); - //pango_font_description_set_size(font_desc, 10 * PANGO_SCALE); - pango_context_set_font_description( ft2_context, font_desc ); - pango_font_description_free( font_desc ); - // TODO fallback to fixed 8, courier new 8 + font_desc = pango_font_description_from_string(font_string); + //pango_font_description_set_size(font_desc, 10 * PANGO_SCALE); + pango_context_set_font_description(ft2_context, font_desc); + pango_font_description_free(font_desc); + // TODO fallback to fixed 8, courier new 8 - layout = pango_layout_new( ft2_context ); + layout = pango_layout_new(ft2_context); #ifdef FONT_SIZE_WORKAROUND - pango_layout_set_width( layout, -1 ); // -1 no wrapping. All text on one line. - pango_layout_set_text( layout, "The quick brown fox jumped over the lazy sleeping dog's back then sat on a tack.", -1 ); // -1 null-terminated string. + pango_layout_set_width( layout, -1 ); // -1 no wrapping. All text on one line. + pango_layout_set_text( layout, "The quick brown fox jumped over the lazy sleeping dog's back then sat on a tack.", -1 ); // -1 null-terminated string. #endif -#if !PANGO_VERSION_CHECK( 1,22,0 ) - PangoLayoutIter *iter; - iter = pango_layout_get_iter( layout ); - font_ascent_pango_units = pango_layout_iter_get_baseline( iter ); - pango_layout_iter_free( iter ); +#if !PANGO_VERSION_CHECK(1, 22, 0) + PangoLayoutIter *iter; + iter = pango_layout_get_iter( layout ); + font_ascent_pango_units = pango_layout_iter_get_baseline( iter ); + pango_layout_iter_free( iter ); #else - font_ascent_pango_units = pango_layout_get_baseline( layout ); + font_ascent_pango_units = pango_layout_get_baseline(layout); #endif - pango_layout_get_extents( layout, NULL, &log_rect ); - g_object_unref( G_OBJECT( layout ) ); - font_descent_pango_units = log_rect.height - font_ascent_pango_units; - - font_ascent = PANGO_PIXELS_CEIL( font_ascent_pango_units ); - font_descent = PANGO_PIXELS_CEIL( font_descent_pango_units ); - font_height = font_ascent + font_descent; - y_offset_bitmap_render_pango_units = ( font_ascent * PANGO_SCALE ) - font_ascent_pango_units; -} - -virtual ~GLFontInternal(){ - g_object_unref( G_OBJECT( ft2_context ) ); - g_object_unref( G_OBJECT( fontmap ) ); -} + pango_layout_get_extents(layout, NULL, &log_rect); + g_object_unref(G_OBJECT(layout)); + font_descent_pango_units = log_rect.height - font_ascent_pango_units; + + font_ascent = PANGO_PIXELS_CEIL(font_ascent_pango_units); + font_descent = PANGO_PIXELS_CEIL(font_descent_pango_units); + font_height = font_ascent + font_descent; + y_offset_bitmap_render_pango_units = (font_ascent * PANGO_SCALE) - font_ascent_pango_units; + } + + virtual ~GLFontInternal() + { + g_object_unref(G_OBJECT(ft2_context)); + g_object_unref(G_OBJECT(fontmap)); + } // Renders the input text at the current location with the current color. // The X position of the current location is used to place the left edge of the text image, @@ -250,92 +264,99 @@ virtual ~GLFontInternal(){ // just a hair outside of the viewport (meaning the current raster position is invalid), // then no text will be rendered. The solution to this is a very hacky one. You can search // Google for "glDrawPixels clipping". -virtual void printString( const char *s ){ - // The idea for this code initially came from the font-pangoft2.c example that comes with GtkGLExt. - - PangoLayout *layout; - PangoRectangle log_rect; - FT_Bitmap bitmap; - unsigned char *begin_bitmap_buffer; - GLfloat color[4]; - GLint previous_unpack_alignment; - GLboolean previous_blend_enabled; - GLint previous_blend_func_src; - GLint previous_blend_func_dst; - GLfloat previous_red_bias; - GLfloat previous_green_bias; - GLfloat previous_blue_bias; - GLfloat previous_alpha_scale; - - layout = pango_layout_new( ft2_context ); - pango_layout_set_width( layout, -1 ); // -1 no wrapping. All text on one line. - pango_layout_set_text( layout, s, -1 ); // -1 null-terminated string. - pango_layout_get_extents( layout, NULL, &log_rect ); - - if ( log_rect.width > 0 && log_rect.height > 0 ) { - bitmap.rows = font_ascent + font_descent; - bitmap.width = PANGO_PIXELS_CEIL( log_rect.width ); - bitmap.pitch = -bitmap.width; // Rendering it "upside down" for OpenGL. - begin_bitmap_buffer = (unsigned char *) g_malloc( bitmap.rows * bitmap.width ); - memset( begin_bitmap_buffer, 0, bitmap.rows * bitmap.width ); - bitmap.buffer = begin_bitmap_buffer + ( bitmap.rows - 1 ) * bitmap.width; // See pitch above. - bitmap.num_grays = 0xff; - bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; - pango_ft2_render_layout_subpixel( &bitmap, layout, -log_rect.x, - y_offset_bitmap_render_pango_units ); - GlobalOpenGL().m_glGetFloatv( GL_CURRENT_COLOR, color ); - - // Save state. I didn't see any OpenGL push/pop operations for these. - // Question: Is saving/restoring this state necessary? Being safe. - GlobalOpenGL().m_glGetIntegerv( GL_UNPACK_ALIGNMENT, &previous_unpack_alignment ); - previous_blend_enabled = GlobalOpenGL().m_glIsEnabled( GL_BLEND ); - GlobalOpenGL().m_glGetIntegerv( GL_BLEND_SRC, &previous_blend_func_src ); - GlobalOpenGL().m_glGetIntegerv( GL_BLEND_DST, &previous_blend_func_dst ); - GlobalOpenGL().m_glGetFloatv( GL_RED_BIAS, &previous_red_bias ); - GlobalOpenGL().m_glGetFloatv( GL_GREEN_BIAS, &previous_green_bias ); - GlobalOpenGL().m_glGetFloatv( GL_BLUE_BIAS, &previous_blue_bias ); - GlobalOpenGL().m_glGetFloatv( GL_ALPHA_SCALE, &previous_alpha_scale ); - - GlobalOpenGL().m_glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); - GlobalOpenGL().m_glEnable( GL_BLEND ); - GlobalOpenGL().m_glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - GlobalOpenGL().m_glPixelTransferf( GL_RED_BIAS, color[0] ); - GlobalOpenGL().m_glPixelTransferf( GL_GREEN_BIAS, color[1] ); - GlobalOpenGL().m_glPixelTransferf( GL_BLUE_BIAS, color[2] ); - GlobalOpenGL().m_glPixelTransferf( GL_ALPHA_SCALE, color[3] ); - - GlobalOpenGL().m_glDrawPixels( bitmap.width, bitmap.rows, - GL_ALPHA, GL_UNSIGNED_BYTE, begin_bitmap_buffer ); - g_free( begin_bitmap_buffer ); - - // Restore state in reverse order of how we set it. - GlobalOpenGL().m_glPixelTransferf( GL_ALPHA_SCALE, previous_alpha_scale ); - GlobalOpenGL().m_glPixelTransferf( GL_BLUE_BIAS, previous_blue_bias ); - GlobalOpenGL().m_glPixelTransferf( GL_GREEN_BIAS, previous_green_bias ); - GlobalOpenGL().m_glPixelTransferf( GL_RED_BIAS, previous_red_bias ); - GlobalOpenGL().m_glBlendFunc( previous_blend_func_src, previous_blend_func_dst ); - if ( !previous_blend_enabled ) { - GlobalOpenGL().m_glDisable( GL_BLEND ); - } - GlobalOpenGL().m_glPixelStorei( GL_UNPACK_ALIGNMENT, previous_unpack_alignment ); - } - - g_object_unref( G_OBJECT( layout ) ); -} - -virtual int getPixelAscent() const { - return font_ascent; -} -virtual int getPixelDescent() const { - return font_descent; -} -virtual int getPixelHeight() const { - return font_height; -} + virtual void printString(const char *s) + { + // The idea for this code initially came from the font-pangoft2.c example that comes with GtkGLExt. + + PangoLayout *layout; + PangoRectangle log_rect; + FT_Bitmap bitmap; + unsigned char *begin_bitmap_buffer; + GLfloat color[4]; + GLint previous_unpack_alignment; + GLboolean previous_blend_enabled; + GLint previous_blend_func_src; + GLint previous_blend_func_dst; + GLfloat previous_red_bias; + GLfloat previous_green_bias; + GLfloat previous_blue_bias; + GLfloat previous_alpha_scale; + + layout = pango_layout_new(ft2_context); + pango_layout_set_width(layout, -1); // -1 no wrapping. All text on one line. + pango_layout_set_text(layout, s, -1); // -1 null-terminated string. + pango_layout_get_extents(layout, NULL, &log_rect); + + if (log_rect.width > 0 && log_rect.height > 0) { + bitmap.rows = font_ascent + font_descent; + bitmap.width = PANGO_PIXELS_CEIL(log_rect.width); + bitmap.pitch = -bitmap.width; // Rendering it "upside down" for OpenGL. + begin_bitmap_buffer = (unsigned char *) g_malloc(bitmap.rows * bitmap.width); + memset(begin_bitmap_buffer, 0, bitmap.rows * bitmap.width); + bitmap.buffer = begin_bitmap_buffer + (bitmap.rows - 1) * bitmap.width; // See pitch above. + bitmap.num_grays = 0xff; + bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; + pango_ft2_render_layout_subpixel(&bitmap, layout, -log_rect.x, + y_offset_bitmap_render_pango_units); + GlobalOpenGL().m_glGetFloatv(GL_CURRENT_COLOR, color); + + // Save state. I didn't see any OpenGL push/pop operations for these. + // Question: Is saving/restoring this state necessary? Being safe. + GlobalOpenGL().m_glGetIntegerv(GL_UNPACK_ALIGNMENT, &previous_unpack_alignment); + previous_blend_enabled = GlobalOpenGL().m_glIsEnabled(GL_BLEND); + GlobalOpenGL().m_glGetIntegerv(GL_BLEND_SRC, &previous_blend_func_src); + GlobalOpenGL().m_glGetIntegerv(GL_BLEND_DST, &previous_blend_func_dst); + GlobalOpenGL().m_glGetFloatv(GL_RED_BIAS, &previous_red_bias); + GlobalOpenGL().m_glGetFloatv(GL_GREEN_BIAS, &previous_green_bias); + GlobalOpenGL().m_glGetFloatv(GL_BLUE_BIAS, &previous_blue_bias); + GlobalOpenGL().m_glGetFloatv(GL_ALPHA_SCALE, &previous_alpha_scale); + + GlobalOpenGL().m_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GlobalOpenGL().m_glEnable(GL_BLEND); + GlobalOpenGL().m_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GlobalOpenGL().m_glPixelTransferf(GL_RED_BIAS, color[0]); + GlobalOpenGL().m_glPixelTransferf(GL_GREEN_BIAS, color[1]); + GlobalOpenGL().m_glPixelTransferf(GL_BLUE_BIAS, color[2]); + GlobalOpenGL().m_glPixelTransferf(GL_ALPHA_SCALE, color[3]); + + GlobalOpenGL().m_glDrawPixels(bitmap.width, bitmap.rows, + GL_ALPHA, GL_UNSIGNED_BYTE, begin_bitmap_buffer); + g_free(begin_bitmap_buffer); + + // Restore state in reverse order of how we set it. + GlobalOpenGL().m_glPixelTransferf(GL_ALPHA_SCALE, previous_alpha_scale); + GlobalOpenGL().m_glPixelTransferf(GL_BLUE_BIAS, previous_blue_bias); + GlobalOpenGL().m_glPixelTransferf(GL_GREEN_BIAS, previous_green_bias); + GlobalOpenGL().m_glPixelTransferf(GL_RED_BIAS, previous_red_bias); + GlobalOpenGL().m_glBlendFunc(previous_blend_func_src, previous_blend_func_dst); + if (!previous_blend_enabled) { + GlobalOpenGL().m_glDisable(GL_BLEND); + } + GlobalOpenGL().m_glPixelStorei(GL_UNPACK_ALIGNMENT, previous_unpack_alignment); + } + + g_object_unref(G_OBJECT(layout)); + } + + virtual int getPixelAscent() const + { + return font_ascent; + } + + virtual int getPixelDescent() const + { + return font_descent; + } + + virtual int getPixelHeight() const + { + return font_height; + } }; -GLFont *glfont_create( const char* font_string ){ - return new GLFontInternal( font_string ); +GLFont *glfont_create(const char *font_string) +{ + return new GLFontInternal(font_string); } #endif diff --git a/libs/gtkutil/glfont.h b/libs/gtkutil/glfont.h index 06bfd4cd..ca39a6a8 100644 --- a/libs/gtkutil/glfont.h +++ b/libs/gtkutil/glfont.h @@ -24,18 +24,22 @@ typedef unsigned int GLuint; -class GLFont -{ +class GLFont { public: -virtual int getPixelHeight() const = 0; -virtual int getPixelAscent() const = 0; -virtual int getPixelDescent() const = 0; -virtual void printString( const char *s ) = 0; -virtual ~GLFont(){ -} + virtual int getPixelHeight() const = 0; + + virtual int getPixelAscent() const = 0; + + virtual int getPixelDescent() const = 0; + + virtual void printString(const char *s) = 0; + + virtual ~GLFont() + { + } }; -GLFont *glfont_create( const char* font_string ); +GLFont *glfont_create(const char *font_string); // release with delete #endif diff --git a/libs/gtkutil/glwidget.h b/libs/gtkutil/glwidget.h index 6a43da88..c0bbff4d 100644 --- a/libs/gtkutil/glwidget.h +++ b/libs/gtkutil/glwidget.h @@ -25,12 +25,17 @@ #define INCLUDED_GTKUTIL_GLWIDGET_H extern void (*GLWidget_sharedContextCreated)(); + extern void (*GLWidget_sharedContextDestroyed)(); ui::GLArea glwidget_new(bool zbuffer); + void glwidget_create_context(ui::GLArea self); + void glwidget_destroy_context(ui::GLArea self); + bool glwidget_make_current(ui::GLArea self); + void glwidget_swap_buffers(ui::GLArea self); #endif diff --git a/libs/gtkutil/idledraw.h b/libs/gtkutil/idledraw.h index 97791023..6c298366 100644 --- a/libs/gtkutil/idledraw.h +++ b/libs/gtkutil/idledraw.h @@ -26,35 +26,44 @@ #include "generic/callback.h" -class IdleDraw -{ -Callback m_draw; -unsigned int m_handler; -static gboolean draw( gpointer data ){ - reinterpret_cast( data )->m_draw(); - reinterpret_cast( data )->m_handler = 0; - return FALSE; -} +class IdleDraw { + Callback m_draw; + unsigned int m_handler; + + static gboolean draw(gpointer data) + { + reinterpret_cast( data )->m_draw(); + reinterpret_cast( data )->m_handler = 0; + return FALSE; + } + public: -IdleDraw( const Callback& draw ) : m_draw( draw ), m_handler( 0 ){ -} -~IdleDraw(){ - if ( m_handler != 0 ) { - g_source_remove( m_handler ); - } -} -void queueDraw(){ - if ( m_handler == 0 ) { - m_handler = g_idle_add( &draw, this ); - } -} -typedef MemberCaller QueueDrawCaller; - -void flush(){ - if ( m_handler != 0 ) { - draw( this ); - } -} + IdleDraw(const Callback &draw) : m_draw(draw), m_handler(0) + { + } + + ~IdleDraw() + { + if (m_handler != 0) { + g_source_remove(m_handler); + } + } + + void queueDraw() + { + if (m_handler == 0) { + m_handler = g_idle_add(&draw, this); + } + } + + typedef MemberCaller QueueDrawCaller; + + void flush() + { + if (m_handler != 0) { + draw(this); + } + } }; diff --git a/libs/gtkutil/image.cpp b/libs/gtkutil/image.cpp index 210b055c..16c03c54 100644 --- a/libs/gtkutil/image.cpp +++ b/libs/gtkutil/image.cpp @@ -28,54 +28,55 @@ #include "stream/textstream.h" -namespace -{ -CopiedString g_bitmapsPath; +namespace { + CopiedString g_bitmapsPath; } -void BitmapsPath_set( const char* path ){ - g_bitmapsPath = path; +void BitmapsPath_set(const char *path) +{ + g_bitmapsPath = path; } -GdkPixbuf* pixbuf_new_from_file_with_mask( const char* filename ){ - GdkPixbuf* rgb = gdk_pixbuf_new_from_file( filename, 0 ); - if ( rgb == 0 ) { - return 0; - } - else - { - GdkPixbuf* rgba = gdk_pixbuf_add_alpha( rgb, FALSE, 255, 0, 255 ); - g_object_unref( rgb ); - return rgba; - } +GdkPixbuf *pixbuf_new_from_file_with_mask(const char *filename) +{ + GdkPixbuf *rgb = gdk_pixbuf_new_from_file(filename, 0); + if (rgb == 0) { + return 0; + } else { + GdkPixbuf *rgba = gdk_pixbuf_add_alpha(rgb, FALSE, 255, 0, 255); + g_object_unref(rgb); + return rgba; + } } -ui::Image image_new_from_file_with_mask( const char* filename ){ - GdkPixbuf* rgba = pixbuf_new_from_file_with_mask( filename ); - if ( rgba == 0 ) { - return ui::Image(ui::null); - } - else - { - auto image = ui::Image::from( gtk_image_new_from_pixbuf( rgba ) ); - g_object_unref( rgba ); - return image; - } +ui::Image image_new_from_file_with_mask(const char *filename) +{ + GdkPixbuf *rgba = pixbuf_new_from_file_with_mask(filename); + if (rgba == 0) { + return ui::Image(ui::null); + } else { + auto image = ui::Image::from(gtk_image_new_from_pixbuf(rgba)); + g_object_unref(rgba); + return image; + } } -ui::Image image_new_missing(){ - return ui::Image::from( gtk_image_new_from_stock( GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_SMALL_TOOLBAR ) ); +ui::Image image_new_missing() +{ + return ui::Image::from(gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_SMALL_TOOLBAR)); } -ui::Image new_image( const char* filename ){ - if ( auto image = image_new_from_file_with_mask( filename ) ) { - return image; - } - return image_new_missing(); +ui::Image new_image(const char *filename) +{ + if (auto image = image_new_from_file_with_mask(filename)) { + return image; + } + return image_new_missing(); } -ui::Image new_local_image( const char* filename ){ - StringOutputStream fullPath( 256 ); - fullPath << g_bitmapsPath.c_str() << filename; - return new_image( fullPath.c_str() ); +ui::Image new_local_image(const char *filename) +{ + StringOutputStream fullPath(256); + fullPath << g_bitmapsPath.c_str() << filename; + return new_image(fullPath.c_str()); } diff --git a/libs/gtkutil/image.h b/libs/gtkutil/image.h index 6a8d419b..6604df2e 100644 --- a/libs/gtkutil/image.h +++ b/libs/gtkutil/image.h @@ -24,14 +24,17 @@ #if !defined( INCLUDED_GTKUTIL_IMAGE_H ) #define INCLUDED_GTKUTIL_IMAGE_H -void BitmapsPath_set( const char* path ); +void BitmapsPath_set(const char *path); typedef struct _GdkPixbuf GdkPixbuf; -GdkPixbuf* pixbuf_new_from_file_with_mask( const char* filename ); -ui::Image image_new_from_file_with_mask( const char* filename ); +GdkPixbuf *pixbuf_new_from_file_with_mask(const char *filename); + +ui::Image image_new_from_file_with_mask(const char *filename); + ui::Image image_new_missing(); -ui::Image new_image( const char* filename ); // filename is full path to image file -ui::Image new_local_image( const char* filename ); // filename is relative to local bitmaps path + +ui::Image new_image(const char *filename); // filename is full path to image file +ui::Image new_local_image(const char *filename); // filename is relative to local bitmaps path #endif diff --git a/libs/gtkutil/menu.cpp b/libs/gtkutil/menu.cpp index 2a8c55fb..8cd72a96 100644 --- a/libs/gtkutil/menu.cpp +++ b/libs/gtkutil/menu.cpp @@ -33,219 +33,243 @@ #include "container.h" #include "pointer.h" -void menu_add_item( ui::Menu menu, ui::MenuItem item ){ - menu.add(item); +void menu_add_item(ui::Menu menu, ui::MenuItem item) +{ + menu.add(item); } -ui::MenuItem menu_separator( ui::Menu menu ){ - auto menu_item = ui::MenuItem::from( gtk_menu_item_new() ); - menu.add(menu_item); - gtk_widget_set_sensitive( menu_item , FALSE ); - menu_item.show(); - return menu_item; +ui::MenuItem menu_separator(ui::Menu menu) +{ + auto menu_item = ui::MenuItem::from(gtk_menu_item_new()); + menu.add(menu_item); + gtk_widget_set_sensitive(menu_item, FALSE); + menu_item.show(); + return menu_item; } -ui::TearoffMenuItem menu_tearoff( ui::Menu menu ){ - auto menu_item = ui::TearoffMenuItem::from( gtk_tearoff_menu_item_new() ); - menu.add(menu_item); +ui::TearoffMenuItem menu_tearoff(ui::Menu menu) +{ + auto menu_item = ui::TearoffMenuItem::from(gtk_tearoff_menu_item_new()); + menu.add(menu_item); // gtk_widget_set_sensitive(menu_item, FALSE); -- controls whether menu is detachable - menu_item.show(); - return menu_item; + menu_item.show(); + return menu_item; } -ui::MenuItem new_sub_menu_item_with_mnemonic( const char* mnemonic ){ - auto item = ui::MenuItem( mnemonic, true ); - item.show(); +ui::MenuItem new_sub_menu_item_with_mnemonic(const char *mnemonic) +{ + auto item = ui::MenuItem(mnemonic, true); + item.show(); - auto sub_menu = ui::Menu(ui::New); - gtk_menu_item_set_submenu( item, sub_menu ); + auto sub_menu = ui::Menu(ui::New); + gtk_menu_item_set_submenu(item, sub_menu); - return item; + return item; } -ui::Menu create_sub_menu_with_mnemonic( ui::MenuShell parent, const char* mnemonic ){ - auto item = new_sub_menu_item_with_mnemonic( mnemonic ); - parent.add(item); - return ui::Menu::from( gtk_menu_item_get_submenu( item ) ); +ui::Menu create_sub_menu_with_mnemonic(ui::MenuShell parent, const char *mnemonic) +{ + auto item = new_sub_menu_item_with_mnemonic(mnemonic); + parent.add(item); + return ui::Menu::from(gtk_menu_item_get_submenu(item)); } -ui::Menu create_sub_menu_with_mnemonic( ui::MenuBar bar, const char* mnemonic ){ - return create_sub_menu_with_mnemonic( ui::MenuShell::from( bar._handle ), mnemonic ); +ui::Menu create_sub_menu_with_mnemonic(ui::MenuBar bar, const char *mnemonic) +{ + return create_sub_menu_with_mnemonic(ui::MenuShell::from(bar._handle), mnemonic); } -ui::Menu create_sub_menu_with_mnemonic( ui::Menu parent, const char* mnemonic ){ - return create_sub_menu_with_mnemonic( ui::MenuShell::from( parent._handle ), mnemonic ); +ui::Menu create_sub_menu_with_mnemonic(ui::Menu parent, const char *mnemonic) +{ + return create_sub_menu_with_mnemonic(ui::MenuShell::from(parent._handle), mnemonic); } -void activate_closure_callback( ui::Widget widget, gpointer data ){ - ( *reinterpret_cast*>( data ) )( ); +void activate_closure_callback(ui::Widget widget, gpointer data) +{ + (*reinterpret_cast *>( data ))(); } -guint menu_item_connect_callback( ui::MenuItem item, const Callback& callback ){ +guint menu_item_connect_callback(ui::MenuItem item, const Callback &callback) +{ #if 1 - return g_signal_connect_swapped( G_OBJECT( item ), "activate", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() ); + return g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(callback.getThunk()), + callback.getEnvironment()); #else - return g_signal_connect_closure( G_OBJECT( item ), "activate", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), FALSE ); + return g_signal_connect_closure( G_OBJECT( item ), "activate", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), FALSE ); #endif } -guint check_menu_item_connect_callback( ui::CheckMenuItem item, const Callback& callback ){ +guint check_menu_item_connect_callback(ui::CheckMenuItem item, const Callback &callback) +{ #if 1 - guint handler = g_signal_connect_swapped( G_OBJECT( item ), "toggled", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() ); + guint handler = g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(callback.getThunk()), + callback.getEnvironment()); #else - guint handler = g_signal_connect_closure( G_OBJECT( item ), "toggled", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), TRUE ); + guint handler = g_signal_connect_closure( G_OBJECT( item ), "toggled", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), TRUE ); #endif - g_object_set_data( G_OBJECT( item ), "handler", gint_to_pointer( handler ) ); - return handler; -} - -ui::MenuItem new_menu_item_with_mnemonic( const char *mnemonic, const Callback& callback ){ - auto item = ui::MenuItem( mnemonic, true ); - item.show(); - menu_item_connect_callback( item, callback ); - return item; -} - -ui::MenuItem create_menu_item_with_mnemonic( ui::Menu menu, const char *mnemonic, const Callback& callback ){ - auto item = new_menu_item_with_mnemonic( mnemonic, callback ); - menu.add(item); - return item; -} - -ui::CheckMenuItem new_check_menu_item_with_mnemonic( const char* mnemonic, const Callback& callback ){ - auto item = ui::CheckMenuItem::from( gtk_check_menu_item_new_with_mnemonic( mnemonic ) ); - item.show(); - check_menu_item_connect_callback( item, callback ); - return item; -} - -ui::CheckMenuItem create_check_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Callback& callback ){ - auto item = new_check_menu_item_with_mnemonic( mnemonic, callback ); - menu.add(item); - return item; -} - -ui::RadioMenuItem new_radio_menu_item_with_mnemonic( GSList** group, const char* mnemonic, const Callback& callback ){ - auto item = ui::RadioMenuItem::from( gtk_radio_menu_item_new_with_mnemonic( *group, mnemonic ) ); - if ( *group == 0 ) { - gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), TRUE ); - } - *group = gtk_radio_menu_item_get_group( item ); - item.show(); - check_menu_item_connect_callback( item, callback ); - return item; -} - -ui::RadioMenuItem create_radio_menu_item_with_mnemonic( ui::Menu menu, GSList** group, const char* mnemonic, const Callback& callback ){ - auto item = new_radio_menu_item_with_mnemonic( group, mnemonic, callback ); - menu.add(item); - return item; -} - -void check_menu_item_set_active_no_signal( ui::CheckMenuItem item, gboolean active ){ - guint handler_id = gpointer_to_int( g_object_get_data( G_OBJECT( item ), "handler" ) ); - g_signal_handler_block( G_OBJECT( item ), handler_id ); - gtk_check_menu_item_set_active( item, active ); - g_signal_handler_unblock( G_OBJECT( item ), handler_id ); -} - - - -void radio_menu_item_set_active_no_signal( ui::RadioMenuItem item, gboolean active ){ - { - for ( GSList* l = gtk_radio_menu_item_get_group( item ); l != 0; l = g_slist_next( l ) ) - { - g_signal_handler_block( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) ); - } - } - gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), active ); - { - for ( GSList* l = gtk_radio_menu_item_get_group( item ); l != 0; l = g_slist_next( l ) ) - { - g_signal_handler_unblock( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) ); - } - } -} - - -void menu_item_set_accelerator( ui::MenuItem item, GClosure* closure ){ - GtkAccelLabel* accel_label = GTK_ACCEL_LABEL( gtk_bin_get_child( GTK_BIN( item ) ) ); - gtk_accel_label_set_accel_closure( accel_label, closure ); -} - -void accelerator_name( const Accelerator& accelerator, GString* gstring ){ - gboolean had_mod = FALSE; - if ( accelerator.modifiers & GDK_SHIFT_MASK ) { - g_string_append( gstring, "Shift" ); - had_mod = TRUE; - } - if ( accelerator.modifiers & GDK_CONTROL_MASK ) { - if ( had_mod ) { - g_string_append( gstring, "+" ); - } - g_string_append( gstring, "Ctrl" ); - had_mod = TRUE; - } - if ( accelerator.modifiers & GDK_MOD1_MASK ) { - if ( had_mod ) { - g_string_append( gstring, "+" ); - } - g_string_append( gstring, "Alt" ); - had_mod = TRUE; - } - - if ( had_mod ) { - g_string_append( gstring, "+" ); - } - if ( accelerator.key < 0x80 || ( accelerator.key > 0x80 && accelerator.key <= 0xff ) ) { - switch ( accelerator.key ) - { - case ' ': - g_string_append( gstring, "Space" ); - break; - case '\\': - g_string_append( gstring, "Backslash" ); - break; - default: - g_string_append_c( gstring, gchar( toupper( accelerator.key ) ) ); - break; - } - } - else - { - gchar *tmp; - - tmp = gtk_accelerator_name( accelerator.key, (GdkModifierType)0 ); - if ( tmp[0] != 0 && tmp[1] == 0 ) { - tmp[0] = gchar( toupper( tmp[0] ) ); - } - g_string_append( gstring, tmp ); - g_free( tmp ); - } -} - -void menu_item_add_accelerator( ui::MenuItem item, Accelerator accelerator ){ - if ( accelerator.key != 0 && gtk_accelerator_valid( accelerator.key, accelerator.modifiers )) { - GClosure* closure = global_accel_group_find( accelerator ); - ASSERT_NOTNULL(closure); - menu_item_set_accelerator( item, closure ); - } -} - -ui::MenuItem create_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Command& command ){ - auto item = create_menu_item_with_mnemonic( menu, mnemonic, command.m_callback ); - menu_item_add_accelerator( item, command.m_accelerator ); - return item; -} - -void check_menu_item_set_active_callback(void *it, bool enabled ){ - auto item = ui::CheckMenuItem::from(it); - check_menu_item_set_active_no_signal( item, enabled ); -} - -ui::CheckMenuItem create_check_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Toggle& toggle ){ - auto item = create_check_menu_item_with_mnemonic( menu, mnemonic, toggle.m_command.m_callback ); - menu_item_add_accelerator( item, toggle.m_command.m_accelerator ); - toggle.m_exportCallback( PointerCaller( item._handle ) ); - return item; + g_object_set_data(G_OBJECT(item), "handler", gint_to_pointer(handler)); + return handler; +} + +ui::MenuItem new_menu_item_with_mnemonic(const char *mnemonic, const Callback &callback) +{ + auto item = ui::MenuItem(mnemonic, true); + item.show(); + menu_item_connect_callback(item, callback); + return item; +} + +ui::MenuItem create_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Callback &callback) +{ + auto item = new_menu_item_with_mnemonic(mnemonic, callback); + menu.add(item); + return item; +} + +ui::CheckMenuItem new_check_menu_item_with_mnemonic(const char *mnemonic, const Callback &callback) +{ + auto item = ui::CheckMenuItem::from(gtk_check_menu_item_new_with_mnemonic(mnemonic)); + item.show(); + check_menu_item_connect_callback(item, callback); + return item; +} + +ui::CheckMenuItem +create_check_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Callback &callback) +{ + auto item = new_check_menu_item_with_mnemonic(mnemonic, callback); + menu.add(item); + return item; +} + +ui::RadioMenuItem +new_radio_menu_item_with_mnemonic(GSList **group, const char *mnemonic, const Callback &callback) +{ + auto item = ui::RadioMenuItem::from(gtk_radio_menu_item_new_with_mnemonic(*group, mnemonic)); + if (*group == 0) { + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); + } + *group = gtk_radio_menu_item_get_group(item); + item.show(); + check_menu_item_connect_callback(item, callback); + return item; +} + +ui::RadioMenuItem create_radio_menu_item_with_mnemonic(ui::Menu menu, GSList **group, const char *mnemonic, + const Callback &callback) +{ + auto item = new_radio_menu_item_with_mnemonic(group, mnemonic, callback); + menu.add(item); + return item; +} + +void check_menu_item_set_active_no_signal(ui::CheckMenuItem item, gboolean active) +{ + guint handler_id = gpointer_to_int(g_object_get_data(G_OBJECT(item), "handler")); + g_signal_handler_block(G_OBJECT(item), handler_id); + gtk_check_menu_item_set_active(item, active); + g_signal_handler_unblock(G_OBJECT(item), handler_id); +} + + +void radio_menu_item_set_active_no_signal(ui::RadioMenuItem item, gboolean active) +{ + { + for (GSList *l = gtk_radio_menu_item_get_group(item); l != 0; l = g_slist_next(l)) { + g_signal_handler_block(G_OBJECT(l->data), gpointer_to_int(g_object_get_data(G_OBJECT(l->data), "handler"))); + } + } + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), active); + { + for (GSList *l = gtk_radio_menu_item_get_group(item); l != 0; l = g_slist_next(l)) { + g_signal_handler_unblock(G_OBJECT(l->data), + gpointer_to_int(g_object_get_data(G_OBJECT(l->data), "handler"))); + } + } +} + + +void menu_item_set_accelerator(ui::MenuItem item, GClosure *closure) +{ + GtkAccelLabel *accel_label = GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(item))); + gtk_accel_label_set_accel_closure(accel_label, closure); +} + +void accelerator_name(const Accelerator &accelerator, GString *gstring) +{ + gboolean had_mod = FALSE; + if (accelerator.modifiers & GDK_SHIFT_MASK) { + g_string_append(gstring, "Shift"); + had_mod = TRUE; + } + if (accelerator.modifiers & GDK_CONTROL_MASK) { + if (had_mod) { + g_string_append(gstring, "+"); + } + g_string_append(gstring, "Ctrl"); + had_mod = TRUE; + } + if (accelerator.modifiers & GDK_MOD1_MASK) { + if (had_mod) { + g_string_append(gstring, "+"); + } + g_string_append(gstring, "Alt"); + had_mod = TRUE; + } + + if (had_mod) { + g_string_append(gstring, "+"); + } + if (accelerator.key < 0x80 || (accelerator.key > 0x80 && accelerator.key <= 0xff)) { + switch (accelerator.key) { + case ' ': + g_string_append(gstring, "Space"); + break; + case '\\': + g_string_append(gstring, "Backslash"); + break; + default: + g_string_append_c(gstring, gchar(toupper(accelerator.key))); + break; + } + } else { + gchar *tmp; + + tmp = gtk_accelerator_name(accelerator.key, (GdkModifierType) 0); + if (tmp[0] != 0 && tmp[1] == 0) { + tmp[0] = gchar(toupper(tmp[0])); + } + g_string_append(gstring, tmp); + g_free(tmp); + } +} + +void menu_item_add_accelerator(ui::MenuItem item, Accelerator accelerator) +{ + if (accelerator.key != 0 && gtk_accelerator_valid(accelerator.key, accelerator.modifiers)) { + GClosure *closure = global_accel_group_find(accelerator); + ASSERT_NOTNULL(closure); + menu_item_set_accelerator(item, closure); + } +} + +ui::MenuItem create_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Command &command) +{ + auto item = create_menu_item_with_mnemonic(menu, mnemonic, command.m_callback); + menu_item_add_accelerator(item, command.m_accelerator); + return item; +} + +void check_menu_item_set_active_callback(void *it, bool enabled) +{ + auto item = ui::CheckMenuItem::from(it); + check_menu_item_set_active_no_signal(item, enabled); +} + +ui::CheckMenuItem create_check_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Toggle &toggle) +{ + auto item = create_check_menu_item_with_mnemonic(menu, mnemonic, toggle.m_command.m_callback); + menu_item_add_accelerator(item, toggle.m_command.m_accelerator); + toggle.m_exportCallback(PointerCaller(item._handle)); + return item; } diff --git a/libs/gtkutil/menu.h b/libs/gtkutil/menu.h index 2ff78f89..08f82241 100644 --- a/libs/gtkutil/menu.h +++ b/libs/gtkutil/menu.h @@ -29,23 +29,37 @@ typedef int gint; typedef gint gboolean; typedef struct _GSList GSList; -void menu_add_item( ui::Menu menu, ui::MenuItem item ); -ui::MenuItem menu_separator( ui::Menu menu ); -ui::TearoffMenuItem menu_tearoff( ui::Menu menu ); -ui::MenuItem new_sub_menu_item_with_mnemonic( const char* mnemonic ); -ui::Menu create_sub_menu_with_mnemonic( ui::MenuBar bar, const char* mnemonic ); -ui::Menu create_sub_menu_with_mnemonic( ui::Menu parent, const char* mnemonic ); -ui::MenuItem create_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Callback& callback ); -ui::CheckMenuItem create_check_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Callback& callback ); -ui::RadioMenuItem create_radio_menu_item_with_mnemonic( ui::Menu menu, GSList** group, const char* mnemonic, const Callback& callback ); +void menu_add_item(ui::Menu menu, ui::MenuItem item); + +ui::MenuItem menu_separator(ui::Menu menu); + +ui::TearoffMenuItem menu_tearoff(ui::Menu menu); + +ui::MenuItem new_sub_menu_item_with_mnemonic(const char *mnemonic); + +ui::Menu create_sub_menu_with_mnemonic(ui::MenuBar bar, const char *mnemonic); + +ui::Menu create_sub_menu_with_mnemonic(ui::Menu parent, const char *mnemonic); + +ui::MenuItem create_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Callback &callback); + +ui::CheckMenuItem +create_check_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Callback &callback); + +ui::RadioMenuItem create_radio_menu_item_with_mnemonic(ui::Menu menu, GSList **group, const char *mnemonic, + const Callback &callback); class Command; -ui::MenuItem create_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Command& command ); + +ui::MenuItem create_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Command &command); + class Toggle; -ui::CheckMenuItem create_check_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Toggle& toggle ); +ui::CheckMenuItem create_check_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Toggle &toggle); + + +void check_menu_item_set_active_no_signal(ui::CheckMenuItem item, gboolean active); -void check_menu_item_set_active_no_signal( ui::CheckMenuItem item, gboolean active ); -void radio_menu_item_set_active_no_signal( ui::RadioMenuItem item, gboolean active ); +void radio_menu_item_set_active_no_signal(ui::RadioMenuItem item, gboolean active); #endif diff --git a/libs/gtkutil/messagebox.cpp b/libs/gtkutil/messagebox.cpp index 82d6dfe4..9b9b899a 100644 --- a/libs/gtkutil/messagebox.cpp +++ b/libs/gtkutil/messagebox.cpp @@ -27,168 +27,169 @@ #include "dialog.h" #include "widget.h" -ui::Widget create_padding( int width, int height ){ - ui::Alignment widget = ui::Alignment( 0.0, 0.0, 0.0, 0.0 ); - widget.show(); - widget.dimensions(width, height); - return widget; +ui::Widget create_padding(int width, int height) +{ + ui::Alignment widget = ui::Alignment(0.0, 0.0, 0.0, 0.0); + widget.show(); + widget.dimensions(width, height); + return widget; } -const char* messagebox_stock_icon( EMessageBoxIcon type ){ - switch ( type ) - { - default: - case eMB_ICONDEFAULT: - return GTK_STOCK_DIALOG_INFO; - case eMB_ICONERROR: - return GTK_STOCK_DIALOG_ERROR; - case eMB_ICONWARNING: - return GTK_STOCK_DIALOG_WARNING; - case eMB_ICONQUESTION: - return GTK_STOCK_DIALOG_QUESTION; - case eMB_ICONASTERISK: - return GTK_STOCK_DIALOG_INFO; - } +const char *messagebox_stock_icon(EMessageBoxIcon type) +{ + switch (type) { + default: + case eMB_ICONDEFAULT: + return GTK_STOCK_DIALOG_INFO; + case eMB_ICONERROR: + return GTK_STOCK_DIALOG_ERROR; + case eMB_ICONWARNING: + return GTK_STOCK_DIALOG_WARNING; + case eMB_ICONQUESTION: + return GTK_STOCK_DIALOG_QUESTION; + case eMB_ICONASTERISK: + return GTK_STOCK_DIALOG_INFO; + } } -EMessageBoxReturn gtk_MessageBox( ui::Window parentWindow, const char* text, const char* title, EMessageBoxType type, EMessageBoxIcon icon ){ - ModalDialog dialog; - ModalDialogButton ok_button( dialog, eIDOK ); - ModalDialogButton cancel_button( dialog, eIDCANCEL ); - ModalDialogButton yes_button( dialog, eIDYES ); - ModalDialogButton no_button( dialog, eIDNO ); - - ui::Window window = create_fixedsize_modal_dialog_window( parentWindow, title, dialog, 400, 100 ); - - if ( parentWindow ) { - //window.connect( "delete_event", G_CALLBACK(floating_window_delete_present), parent); - gtk_window_deiconify( parentWindow ); - } - - auto accel = ui::AccelGroup(ui::New); - window.add_accel_group( accel ); - - auto vbox = create_dialog_vbox( 8, 8 ); - window.add(vbox); - - - auto hboxDummy = create_dialog_hbox( 0, 0 ); - vbox.pack_start( hboxDummy, FALSE, FALSE, 0 ); - - hboxDummy.pack_start( create_padding( 0, 50 ), FALSE, FALSE, 0 ); // HACK to force minimum height - - auto iconBox = create_dialog_hbox( 16, 0 ); - hboxDummy.pack_start( iconBox, FALSE, FALSE, 0 ); - - auto image = ui::Image::from( gtk_image_new_from_stock( messagebox_stock_icon( icon ), GTK_ICON_SIZE_DIALOG ) ); - image.show(); - iconBox.pack_start( image, FALSE, FALSE, 0 ); - - auto label = ui::Label( text ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - gtk_label_set_justify( label, GTK_JUSTIFY_LEFT ); - gtk_label_set_line_wrap( label, TRUE ); - iconBox.pack_start( label, TRUE, TRUE, 0 ); - - - auto vboxDummy = create_dialog_vbox( 0, 0 ); - vbox.pack_start( vboxDummy, FALSE, FALSE, 0 ); - - auto alignment = ui::Alignment( 0.5, 0.0, 0.0, 0.0 ); - alignment.show(); - vboxDummy.pack_start( alignment, FALSE, FALSE, 0 ); - - auto hbox = create_dialog_hbox( 8, 0 ); - alignment.add(hbox); - - vboxDummy.pack_start( create_padding( 400, 0 ), FALSE, FALSE, 0 ); // HACK to force minimum width - - - if ( type == eMB_OK ) { - auto button = create_modal_dialog_button( "OK", ok_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); - widget_make_default( button ); - button.show(); - - dialog.ret = eIDOK; - } - else if ( type == eMB_OKCANCEL ) { - { - auto button = create_modal_dialog_button( "OK", ok_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); - widget_make_default( button ); - button.show(); - } - - { - auto button = create_modal_dialog_button( "OK", cancel_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); - button.show(); - } - - dialog.ret = eIDCANCEL; - } - else if ( type == eMB_YESNOCANCEL ) { - { - auto button = create_modal_dialog_button( "Yes", yes_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - widget_make_default( button ); - button.show(); - } - - { - auto button = create_modal_dialog_button( "No", no_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - button.show(); - } - { - auto button = create_modal_dialog_button( "Cancel", cancel_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - button.show(); - } - - dialog.ret = eIDCANCEL; - } - else if ( type == eMB_NOYES ) { - { - auto button = create_modal_dialog_button( "No", no_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - widget_make_default( button ); - button.show(); - } - { - auto button = create_modal_dialog_button( "Yes", yes_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - button.show(); - } - - dialog.ret = eIDNO; - } - else /* if (type == eMB_YESNO) */ - { - { - auto button = create_modal_dialog_button( "Yes", yes_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - widget_make_default( button ); - button.show(); - } - - { - auto button = create_modal_dialog_button( "No", no_button ); - hbox.pack_start( button, TRUE, FALSE, 0 ); - button.show(); - } - dialog.ret = eIDNO; - } - - modal_dialog_show( window, dialog ); - - window.destroy(); - - return dialog.ret; +EMessageBoxReturn +gtk_MessageBox(ui::Window parentWindow, const char *text, const char *title, EMessageBoxType type, EMessageBoxIcon icon) +{ + ModalDialog dialog; + ModalDialogButton ok_button(dialog, eIDOK); + ModalDialogButton cancel_button(dialog, eIDCANCEL); + ModalDialogButton yes_button(dialog, eIDYES); + ModalDialogButton no_button(dialog, eIDNO); + + ui::Window window = create_fixedsize_modal_dialog_window(parentWindow, title, dialog, 400, 100); + + if (parentWindow) { + //window.connect( "delete_event", G_CALLBACK(floating_window_delete_present), parent); + gtk_window_deiconify(parentWindow); + } + + auto accel = ui::AccelGroup(ui::New); + window.add_accel_group(accel); + + auto vbox = create_dialog_vbox(8, 8); + window.add(vbox); + + + auto hboxDummy = create_dialog_hbox(0, 0); + vbox.pack_start(hboxDummy, FALSE, FALSE, 0); + + hboxDummy.pack_start(create_padding(0, 50), FALSE, FALSE, 0); // HACK to force minimum height + + auto iconBox = create_dialog_hbox(16, 0); + hboxDummy.pack_start(iconBox, FALSE, FALSE, 0); + + auto image = ui::Image::from(gtk_image_new_from_stock(messagebox_stock_icon(icon), GTK_ICON_SIZE_DIALOG)); + image.show(); + iconBox.pack_start(image, FALSE, FALSE, 0); + + auto label = ui::Label(text); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_label_set_justify(label, GTK_JUSTIFY_LEFT); + gtk_label_set_line_wrap(label, TRUE); + iconBox.pack_start(label, TRUE, TRUE, 0); + + + auto vboxDummy = create_dialog_vbox(0, 0); + vbox.pack_start(vboxDummy, FALSE, FALSE, 0); + + auto alignment = ui::Alignment(0.5, 0.0, 0.0, 0.0); + alignment.show(); + vboxDummy.pack_start(alignment, FALSE, FALSE, 0); + + auto hbox = create_dialog_hbox(8, 0); + alignment.add(hbox); + + vboxDummy.pack_start(create_padding(400, 0), FALSE, FALSE, 0); // HACK to force minimum width + + + if (type == eMB_OK) { + auto button = create_modal_dialog_button("OK", ok_button); + hbox.pack_start(button, TRUE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, (GtkAccelFlags) 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, (GtkAccelFlags) 0); + widget_make_default(button); + button.show(); + + dialog.ret = eIDOK; + } else if (type == eMB_OKCANCEL) { + { + auto button = create_modal_dialog_button("OK", ok_button); + hbox.pack_start(button, TRUE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, + (GtkAccelFlags) 0); + widget_make_default(button); + button.show(); + } + + { + auto button = create_modal_dialog_button("OK", cancel_button); + hbox.pack_start(button, TRUE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, + (GtkAccelFlags) 0); + button.show(); + } + + dialog.ret = eIDCANCEL; + } else if (type == eMB_YESNOCANCEL) { + { + auto button = create_modal_dialog_button("Yes", yes_button); + hbox.pack_start(button, TRUE, FALSE, 0); + widget_make_default(button); + button.show(); + } + + { + auto button = create_modal_dialog_button("No", no_button); + hbox.pack_start(button, TRUE, FALSE, 0); + button.show(); + } + { + auto button = create_modal_dialog_button("Cancel", cancel_button); + hbox.pack_start(button, TRUE, FALSE, 0); + button.show(); + } + + dialog.ret = eIDCANCEL; + } else if (type == eMB_NOYES) { + { + auto button = create_modal_dialog_button("No", no_button); + hbox.pack_start(button, TRUE, FALSE, 0); + widget_make_default(button); + button.show(); + } + { + auto button = create_modal_dialog_button("Yes", yes_button); + hbox.pack_start(button, TRUE, FALSE, 0); + button.show(); + } + + dialog.ret = eIDNO; + } else /* if (type == eMB_YESNO) */ + { + { + auto button = create_modal_dialog_button("Yes", yes_button); + hbox.pack_start(button, TRUE, FALSE, 0); + widget_make_default(button); + button.show(); + } + + { + auto button = create_modal_dialog_button("No", no_button); + hbox.pack_start(button, TRUE, FALSE, 0); + button.show(); + } + dialog.ret = eIDNO; + } + + modal_dialog_show(window, dialog); + + window.destroy(); + + return dialog.ret; } diff --git a/libs/gtkutil/messagebox.h b/libs/gtkutil/messagebox.h index 4ae8a3f8..331ae169 100644 --- a/libs/gtkutil/messagebox.h +++ b/libs/gtkutil/messagebox.h @@ -25,6 +25,8 @@ #include "qerplugin.h" /// \brief Shows a modal message-box. -EMessageBoxReturn gtk_MessageBox( ui::Window parent, const char* text, const char* title = "NetRadiant", EMessageBoxType type = eMB_OK, EMessageBoxIcon icon = eMB_ICONDEFAULT ); +EMessageBoxReturn +gtk_MessageBox(ui::Window parent, const char *text, const char *title = "NetRadiant", EMessageBoxType type = eMB_OK, + EMessageBoxIcon icon = eMB_ICONDEFAULT); #endif diff --git a/libs/gtkutil/nonmodal.h b/libs/gtkutil/nonmodal.h index 53318679..cb3f08d4 100644 --- a/libs/gtkutil/nonmodal.h +++ b/libs/gtkutil/nonmodal.h @@ -48,7 +48,8 @@ class NonModalEntry { static gboolean escape(ui::Entry entry, GdkEventKey *event, NonModalEntry *self); public: - NonModalEntry(const Callback &apply, const Callback &cancel) : m_editing(false), m_apply(apply), m_cancel(cancel) + NonModalEntry(const Callback &apply, const Callback &cancel) : m_editing(false), m_apply(apply), + m_cancel(cancel) { } diff --git a/libs/gtkutil/paned.cpp b/libs/gtkutil/paned.cpp index 4f724eef..b387c655 100644 --- a/libs/gtkutil/paned.cpp +++ b/libs/gtkutil/paned.cpp @@ -27,68 +27,71 @@ #include "frame.h" -class PanedState -{ +class PanedState { public: -float position; -int size; + float position; + int size; }; -gboolean hpaned_allocate(ui::Widget widget, GtkAllocation* allocation, PanedState* paned ){ - if ( paned->size != allocation->width ) { - paned->size = allocation->width; - gtk_paned_set_position( GTK_PANED( widget ), static_cast( paned->size * paned->position ) ); - } - return FALSE; +gboolean hpaned_allocate(ui::Widget widget, GtkAllocation *allocation, PanedState *paned) +{ + if (paned->size != allocation->width) { + paned->size = allocation->width; + gtk_paned_set_position(GTK_PANED(widget), static_cast( paned->size * paned->position )); + } + return FALSE; } -gboolean vpaned_allocate(ui::Widget widget, GtkAllocation* allocation, PanedState* paned ){ - if ( paned->size != allocation->height ) { - paned->size = allocation->height; - gtk_paned_set_position( GTK_PANED( widget ), static_cast( paned->size * paned->position ) ); - } - return FALSE; +gboolean vpaned_allocate(ui::Widget widget, GtkAllocation *allocation, PanedState *paned) +{ + if (paned->size != allocation->height) { + paned->size = allocation->height; + gtk_paned_set_position(GTK_PANED(widget), static_cast( paned->size * paned->position )); + } + return FALSE; } -gboolean paned_position(ui::Widget widget, gpointer dummy, PanedState* paned ){ - if ( paned->size != -1 ) { - paned->position = gtk_paned_get_position( GTK_PANED( widget ) ) / static_cast( paned->size ); - } - return FALSE; +gboolean paned_position(ui::Widget widget, gpointer dummy, PanedState *paned) +{ + if (paned->size != -1) { + paned->position = gtk_paned_get_position(GTK_PANED(widget)) / static_cast( paned->size ); + } + return FALSE; } -PanedState g_hpaned = { 0.5f, -1, }; -PanedState g_vpaned1 = { 0.5f, -1, }; -PanedState g_vpaned2 = { 0.5f, -1, }; - -ui::HPaned create_split_views( ui::Widget topleft, ui::Widget topright, ui::Widget botleft, ui::Widget botright ){ - auto hsplit = ui::HPaned(ui::New); - hsplit.show(); - - hsplit.connect( "size_allocate", G_CALLBACK( hpaned_allocate ), &g_hpaned ); - hsplit.connect( "notify::position", G_CALLBACK( paned_position ), &g_hpaned ); +PanedState g_hpaned = {0.5f, -1,}; +PanedState g_vpaned1 = {0.5f, -1,}; +PanedState g_vpaned2 = {0.5f, -1,}; - { - auto vsplit = ui::VPaned(ui::New); - gtk_paned_add1( GTK_PANED( hsplit ), vsplit ); - vsplit.show(); - - vsplit.connect( "size_allocate", G_CALLBACK( vpaned_allocate ), &g_vpaned1 ); - vsplit.connect( "notify::position", G_CALLBACK( paned_position ), &g_vpaned1 ); - - gtk_paned_add1( GTK_PANED( vsplit ), create_framed_widget( topleft ) ); - gtk_paned_add2( GTK_PANED( vsplit ), create_framed_widget( topright ) ); - } - { - auto vsplit = ui::VPaned(ui::New); - gtk_paned_add2( GTK_PANED( hsplit ), vsplit ); - vsplit.show(); - - vsplit.connect( "size_allocate", G_CALLBACK( vpaned_allocate ), &g_vpaned2 ); - vsplit.connect( "notify::position", G_CALLBACK( paned_position ), &g_vpaned2 ); - - gtk_paned_add1( GTK_PANED( vsplit ), create_framed_widget( botleft ) ); - gtk_paned_add2( GTK_PANED( vsplit ), create_framed_widget( botright ) ); - } - return hsplit; +ui::HPaned create_split_views(ui::Widget topleft, ui::Widget topright, ui::Widget botleft, ui::Widget botright) +{ + auto hsplit = ui::HPaned(ui::New); + hsplit.show(); + + hsplit.connect("size_allocate", G_CALLBACK(hpaned_allocate), &g_hpaned); + hsplit.connect("notify::position", G_CALLBACK(paned_position), &g_hpaned); + + { + auto vsplit = ui::VPaned(ui::New); + gtk_paned_add1(GTK_PANED(hsplit), vsplit); + vsplit.show(); + + vsplit.connect("size_allocate", G_CALLBACK(vpaned_allocate), &g_vpaned1); + vsplit.connect("notify::position", G_CALLBACK(paned_position), &g_vpaned1); + + gtk_paned_add1(GTK_PANED(vsplit), create_framed_widget(topleft)); + gtk_paned_add2(GTK_PANED(vsplit), create_framed_widget(topright)); + } + { + auto vsplit = ui::VPaned(ui::New); + gtk_paned_add2(GTK_PANED(hsplit), vsplit); + vsplit.show(); + + vsplit.connect("size_allocate", G_CALLBACK(vpaned_allocate), &g_vpaned2); + vsplit.connect("notify::position", G_CALLBACK(paned_position), &g_vpaned2); + + gtk_paned_add1(GTK_PANED(vsplit), create_framed_widget(botleft)); + gtk_paned_add2(GTK_PANED(vsplit), create_framed_widget(botright)); + } + return hsplit; } diff --git a/libs/gtkutil/paned.h b/libs/gtkutil/paned.h index 842996ef..1c80ae6e 100644 --- a/libs/gtkutil/paned.h +++ b/libs/gtkutil/paned.h @@ -24,6 +24,6 @@ #if !defined( INCLUDED_GTKUTIL_PANED_H ) #define INCLUDED_GTKUTIL_PANED_H -ui::HPaned create_split_views( ui::Widget topleft, ui::Widget topright, ui::Widget botleft, ui::Widget botright ); +ui::HPaned create_split_views(ui::Widget topleft, ui::Widget topright, ui::Widget botleft, ui::Widget botright); #endif diff --git a/libs/gtkutil/pointer.h b/libs/gtkutil/pointer.h index 035ab8e3..45e3eb02 100644 --- a/libs/gtkutil/pointer.h +++ b/libs/gtkutil/pointer.h @@ -23,16 +23,18 @@ #define INCLUDED_GTKUTIL_POINTER_H typedef int gint; -typedef void* gpointer; +typedef void *gpointer; #include -inline gint gpointer_to_int( gpointer p ){ - return gint( std::size_t( p ) ); +inline gint gpointer_to_int(gpointer p) +{ + return gint(std::size_t(p)); } -inline gpointer gint_to_pointer( gint i ){ - return gpointer( std::size_t( i ) ); +inline gpointer gint_to_pointer(gint i) +{ + return gpointer(std::size_t(i)); } #endif diff --git a/libs/gtkutil/toolbar.cpp b/libs/gtkutil/toolbar.cpp index 049d05ec..fa7cc4f4 100644 --- a/libs/gtkutil/toolbar.cpp +++ b/libs/gtkutil/toolbar.cpp @@ -31,39 +31,49 @@ #include "image.h" -void toolbar_append( ui::Toolbar toolbar, ui::ToolItem button, const char* description ){ - gtk_widget_show_all(button); - gtk_widget_set_tooltip_text(button, description); - toolbar.add(button); +void toolbar_append(ui::Toolbar toolbar, ui::ToolItem button, const char *description) +{ + gtk_widget_show_all(button); + gtk_widget_set_tooltip_text(button, description); + toolbar.add(button); } -ui::ToolButton toolbar_append_button( ui::Toolbar toolbar, const char* description, const char* icon, const Callback& callback ){ - auto button = ui::ToolButton::from(gtk_tool_button_new(new_local_image(icon), nullptr)); - button_connect_callback(button, callback); - toolbar_append(toolbar, button, description); - return button; +ui::ToolButton +toolbar_append_button(ui::Toolbar toolbar, const char *description, const char *icon, const Callback &callback) +{ + auto button = ui::ToolButton::from(gtk_tool_button_new(new_local_image(icon), nullptr)); + button_connect_callback(button, callback); + toolbar_append(toolbar, button, description); + return button; } -ui::ToggleToolButton toolbar_append_toggle_button( ui::Toolbar toolbar, const char* description, const char* icon, const Callback& callback ){ - auto button = ui::ToggleToolButton::from(gtk_toggle_tool_button_new()); - toggle_button_connect_callback(button, callback); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(button), new_local_image(icon)); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(button), description); - toolbar_append(toolbar, button, description); - return button; +ui::ToggleToolButton toolbar_append_toggle_button(ui::Toolbar toolbar, const char *description, const char *icon, + const Callback &callback) +{ + auto button = ui::ToggleToolButton::from(gtk_toggle_tool_button_new()); + toggle_button_connect_callback(button, callback); + gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(button), new_local_image(icon)); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(button), description); + toolbar_append(toolbar, button, description); + return button; } -ui::ToolButton toolbar_append_button( ui::Toolbar toolbar, const char* description, const char* icon, const Command& command ){ - return toolbar_append_button( toolbar, description, icon, command.m_callback ); +ui::ToolButton +toolbar_append_button(ui::Toolbar toolbar, const char *description, const char *icon, const Command &command) +{ + return toolbar_append_button(toolbar, description, icon, command.m_callback); } -void toggle_button_set_active_callback(void *it, bool active ){ - auto button = ui::ToggleToolButton::from(it); - toggle_button_set_active_no_signal( button, active ); +void toggle_button_set_active_callback(void *it, bool active) +{ + auto button = ui::ToggleToolButton::from(it); + toggle_button_set_active_no_signal(button, active); } -ui::ToggleToolButton toolbar_append_toggle_button( ui::Toolbar toolbar, const char* description, const char* icon, const Toggle& toggle ){ - auto button = toolbar_append_toggle_button( toolbar, description, icon, toggle.m_command.m_callback ); - toggle.m_exportCallback( PointerCaller( button._handle ) ); - return button; +ui::ToggleToolButton +toolbar_append_toggle_button(ui::Toolbar toolbar, const char *description, const char *icon, const Toggle &toggle) +{ + auto button = toolbar_append_toggle_button(toolbar, description, icon, toggle.m_command.m_callback); + toggle.m_exportCallback(PointerCaller(button._handle)); + return button; } diff --git a/libs/gtkutil/toolbar.h b/libs/gtkutil/toolbar.h index f3481783..b016ab22 100644 --- a/libs/gtkutil/toolbar.h +++ b/libs/gtkutil/toolbar.h @@ -26,11 +26,19 @@ #include "generic/callback.h" class Command; + class Toggle; -ui::ToolButton toolbar_append_button( ui::Toolbar toolbar, const char* description, const char* icon, const Callback& callback ); -ui::ToolButton toolbar_append_button( ui::Toolbar toolbar, const char* description, const char* icon, const Command& command ); -ui::ToggleToolButton toolbar_append_toggle_button( ui::Toolbar toolbar, const char* description, const char* icon, const Callback& callback ); -ui::ToggleToolButton toolbar_append_toggle_button( ui::Toolbar toolbar, const char* description, const char* icon, const Toggle& toggle ); +ui::ToolButton +toolbar_append_button(ui::Toolbar toolbar, const char *description, const char *icon, const Callback &callback); + +ui::ToolButton +toolbar_append_button(ui::Toolbar toolbar, const char *description, const char *icon, const Command &command); + +ui::ToggleToolButton toolbar_append_toggle_button(ui::Toolbar toolbar, const char *description, const char *icon, + const Callback &callback); + +ui::ToggleToolButton +toolbar_append_toggle_button(ui::Toolbar toolbar, const char *description, const char *icon, const Toggle &toggle); #endif diff --git a/libs/gtkutil/window.cpp b/libs/gtkutil/window.cpp index 11b6efeb..6381934a 100644 --- a/libs/gtkutil/window.cpp +++ b/libs/gtkutil/window.cpp @@ -26,212 +26,228 @@ #include "pointer.h" #include "accelerator.h" -inline void CHECK_RESTORE( ui::Widget w ){ - if ( gpointer_to_int( g_object_get_data( G_OBJECT( w ), "was_mapped" ) ) != 0 ) { - w.show(); - } +inline void CHECK_RESTORE(ui::Widget w) +{ + if (gpointer_to_int(g_object_get_data(G_OBJECT(w), "was_mapped")) != 0) { + w.show(); + } } -inline void CHECK_MINIMIZE( ui::Widget w ){ - g_object_set_data( G_OBJECT( w ), "was_mapped", gint_to_pointer( gtk_widget_get_visible( w ) ) ); - w.hide(); +inline void CHECK_MINIMIZE(ui::Widget w) +{ + g_object_set_data(G_OBJECT(w), "was_mapped", gint_to_pointer(gtk_widget_get_visible(w))); + w.hide(); } -static gboolean main_window_iconified( ui::Widget widget, GdkEventWindowState* event, gpointer data ){ - if ( ( event->changed_mask & ( GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_WITHDRAWN ) ) != 0 ) { - if ( ( event->new_window_state & ( GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_WITHDRAWN ) ) != 0 ) { - CHECK_MINIMIZE( ui::Widget::from( data ) ); - } - else - { - CHECK_RESTORE( ui::Widget::from( data ) ); - } - } - return FALSE; +static gboolean main_window_iconified(ui::Widget widget, GdkEventWindowState *event, gpointer data) +{ + if ((event->changed_mask & (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_WITHDRAWN)) != 0) { + if ((event->new_window_state & (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_WITHDRAWN)) != 0) { + CHECK_MINIMIZE(ui::Widget::from(data)); + } else { + CHECK_RESTORE(ui::Widget::from(data)); + } + } + return FALSE; } -unsigned int connect_floating( ui::Window main_window, ui::Window floating ){ - return main_window.connect( "window_state_event", G_CALLBACK( main_window_iconified ), floating ); +unsigned int connect_floating(ui::Window main_window, ui::Window floating) +{ + return main_window.connect("window_state_event", G_CALLBACK(main_window_iconified), floating); } -gboolean destroy_disconnect_floating( ui::Window widget, gpointer data ){ - g_signal_handler_disconnect( G_OBJECT( data ), gpointer_to_int( g_object_get_data( G_OBJECT( widget ), "floating_handler" ) ) ); - return FALSE; +gboolean destroy_disconnect_floating(ui::Window widget, gpointer data) +{ + g_signal_handler_disconnect(G_OBJECT(data), + gpointer_to_int(g_object_get_data(G_OBJECT(widget), "floating_handler"))); + return FALSE; } -gboolean floating_window_delete_present( ui::Window floating, GdkEventFocus *event, ui::Window main_window ){ - if ( gtk_window_is_active( floating ) || gtk_window_is_active( main_window ) ) { - gtk_window_present( main_window ); - } - return FALSE; +gboolean floating_window_delete_present(ui::Window floating, GdkEventFocus *event, ui::Window main_window) +{ + if (gtk_window_is_active(floating) || gtk_window_is_active(main_window)) { + gtk_window_present(main_window); + } + return FALSE; } -guint connect_floating_window_delete_present( ui::Window floating, ui::Window main_window ){ - return floating.connect( "delete_event", G_CALLBACK( floating_window_delete_present ), main_window ); +guint connect_floating_window_delete_present(ui::Window floating, ui::Window main_window) +{ + return floating.connect("delete_event", G_CALLBACK(floating_window_delete_present), main_window); } -gboolean floating_window_destroy_present( ui::Window floating, ui::Window main_window ){ - if ( gtk_window_is_active( floating ) || gtk_window_is_active( main_window ) ) { - gtk_window_present( main_window ); - } - return FALSE; +gboolean floating_window_destroy_present(ui::Window floating, ui::Window main_window) +{ + if (gtk_window_is_active(floating) || gtk_window_is_active(main_window)) { + gtk_window_present(main_window); + } + return FALSE; } -guint connect_floating_window_destroy_present( ui::Window floating, ui::Window main_window ){ - return floating.connect( "destroy", G_CALLBACK( floating_window_destroy_present ), main_window ); +guint connect_floating_window_destroy_present(ui::Window floating, ui::Window main_window) +{ + return floating.connect("destroy", G_CALLBACK(floating_window_destroy_present), main_window); } -ui::Window create_floating_window( const char* title, ui::Window parent ){ - ui::Window window = ui::Window( ui::window_type::TOP ); - gtk_window_set_title( window, title ); +ui::Window create_floating_window(const char *title, ui::Window parent) +{ + ui::Window window = ui::Window(ui::window_type::TOP); + gtk_window_set_title(window, title); - if ( parent ) { - gtk_window_set_transient_for( window, parent ); - connect_floating_window_destroy_present( window, parent ); - g_object_set_data( G_OBJECT( window ), "floating_handler", gint_to_pointer( connect_floating( parent, window ) ) ); - window.connect( "destroy", G_CALLBACK( destroy_disconnect_floating ), parent ); - } + if (parent) { + gtk_window_set_transient_for(window, parent); + connect_floating_window_destroy_present(window, parent); + g_object_set_data(G_OBJECT(window), "floating_handler", gint_to_pointer(connect_floating(parent, window))); + window.connect("destroy", G_CALLBACK(destroy_disconnect_floating), parent); + } - return window; + return window; } -void destroy_floating_window( ui::Window window ){ - window.destroy(); +void destroy_floating_window(ui::Window window) +{ + window.destroy(); } -gint window_realize_remove_sysmenu( ui::Widget widget, gpointer data ){ - gdk_window_set_decorations( gtk_widget_get_window(widget), (GdkWMDecoration)( GDK_DECOR_ALL | GDK_DECOR_MENU ) ); - return FALSE; +gint window_realize_remove_sysmenu(ui::Widget widget, gpointer data) +{ + gdk_window_set_decorations(gtk_widget_get_window(widget), (GdkWMDecoration) (GDK_DECOR_ALL | GDK_DECOR_MENU)); + return FALSE; } -gboolean persistent_floating_window_delete( ui::Window floating, GdkEvent *event, ui::Window main_window ){ - floating.hide(); - return TRUE; +gboolean persistent_floating_window_delete(ui::Window floating, GdkEvent *event, ui::Window main_window) +{ + floating.hide(); + return TRUE; } -ui::Window create_persistent_floating_window( const char* title, ui::Window main_window ){ - auto window = create_floating_window( title, main_window ); +ui::Window create_persistent_floating_window(const char *title, ui::Window main_window) +{ + auto window = create_floating_window(title, main_window); - gtk_widget_set_events( window , GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK ); + gtk_widget_set_events(window, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); - connect_floating_window_delete_present( window, main_window ); - window.connect( "delete_event", G_CALLBACK( persistent_floating_window_delete ), 0 ); + connect_floating_window_delete_present(window, main_window); + window.connect("delete_event", G_CALLBACK(persistent_floating_window_delete), 0); #if 0 - if ( g_multimon_globals.m_bStartOnPrimMon && g_multimon_globals.m_bNoSysMenuPopups ) { - window.connect( "realize", G_CALLBACK( window_realize_remove_sysmenu ), 0 ); - } + if ( g_multimon_globals.m_bStartOnPrimMon && g_multimon_globals.m_bNoSysMenuPopups ) { + window.connect( "realize", G_CALLBACK( window_realize_remove_sysmenu ), 0 ); + } #endif - return window; + return window; } -gint window_realize_remove_minmax( ui::Widget widget, gpointer data ){ - gdk_window_set_decorations( gtk_widget_get_window(widget), (GdkWMDecoration)( GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE ) ); - return FALSE; +gint window_realize_remove_minmax(ui::Widget widget, gpointer data) +{ + gdk_window_set_decorations(gtk_widget_get_window(widget), + (GdkWMDecoration) (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE)); + return FALSE; } -void window_remove_minmax( ui::Window window ){ - window.connect( "realize", G_CALLBACK( window_realize_remove_minmax ), 0 ); +void window_remove_minmax(ui::Window window) +{ + window.connect("realize", G_CALLBACK(window_realize_remove_minmax), 0); } -ui::ScrolledWindow create_scrolled_window( ui::Policy hscrollbar_policy, ui::Policy vscrollbar_policy, int border ){ - auto scr = ui::ScrolledWindow(ui::New); - scr.show(); - gtk_scrolled_window_set_policy( scr, (GtkPolicyType) hscrollbar_policy, (GtkPolicyType) vscrollbar_policy ); - gtk_scrolled_window_set_shadow_type( scr, GTK_SHADOW_IN ); - gtk_container_set_border_width( GTK_CONTAINER( scr ), border ); - return scr; +ui::ScrolledWindow create_scrolled_window(ui::Policy hscrollbar_policy, ui::Policy vscrollbar_policy, int border) +{ + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + gtk_scrolled_window_set_policy(scr, (GtkPolicyType) hscrollbar_policy, (GtkPolicyType) vscrollbar_policy); + gtk_scrolled_window_set_shadow_type(scr, GTK_SHADOW_IN); + gtk_container_set_border_width(GTK_CONTAINER(scr), border); + return scr; } gboolean window_focus_in_clear_focus_widget(ui::Window widget, GdkEventKey *event, gpointer data) { - gtk_window_set_focus( widget, NULL ); + gtk_window_set_focus(widget, NULL); return FALSE; } guint window_connect_focus_in_clear_focus_widget(ui::Window window) { - return window.connect( "focus_in_event", G_CALLBACK( window_focus_in_clear_focus_widget ), NULL ); + return window.connect("focus_in_event", G_CALLBACK(window_focus_in_clear_focus_widget), NULL); } void window_get_position(ui::Window window, WindowPosition &position) { - ASSERT_MESSAGE( window , "error saving window position" ); + ASSERT_MESSAGE(window, "error saving window position"); - gtk_window_get_position( window, &position.x, &position.y ); - gtk_window_get_size( window, &position.w, &position.h ); + gtk_window_get_position(window, &position.x, &position.y); + gtk_window_get_size(window, &position.w, &position.h); } void window_set_position(ui::Window window, const WindowPosition &position) { - gtk_window_set_gravity( window, GDK_GRAVITY_STATIC ); + gtk_window_set_gravity(window, GDK_GRAVITY_STATIC); - GdkScreen* screen = gdk_screen_get_default(); - if ( position.x < 0 - || position.y < 0 - || position.x > gdk_screen_get_width( screen ) - || position.y > gdk_screen_get_height( screen ) ) { - gtk_window_set_position( window, GTK_WIN_POS_CENTER_ON_PARENT ); - } - else - { - gtk_window_move( window, position.x, position.y ); - } + GdkScreen *screen = gdk_screen_get_default(); + if (position.x < 0 + || position.y < 0 + || position.x > gdk_screen_get_width(screen) + || position.y > gdk_screen_get_height(screen)) { + gtk_window_set_position(window, GTK_WIN_POS_CENTER_ON_PARENT); + } else { + gtk_window_move(window, position.x, position.y); + } - gtk_window_set_default_size( window, position.w, position.h ); + gtk_window_set_default_size(window, position.w, position.h); } void WindowPosition_String::Import(WindowPosition &position, const char *value) { - if ( sscanf( value, "%d %d %d %d", &position.x, &position.y, &position.w, &position.h ) != 4 ) { - position = WindowPosition( c_default_window_pos ); // ensure sane default value for window position - } + if (sscanf(value, "%d %d %d %d", &position.x, &position.y, &position.w, &position.h) != 4) { + position = WindowPosition(c_default_window_pos); // ensure sane default value for window position + } } void WindowPosition_String::Export(const WindowPosition &self, const Callback &returnz) { - char buffer[64]; - sprintf( buffer, "%d %d %d %d", self.x, self.y, self.w, self.h ); - returnz( buffer ); + char buffer[64]; + sprintf(buffer, "%d %d %d %d", self.x, self.y, self.w, self.h); + returnz(buffer); } void WindowPositionTracker_String::Import(WindowPositionTracker &self, const char *value) { - WindowPosition position; - WindowPosition_String::Import( position, value ); - self.setPosition( position ); + WindowPosition position; + WindowPosition_String::Import(position, value); + self.setPosition(position); } -void WindowPositionTracker_String::Export(const WindowPositionTracker &self, const Callback &returnz) +void +WindowPositionTracker_String::Export(const WindowPositionTracker &self, const Callback &returnz) { - WindowPosition_String::Export( self.getPosition(), returnz ); + WindowPosition_String::Export(self.getPosition(), returnz); } gboolean WindowPositionTracker::configure(ui::Widget widget, GdkEventConfigure *event, WindowPositionTracker *self) { - self->m_position = WindowPosition( event->x, event->y, event->width, event->height ); - return FALSE; + self->m_position = WindowPosition(event->x, event->y, event->width, event->height); + return FALSE; } void WindowPositionTracker::sync(ui::Window window) { - window_set_position( window, m_position ); + window_set_position(window, m_position); } void WindowPositionTracker::connect(ui::Window window) { - sync( window ); - window.connect( "configure_event", G_CALLBACK( configure ), this ); + sync(window); + window.connect("configure_event", G_CALLBACK(configure), this); } const WindowPosition &WindowPositionTracker::getPosition() const { - return m_position; + return m_position; } void WindowPositionTracker::setPosition(const WindowPosition &position) { - m_position = position; + m_position = position; } diff --git a/libs/gtkutil/xorrectangle.h b/libs/gtkutil/xorrectangle.h index 2341f1f0..eab7bf1f 100644 --- a/libs/gtkutil/xorrectangle.h +++ b/libs/gtkutil/xorrectangle.h @@ -26,55 +26,62 @@ #include #include "math/vector.h" -class rectangle_t -{ +class rectangle_t { public: -rectangle_t() - : x( 0 ), y( 0 ), w( 0 ), h( 0 ) -{} -rectangle_t( float _x, float _y, float _w, float _h ) - : x( _x ), y( _y ), w( _w ), h( _h ) -{} -float x; -float y; -float w; -float h; + rectangle_t() + : x(0), y(0), w(0), h(0) + {} + + rectangle_t(float _x, float _y, float _w, float _h) + : x(_x), y(_y), w(_w), h(_h) + {} + + float x; + float y; + float w; + float h; }; -struct Coord2D -{ - float x, y; - Coord2D( float _x, float _y ) - : x( _x ), y( _y ){ - } +struct Coord2D { + float x, y; + + Coord2D(float _x, float _y) + : x(_x), y(_y) + { + } }; -inline Coord2D coord2d_device2screen( const Coord2D& coord, unsigned int width, unsigned int height ){ - return Coord2D( ( ( coord.x + 1.0f ) * 0.5f ) * width, ( ( coord.y + 1.0f ) * 0.5f ) * height ); +inline Coord2D coord2d_device2screen(const Coord2D &coord, unsigned int width, unsigned int height) +{ + return Coord2D(((coord.x + 1.0f) * 0.5f) * width, ((coord.y + 1.0f) * 0.5f) * height); } -inline rectangle_t rectangle_from_area( const float min[2], const float max[2], unsigned int width, unsigned int height ){ - Coord2D botleft( coord2d_device2screen( Coord2D( min[0], min[1] ), width, height ) ); - Coord2D topright( coord2d_device2screen( Coord2D( max[0], max[1] ), width, height ) ); - return rectangle_t( botleft.x, botleft.y, topright.x - botleft.x, topright.y - botleft.y ); +inline rectangle_t rectangle_from_area(const float min[2], const float max[2], unsigned int width, unsigned int height) +{ + Coord2D botleft(coord2d_device2screen(Coord2D(min[0], min[1]), width, height)); + Coord2D topright(coord2d_device2screen(Coord2D(max[0], max[1]), width, height)); + return rectangle_t(botleft.x, botleft.y, topright.x - botleft.x, topright.y - botleft.y); } -class XORRectangle -{ +class XORRectangle { + + rectangle_t m_rectangle; + + ui::GLArea m_widget; + cairo_t *cr; -rectangle_t m_rectangle; + bool initialised() const; -ui::GLArea m_widget; -cairo_t *cr; + void lazy_init(); -bool initialised() const; -void lazy_init(); -void draw() const; + void draw() const; public: -XORRectangle( ui::GLArea widget ); -~XORRectangle(); -void set( rectangle_t rectangle ); + XORRectangle(ui::GLArea widget); + + ~XORRectangle(); + + void set(rectangle_t rectangle); }; diff --git a/plugins/archivepak/archive.cpp b/plugins/archivepak/archive.cpp index ee193339..28da29cd 100644 --- a/plugins/archivepak/archive.cpp +++ b/plugins/archivepak/archive.cpp @@ -36,107 +36,120 @@ #include "string/string.h" #include "fs_filesystem.h" -inline void buffer_findreplace( char* buffer, char find, char replace ){ - while ( *buffer != '\0' ) - { - if ( *buffer == find ) { - *buffer = replace; - } - ++buffer; - } +inline void buffer_findreplace(char *buffer, char find, char replace) +{ + while (*buffer != '\0') { + if (*buffer == find) { + *buffer = replace; + } + ++buffer; + } } #include "pak.h" -class PakArchive : public Archive -{ -class PakRecord -{ -public: -PakRecord( unsigned int position, unsigned int stream_size ) - : m_position( position ), m_stream_size( stream_size ){ -} -unsigned int m_position; -unsigned int m_stream_size; -}; -typedef GenericFileSystem PakFileSystem; -PakFileSystem m_filesystem; -FileInputStream m_pakfile; -CopiedString m_name; +class PakArchive : public Archive { + class PakRecord { + public: + PakRecord(unsigned int position, unsigned int stream_size) + : m_position(position), m_stream_size(stream_size) + { + } -public: + unsigned int m_position; + unsigned int m_stream_size; + }; -PakArchive( const char* name ) - : m_pakfile( name ), m_name( name ){ - if ( !m_pakfile.failed() ) { - pakheader_t header; - - m_pakfile.read( reinterpret_cast( header.magic ), 4 ); - header.diroffset = istream_read_uint32_le( m_pakfile ); - header.dirsize = istream_read_uint32_le( m_pakfile ); - - if ( strncmp( header.magic, "PACK", 4 ) == 0 ) { - m_pakfile.seek( header.diroffset ); - - for ( unsigned int i = 0; i < header.dirsize; i += sizeof( pakentry_t ) ) - { - pakentry_t entry; - - m_pakfile.read( reinterpret_cast( entry.filename ), 0x38 ); - entry.offset = istream_read_uint32_le( m_pakfile ); - entry.size = istream_read_uint32_le( m_pakfile ); - - buffer_findreplace( entry.filename, '\\', '/' ); - - PakFileSystem::entry_type& file = m_filesystem[entry.filename]; - if ( !file.is_directory() ) { - globalOutputStream() << "Warning: pak archive " << makeQuoted( m_name.c_str() ) << " contains duplicated file: " << makeQuoted( entry.filename ) << "\n"; - } - else - { - file = new PakRecord( entry.offset, entry.size ); - } - } - } - } -} + typedef GenericFileSystem PakFileSystem; + PakFileSystem m_filesystem; + FileInputStream m_pakfile; + CopiedString m_name; -~PakArchive(){ - for ( PakFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i ) - delete i->second.file(); -} +public: -void release(){ - delete this; -} -ArchiveFile* openFile( const char* name ){ - PakFileSystem::iterator i = m_filesystem.find( name ); - if ( i != m_filesystem.end() && !i->second.is_directory() ) { - PakRecord* file = i->second.file(); - return StoredArchiveFile::create( name, m_name.c_str(), file->m_position, file->m_stream_size, file->m_stream_size ); - } - return 0; -} -virtual ArchiveTextFile* openTextFile( const char* name ){ - PakFileSystem::iterator i = m_filesystem.find( name ); - if ( i != m_filesystem.end() && !i->second.is_directory() ) { - PakRecord* file = i->second.file(); - return StoredArchiveTextFile::create( name, m_name.c_str(), file->m_position, file->m_stream_size ); - } - return 0; -} -bool containsFile( const char* name ){ - PakFileSystem::iterator i = m_filesystem.find( name ); - return i != m_filesystem.end() && !i->second.is_directory(); -} -void forEachFile( VisitorFunc visitor, const char* root ){ - m_filesystem.traverse( visitor, root ); -} + PakArchive(const char *name) + : m_pakfile(name), m_name(name) + { + if (!m_pakfile.failed()) { + pakheader_t header; + + m_pakfile.read(reinterpret_cast( header.magic ), 4); + header.diroffset = istream_read_uint32_le(m_pakfile); + header.dirsize = istream_read_uint32_le(m_pakfile); + + if (strncmp(header.magic, "PACK", 4) == 0) { + m_pakfile.seek(header.diroffset); + + for (unsigned int i = 0; i < header.dirsize; i += sizeof(pakentry_t)) { + pakentry_t entry; + + m_pakfile.read(reinterpret_cast( entry.filename ), 0x38); + entry.offset = istream_read_uint32_le(m_pakfile); + entry.size = istream_read_uint32_le(m_pakfile); + + buffer_findreplace(entry.filename, '\\', '/'); + + PakFileSystem::entry_type &file = m_filesystem[entry.filename]; + if (!file.is_directory()) { + globalOutputStream() << "Warning: pak archive " << makeQuoted(m_name.c_str()) + << " contains duplicated file: " << makeQuoted(entry.filename) << "\n"; + } else { + file = new PakRecord(entry.offset, entry.size); + } + } + } + } + } + + ~PakArchive() + { + for (PakFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i) { + delete i->second.file(); + } + } + + void release() + { + delete this; + } + + ArchiveFile *openFile(const char *name) + { + PakFileSystem::iterator i = m_filesystem.find(name); + if (i != m_filesystem.end() && !i->second.is_directory()) { + PakRecord *file = i->second.file(); + return StoredArchiveFile::create(name, m_name.c_str(), file->m_position, file->m_stream_size, + file->m_stream_size); + } + return 0; + } + + virtual ArchiveTextFile *openTextFile(const char *name) + { + PakFileSystem::iterator i = m_filesystem.find(name); + if (i != m_filesystem.end() && !i->second.is_directory()) { + PakRecord *file = i->second.file(); + return StoredArchiveTextFile::create(name, m_name.c_str(), file->m_position, file->m_stream_size); + } + return 0; + } + + bool containsFile(const char *name) + { + PakFileSystem::iterator i = m_filesystem.find(name); + return i != m_filesystem.end() && !i->second.is_directory(); + } + + void forEachFile(VisitorFunc visitor, const char *root) + { + m_filesystem.traverse(visitor, root); + } }; -Archive* OpenArchive( const char* name ){ - return new PakArchive( name ); +Archive *OpenArchive(const char *name) +{ + return new PakArchive(name); } #if 0 @@ -145,14 +158,14 @@ class TestArchive { public: TestArchive(){ - Archive* archive = OpenArchive( "c:/quake3/baseq3/pak0.pak" ); - ArchiveFile* file = archive->openFile( "gfx/palette.lmp" ); - if ( file != 0 ) { - char buffer[1024]; - file->getInputStream().read( (InputStream::byte_type*)buffer, 1024 ); - file->release(); - } - archive->release(); + Archive* archive = OpenArchive( "c:/quake3/baseq3/pak0.pak" ); + ArchiveFile* file = archive->openFile( "gfx/palette.lmp" ); + if ( file != 0 ) { + char buffer[1024]; + file->getInputStream().read( (InputStream::byte_type*)buffer, 1024 ); + file->release(); + } + archive->release(); } }; @@ -168,38 +181,38 @@ class TestVisitor : public Archive::IVisitor { public: void visit( const char* name ){ - int bleh = 0; + int bleh = 0; } }; public: TestArchive(){ - { - Archive* archive = OpenArchive( "" ); - archive->release(); - } - { - Archive* archive = OpenArchive( "NONEXISTANTFILE" ); - archive->release(); - } - { - Archive* archive = OpenArchive( "c:/quake/id1/pak0.pak" ); - ArchiveFile* file = archive->openFile( "gfx/palette.lmp" ); - if ( file != 0 ) { - char buffer[1024]; - file->getInputStream().read( (InputStream::byte_type*)buffer, 1024 ); - file->release(); - } - TestVisitor visitor; - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 0 ), "progs/" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 0 ), "maps/" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "sound/ambience/" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "sound/" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "sound/" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "sound/" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" ); - archive->release(); - } + { + Archive* archive = OpenArchive( "" ); + archive->release(); + } + { + Archive* archive = OpenArchive( "NONEXISTANTFILE" ); + archive->release(); + } + { + Archive* archive = OpenArchive( "c:/quake/id1/pak0.pak" ); + ArchiveFile* file = archive->openFile( "gfx/palette.lmp" ); + if ( file != 0 ) { + char buffer[1024]; + file->getInputStream().read( (InputStream::byte_type*)buffer, 1024 ); + file->release(); + } + TestVisitor visitor; + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 0 ), "progs/" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 0 ), "maps/" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "sound/ambience/" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "sound/" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "sound/" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "sound/" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" ); + archive->release(); + } } }; diff --git a/plugins/archivepak/archive.h b/plugins/archivepak/archive.h index 309cef5b..8a61b744 100644 --- a/plugins/archivepak/archive.h +++ b/plugins/archivepak/archive.h @@ -20,4 +20,5 @@ */ class Archive; -Archive* OpenArchive( const char* name ); + +Archive *OpenArchive(const char *name); diff --git a/plugins/archivepak/pak.h b/plugins/archivepak/pak.h index 22051568..7b0ff292 100644 --- a/plugins/archivepak/pak.h +++ b/plugins/archivepak/pak.h @@ -22,18 +22,16 @@ #if !defined( INCLUDED_PAK_H ) #define INCLUDED_PAK_H -struct pakheader_t -{ - char magic[4]; // Name of the new WAD format ("PACK") - unsigned int diroffset; // Position of WAD directory from start of file - unsigned int dirsize; // Number of entries * 0x40 (64 char) +struct pakheader_t { + char magic[4]; // Name of the new WAD format ("PACK") + unsigned int diroffset; // Position of WAD directory from start of file + unsigned int dirsize; // Number of entries * 0x40 (64 char) }; -struct pakentry_t -{ - char filename[0x38]; // Name of the file, Unix style, with extension, 50 chars, padded with '\0'. - unsigned int offset; // Position of the entry in PACK file - unsigned int size; // Size of the entry in PACK file +struct pakentry_t { + char filename[0x38]; // Name of the file, Unix style, with extension, 50 chars, padded with '\0'. + unsigned int offset; // Position of the entry in PACK file + unsigned int size; // Size of the entry in PACK file }; #endif diff --git a/plugins/archivepak/plugin.cpp b/plugins/archivepak/plugin.cpp index 489af0b3..532437c4 100644 --- a/plugins/archivepak/plugin.cpp +++ b/plugins/archivepak/plugin.cpp @@ -26,19 +26,22 @@ #include "archive.h" -class ArchivePakAPI -{ -_QERArchiveTable m_archivepak; +class ArchivePakAPI { + _QERArchiveTable m_archivepak; public: -typedef _QERArchiveTable Type; -STRING_CONSTANT( Name, "pak" ); + typedef _QERArchiveTable Type; -ArchivePakAPI(){ - m_archivepak.m_pfnOpenArchive = &OpenArchive; -} -_QERArchiveTable* getTable(){ - return &m_archivepak; -} + STRING_CONSTANT(Name, "pak"); + + ArchivePakAPI() + { + m_archivepak.m_pfnOpenArchive = &OpenArchive; + } + + _QERArchiveTable *getTable() + { + return &m_archivepak; + } }; typedef SingletonModule ArchivePakModule; @@ -46,8 +49,9 @@ typedef SingletonModule ArchivePakModule; ArchivePakModule g_ArchivePakModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_ArchivePakModule.selfRegister(); + g_ArchivePakModule.selfRegister(); } diff --git a/plugins/archivewad/archive.cpp b/plugins/archivewad/archive.cpp index e67d19e8..eae4f92e 100644 --- a/plugins/archivewad/archive.cpp +++ b/plugins/archivewad/archive.cpp @@ -36,134 +36,145 @@ #include "wad.h" -class WadArchive : public Archive -{ -class wad_record_t -{ -public: -wad_record_t( unsigned int position, unsigned int stream_size, unsigned int file_size ) - : m_position( position ), m_stream_size( stream_size ), m_file_size( file_size ) -{} -unsigned int m_position; -unsigned int m_stream_size; -unsigned int m_file_size; -}; - -enum EWadVersion -{ - eNotValid, - eWAD2, - eWAD3, -}; - -typedef std::map files_t; -files_t m_files; -CopiedString m_name; -FileInputStream m_wadfile; - -EWadVersion wad_version( const char* identification ){ - if ( strncmp( identification, "WAD2", 4 ) == 0 ) { - return eWAD2; - } - if ( strncmp( identification, "WAD3", 4 ) == 0 ) { - return eWAD3; - } - return eNotValid; -} - -const char* type_for_version( EWadVersion version ){ - switch ( version ) - { - case eWAD2: - return ".mip"; - case eWAD3: - return ".hlw"; - default: - break; - } - return ""; -} - -int miptex_type_for_version( EWadVersion version ){ - switch ( version ) - { - case eWAD2: - return TYP_MIPTEX; - case eWAD3: - return 67; - default: - break; - } - return -1; -} +class WadArchive : public Archive { + class wad_record_t { + public: + wad_record_t(unsigned int position, unsigned int stream_size, unsigned int file_size) + : m_position(position), m_stream_size(stream_size), m_file_size(file_size) + {} + + unsigned int m_position; + unsigned int m_stream_size; + unsigned int m_file_size; + }; + + enum EWadVersion { + eNotValid, + eWAD2, + eWAD3, + }; + + typedef std::map files_t; + files_t m_files; + CopiedString m_name; + FileInputStream m_wadfile; + + EWadVersion wad_version(const char *identification) + { + if (strncmp(identification, "WAD2", 4) == 0) { + return eWAD2; + } + if (strncmp(identification, "WAD3", 4) == 0) { + return eWAD3; + } + return eNotValid; + } + + const char *type_for_version(EWadVersion version) + { + switch (version) { + case eWAD2: + return ".mip"; + case eWAD3: + return ".hlw"; + default: + break; + } + return ""; + } + + int miptex_type_for_version(EWadVersion version) + { + switch (version) { + case eWAD2: + return TYP_MIPTEX; + case eWAD3: + return 67; + default: + break; + } + return -1; + } public: -WadArchive( const char* name ) - : m_name( name ), m_wadfile( name ){ - if ( !m_wadfile.failed() ) { - wadinfo_t wadinfo; - istream_read_wadinfo( m_wadfile, wadinfo ); - - EWadVersion version = wad_version( wadinfo.identification ); - int miptexType = miptex_type_for_version( version ); - - if ( version != eNotValid ) { - m_wadfile.seek( wadinfo.infotableofs ); - - for ( int i = 0; i < wadinfo.numlumps; ++i ) - { - char buffer[32]; - lumpinfo_t lumpinfo; - istream_read_lumpinfo( m_wadfile, lumpinfo ); - if ( lumpinfo.type == miptexType ) { - strcpy( buffer, "textures/" ); - strcat( buffer, lumpinfo.name ); - strcat( buffer, type_for_version( version ) ); - m_files.insert( files_t::value_type( buffer, wad_record_t( lumpinfo.filepos, lumpinfo.disksize, lumpinfo.size ) ) ); - } - } - } - } -} - -void release(){ - delete this; -} -ArchiveFile* openFile( const char* name ){ - files_t::iterator i = m_files.find( name ); - if ( i != m_files.end() ) { - return StoredArchiveFile::create( name, m_name.c_str(), i->second.m_position, i->second.m_stream_size, i->second.m_file_size ); - } - return 0; -} -virtual ArchiveTextFile* openTextFile( const char* name ){ - files_t::iterator i = m_files.find( name ); - if ( i != m_files.end() ) { - return StoredArchiveTextFile::create( name, m_name.c_str(), i->second.m_position, i->second.m_stream_size ); - } - return 0; -} -bool containsFile( const char* name ){ - return m_files.find( name ) != m_files.end(); -} -void forEachFile( VisitorFunc visitor, const char* root ){ - if ( root[0] == '\0' ) { - if ( visitor.directory( "textures/", 1 ) ) { - return; - } - } - else if ( strcmp( root, "textures/" ) != 0 ) { - return; - } - - for ( files_t::iterator i = m_files.begin(); i != m_files.end(); ++i ) - visitor.file( i->first.c_str() ); -} + WadArchive(const char *name) + : m_name(name), m_wadfile(name) + { + if (!m_wadfile.failed()) { + wadinfo_t wadinfo; + istream_read_wadinfo(m_wadfile, wadinfo); + + EWadVersion version = wad_version(wadinfo.identification); + int miptexType = miptex_type_for_version(version); + + if (version != eNotValid) { + m_wadfile.seek(wadinfo.infotableofs); + + for (int i = 0; i < wadinfo.numlumps; ++i) { + char buffer[32]; + lumpinfo_t lumpinfo; + istream_read_lumpinfo(m_wadfile, lumpinfo); + if (lumpinfo.type == miptexType) { + strcpy(buffer, "textures/"); + strcat(buffer, lumpinfo.name); + strcat(buffer, type_for_version(version)); + m_files.insert(files_t::value_type(buffer, wad_record_t(lumpinfo.filepos, lumpinfo.disksize, + lumpinfo.size))); + } + } + } + } + } + + void release() + { + delete this; + } + + ArchiveFile *openFile(const char *name) + { + files_t::iterator i = m_files.find(name); + if (i != m_files.end()) { + return StoredArchiveFile::create(name, m_name.c_str(), i->second.m_position, i->second.m_stream_size, + i->second.m_file_size); + } + return 0; + } + + virtual ArchiveTextFile *openTextFile(const char *name) + { + files_t::iterator i = m_files.find(name); + if (i != m_files.end()) { + return StoredArchiveTextFile::create(name, m_name.c_str(), i->second.m_position, i->second.m_stream_size); + } + return 0; + } + + bool containsFile(const char *name) + { + return m_files.find(name) != m_files.end(); + } + + void forEachFile(VisitorFunc visitor, const char *root) + { + if (root[0] == '\0') { + if (visitor.directory("textures/", 1)) { + return; + } + } else if (strcmp(root, "textures/") != 0) { + return; + } + + for (files_t::iterator i = m_files.begin(); i != m_files.end(); ++i) { + visitor.file(i->first.c_str()); + } + } }; -Archive* OpenArchive( const char* name ){ - return new WadArchive( name ); +Archive *OpenArchive(const char *name) +{ + return new WadArchive(name); } #if 0 @@ -174,35 +185,35 @@ class TestVisitor : public Archive::IVisitor { public: void visit( const char* name ){ - int bleh = 0; + int bleh = 0; } }; public: TestArchive(){ - { - Archive* archive = OpenArchive( "" ); - archive->release(); - } - { - Archive* archive = OpenArchive( "NONEXISTANTFILE" ); - archive->release(); - } - { - Archive* archive = OpenArchive( "c:/quake/id1/quake101.wad" ); - ArchiveFile* file = archive->openFile( "textures/sky1.mip" ); - if ( file != 0 ) { - unsigned char* buffer = new unsigned char[file->size()]; - file->getInputStream().read( (InputStream::byte_type*)buffer, file->size() ); - delete[] buffer; - file->release(); - } - TestVisitor visitor; - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "textures/" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures/" ); - archive->release(); - } + { + Archive* archive = OpenArchive( "" ); + archive->release(); + } + { + Archive* archive = OpenArchive( "NONEXISTANTFILE" ); + archive->release(); + } + { + Archive* archive = OpenArchive( "c:/quake/id1/quake101.wad" ); + ArchiveFile* file = archive->openFile( "textures/sky1.mip" ); + if ( file != 0 ) { + unsigned char* buffer = new unsigned char[file->size()]; + file->getInputStream().read( (InputStream::byte_type*)buffer, file->size() ); + delete[] buffer; + file->release(); + } + TestVisitor visitor; + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "textures/" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures/" ); + archive->release(); + } } }; diff --git a/plugins/archivewad/archive.h b/plugins/archivewad/archive.h index 309cef5b..8a61b744 100644 --- a/plugins/archivewad/archive.h +++ b/plugins/archivewad/archive.h @@ -20,4 +20,5 @@ */ class Archive; -Archive* OpenArchive( const char* name ); + +Archive *OpenArchive(const char *name); diff --git a/plugins/archivewad/plugin.cpp b/plugins/archivewad/plugin.cpp index 95813572..d4452280 100644 --- a/plugins/archivewad/plugin.cpp +++ b/plugins/archivewad/plugin.cpp @@ -26,19 +26,22 @@ #include "archive.h" -class ArchiveWadAPI -{ -_QERArchiveTable m_archivewad; +class ArchiveWadAPI { + _QERArchiveTable m_archivewad; public: -typedef _QERArchiveTable Type; -STRING_CONSTANT( Name, "wad" ); + typedef _QERArchiveTable Type; -ArchiveWadAPI(){ - m_archivewad.m_pfnOpenArchive = &OpenArchive; -} -_QERArchiveTable* getTable(){ - return &m_archivewad; -} + STRING_CONSTANT(Name, "wad"); + + ArchiveWadAPI() + { + m_archivewad.m_pfnOpenArchive = &OpenArchive; + } + + _QERArchiveTable *getTable() + { + return &m_archivewad; + } }; typedef SingletonModule ArchiveWadModule; @@ -46,8 +49,9 @@ typedef SingletonModule ArchiveWadModule; ArchiveWadModule g_ArchiveWadModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_ArchiveWadModule.selfRegister(); + g_ArchiveWadModule.selfRegister(); } diff --git a/plugins/archivewad/wad.h b/plugins/archivewad/wad.h index 617900c3..ab67a62d 100644 --- a/plugins/archivewad/wad.h +++ b/plugins/archivewad/wad.h @@ -38,39 +38,39 @@ #define TYP_SOUND 67 #define TYP_MIPTEX 68 -typedef struct -{ - char identification[4]; // should be WAD2 or 2DAW - int numlumps; - int infotableofs; +typedef struct { + char identification[4]; // should be WAD2 or 2DAW + int numlumps; + int infotableofs; } wadinfo_t; -typedef struct -{ - int filepos; - int disksize; - int size; // uncompressed - char type; - char compression; - char pad1, pad2; - char name[16]; // must be null terminated +typedef struct { + int filepos; + int disksize; + int size; // uncompressed + char type; + char compression; + char pad1, pad2; + char name[16]; // must be null terminated } lumpinfo_t; -inline void istream_read_wadinfo( InputStream& istream, wadinfo_t& wadinfo ){ - istream.read( reinterpret_cast( wadinfo.identification ), 4 ); - wadinfo.numlumps = istream_read_int32_le( istream ); - wadinfo.infotableofs = istream_read_int32_le( istream ); +inline void istream_read_wadinfo(InputStream &istream, wadinfo_t &wadinfo) +{ + istream.read(reinterpret_cast( wadinfo.identification ), 4); + wadinfo.numlumps = istream_read_int32_le(istream); + wadinfo.infotableofs = istream_read_int32_le(istream); } -inline void istream_read_lumpinfo( InputStream& istream, lumpinfo_t& lumpinfo ){ - lumpinfo.filepos = istream_read_int32_le( istream ); - lumpinfo.disksize = istream_read_int32_le( istream ); - lumpinfo.size = istream_read_int32_le( istream ); - lumpinfo.type = istream_read_byte( istream ); - lumpinfo.compression = istream_read_byte( istream ); - lumpinfo.pad1 = istream_read_byte( istream ); - lumpinfo.pad2 = istream_read_byte( istream ); - istream.read( reinterpret_cast( lumpinfo.name ), 16 ); +inline void istream_read_lumpinfo(InputStream &istream, lumpinfo_t &lumpinfo) +{ + lumpinfo.filepos = istream_read_int32_le(istream); + lumpinfo.disksize = istream_read_int32_le(istream); + lumpinfo.size = istream_read_int32_le(istream); + lumpinfo.type = istream_read_byte(istream); + lumpinfo.compression = istream_read_byte(istream); + lumpinfo.pad1 = istream_read_byte(istream); + lumpinfo.pad2 = istream_read_byte(istream); + istream.read(reinterpret_cast( lumpinfo.name ), 16); } #endif diff --git a/plugins/archivezip/archive.cpp b/plugins/archivezip/archive.cpp index a8616e62..bbbda40e 100644 --- a/plugins/archivezip/archive.cpp +++ b/plugins/archivezip/archive.cpp @@ -32,56 +32,69 @@ #include "archivelib.h" #include "zlibstream.h" -class DeflatedArchiveFile : public ArchiveFile -{ -CopiedString m_name; -FileInputStream m_istream; -SubFileInputStream m_substream; -DeflatedInputStream m_zipstream; -FileInputStream::size_type m_size; +class DeflatedArchiveFile : public ArchiveFile { + CopiedString m_name; + FileInputStream m_istream; + SubFileInputStream m_substream; + DeflatedInputStream m_zipstream; + FileInputStream::size_type m_size; public: -typedef FileInputStream::size_type size_type; -typedef FileInputStream::position_type position_type; - -DeflatedArchiveFile( const char* name, const char* archiveName, position_type position, size_type stream_size, size_type file_size ) - : m_name( name ), m_istream( archiveName ), m_substream( m_istream, position, stream_size ), m_zipstream( m_substream ), m_size( file_size ){ -} - -void release(){ - delete this; -} -size_type size() const { - return m_size; -} -const char* getName() const { - return m_name.c_str(); -} -InputStream& getInputStream(){ - return m_zipstream; -} + typedef FileInputStream::size_type size_type; + typedef FileInputStream::position_type position_type; + + DeflatedArchiveFile(const char *name, const char *archiveName, position_type position, size_type stream_size, + size_type file_size) + : m_name(name), m_istream(archiveName), m_substream(m_istream, position, stream_size), + m_zipstream(m_substream), m_size(file_size) + { + } + + void release() + { + delete this; + } + + size_type size() const + { + return m_size; + } + + const char *getName() const + { + return m_name.c_str(); + } + + InputStream &getInputStream() + { + return m_zipstream; + } }; -class DeflatedArchiveTextFile : public ArchiveTextFile -{ -CopiedString m_name; -FileInputStream m_istream; -SubFileInputStream m_substream; -DeflatedInputStream m_zipstream; -BinaryToTextInputStream m_textStream; +class DeflatedArchiveTextFile : public ArchiveTextFile { + CopiedString m_name; + FileInputStream m_istream; + SubFileInputStream m_substream; + DeflatedInputStream m_zipstream; + BinaryToTextInputStream m_textStream; public: -typedef FileInputStream::size_type size_type; -typedef FileInputStream::position_type position_type; - -DeflatedArchiveTextFile( const char* name, const char* archiveName, position_type position, size_type stream_size ) - : m_name( name ), m_istream( archiveName ), m_substream( m_istream, position, stream_size ), m_zipstream( m_substream ), m_textStream( m_zipstream ){ -} - -void release(){ - delete this; -} -TextInputStream& getInputStream(){ - return m_textStream; -} + typedef FileInputStream::size_type size_type; + typedef FileInputStream::position_type position_type; + + DeflatedArchiveTextFile(const char *name, const char *archiveName, position_type position, size_type stream_size) + : m_name(name), m_istream(archiveName), m_substream(m_istream, position, stream_size), + m_zipstream(m_substream), m_textStream(m_zipstream) + { + } + + void release() + { + delete this; + } + + TextInputStream &getInputStream() + { + return m_textStream; + } }; #include "pkzip.h" @@ -91,188 +104,202 @@ TextInputStream& getInputStream(){ #include "fs_filesystem.h" -class ZipArchive : public Archive -{ -class ZipRecord -{ -public: -enum ECompressionMode -{ - eStored, - eDeflated, -}; -ZipRecord( unsigned int position, unsigned int compressed_size, unsigned int uncompressed_size, ECompressionMode mode ) - : m_position( position ), m_stream_size( compressed_size ), m_file_size( uncompressed_size ), m_mode( mode ){ -} -unsigned int m_position; -unsigned int m_stream_size; -unsigned int m_file_size; -ECompressionMode m_mode; -}; - -typedef GenericFileSystem ZipFileSystem; -ZipFileSystem m_filesystem; -CopiedString m_name; -FileInputStream m_istream; - -bool read_record(){ - zip_magic magic; - istream_read_zip_magic( m_istream, magic ); - if ( !( magic == zip_root_dirent_magic ) ) { - return false; - } - zip_version version_encoder; - istream_read_zip_version( m_istream, version_encoder ); - zip_version version_extract; - istream_read_zip_version( m_istream, version_extract ); - //unsigned short flags = - istream_read_int16_le( m_istream ); - unsigned short compression_mode = istream_read_int16_le( m_istream ); - if ( compression_mode != Z_DEFLATED && compression_mode != 0 ) { - return false; - } - zip_dostime dostime; - istream_read_zip_dostime( m_istream, dostime ); - //unsigned int crc32 = - istream_read_int32_le( m_istream ); - unsigned int compressed_size = istream_read_uint32_le( m_istream ); - unsigned int uncompressed_size = istream_read_uint32_le( m_istream ); - unsigned int namelength = istream_read_uint16_le( m_istream ); - unsigned short extras = istream_read_uint16_le( m_istream ); - unsigned short comment = istream_read_uint16_le( m_istream ); - //unsigned short diskstart = - istream_read_int16_le( m_istream ); - //unsigned short filetype = - istream_read_int16_le( m_istream ); - //unsigned int filemode = - istream_read_int32_le( m_istream ); - unsigned int position = istream_read_int32_le( m_istream ); - - Array filename( namelength + 1 ); - m_istream.read( reinterpret_cast( filename.data() ), namelength ); - filename[namelength] = '\0'; - - m_istream.seek( extras + comment, FileInputStream::cur ); - - if ( path_is_directory( filename.data() ) ) { - m_filesystem[filename.data()] = 0; - } - else - { - ZipFileSystem::entry_type& file = m_filesystem[filename.data()]; - if ( !file.is_directory() ) { - globalOutputStream() << "Warning: zip archive " << makeQuoted( m_name.c_str() ) << " contains duplicated file: " << makeQuoted( filename.data() ) << "\n"; - } - else - { - file = new ZipRecord( position, compressed_size, uncompressed_size, ( compression_mode == Z_DEFLATED ) ? ZipRecord::eDeflated : ZipRecord::eStored ); - } - } - - return true; -} +class ZipArchive : public Archive { + class ZipRecord { + public: + enum ECompressionMode { + eStored, + eDeflated, + }; + + ZipRecord(unsigned int position, unsigned int compressed_size, unsigned int uncompressed_size, + ECompressionMode mode) + : m_position(position), m_stream_size(compressed_size), m_file_size(uncompressed_size), m_mode(mode) + { + } + + unsigned int m_position; + unsigned int m_stream_size; + unsigned int m_file_size; + ECompressionMode m_mode; + }; + + typedef GenericFileSystem ZipFileSystem; + ZipFileSystem m_filesystem; + CopiedString m_name; + FileInputStream m_istream; + + bool read_record() + { + zip_magic magic; + istream_read_zip_magic(m_istream, magic); + if (!(magic == zip_root_dirent_magic)) { + return false; + } + zip_version version_encoder; + istream_read_zip_version(m_istream, version_encoder); + zip_version version_extract; + istream_read_zip_version(m_istream, version_extract); + //unsigned short flags = + istream_read_int16_le(m_istream); + unsigned short compression_mode = istream_read_int16_le(m_istream); + if (compression_mode != Z_DEFLATED && compression_mode != 0) { + return false; + } + zip_dostime dostime; + istream_read_zip_dostime(m_istream, dostime); + //unsigned int crc32 = + istream_read_int32_le(m_istream); + unsigned int compressed_size = istream_read_uint32_le(m_istream); + unsigned int uncompressed_size = istream_read_uint32_le(m_istream); + unsigned int namelength = istream_read_uint16_le(m_istream); + unsigned short extras = istream_read_uint16_le(m_istream); + unsigned short comment = istream_read_uint16_le(m_istream); + //unsigned short diskstart = + istream_read_int16_le(m_istream); + //unsigned short filetype = + istream_read_int16_le(m_istream); + //unsigned int filemode = + istream_read_int32_le(m_istream); + unsigned int position = istream_read_int32_le(m_istream); + + Array filename(namelength + 1); + m_istream.read(reinterpret_cast( filename.data()), namelength); + filename[namelength] = '\0'; + + m_istream.seek(extras + comment, FileInputStream::cur); + + if (path_is_directory(filename.data())) { + m_filesystem[filename.data()] = 0; + } else { + ZipFileSystem::entry_type &file = m_filesystem[filename.data()]; + if (!file.is_directory()) { + globalOutputStream() << "Warning: zip archive " << makeQuoted(m_name.c_str()) + << " contains duplicated file: " << makeQuoted(filename.data()) << "\n"; + } else { + file = new ZipRecord(position, compressed_size, uncompressed_size, + (compression_mode == Z_DEFLATED) ? ZipRecord::eDeflated : ZipRecord::eStored); + } + } + + return true; + } + + bool read_pkzip() + { + SeekableStream::position_type pos = pkzip_find_disk_trailer(m_istream); + if (pos != 0) { + zip_disk_trailer disk_trailer; + m_istream.seek(pos); + istream_read_zip_disk_trailer(m_istream, disk_trailer); + if (!(disk_trailer.z_magic == zip_disk_trailer_magic)) { + return false; + } + + m_istream.seek(disk_trailer.z_rootseek); + for (unsigned int i = 0; i < disk_trailer.z_entries; ++i) { + if (!read_record()) { + return false; + } + } + return true; + } + return false; + } -bool read_pkzip(){ - SeekableStream::position_type pos = pkzip_find_disk_trailer( m_istream ); - if ( pos != 0 ) { - zip_disk_trailer disk_trailer; - m_istream.seek( pos ); - istream_read_zip_disk_trailer( m_istream, disk_trailer ); - if ( !( disk_trailer.z_magic == zip_disk_trailer_magic ) ) { - return false; - } - - m_istream.seek( disk_trailer.z_rootseek ); - for ( unsigned int i = 0; i < disk_trailer.z_entries; ++i ) - { - if ( !read_record() ) { - return false; - } - } - return true; - } - return false; -} public: -ZipArchive( const char* name ) - : m_name( name ), m_istream( name ){ - if ( !m_istream.failed() ) { - if ( !read_pkzip() ) { - globalErrorStream() << "ERROR: invalid zip-file " << makeQuoted( name ) << '\n'; - } - } -} -~ZipArchive(){ - for ( ZipFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i ) - { - delete i->second.file(); - } -} - -bool failed(){ - return m_istream.failed(); -} - -void release(){ - delete this; -} -ArchiveFile* openFile( const char* name ){ - ZipFileSystem::iterator i = m_filesystem.find( name ); - if ( i != m_filesystem.end() && !i->second.is_directory() ) { - ZipRecord* file = i->second.file(); - - m_istream.seek( file->m_position ); - zip_file_header file_header; - istream_read_zip_file_header( m_istream, file_header ); - if ( file_header.z_magic != zip_file_header_magic ) { - globalErrorStream() << "error reading zip file " << makeQuoted( m_name.c_str() ); - return 0; - } - - switch ( file->m_mode ) - { - case ZipRecord::eStored: - return StoredArchiveFile::create( name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size ); - case ZipRecord::eDeflated: - return new DeflatedArchiveFile( name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size ); - } - } - return 0; -} -ArchiveTextFile* openTextFile( const char* name ){ - ZipFileSystem::iterator i = m_filesystem.find( name ); - if ( i != m_filesystem.end() && !i->second.is_directory() ) { - ZipRecord* file = i->second.file(); - - m_istream.seek( file->m_position ); - zip_file_header file_header; - istream_read_zip_file_header( m_istream, file_header ); - if ( file_header.z_magic != zip_file_header_magic ) { - globalErrorStream() << "error reading zip file " << makeQuoted( m_name.c_str() ); - return 0; - } - - switch ( file->m_mode ) - { - case ZipRecord::eStored: - return StoredArchiveTextFile::create( name, m_name.c_str(), m_istream.tell(), file->m_stream_size ); - case ZipRecord::eDeflated: - return new DeflatedArchiveTextFile( name, m_name.c_str(), m_istream.tell(), file->m_stream_size ); - } - } - return 0; -} -bool containsFile( const char* name ){ - ZipFileSystem::iterator i = m_filesystem.find( name ); - return i != m_filesystem.end() && !i->second.is_directory(); -} -void forEachFile( VisitorFunc visitor, const char* root ){ - m_filesystem.traverse( visitor, root ); -} + ZipArchive(const char *name) + : m_name(name), m_istream(name) + { + if (!m_istream.failed()) { + if (!read_pkzip()) { + globalErrorStream() << "ERROR: invalid zip-file " << makeQuoted(name) << '\n'; + } + } + } + + ~ZipArchive() + { + for (ZipFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i) { + delete i->second.file(); + } + } + + bool failed() + { + return m_istream.failed(); + } + + void release() + { + delete this; + } + + ArchiveFile *openFile(const char *name) + { + ZipFileSystem::iterator i = m_filesystem.find(name); + if (i != m_filesystem.end() && !i->second.is_directory()) { + ZipRecord *file = i->second.file(); + + m_istream.seek(file->m_position); + zip_file_header file_header; + istream_read_zip_file_header(m_istream, file_header); + if (file_header.z_magic != zip_file_header_magic) { + globalErrorStream() << "error reading zip file " << makeQuoted(m_name.c_str()); + return 0; + } + + switch (file->m_mode) { + case ZipRecord::eStored: + return StoredArchiveFile::create(name, m_name.c_str(), m_istream.tell(), file->m_stream_size, + file->m_file_size); + case ZipRecord::eDeflated: + return new DeflatedArchiveFile(name, m_name.c_str(), m_istream.tell(), file->m_stream_size, + file->m_file_size); + } + } + return 0; + } + + ArchiveTextFile *openTextFile(const char *name) + { + ZipFileSystem::iterator i = m_filesystem.find(name); + if (i != m_filesystem.end() && !i->second.is_directory()) { + ZipRecord *file = i->second.file(); + + m_istream.seek(file->m_position); + zip_file_header file_header; + istream_read_zip_file_header(m_istream, file_header); + if (file_header.z_magic != zip_file_header_magic) { + globalErrorStream() << "error reading zip file " << makeQuoted(m_name.c_str()); + return 0; + } + + switch (file->m_mode) { + case ZipRecord::eStored: + return StoredArchiveTextFile::create(name, m_name.c_str(), m_istream.tell(), file->m_stream_size); + case ZipRecord::eDeflated: + return new DeflatedArchiveTextFile(name, m_name.c_str(), m_istream.tell(), file->m_stream_size); + } + } + return 0; + } + + bool containsFile(const char *name) + { + ZipFileSystem::iterator i = m_filesystem.find(name); + return i != m_filesystem.end() && !i->second.is_directory(); + } + + void forEachFile(VisitorFunc visitor, const char *root) + { + m_filesystem.traverse(visitor, root); + } }; -Archive* OpenArchive( const char* name ){ - return new ZipArchive( name ); +Archive *OpenArchive(const char *name) +{ + return new ZipArchive(name); } #if 0 @@ -283,31 +310,31 @@ class TestVisitor : public Archive::IVisitor { public: void visit( const char* name ){ - int bleh = 0; + int bleh = 0; } }; public: TestZip(){ - testzip( "c:/quake3/baseq3/mapmedia.pk3", "textures/radiant/notex.tga" ); + testzip( "c:/quake3/baseq3/mapmedia.pk3", "textures/radiant/notex.tga" ); } void testzip( const char* name, const char* filename ){ - Archive* archive = OpenArchive( name ); - ArchiveFile* file = archive->openFile( filename ); - if ( file != 0 ) { - unsigned char buffer[4096]; - std::size_t count = file->getInputStream().read( (InputStream::byte_type*)buffer, 4096 ); - file->release(); - } - TestVisitor visitor; - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures/" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" ); - archive->release(); + Archive* archive = OpenArchive( name ); + ArchiveFile* file = archive->openFile( filename ); + if ( file != 0 ) { + unsigned char buffer[4096]; + std::size_t count = file->getInputStream().read( (InputStream::byte_type*)buffer, 4096 ); + file->release(); + } + TestVisitor visitor; + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures/" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" ); + archive->release(); } }; diff --git a/plugins/archivezip/archive.h b/plugins/archivezip/archive.h index 04ed6e33..95f64d91 100644 --- a/plugins/archivezip/archive.h +++ b/plugins/archivezip/archive.h @@ -19,4 +19,4 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -Archive* OpenArchive( const char* name ); +Archive *OpenArchive(const char *name); diff --git a/plugins/archivezip/pkzip.h b/plugins/archivezip/pkzip.h index 01d4b5f2..94cdf843 100644 --- a/plugins/archivezip/pkzip.h +++ b/plugins/archivezip/pkzip.h @@ -26,78 +26,82 @@ #include "idatastream.h" #include -class zip_magic -{ +class zip_magic { public: -bool operator==( const zip_magic& other ) const { - return m_value[0] == other.m_value[0] - && m_value[1] == other.m_value[1] - && m_value[2] == other.m_value[2] - && m_value[3] == other.m_value[3]; -} -bool operator!=( const zip_magic& other ) const { - return !( *this == other ); -} -char m_value[4]; + bool operator==(const zip_magic &other) const + { + return m_value[0] == other.m_value[0] + && m_value[1] == other.m_value[1] + && m_value[2] == other.m_value[2] + && m_value[3] == other.m_value[3]; + } + + bool operator!=(const zip_magic &other) const + { + return !(*this == other); + } + + char m_value[4]; }; -inline void istream_read_zip_magic( InputStream& istream, zip_magic& magic ){ - istream.read( reinterpret_cast( magic.m_value ), 4 ); +inline void istream_read_zip_magic(InputStream &istream, zip_magic &magic) +{ + istream.read(reinterpret_cast( magic.m_value ), 4); } -struct zip_version -{ - char version; - char ostype; +struct zip_version { + char version; + char ostype; }; -inline void istream_read_zip_version( InputStream& istream, zip_version& version ){ - version.version = istream_read_byte( istream ); - version.ostype = istream_read_byte( istream ); +inline void istream_read_zip_version(InputStream &istream, zip_version &version) +{ + version.version = istream_read_byte(istream); + version.ostype = istream_read_byte(istream); } -struct zip_dostime -{ - unsigned short time; - unsigned short date; +struct zip_dostime { + unsigned short time; + unsigned short date; }; -inline void istream_read_zip_dostime( InputStream& istream, zip_dostime& dostime ){ - dostime.time = istream_read_int16_le( istream ); - dostime.date = istream_read_int16_le( istream ); +inline void istream_read_zip_dostime(InputStream &istream, zip_dostime &dostime) +{ + dostime.time = istream_read_int16_le(istream); + dostime.date = istream_read_int16_le(istream); } -const zip_magic zip_file_header_magic = { { 'P', 'K', 0x03, 0x04 } }; +const zip_magic zip_file_header_magic = {{'P', 'K', 0x03, 0x04}}; /* A. Local file header */ -struct zip_file_header -{ - zip_magic z_magic; /* local file header signature (0x04034b50) */ - zip_version z_extract; /* version needed to extract */ - unsigned short z_flags; /* general purpose bit flag */ - unsigned short z_compr; /* compression method */ - zip_dostime z_dostime; /* last mod file time (dos format) */ - unsigned int z_crc32; /* crc-32 */ - unsigned int z_csize; /* compressed size */ - unsigned int z_usize; /* uncompressed size */ - unsigned short z_namlen; /* filename length (null if stdin) */ - unsigned short z_extras; /* extra field length */ - /* followed by filename (of variable size) */ - /* followed by extra field (of variable size) */ +struct zip_file_header { + zip_magic z_magic; /* local file header signature (0x04034b50) */ + zip_version z_extract; /* version needed to extract */ + unsigned short z_flags; /* general purpose bit flag */ + unsigned short z_compr; /* compression method */ + zip_dostime z_dostime; /* last mod file time (dos format) */ + unsigned int z_crc32; /* crc-32 */ + unsigned int z_csize; /* compressed size */ + unsigned int z_usize; /* uncompressed size */ + unsigned short z_namlen; /* filename length (null if stdin) */ + unsigned short z_extras; /* extra field length */ + /* followed by filename (of variable size) */ + /* followed by extra field (of variable size) */ }; -inline void istream_read_zip_file_header( SeekableInputStream& istream, zip_file_header& file_header ){ - istream_read_zip_magic( istream, file_header.z_magic ); - istream_read_zip_version( istream, file_header.z_extract ); - file_header.z_flags = istream_read_uint16_le( istream ); - file_header.z_compr = istream_read_uint16_le( istream ); - istream_read_zip_dostime( istream, file_header.z_dostime ); - file_header.z_crc32 = istream_read_uint32_le( istream ); - file_header.z_csize = istream_read_uint32_le( istream ); - file_header.z_usize = istream_read_uint32_le( istream ); - file_header.z_namlen = istream_read_uint16_le( istream ); - file_header.z_extras = istream_read_uint16_le( istream ); - istream.seek( file_header.z_namlen + file_header.z_extras, SeekableInputStream::cur ); +inline void istream_read_zip_file_header(SeekableInputStream &istream, zip_file_header &file_header) +{ + istream_read_zip_magic(istream, file_header.z_magic); + istream_read_zip_version(istream, file_header.z_extract); + file_header.z_flags = istream_read_uint16_le(istream); + file_header.z_compr = istream_read_uint16_le(istream); + istream_read_zip_dostime(istream, file_header.z_dostime); + file_header.z_crc32 = istream_read_uint32_le(istream); + file_header.z_csize = istream_read_uint32_le(istream); + file_header.z_usize = istream_read_uint32_le(istream); + file_header.z_namlen = istream_read_uint16_le(istream); + file_header.z_extras = istream_read_uint16_le(istream); + istream.seek(file_header.z_namlen + file_header.z_extras, SeekableInputStream::cur); } /* B. data descriptor @@ -105,21 +109,21 @@ inline void istream_read_zip_file_header( SeekableInputStream& istream, zip_file * and immediately follows the last byte of compressed data. It is only used if * the output media of the compressor was not seekable, eg. standard output. */ -const zip_magic zip_file_trailer_magic = { { 'P', 'K', 0x07, 0x08} }; +const zip_magic zip_file_trailer_magic = {{'P', 'K', 0x07, 0x08}}; -struct zip_file_trailer -{ - zip_magic z_magic; - unsigned int z_crc32; /* crc-32 */ - unsigned int z_csize; /* compressed size */ - unsigned int z_usize; /* uncompressed size */ +struct zip_file_trailer { + zip_magic z_magic; + unsigned int z_crc32; /* crc-32 */ + unsigned int z_csize; /* compressed size */ + unsigned int z_usize; /* uncompressed size */ }; -inline void istream_read_zip_file_trailer( InputStream& istream, zip_file_trailer& file_trailer ){ - istream_read_zip_magic( istream, file_trailer.z_magic ); - file_trailer.z_crc32 = istream_read_uint32_le( istream ); - file_trailer.z_csize = istream_read_uint32_le( istream ); - file_trailer.z_usize = istream_read_uint32_le( istream ); +inline void istream_read_zip_file_trailer(InputStream &istream, zip_file_trailer &file_trailer) +{ + istream_read_zip_magic(istream, file_trailer.z_magic); + file_trailer.z_crc32 = istream_read_uint32_le(istream); + file_trailer.z_csize = istream_read_uint32_le(istream); + file_trailer.z_usize = istream_read_uint32_le(istream); } @@ -131,127 +135,124 @@ inline void istream_read_zip_file_trailer( InputStream& istream, zip_file_traile * - a single entry including filename, extras and comment may not exceed 64k. */ -const zip_magic zip_root_dirent_magic = { { 'P', 'K', 0x01, 0x02 } }; - -struct zip_root_dirent -{ - zip_magic z_magic; - zip_version z_encoder; /* version made by */ - zip_version z_extract; /* version need to extract */ - unsigned short z_flags; /* general purpose bit flag */ - unsigned short z_compr; /* compression method */ - zip_dostime z_dostime; /* last mod file time&date (dos format) */ - unsigned int z_crc32; /* crc-32 */ - unsigned int z_csize; /* compressed size */ - unsigned int z_usize; /* uncompressed size */ - unsigned short z_namlen; /* filename length (null if stdin) */ - unsigned short z_extras; /* extra field length */ - unsigned short z_comment; /* file comment length */ - unsigned short z_diskstart; /* disk number of start (if spanning zip over multiple disks) */ - unsigned short z_filetype; /* internal file attributes, bit0 = ascii */ - unsigned int z_filemode; /* extrnal file attributes, eg. msdos attrib byte */ - unsigned int z_off; /* relative offset of local file header, seekval if singledisk */ - /* followed by filename (of variable size) */ - /* followed by extra field (of variable size) */ - /* followed by file comment (of variable size) */ +const zip_magic zip_root_dirent_magic = {{'P', 'K', 0x01, 0x02}}; + +struct zip_root_dirent { + zip_magic z_magic; + zip_version z_encoder; /* version made by */ + zip_version z_extract; /* version need to extract */ + unsigned short z_flags; /* general purpose bit flag */ + unsigned short z_compr; /* compression method */ + zip_dostime z_dostime; /* last mod file time&date (dos format) */ + unsigned int z_crc32; /* crc-32 */ + unsigned int z_csize; /* compressed size */ + unsigned int z_usize; /* uncompressed size */ + unsigned short z_namlen; /* filename length (null if stdin) */ + unsigned short z_extras; /* extra field length */ + unsigned short z_comment; /* file comment length */ + unsigned short z_diskstart; /* disk number of start (if spanning zip over multiple disks) */ + unsigned short z_filetype; /* internal file attributes, bit0 = ascii */ + unsigned int z_filemode; /* extrnal file attributes, eg. msdos attrib byte */ + unsigned int z_off; /* relative offset of local file header, seekval if singledisk */ + /* followed by filename (of variable size) */ + /* followed by extra field (of variable size) */ + /* followed by file comment (of variable size) */ }; -inline void istream_read_zip_root_dirent( SeekableInputStream& istream, zip_root_dirent& root_dirent ){ - istream_read_zip_magic( istream, root_dirent.z_magic ); - istream_read_zip_version( istream, root_dirent.z_encoder ); - istream_read_zip_version( istream, root_dirent.z_extract ); - root_dirent.z_flags = istream_read_uint16_le( istream ); - root_dirent.z_compr = istream_read_uint16_le( istream ); - istream_read_zip_dostime( istream, root_dirent.z_dostime ); - root_dirent.z_crc32 = istream_read_uint32_le( istream ); - root_dirent.z_csize = istream_read_uint32_le( istream ); - root_dirent.z_usize = istream_read_uint32_le( istream ); - root_dirent.z_namlen = istream_read_uint16_le( istream ); - root_dirent.z_extras = istream_read_uint16_le( istream ); - root_dirent.z_comment = istream_read_uint16_le( istream ); - root_dirent.z_diskstart = istream_read_uint16_le( istream ); - root_dirent.z_filetype = istream_read_uint16_le( istream ); - root_dirent.z_filemode = istream_read_uint32_le( istream ); - root_dirent.z_off = istream_read_uint32_le( istream ); - istream.seek( root_dirent.z_namlen + root_dirent.z_extras + root_dirent.z_comment, SeekableInputStream::cur ); +inline void istream_read_zip_root_dirent(SeekableInputStream &istream, zip_root_dirent &root_dirent) +{ + istream_read_zip_magic(istream, root_dirent.z_magic); + istream_read_zip_version(istream, root_dirent.z_encoder); + istream_read_zip_version(istream, root_dirent.z_extract); + root_dirent.z_flags = istream_read_uint16_le(istream); + root_dirent.z_compr = istream_read_uint16_le(istream); + istream_read_zip_dostime(istream, root_dirent.z_dostime); + root_dirent.z_crc32 = istream_read_uint32_le(istream); + root_dirent.z_csize = istream_read_uint32_le(istream); + root_dirent.z_usize = istream_read_uint32_le(istream); + root_dirent.z_namlen = istream_read_uint16_le(istream); + root_dirent.z_extras = istream_read_uint16_le(istream); + root_dirent.z_comment = istream_read_uint16_le(istream); + root_dirent.z_diskstart = istream_read_uint16_le(istream); + root_dirent.z_filetype = istream_read_uint16_le(istream); + root_dirent.z_filemode = istream_read_uint32_le(istream); + root_dirent.z_off = istream_read_uint32_le(istream); + istream.seek(root_dirent.z_namlen + root_dirent.z_extras + root_dirent.z_comment, SeekableInputStream::cur); } /* end of central dir record */ -const zip_magic zip_disk_trailer_magic = { { 'P', 'K', 0x05, 0x06 } }; +const zip_magic zip_disk_trailer_magic = {{'P', 'K', 0x05, 0x06}}; const unsigned int disk_trailer_length = 22; -struct zip_disk_trailer -{ - zip_magic z_magic; - unsigned short z_disk; /* number of this disk */ - unsigned short z_finaldisk; /* number of the disk with the start of the central dir */ - unsigned short z_entries; /* total number of entries in the central dir on this disk */ - unsigned short z_finalentries; /* total number of entries in the central dir */ - unsigned int z_rootsize; /* size of the central directory */ - unsigned int z_rootseek; /* offset of start of central directory with respect to * +struct zip_disk_trailer { + zip_magic z_magic; + unsigned short z_disk; /* number of this disk */ + unsigned short z_finaldisk; /* number of the disk with the start of the central dir */ + unsigned short z_entries; /* total number of entries in the central dir on this disk */ + unsigned short z_finalentries; /* total number of entries in the central dir */ + unsigned int z_rootsize; /* size of the central directory */ + unsigned int z_rootseek; /* offset of start of central directory with respect to * * the starting disk number */ - unsigned short z_comment; /* zipfile comment length */ - /* followed by zipfile comment (of variable size) */ + unsigned short z_comment; /* zipfile comment length */ + /* followed by zipfile comment (of variable size) */ }; -inline void istream_read_zip_disk_trailer( SeekableInputStream& istream, zip_disk_trailer& disk_trailer ){ - istream_read_zip_magic( istream, disk_trailer.z_magic ); - disk_trailer.z_disk = istream_read_uint16_le( istream ); - disk_trailer.z_finaldisk = istream_read_uint16_le( istream ); - disk_trailer.z_entries = istream_read_uint16_le( istream ); - disk_trailer.z_finalentries = istream_read_uint16_le( istream ); - disk_trailer.z_rootsize = istream_read_uint32_le( istream ); - disk_trailer.z_rootseek = istream_read_uint32_le( istream ); - disk_trailer.z_comment = istream_read_uint16_le( istream ); - istream.seek( disk_trailer.z_comment, SeekableInputStream::cur ); +inline void istream_read_zip_disk_trailer(SeekableInputStream &istream, zip_disk_trailer &disk_trailer) +{ + istream_read_zip_magic(istream, disk_trailer.z_magic); + disk_trailer.z_disk = istream_read_uint16_le(istream); + disk_trailer.z_finaldisk = istream_read_uint16_le(istream); + disk_trailer.z_entries = istream_read_uint16_le(istream); + disk_trailer.z_finalentries = istream_read_uint16_le(istream); + disk_trailer.z_rootsize = istream_read_uint32_le(istream); + disk_trailer.z_rootseek = istream_read_uint32_le(istream); + disk_trailer.z_comment = istream_read_uint16_le(istream); + istream.seek(disk_trailer.z_comment, SeekableInputStream::cur); } -inline SeekableStream::position_type pkzip_find_disk_trailer( SeekableInputStream& istream ){ - istream.seek( 0, SeekableInputStream::end ); - SeekableStream::position_type start_position = istream.tell(); - if ( start_position < disk_trailer_length ) { - return 0; - } - start_position -= disk_trailer_length; - - zip_magic magic; - istream.seek( start_position ); - istream_read_zip_magic( istream, magic ); - - if ( magic == zip_disk_trailer_magic ) { - return start_position; - } - else - { - const SeekableStream::position_type max_comment = 0x10000; - const SeekableStream::position_type bufshift = 6; - const SeekableStream::position_type bufsize = max_comment >> bufshift; - unsigned char buffer[bufsize]; - - SeekableStream::position_type search_end = ( max_comment < start_position ) ? start_position - max_comment : 0; - SeekableStream::position_type position = start_position; - while ( position != search_end ) - { - StreamBase::size_type to_read = std::min( bufsize, position - search_end ); - position -= to_read; - - istream.seek( position ); - StreamBase::size_type size = istream.read( buffer, to_read ); - - unsigned char* p = buffer + size; - while ( p != buffer ) - { - --p; - magic.m_value[3] = magic.m_value[2]; - magic.m_value[2] = magic.m_value[1]; - magic.m_value[1] = magic.m_value[0]; - magic.m_value[0] = *p; - if ( magic == zip_disk_trailer_magic ) { - return position + ( p - buffer ); - } - } - } - return 0; - } +inline SeekableStream::position_type pkzip_find_disk_trailer(SeekableInputStream &istream) +{ + istream.seek(0, SeekableInputStream::end); + SeekableStream::position_type start_position = istream.tell(); + if (start_position < disk_trailer_length) { + return 0; + } + start_position -= disk_trailer_length; + + zip_magic magic; + istream.seek(start_position); + istream_read_zip_magic(istream, magic); + + if (magic == zip_disk_trailer_magic) { + return start_position; + } else { + const SeekableStream::position_type max_comment = 0x10000; + const SeekableStream::position_type bufshift = 6; + const SeekableStream::position_type bufsize = max_comment >> bufshift; + unsigned char buffer[bufsize]; + + SeekableStream::position_type search_end = (max_comment < start_position) ? start_position - max_comment : 0; + SeekableStream::position_type position = start_position; + while (position != search_end) { + StreamBase::size_type to_read = std::min(bufsize, position - search_end); + position -= to_read; + + istream.seek(position); + StreamBase::size_type size = istream.read(buffer, to_read); + + unsigned char *p = buffer + size; + while (p != buffer) { + --p; + magic.m_value[3] = magic.m_value[2]; + magic.m_value[2] = magic.m_value[1]; + magic.m_value[1] = magic.m_value[0]; + magic.m_value[0] = *p; + if (magic == zip_disk_trailer_magic) { + return position + (p - buffer); + } + } + } + return 0; + } } #endif diff --git a/plugins/archivezip/plugin.cpp b/plugins/archivezip/plugin.cpp index 69a344b9..eda88c3b 100644 --- a/plugins/archivezip/plugin.cpp +++ b/plugins/archivezip/plugin.cpp @@ -27,19 +27,22 @@ #include "archive.h" -class ArchiveZipAPI -{ -_QERArchiveTable m_archivezip; +class ArchiveZipAPI { + _QERArchiveTable m_archivezip; public: -typedef _QERArchiveTable Type; -STRING_CONSTANT( Name, "pk3" ); + typedef _QERArchiveTable Type; -ArchiveZipAPI(){ - m_archivezip.m_pfnOpenArchive = &OpenArchive; -} -_QERArchiveTable* getTable(){ - return &m_archivezip; -} + STRING_CONSTANT(Name, "pk3"); + + ArchiveZipAPI() + { + m_archivezip.m_pfnOpenArchive = &OpenArchive; + } + + _QERArchiveTable *getTable() + { + return &m_archivezip; + } }; typedef SingletonModule ArchiveZipModule; @@ -47,19 +50,22 @@ typedef SingletonModule ArchiveZipModule; ArchiveZipModule g_ArchiveZipModule; -class ArchivePK4API -{ -_QERArchiveTable m_archivepk4; +class ArchivePK4API { + _QERArchiveTable m_archivepk4; public: -typedef _QERArchiveTable Type; -STRING_CONSTANT( Name, "pk4" ); + typedef _QERArchiveTable Type; -ArchivePK4API(){ - m_archivepk4.m_pfnOpenArchive = &OpenArchive; -} -_QERArchiveTable* getTable(){ - return &m_archivepk4; -} + STRING_CONSTANT(Name, "pk4"); + + ArchivePK4API() + { + m_archivepk4.m_pfnOpenArchive = &OpenArchive; + } + + _QERArchiveTable *getTable() + { + return &m_archivepk4; + } }; typedef SingletonModule ArchivePK4Module; @@ -67,19 +73,22 @@ typedef SingletonModule ArchivePK4Module; ArchivePK4Module g_ArchivePK4Module; -class ArchiveDPKAPI -{ -_QERArchiveTable m_archivedpk; +class ArchiveDPKAPI { + _QERArchiveTable m_archivedpk; public: -typedef _QERArchiveTable Type; -STRING_CONSTANT( Name, "dpk" ); + typedef _QERArchiveTable Type; -ArchiveDPKAPI(){ - m_archivedpk.m_pfnOpenArchive = &OpenArchive; -} -_QERArchiveTable* getTable(){ - return &m_archivedpk; -} + STRING_CONSTANT(Name, "dpk"); + + ArchiveDPKAPI() + { + m_archivedpk.m_pfnOpenArchive = &OpenArchive; + } + + _QERArchiveTable *getTable() + { + return &m_archivedpk; + } }; typedef SingletonModule ArchiveDPKModule; @@ -87,10 +96,11 @@ typedef SingletonModule ArchiveDPKModule; ArchiveDPKModule g_ArchiveDPKModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_ArchiveZipModule.selfRegister(); - g_ArchivePK4Module.selfRegister(); - g_ArchiveDPKModule.selfRegister(); + g_ArchiveZipModule.selfRegister(); + g_ArchivePK4Module.selfRegister(); + g_ArchiveDPKModule.selfRegister(); } diff --git a/plugins/archivezip/zlibstream.h b/plugins/archivezip/zlibstream.h index 2e2e7d8f..5e2b2096 100644 --- a/plugins/archivezip/zlibstream.h +++ b/plugins/archivezip/zlibstream.h @@ -29,40 +29,43 @@ /// /// - Uses z_stream to decompress the data stream on the fly. /// - Uses a buffer to reduce the number of times the wrapped stream must be read. -class DeflatedInputStream : public InputStream -{ -InputStream& m_istream; -z_stream m_zipstream; -enum unnamed0 { m_bufsize = 1024 }; -unsigned char m_buffer[m_bufsize]; +class DeflatedInputStream : public InputStream { + InputStream &m_istream; + z_stream m_zipstream; + enum unnamed0 { m_bufsize = 1024 }; + unsigned char m_buffer[m_bufsize]; public: -DeflatedInputStream( InputStream& istream ) - : m_istream( istream ){ - m_zipstream.zalloc = 0; - m_zipstream.zfree = 0; - m_zipstream.opaque = 0; - m_zipstream.avail_in = 0; - inflateInit2( &m_zipstream, -MAX_WBITS ); -} -~DeflatedInputStream(){ - inflateEnd( &m_zipstream ); -} -size_type read( byte_type* buffer, size_type length ){ - m_zipstream.next_out = buffer; - m_zipstream.avail_out = static_cast( length ); - while ( m_zipstream.avail_out != 0 ) - { - if ( m_zipstream.avail_in == 0 ) { - m_zipstream.next_in = m_buffer; - m_zipstream.avail_in = static_cast( m_istream.read( m_buffer, m_bufsize ) ); - } - if ( inflate( &m_zipstream, Z_SYNC_FLUSH ) != Z_OK ) { - break; - } - } - return length - m_zipstream.avail_out; -} + DeflatedInputStream(InputStream &istream) + : m_istream(istream) + { + m_zipstream.zalloc = 0; + m_zipstream.zfree = 0; + m_zipstream.opaque = 0; + m_zipstream.avail_in = 0; + inflateInit2(&m_zipstream, -MAX_WBITS); + } + + ~DeflatedInputStream() + { + inflateEnd(&m_zipstream); + } + + size_type read(byte_type *buffer, size_type length) + { + m_zipstream.next_out = buffer; + m_zipstream.avail_out = static_cast( length ); + while (m_zipstream.avail_out != 0) { + if (m_zipstream.avail_in == 0) { + m_zipstream.next_in = m_buffer; + m_zipstream.avail_in = static_cast( m_istream.read(m_buffer, m_bufsize)); + } + if (inflate(&m_zipstream, Z_SYNC_FLUSH) != Z_OK) { + break; + } + } + return length - m_zipstream.avail_out; + } }; #endif diff --git a/plugins/entity/CMakeLists.txt b/plugins/entity/CMakeLists.txt index 8e359919..8ef63d0e 100644 --- a/plugins/entity/CMakeLists.txt +++ b/plugins/entity/CMakeLists.txt @@ -25,5 +25,5 @@ radiant_plugin(entity ) target_include_directories(entity - PRIVATE $ -) + PRIVATE $ + ) diff --git a/plugins/entity/angle.h b/plugins/entity/angle.h index a73c5332..775a7129 100644 --- a/plugins/entity/angle.h +++ b/plugins/entity/angle.h @@ -30,62 +30,69 @@ const float ANGLEKEY_IDENTITY = 0; -inline void default_angle( float& angle ){ - angle = ANGLEKEY_IDENTITY; -} -inline void normalise_angle( float& angle ){ - angle = static_cast( float_mod( angle, 360.0 ) ); +inline void default_angle(float &angle) +{ + angle = ANGLEKEY_IDENTITY; } -inline void read_angle( float& angle, const char* value ){ - if ( !string_parse_float( value, angle ) ) { - angle = 0; - } - else - { - normalise_angle( angle ); - } + +inline void normalise_angle(float &angle) +{ + angle = static_cast( float_mod(angle, 360.0)); } -inline void write_angle( float angle, Entity* entity ){ - if ( angle == 0 ) { - entity->setKeyValue( "angle", "" ); - } - else - { - char value[64]; - sprintf( value, "%f", angle ); - entity->setKeyValue( "angle", value ); - } + +inline void read_angle(float &angle, const char *value) +{ + if (!string_parse_float(value, angle)) { + angle = 0; + } else { + normalise_angle(angle); + } } -class AngleKey +inline void write_angle(float angle, Entity *entity) { -Callback m_angleChanged; + if (angle == 0) { + entity->setKeyValue("angle", ""); + } else { + char value[64]; + sprintf(value, "%f", angle); + entity->setKeyValue("angle", value); + } +} + +class AngleKey { + Callback m_angleChanged; public: -float m_angle; + float m_angle; -AngleKey( const Callback& angleChanged ) - : m_angleChanged( angleChanged ), m_angle( ANGLEKEY_IDENTITY ){ -} + AngleKey(const Callback &angleChanged) + : m_angleChanged(angleChanged), m_angle(ANGLEKEY_IDENTITY) + { + } -void angleChanged( const char* value ){ - read_angle( m_angle, value ); - m_angleChanged(); -} -typedef MemberCaller AngleChangedCaller; + void angleChanged(const char *value) + { + read_angle(m_angle, value); + m_angleChanged(); + } -void write( Entity* entity ) const { - write_angle( m_angle, entity ); -} + typedef MemberCaller AngleChangedCaller; + + void write(Entity *entity) const + { + write_angle(m_angle, entity); + } }; -inline float angle_rotated( float angle, const Quaternion& rotation ){ - return matrix4_get_rotation_euler_xyz_degrees( - matrix4_multiplied_by_matrix4( - matrix4_rotation_for_z_degrees( angle ), - matrix4_rotation_for_quaternion_quantised( rotation ) - ) - ).z(); +inline float angle_rotated(float angle, const Quaternion &rotation) +{ + return matrix4_get_rotation_euler_xyz_degrees( + matrix4_multiplied_by_matrix4( + matrix4_rotation_for_z_degrees(angle), + matrix4_rotation_for_quaternion_quantised(rotation) + ) + ).z(); } #endif diff --git a/plugins/entity/angles.h b/plugins/entity/angles.h index 54f51f9b..10e77bd8 100644 --- a/plugins/entity/angles.h +++ b/plugins/entity/angles.h @@ -30,96 +30,103 @@ #include "angle.h" -const Vector3 ANGLESKEY_IDENTITY = Vector3( 0, 0, 0 ); +const Vector3 ANGLESKEY_IDENTITY = Vector3(0, 0, 0); -inline void default_angles( Vector3& angles ){ - angles = ANGLESKEY_IDENTITY; -} -inline void normalise_angles( Vector3& angles ){ - angles[0] = static_cast( float_mod( angles[0], 360 ) ); - angles[1] = static_cast( float_mod( angles[1], 360 ) ); - angles[2] = static_cast( float_mod( angles[2], 360 ) ); +inline void default_angles(Vector3 &angles) +{ + angles = ANGLESKEY_IDENTITY; } -inline void read_angle( Vector3& angles, const char* value ){ - if ( !string_parse_float( value, angles[2] ) ) { - default_angles( angles ); - } - else - { - angles[0] = 0; - angles[1] = 0; - normalise_angles( angles ); - } + +inline void normalise_angles(Vector3 &angles) +{ + angles[0] = static_cast( float_mod(angles[0], 360)); + angles[1] = static_cast( float_mod(angles[1], 360)); + angles[2] = static_cast( float_mod(angles[2], 360)); } -inline void read_angles( Vector3& angles, const char* value ){ - if ( !string_parse_vector3( value, angles ) ) { - default_angles( angles ); - } - else - { - angles = Vector3( angles[2], angles[0], angles[1] ); - normalise_angles( angles ); - } + +inline void read_angle(Vector3 &angles, const char *value) +{ + if (!string_parse_float(value, angles[2])) { + default_angles(angles); + } else { + angles[0] = 0; + angles[1] = 0; + normalise_angles(angles); + } } -inline void write_angles( const Vector3& angles, Entity* entity ){ - if ( angles[0] == 0 - && angles[1] == 0 - && angles[2] == 0 ) { - entity->setKeyValue( "angle", "" ); - entity->setKeyValue( "angles", "" ); - } - else - { - char value[64]; - - if ( angles[0] == 0 && angles[1] == 0 ) { - entity->setKeyValue( "angles", "" ); - write_angle( angles[2], entity ); - } - else - { - sprintf( value, "%f %f %f", angles[1], angles[2], angles[0] ); - entity->setKeyValue( "angle", "" ); - entity->setKeyValue( "angles", value ); - } - } + +inline void read_angles(Vector3 &angles, const char *value) +{ + if (!string_parse_vector3(value, angles)) { + default_angles(angles); + } else { + angles = Vector3(angles[2], angles[0], angles[1]); + normalise_angles(angles); + } } -inline Vector3 angles_rotated( const Vector3& angles, const Quaternion& rotation ){ - return matrix4_get_rotation_euler_xyz_degrees( - matrix4_multiplied_by_matrix4( - matrix4_rotation_for_euler_xyz_degrees( angles ), - matrix4_rotation_for_quaternion_quantised( rotation ) - ) - ); +inline void write_angles(const Vector3 &angles, Entity *entity) +{ + if (angles[0] == 0 + && angles[1] == 0 + && angles[2] == 0) { + entity->setKeyValue("angle", ""); + entity->setKeyValue("angles", ""); + } else { + char value[64]; + + if (angles[0] == 0 && angles[1] == 0) { + entity->setKeyValue("angles", ""); + write_angle(angles[2], entity); + } else { + sprintf(value, "%f %f %f", angles[1], angles[2], angles[0]); + entity->setKeyValue("angle", ""); + entity->setKeyValue("angles", value); + } + } } -class AnglesKey +inline Vector3 angles_rotated(const Vector3 &angles, const Quaternion &rotation) { -Callback m_anglesChanged; + return matrix4_get_rotation_euler_xyz_degrees( + matrix4_multiplied_by_matrix4( + matrix4_rotation_for_euler_xyz_degrees(angles), + matrix4_rotation_for_quaternion_quantised(rotation) + ) + ); +} + +class AnglesKey { + Callback m_anglesChanged; public: -Vector3 m_angles; + Vector3 m_angles; -AnglesKey( const Callback& anglesChanged ) - : m_anglesChanged( anglesChanged ), m_angles( ANGLESKEY_IDENTITY ){ -} + AnglesKey(const Callback &anglesChanged) + : m_anglesChanged(anglesChanged), m_angles(ANGLESKEY_IDENTITY) + { + } -void angleChanged( const char* value ){ - read_angle( m_angles, value ); - m_anglesChanged(); -} -typedef MemberCaller AngleChangedCaller; + void angleChanged(const char *value) + { + read_angle(m_angles, value); + m_anglesChanged(); + } -void anglesChanged( const char* value ){ - read_angles( m_angles, value ); - m_anglesChanged(); -} -typedef MemberCaller AnglesChangedCaller; + typedef MemberCaller AngleChangedCaller; -void write( Entity* entity ) const { - write_angles( m_angles, entity ); -} + void anglesChanged(const char *value) + { + read_angles(m_angles, value); + m_anglesChanged(); + } + + typedef MemberCaller AnglesChangedCaller; + + void write(Entity *entity) const + { + write_angles(m_angles, entity); + } }; diff --git a/plugins/entity/colour.h b/plugins/entity/colour.h index 86e0deb6..ae209d23 100644 --- a/plugins/entity/colour.h +++ b/plugins/entity/colour.h @@ -30,62 +30,76 @@ #include "generic/callback.h" #include "stringio.h" -inline void default_colour( Vector3& colour ){ - colour = Vector3( 1, 1, 1 ); -} -inline void read_colour( Vector3& colour, const char* value ){ - if ( !string_parse_vector3( value, colour ) ) { - default_colour( colour ); - } +inline void default_colour(Vector3 &colour) +{ + colour = Vector3(1, 1, 1); } -inline void write_colour( const Vector3& colour, Entity* entity ){ - char value[64]; - sprintf( value, "%f %f %f", colour[0], colour[1], colour[2] ); - entity->setKeyValue( "_color", value ); +inline void read_colour(Vector3 &colour, const char *value) +{ + if (!string_parse_vector3(value, colour)) { + default_colour(colour); + } } -class Colour +inline void write_colour(const Vector3 &colour, Entity *entity) { -Callback m_colourChanged; -Shader* m_state; + char value[64]; -void capture_state(){ - m_state = colour_capture_state_fill( m_colour ); -} -void release_state(){ - colour_release_state_fill( m_colour ); + sprintf(value, "%f %f %f", colour[0], colour[1], colour[2]); + entity->setKeyValue("_color", value); } +class Colour { + Callback m_colourChanged; + Shader *m_state; + + void capture_state() + { + m_state = colour_capture_state_fill(m_colour); + } + + void release_state() + { + colour_release_state_fill(m_colour); + } + public: -Vector3 m_colour; + Vector3 m_colour; -Colour( const Callback& colourChanged ) - : m_colourChanged( colourChanged ){ - default_colour( m_colour ); - capture_state(); -} -~Colour(){ - release_state(); -} + Colour(const Callback &colourChanged) + : m_colourChanged(colourChanged) + { + default_colour(m_colour); + capture_state(); + } -void colourChanged( const char* value ){ - release_state(); - read_colour( m_colour, value ); - capture_state(); + ~Colour() + { + release_state(); + } - m_colourChanged(); -} -typedef MemberCaller ColourChangedCaller; + void colourChanged(const char *value) + { + release_state(); + read_colour(m_colour, value); + capture_state(); + m_colourChanged(); + } -void write( Entity* entity ) const { - write_colour( m_colour, entity ); -} + typedef MemberCaller ColourChangedCaller; -Shader* state() const { - return m_state; -} + + void write(Entity *entity) const + { + write_colour(m_colour, entity); + } + + Shader *state() const + { + return m_state; + } }; #endif diff --git a/plugins/entity/curve.h b/plugins/entity/curve.h index c22a51aa..43dc9b3b 100644 --- a/plugins/entity/curve.h +++ b/plugins/entity/curve.h @@ -35,387 +35,418 @@ #include "render.h" #include "stringio.h" -class RenderableCurve : public OpenGLRenderable -{ +class RenderableCurve : public OpenGLRenderable { public: -std::vector m_vertices; -void render( RenderStateFlags state ) const { - pointvertex_gl_array( &m_vertices.front() ); - glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_vertices.size() ) ); -} -}; - -inline void plotBasisFunction( std::size_t numSegments, int point, int degree ){ - Knots knots; - KnotVector_openUniform( knots, 4, degree ); - - globalOutputStream() << "plotBasisFunction point " << point << " of 4, knot vector:"; - for ( Knots::iterator i = knots.begin(); i != knots.end(); ++i ) - { - globalOutputStream() << " " << *i; - } - globalOutputStream() << "\n"; - globalOutputStream() << "t=0 basis=" << BSpline_basis( knots, point, degree, 0.0 ) << "\n"; - for ( std::size_t i = 1; i < numSegments; ++i ) - { - double t = ( 1.0 / double(numSegments) ) * double(i); - globalOutputStream() << "t=" << t << " basis=" << BSpline_basis( knots, point, degree, t ) << "\n"; - } - globalOutputStream() << "t=1 basis=" << BSpline_basis( knots, point, degree, 1.0 ) << "\n"; -} + std::vector m_vertices; -inline bool ControlPoints_parse( ControlPoints& controlPoints, const char* value ){ - StringTokeniser tokeniser( value, " " ); - - std::size_t size; - if ( !string_parse_size( tokeniser.getToken(), size ) ) { - return false; - } - - if ( size < 3 ) { - return false; - } - controlPoints.resize( size ); - - if ( !string_equal( tokeniser.getToken(), "(" ) ) { - return false; - } - for ( ControlPoints::iterator i = controlPoints.begin(); i != controlPoints.end(); ++i ) - { - if ( !string_parse_float( tokeniser.getToken(), ( *i ).x() ) - || !string_parse_float( tokeniser.getToken(), ( *i ).y() ) - || !string_parse_float( tokeniser.getToken(), ( *i ).z() ) ) { - return false; - } - } - if ( !string_equal( tokeniser.getToken(), ")" ) ) { - return false; - } - return true; -} + void render(RenderStateFlags state) const + { + pointvertex_gl_array(&m_vertices.front()); + glDrawArrays(GL_LINE_STRIP, 0, GLsizei(m_vertices.size())); + } +}; -inline void ControlPoints_write( const ControlPoints& controlPoints, StringOutputStream& value ){ - value << Unsigned( controlPoints.size() ) << " ("; - for ( ControlPoints::const_iterator i = controlPoints.begin(); i != controlPoints.end(); ++i ) - { - value << " " << ( *i ).x() << " " << ( *i ).y() << " " << ( *i ).z() << " "; - } - value << ")"; +inline void plotBasisFunction(std::size_t numSegments, int point, int degree) +{ + Knots knots; + KnotVector_openUniform(knots, 4, degree); + + globalOutputStream() << "plotBasisFunction point " << point << " of 4, knot vector:"; + for (Knots::iterator i = knots.begin(); i != knots.end(); ++i) { + globalOutputStream() << " " << *i; + } + globalOutputStream() << "\n"; + globalOutputStream() << "t=0 basis=" << BSpline_basis(knots, point, degree, 0.0) << "\n"; + for (std::size_t i = 1; i < numSegments; ++i) { + double t = (1.0 / double(numSegments)) * double(i); + globalOutputStream() << "t=" << t << " basis=" << BSpline_basis(knots, point, degree, t) << "\n"; + } + globalOutputStream() << "t=1 basis=" << BSpline_basis(knots, point, degree, 1.0) << "\n"; +} + +inline bool ControlPoints_parse(ControlPoints &controlPoints, const char *value) +{ + StringTokeniser tokeniser(value, " "); + + std::size_t size; + if (!string_parse_size(tokeniser.getToken(), size)) { + return false; + } + + if (size < 3) { + return false; + } + controlPoints.resize(size); + + if (!string_equal(tokeniser.getToken(), "(")) { + return false; + } + for (ControlPoints::iterator i = controlPoints.begin(); i != controlPoints.end(); ++i) { + if (!string_parse_float(tokeniser.getToken(), (*i).x()) + || !string_parse_float(tokeniser.getToken(), (*i).y()) + || !string_parse_float(tokeniser.getToken(), (*i).z())) { + return false; + } + } + if (!string_equal(tokeniser.getToken(), ")")) { + return false; + } + return true; +} + +inline void ControlPoints_write(const ControlPoints &controlPoints, StringOutputStream &value) +{ + value << Unsigned(controlPoints.size()) << " ("; + for (ControlPoints::const_iterator i = controlPoints.begin(); i != controlPoints.end(); ++i) { + value << " " << (*i).x() << " " << (*i).y() << " " << (*i).z() << " "; + } + value << ")"; } -inline void ControlPoint_testSelect( const Vector3& point, ObservedSelectable& selectable, Selector& selector, SelectionTest& test ){ - SelectionIntersection best; - test.TestPoint( point, best ); - if ( best.valid() ) { - Selector_add( selector, selectable, best ); - } +inline void +ControlPoint_testSelect(const Vector3 &point, ObservedSelectable &selectable, Selector &selector, SelectionTest &test) +{ + SelectionIntersection best; + test.TestPoint(point, best); + if (best.valid()) { + Selector_add(selector, selectable, best); + } } -class CurveEditType -{ +class CurveEditType { public: -Shader* m_controlsShader; -Shader* m_selectedShader; + Shader *m_controlsShader; + Shader *m_selectedShader; }; -inline void ControlPoints_write( ControlPoints& controlPoints, const char* key, Entity& entity ){ - StringOutputStream value( 256 ); - if ( !controlPoints.empty() ) { - ControlPoints_write( controlPoints, value ); - } - entity.setKeyValue( key, value.c_str() ); -} - -class CurveEdit +inline void ControlPoints_write(ControlPoints &controlPoints, const char *key, Entity &entity) { -SelectionChangeCallback m_selectionChanged; -ControlPoints& m_controlPoints; -typedef Array Selectables; -Selectables m_selectables; - -RenderablePointVector m_controlsRender; -mutable RenderablePointVector m_selectedRender; - -public: -typedef Static Type; - -CurveEdit( ControlPoints& controlPoints, const SelectionChangeCallback& selectionChanged ) : - m_selectionChanged( selectionChanged ), - m_controlPoints( controlPoints ), - m_controlsRender( GL_POINTS ), - m_selectedRender( GL_POINTS ){ + StringOutputStream value(256); + if (!controlPoints.empty()) { + ControlPoints_write(controlPoints, value); + } + entity.setKeyValue(key, value.c_str()); } -template -const Functor& forEachSelected( const Functor& functor ){ - ASSERT_MESSAGE( m_controlPoints.size() == m_selectables.size(), "curve instance mismatch" ); - ControlPoints::iterator p = m_controlPoints.begin(); - for ( Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p ) - { - if ( ( *i ).isSelected() ) { - functor( *p ); - } - } - return functor; -} -template -const Functor& forEachSelected( const Functor& functor ) const { - ASSERT_MESSAGE( m_controlPoints.size() == m_selectables.size(), "curve instance mismatch" ); - ControlPoints::const_iterator p = m_controlPoints.begin(); - for ( Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p ) - { - if ( ( *i ).isSelected() ) { - functor( *p ); - } - } - return functor; -} -template -const Functor& forEach( const Functor& functor ) const { - for ( ControlPoints::const_iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i ) - { - functor( *i ); - } - return functor; -} - -void testSelect( Selector& selector, SelectionTest& test ){ - ASSERT_MESSAGE( m_controlPoints.size() == m_selectables.size(), "curve instance mismatch" ); - ControlPoints::const_iterator p = m_controlPoints.begin(); - for ( Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p ) - { - ControlPoint_testSelect( *p, *i, selector, test ); - } -} - -bool isSelected() const { - for ( Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i ) - { - if ( ( *i ).isSelected() ) { - return true; - } - } - return false; -} -void setSelected( bool selected ){ - for ( Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i ) - { - ( *i ).setSelected( selected ); - } -} - -void write( const char* key, Entity& entity ){ - ControlPoints_write( m_controlPoints, key, entity ); -} +class CurveEdit { + SelectionChangeCallback m_selectionChanged; + ControlPoints &m_controlPoints; + typedef Array Selectables; + Selectables m_selectables; -void transform( const Matrix4& matrix ){ - forEachSelected([&](Vector3 &point) { - matrix4_transform_point(matrix, point); - }); -} -void snapto( float snap ){ - forEachSelected([&](Vector3 &point) { - vector3_snap(point, snap); - }); -} + RenderablePointVector m_controlsRender; + mutable RenderablePointVector m_selectedRender; -void updateSelected() const { - m_selectedRender.clear(); - forEachSelected([&](const Vector3 &point) { - m_selectedRender.push_back(PointVertex(vertex3f_for_vector3(point), colour_selected)); - }); -} - -void renderComponents( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - renderer.SetState( Type::instance().m_controlsShader, Renderer::eWireframeOnly ); - renderer.SetState( Type::instance().m_controlsShader, Renderer::eFullMaterials ); - renderer.addRenderable( m_controlsRender, localToWorld ); -} - -void renderComponentsSelected( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - updateSelected(); - if ( !m_selectedRender.empty() ) { - renderer.Highlight( Renderer::ePrimitive, false ); - renderer.SetState( Type::instance().m_selectedShader, Renderer::eWireframeOnly ); - renderer.SetState( Type::instance().m_selectedShader, Renderer::eFullMaterials ); - renderer.addRenderable( m_selectedRender, localToWorld ); - } -} - -void curveChanged(){ - m_selectables.resize( m_controlPoints.size(), m_selectionChanged ); - - m_controlsRender.clear(); - m_controlsRender.reserve( m_controlPoints.size() ); - forEach([&](const Vector3 &point) { - m_controlsRender.push_back(PointVertex(vertex3f_for_vector3(point), colour_vertex)); - }); - - m_selectedRender.reserve( m_controlPoints.size() ); -} -typedef MemberCaller CurveChangedCaller; +public: + typedef Static Type; + + CurveEdit(ControlPoints &controlPoints, const SelectionChangeCallback &selectionChanged) : + m_selectionChanged(selectionChanged), + m_controlPoints(controlPoints), + m_controlsRender(GL_POINTS), + m_selectedRender(GL_POINTS) + { + } + + template + const Functor &forEachSelected(const Functor &functor) + { + ASSERT_MESSAGE(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch"); + ControlPoints::iterator p = m_controlPoints.begin(); + for (Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p) { + if ((*i).isSelected()) { + functor(*p); + } + } + return functor; + } + + template + const Functor &forEachSelected(const Functor &functor) const + { + ASSERT_MESSAGE(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch"); + ControlPoints::const_iterator p = m_controlPoints.begin(); + for (Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p) { + if ((*i).isSelected()) { + functor(*p); + } + } + return functor; + } + + template + const Functor &forEach(const Functor &functor) const + { + for (ControlPoints::const_iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i) { + functor(*i); + } + return functor; + } + + void testSelect(Selector &selector, SelectionTest &test) + { + ASSERT_MESSAGE(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch"); + ControlPoints::const_iterator p = m_controlPoints.begin(); + for (Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p) { + ControlPoint_testSelect(*p, *i, selector, test); + } + } + + bool isSelected() const + { + for (Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i) { + if ((*i).isSelected()) { + return true; + } + } + return false; + } + + void setSelected(bool selected) + { + for (Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i) { + (*i).setSelected(selected); + } + } + + void write(const char *key, Entity &entity) + { + ControlPoints_write(m_controlPoints, key, entity); + } + + void transform(const Matrix4 &matrix) + { + forEachSelected([&](Vector3 &point) { + matrix4_transform_point(matrix, point); + }); + } + + void snapto(float snap) + { + forEachSelected([&](Vector3 &point) { + vector3_snap(point, snap); + }); + } + + void updateSelected() const + { + m_selectedRender.clear(); + forEachSelected([&](const Vector3 &point) { + m_selectedRender.push_back(PointVertex(vertex3f_for_vector3(point), colour_selected)); + }); + } + + void renderComponents(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + renderer.SetState(Type::instance().m_controlsShader, Renderer::eWireframeOnly); + renderer.SetState(Type::instance().m_controlsShader, Renderer::eFullMaterials); + renderer.addRenderable(m_controlsRender, localToWorld); + } + + void renderComponentsSelected(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + updateSelected(); + if (!m_selectedRender.empty()) { + renderer.Highlight(Renderer::ePrimitive, false); + renderer.SetState(Type::instance().m_selectedShader, Renderer::eWireframeOnly); + renderer.SetState(Type::instance().m_selectedShader, Renderer::eFullMaterials); + renderer.addRenderable(m_selectedRender, localToWorld); + } + } + + void curveChanged() + { + m_selectables.resize(m_controlPoints.size(), m_selectionChanged); + + m_controlsRender.clear(); + m_controlsRender.reserve(m_controlPoints.size()); + forEach([&](const Vector3 &point) { + m_controlsRender.push_back(PointVertex(vertex3f_for_vector3(point), colour_vertex)); + }); + + m_selectedRender.reserve(m_controlPoints.size()); + } + + typedef MemberCaller CurveChangedCaller; }; - const int NURBS_degree = 3; -class NURBSCurve -{ -Signal0 m_curveChanged; -Callback m_boundsChanged; +class NURBSCurve { + Signal0 m_curveChanged; + Callback m_boundsChanged; public: -ControlPoints m_controlPoints; -ControlPoints m_controlPointsTransformed; -NURBSWeights m_weights; -Knots m_knots; -RenderableCurve m_renderCurve; -AABB m_bounds; - -NURBSCurve( const Callback& boundsChanged ) : m_boundsChanged( boundsChanged ){ -} - -SignalHandlerId connect( const SignalHandler& curveChanged ){ - curveChanged(); - return m_curveChanged.connectLast( curveChanged ); -} -void disconnect( SignalHandlerId id ){ - m_curveChanged.disconnect( id ); -} -void notify(){ - m_curveChanged(); -} - -void tesselate(){ - if ( !m_controlPointsTransformed.empty() ) { - const std::size_t numSegments = ( m_controlPointsTransformed.size() - 1 ) * 16; - m_renderCurve.m_vertices.resize( numSegments + 1 ); - m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3( m_controlPointsTransformed[0] ); - for ( std::size_t i = 1; i < numSegments; ++i ) - { - m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3( NURBS_evaluate( m_controlPointsTransformed, m_weights, m_knots, NURBS_degree, ( 1.0 / double(numSegments) ) * double(i) ) ); - } - m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3( m_controlPointsTransformed[m_controlPointsTransformed.size() - 1] ); - } - else - { - m_renderCurve.m_vertices.clear(); - } -} - -void curveChanged(){ - tesselate(); - - m_bounds = AABB(); - for ( ControlPoints::iterator i = m_controlPointsTransformed.begin(); i != m_controlPointsTransformed.end(); ++i ) - { - aabb_extend_by_point_safe( m_bounds, ( *i ) ); - } - - m_boundsChanged(); - notify(); -} - -bool parseCurve( const char* value ){ - if ( !ControlPoints_parse( m_controlPoints, value ) ) { - return false; - } - - m_weights.resize( m_controlPoints.size() ); - for ( NURBSWeights::iterator i = m_weights.begin(); i != m_weights.end(); ++i ) - { - ( *i ) = 1; - } - - KnotVector_openUniform( m_knots, m_controlPoints.size(), NURBS_degree ); - - //plotBasisFunction(8, 0, NURBS_degree); - - return true; -} - -void curveChanged( const char* value ){ - if ( string_empty( value ) || !parseCurve( value ) ) { - m_controlPoints.resize( 0 ); - m_knots.resize( 0 ); - m_weights.resize( 0 ); - } - m_controlPointsTransformed = m_controlPoints; - curveChanged(); -} -typedef MemberCaller CurveChangedCaller; + ControlPoints m_controlPoints; + ControlPoints m_controlPointsTransformed; + NURBSWeights m_weights; + Knots m_knots; + RenderableCurve m_renderCurve; + AABB m_bounds; + + NURBSCurve(const Callback &boundsChanged) : m_boundsChanged(boundsChanged) + { + } + + SignalHandlerId connect(const SignalHandler &curveChanged) + { + curveChanged(); + return m_curveChanged.connectLast(curveChanged); + } + + void disconnect(SignalHandlerId id) + { + m_curveChanged.disconnect(id); + } + + void notify() + { + m_curveChanged(); + } + + void tesselate() + { + if (!m_controlPointsTransformed.empty()) { + const std::size_t numSegments = (m_controlPointsTransformed.size() - 1) * 16; + m_renderCurve.m_vertices.resize(numSegments + 1); + m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3(m_controlPointsTransformed[0]); + for (std::size_t i = 1; i < numSegments; ++i) { + m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3( + NURBS_evaluate(m_controlPointsTransformed, m_weights, m_knots, NURBS_degree, + (1.0 / double(numSegments)) * double(i))); + } + m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3( + m_controlPointsTransformed[m_controlPointsTransformed.size() - 1]); + } else { + m_renderCurve.m_vertices.clear(); + } + } + + void curveChanged() + { + tesselate(); + + m_bounds = AABB(); + for (ControlPoints::iterator i = m_controlPointsTransformed.begin(); + i != m_controlPointsTransformed.end(); ++i) { + aabb_extend_by_point_safe(m_bounds, (*i)); + } + + m_boundsChanged(); + notify(); + } + + bool parseCurve(const char *value) + { + if (!ControlPoints_parse(m_controlPoints, value)) { + return false; + } + + m_weights.resize(m_controlPoints.size()); + for (NURBSWeights::iterator i = m_weights.begin(); i != m_weights.end(); ++i) { + (*i) = 1; + } + + KnotVector_openUniform(m_knots, m_controlPoints.size(), NURBS_degree); + + //plotBasisFunction(8, 0, NURBS_degree); + + return true; + } + + void curveChanged(const char *value) + { + if (string_empty(value) || !parseCurve(value)) { + m_controlPoints.resize(0); + m_knots.resize(0); + m_weights.resize(0); + } + m_controlPointsTransformed = m_controlPoints; + curveChanged(); + } + + typedef MemberCaller CurveChangedCaller; }; -class CatmullRomSpline -{ -Signal0 m_curveChanged; -Callback m_boundsChanged; +class CatmullRomSpline { + Signal0 m_curveChanged; + Callback m_boundsChanged; public: -ControlPoints m_controlPoints; -ControlPoints m_controlPointsTransformed; -RenderableCurve m_renderCurve; -AABB m_bounds; - -CatmullRomSpline( const Callback& boundsChanged ) : m_boundsChanged( boundsChanged ){ -} - -SignalHandlerId connect( const SignalHandler& curveChanged ){ - curveChanged(); - return m_curveChanged.connectLast( curveChanged ); -} -void disconnect( SignalHandlerId id ){ - m_curveChanged.disconnect( id ); -} -void notify(){ - m_curveChanged(); -} - -void tesselate(){ - if ( !m_controlPointsTransformed.empty() ) { - const std::size_t numSegments = ( m_controlPointsTransformed.size() - 1 ) * 16; - m_renderCurve.m_vertices.resize( numSegments + 1 ); - m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3( m_controlPointsTransformed[0] ); - for ( std::size_t i = 1; i < numSegments; ++i ) - { - m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3( CatmullRom_evaluate( m_controlPointsTransformed, ( 1.0 / double(numSegments) ) * double(i) ) ); - } - m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3( m_controlPointsTransformed[m_controlPointsTransformed.size() - 1] ); - } - else - { - m_renderCurve.m_vertices.clear(); - } -} - -bool parseCurve( const char* value ){ - return ControlPoints_parse( m_controlPoints, value ); -} - -void curveChanged(){ - tesselate(); - - m_bounds = AABB(); - for ( ControlPoints::iterator i = m_controlPointsTransformed.begin(); i != m_controlPointsTransformed.end(); ++i ) - { - aabb_extend_by_point_safe( m_bounds, ( *i ) ); - } - - m_boundsChanged(); - notify(); -} - -void curveChanged( const char* value ){ - if ( string_empty( value ) || !parseCurve( value ) ) { - m_controlPoints.resize( 0 ); - } - m_controlPointsTransformed = m_controlPoints; - curveChanged(); -} -typedef MemberCaller CurveChangedCaller; + ControlPoints m_controlPoints; + ControlPoints m_controlPointsTransformed; + RenderableCurve m_renderCurve; + AABB m_bounds; + + CatmullRomSpline(const Callback &boundsChanged) : m_boundsChanged(boundsChanged) + { + } + + SignalHandlerId connect(const SignalHandler &curveChanged) + { + curveChanged(); + return m_curveChanged.connectLast(curveChanged); + } + + void disconnect(SignalHandlerId id) + { + m_curveChanged.disconnect(id); + } + + void notify() + { + m_curveChanged(); + } + + void tesselate() + { + if (!m_controlPointsTransformed.empty()) { + const std::size_t numSegments = (m_controlPointsTransformed.size() - 1) * 16; + m_renderCurve.m_vertices.resize(numSegments + 1); + m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3(m_controlPointsTransformed[0]); + for (std::size_t i = 1; i < numSegments; ++i) { + m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3( + CatmullRom_evaluate(m_controlPointsTransformed, (1.0 / double(numSegments)) * double(i))); + } + m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3( + m_controlPointsTransformed[m_controlPointsTransformed.size() - 1]); + } else { + m_renderCurve.m_vertices.clear(); + } + } + + bool parseCurve(const char *value) + { + return ControlPoints_parse(m_controlPoints, value); + } + + void curveChanged() + { + tesselate(); + + m_bounds = AABB(); + for (ControlPoints::iterator i = m_controlPointsTransformed.begin(); + i != m_controlPointsTransformed.end(); ++i) { + aabb_extend_by_point_safe(m_bounds, (*i)); + } + + m_boundsChanged(); + notify(); + } + + void curveChanged(const char *value) + { + if (string_empty(value) || !parseCurve(value)) { + m_controlPoints.resize(0); + } + m_controlPointsTransformed = m_controlPoints; + curveChanged(); + } + + typedef MemberCaller CurveChangedCaller; }; -const char* const curve_Nurbs = "curve_Nurbs"; -const char* const curve_CatmullRomSpline = "curve_CatmullRomSpline"; +const char *const curve_Nurbs = "curve_Nurbs"; +const char *const curve_CatmullRomSpline = "curve_CatmullRomSpline"; #endif diff --git a/plugins/entity/doom3group.cpp b/plugins/entity/doom3group.cpp index ceb19b0b..a891fd67 100644 --- a/plugins/entity/doom3group.cpp +++ b/plugins/entity/doom3group.cpp @@ -58,659 +58,797 @@ #include "entity.h" -inline void PointVertexArray_testSelect( PointVertex* first, std::size_t count, SelectionTest& test, SelectionIntersection& best ){ - test.TestLineStrip( - VertexPointer( - reinterpret_cast( &first->vertex ), - sizeof( PointVertex ) - ), - IndexPointer::index_type( count ), - best - ); +inline void +PointVertexArray_testSelect(PointVertex *first, std::size_t count, SelectionTest &test, SelectionIntersection &best) +{ + test.TestLineStrip( + VertexPointer( + reinterpret_cast( &first->vertex ), + sizeof(PointVertex) + ), + IndexPointer::index_type(count), + best + ); } class Doom3Group : - public Bounded, - public Snappable -{ -EntityKeyValues m_entity; -KeyObserverMap m_keyObservers; -TraversableNodeSet m_traverse; -MatrixTransform m_transform; - -SingletonModel m_model; -OriginKey m_originKey; -Vector3 m_origin; - -RotationKey m_rotationKey; -Float9 m_rotation; - -ClassnameFilter m_filter; -NamedEntity m_named; -NameKeys m_nameKeys; -TraversableObserverPairRelay m_traverseObservers; -Doom3GroupOrigin m_funcStaticOrigin; -RenderablePivot m_renderOrigin; -RenderableNamedEntity m_renderName; -mutable Vector3 m_name_origin; -ModelSkinKey m_skin; + public Bounded, + public Snappable { + EntityKeyValues m_entity; + KeyObserverMap m_keyObservers; + TraversableNodeSet m_traverse; + MatrixTransform m_transform; + + SingletonModel m_model; + OriginKey m_originKey; + Vector3 m_origin; + + RotationKey m_rotationKey; + Float9 m_rotation; + + ClassnameFilter m_filter; + NamedEntity m_named; + NameKeys m_nameKeys; + TraversableObserverPairRelay m_traverseObservers; + Doom3GroupOrigin m_funcStaticOrigin; + RenderablePivot m_renderOrigin; + RenderableNamedEntity m_renderName; + mutable Vector3 m_name_origin; + ModelSkinKey m_skin; public: -NURBSCurve m_curveNURBS; -SignalHandlerId m_curveNURBSChanged; -CatmullRomSpline m_curveCatmullRom; -SignalHandlerId m_curveCatmullRomChanged; + NURBSCurve m_curveNURBS; + SignalHandlerId m_curveNURBSChanged; + CatmullRomSpline m_curveCatmullRom; + SignalHandlerId m_curveCatmullRomChanged; private: -mutable AABB m_curveBounds; - -Callback m_transformChanged; -Callback m_evaluateTransform; - -CopiedString m_name; -CopiedString m_modelKey; -bool m_isModel; - -scene::Traversable* m_traversable; - -void construct(){ - default_rotation( m_rotation ); - - m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) ); - m_keyObservers.insert( Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) ); - m_keyObservers.insert( "model", Doom3Group::ModelChangedCaller( *this ) ); - m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) ); - m_keyObservers.insert( "angle", RotationKey::AngleChangedCaller( m_rotationKey ) ); - m_keyObservers.insert( "rotation", RotationKey::RotationChangedCaller( m_rotationKey ) ); - m_keyObservers.insert( "name", NameChangedCaller( *this ) ); - m_keyObservers.insert( curve_Nurbs, NURBSCurve::CurveChangedCaller( m_curveNURBS ) ); - m_keyObservers.insert( curve_CatmullRomSpline, CatmullRomSpline::CurveChangedCaller( m_curveCatmullRom ) ); - m_keyObservers.insert( "skin", ModelSkinKey::SkinChangedCaller( m_skin ) ); - - m_traverseObservers.attach( m_funcStaticOrigin ); - m_isModel = false; - m_nameKeys.setKeyIsName( keyIsNameDoom3Doom3Group ); - attachTraverse(); - - m_entity.attach( m_keyObservers ); -} -void destroy(){ - m_entity.detach( m_keyObservers ); - - if ( isModel() ) { - detachModel(); - } - else - { - detachTraverse(); - } - - m_traverseObservers.detach( m_funcStaticOrigin ); -} - -void attachModel(){ - m_traversable = &m_model.getTraversable(); - m_model.attach( &m_traverseObservers ); -} -void detachModel(){ - m_traversable = 0; - m_model.detach( &m_traverseObservers ); -} -void attachTraverse(){ - m_traversable = &m_traverse; - m_traverse.attach( &m_traverseObservers ); -} -void detachTraverse(){ - m_traversable = 0; - m_traverse.detach( &m_traverseObservers ); -} - -bool isModel() const { - return m_isModel; -} - -void setIsModel( bool newValue ){ - if ( newValue && !m_isModel ) { - detachTraverse(); - attachModel(); - - m_nameKeys.setKeyIsName( Static::instance().m_keyIsName ); - m_model.modelChanged( m_modelKey.c_str() ); - } - else if ( !newValue && m_isModel ) { - detachModel(); - attachTraverse(); - - m_nameKeys.setKeyIsName( keyIsNameDoom3Doom3Group ); - } - m_isModel = newValue; - updateTransform(); -} - -void updateIsModel(){ - setIsModel( !string_equal( m_modelKey.c_str(), m_name.c_str() ) ); -} + mutable AABB m_curveBounds; + + Callback m_transformChanged; + Callback m_evaluateTransform; + + CopiedString m_name; + CopiedString m_modelKey; + bool m_isModel; + + scene::Traversable *m_traversable; + + void construct() + { + default_rotation(m_rotation); + + m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter)); + m_keyObservers.insert(Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named)); + m_keyObservers.insert("model", Doom3Group::ModelChangedCaller(*this)); + m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey)); + m_keyObservers.insert("angle", RotationKey::AngleChangedCaller(m_rotationKey)); + m_keyObservers.insert("rotation", RotationKey::RotationChangedCaller(m_rotationKey)); + m_keyObservers.insert("name", NameChangedCaller(*this)); + m_keyObservers.insert(curve_Nurbs, NURBSCurve::CurveChangedCaller(m_curveNURBS)); + m_keyObservers.insert(curve_CatmullRomSpline, CatmullRomSpline::CurveChangedCaller(m_curveCatmullRom)); + m_keyObservers.insert("skin", ModelSkinKey::SkinChangedCaller(m_skin)); + + m_traverseObservers.attach(m_funcStaticOrigin); + m_isModel = false; + m_nameKeys.setKeyIsName(keyIsNameDoom3Doom3Group); + attachTraverse(); + + m_entity.attach(m_keyObservers); + } + + void destroy() + { + m_entity.detach(m_keyObservers); + + if (isModel()) { + detachModel(); + } else { + detachTraverse(); + } + + m_traverseObservers.detach(m_funcStaticOrigin); + } + + void attachModel() + { + m_traversable = &m_model.getTraversable(); + m_model.attach(&m_traverseObservers); + } + + void detachModel() + { + m_traversable = 0; + m_model.detach(&m_traverseObservers); + } + + void attachTraverse() + { + m_traversable = &m_traverse; + m_traverse.attach(&m_traverseObservers); + } + + void detachTraverse() + { + m_traversable = 0; + m_traverse.detach(&m_traverseObservers); + } + + bool isModel() const + { + return m_isModel; + } + + void setIsModel(bool newValue) + { + if (newValue && !m_isModel) { + detachTraverse(); + attachModel(); + + m_nameKeys.setKeyIsName(Static::instance().m_keyIsName); + m_model.modelChanged(m_modelKey.c_str()); + } else if (!newValue && m_isModel) { + detachModel(); + attachTraverse(); + + m_nameKeys.setKeyIsName(keyIsNameDoom3Doom3Group); + } + m_isModel = newValue; + updateTransform(); + } + + void updateIsModel() + { + setIsModel(!string_equal(m_modelKey.c_str(), m_name.c_str())); + } // vc 2k5 compiler fix #if _MSC_VER >= 1400 -public: + public: #endif -void nameChanged( const char* value ){ - m_name = value; - updateIsModel(); -} -typedef MemberCaller NameChangedCaller; - -void modelChanged( const char* value ){ - m_modelKey = value; - updateIsModel(); - if ( isModel() ) { - m_model.modelChanged( value ); - } - else - { - m_model.modelChanged( "" ); - } -} -typedef MemberCaller ModelChangedCaller; - -void updateTransform(){ - m_transform.localToParent() = g_matrix4_identity; - if ( isModel() ) { - matrix4_translate_by_vec3( m_transform.localToParent(), m_origin ); - matrix4_multiply_by_matrix4( m_transform.localToParent(), rotation_toMatrix( m_rotation ) ); - } - m_transformChanged(); - if ( !isModel() ) { - m_funcStaticOrigin.originChanged(); - } -} -typedef MemberCaller UpdateTransformCaller; - -void originChanged(){ - m_origin = m_originKey.m_origin; - updateTransform(); -} -typedef MemberCaller OriginChangedCaller; - -void rotationChanged(){ - rotation_assign( m_rotation, m_rotationKey.m_rotation ); - updateTransform(); -} -typedef MemberCaller RotationChangedCaller; - -void skinChanged(){ - if ( isModel() ) { - scene::Node* node = m_model.getNode(); - if ( node != 0 ) { - Node_modelSkinChanged( *node ); - } - } -} -typedef MemberCaller SkinChangedCaller; + void nameChanged(const char *value) + { + m_name = value; + updateIsModel(); + } + + typedef MemberCaller NameChangedCaller; + + void modelChanged(const char *value) + { + m_modelKey = value; + updateIsModel(); + if (isModel()) { + m_model.modelChanged(value); + } else { + m_model.modelChanged(""); + } + } + + typedef MemberCaller ModelChangedCaller; + + void updateTransform() + { + m_transform.localToParent() = g_matrix4_identity; + if (isModel()) { + matrix4_translate_by_vec3(m_transform.localToParent(), m_origin); + matrix4_multiply_by_matrix4(m_transform.localToParent(), rotation_toMatrix(m_rotation)); + } + m_transformChanged(); + if (!isModel()) { + m_funcStaticOrigin.originChanged(); + } + } + + typedef MemberCaller UpdateTransformCaller; + + void originChanged() + { + m_origin = m_originKey.m_origin; + updateTransform(); + } + + typedef MemberCaller OriginChangedCaller; + + void rotationChanged() + { + rotation_assign(m_rotation, m_rotationKey.m_rotation); + updateTransform(); + } + + typedef MemberCaller RotationChangedCaller; + + void skinChanged() + { + if (isModel()) { + scene::Node *node = m_model.getNode(); + if (node != 0) { + Node_modelSkinChanged(*node); + } + } + } + + typedef MemberCaller SkinChangedCaller; public: -Doom3Group( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& boundsChanged, const Callback& evaluateTransform ) : - m_entity( eclass ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_rotationKey( RotationChangedCaller( *this ) ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_funcStaticOrigin( m_traverse, m_origin ), - m_renderName( m_named, m_name_origin ), - m_name_origin( g_vector3_identity ), - m_skin( SkinChangedCaller( *this ) ), - m_curveNURBS( boundsChanged ), - m_curveCatmullRom( boundsChanged ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ), - m_traversable( 0 ){ - construct(); -} -Doom3Group( const Doom3Group& other, scene::Node& node, const Callback& transformChanged, const Callback& boundsChanged, const Callback& evaluateTransform ) : - m_entity( other.m_entity ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_rotationKey( RotationChangedCaller( *this ) ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_funcStaticOrigin( m_traverse, m_origin ), - m_renderName( m_named, g_vector3_identity ), - m_skin( SkinChangedCaller( *this ) ), - m_curveNURBS( boundsChanged ), - m_curveCatmullRom( boundsChanged ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ), - m_traversable( 0 ){ - construct(); -} -~Doom3Group(){ - destroy(); -} - -InstanceCounter m_instanceCounter; -void instanceAttach( const scene::Path& path ){ - if ( ++m_instanceCounter.m_count == 1 ) { - m_filter.instanceAttach(); - m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) ); - m_traverse.instanceAttach( path_find_mapfile( path.begin(), path.end() ) ); - - m_funcStaticOrigin.enable(); - } -} -void instanceDetach( const scene::Path& path ){ - if ( --m_instanceCounter.m_count == 0 ) { - m_funcStaticOrigin.disable(); - - m_traverse.instanceDetach( path_find_mapfile( path.begin(), path.end() ) ); - m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) ); - m_filter.instanceDetach(); - } -} - -EntityKeyValues& getEntity(){ - return m_entity; -} -const EntityKeyValues& getEntity() const { - return m_entity; -} - -scene::Traversable& getTraversable(){ - return *m_traversable; -} -Namespaced& getNamespaced(){ - return m_nameKeys; -} -Nameable& getNameable(){ - return m_named; -} -TransformNode& getTransformNode(){ - return m_transform; -} -ModelSkin& getModelSkin(){ - return m_skin.get(); -} - -void attach( scene::Traversable::Observer* observer ){ - m_traverseObservers.attach( *observer ); -} -void detach( scene::Traversable::Observer* observer ){ - m_traverseObservers.detach( *observer ); -} - -const AABB& localAABB() const { - m_curveBounds = m_curveNURBS.m_bounds; - aabb_extend_by_aabb_safe( m_curveBounds, m_curveCatmullRom.m_bounds ); - return m_curveBounds; -} - -void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const { - if ( isModel() && selected ) { - m_renderOrigin.render( renderer, volume, localToWorld ); - } - - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials ); - - if ( !m_curveNURBS.m_renderCurve.m_vertices.empty() ) { - renderer.addRenderable( m_curveNURBS.m_renderCurve, localToWorld ); - } - if ( !m_curveCatmullRom.m_renderCurve.m_vertices.empty() ) { - renderer.addRenderable( m_curveCatmullRom.m_renderCurve, localToWorld ); - } -} - -void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected, const AABB& childBounds ) const { - renderSolid( renderer, volume, localToWorld, selected ); - - if ( g_showNames ) { - // draw models as usual - if ( !isModel() ) { - // don't draw the name for worldspawn - if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { - return; - } - - // place name in the middle of the "children cloud" - m_name_origin = childBounds.origin; - } - - renderer.addRenderable( m_renderName, localToWorld ); - } -} - -void testSelect( Selector& selector, SelectionTest& test, SelectionIntersection& best ){ - PointVertexArray_testSelect( &m_curveNURBS.m_renderCurve.m_vertices[0], m_curveNURBS.m_renderCurve.m_vertices.size(), test, best ); - PointVertexArray_testSelect( &m_curveCatmullRom.m_renderCurve.m_vertices[0], m_curveCatmullRom.m_renderCurve.m_vertices.size(), test, best ); -} - -void translate( const Vector3& translation ){ - m_origin = origin_translated( m_origin, translation ); -} -void rotate( const Quaternion& rotation ){ - rotation_rotate( m_rotation, rotation ); -} -void snapto( float snap ){ - m_originKey.m_origin = origin_snapped( m_originKey.m_origin, snap ); - m_originKey.write( &m_entity ); -} -void revertTransform(){ - m_origin = m_originKey.m_origin; - rotation_assign( m_rotation, m_rotationKey.m_rotation ); - m_curveNURBS.m_controlPointsTransformed = m_curveNURBS.m_controlPoints; - m_curveCatmullRom.m_controlPointsTransformed = m_curveCatmullRom.m_controlPoints; -} -void freezeTransform(){ - m_originKey.m_origin = m_origin; - m_originKey.write( &m_entity ); - rotation_assign( m_rotationKey.m_rotation, m_rotation ); - m_rotationKey.write( &m_entity ); - m_curveNURBS.m_controlPoints = m_curveNURBS.m_controlPointsTransformed; - ControlPoints_write( m_curveNURBS.m_controlPoints, curve_Nurbs, m_entity ); - m_curveCatmullRom.m_controlPoints = m_curveCatmullRom.m_controlPointsTransformed; - ControlPoints_write( m_curveCatmullRom.m_controlPoints, curve_CatmullRomSpline, m_entity ); -} -void transformChanged(){ - revertTransform(); - m_evaluateTransform(); - updateTransform(); - m_curveNURBS.curveChanged(); - m_curveCatmullRom.curveChanged(); -} -typedef MemberCaller TransformChangedCaller; + Doom3Group(EntityClass *eclass, scene::Node &node, const Callback &transformChanged, + const Callback &boundsChanged, const Callback &evaluateTransform) : + m_entity(eclass), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_rotationKey(RotationChangedCaller(*this)), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_funcStaticOrigin(m_traverse, m_origin), + m_renderName(m_named, m_name_origin), + m_name_origin(g_vector3_identity), + m_skin(SkinChangedCaller(*this)), + m_curveNURBS(boundsChanged), + m_curveCatmullRom(boundsChanged), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform), + m_traversable(0) + { + construct(); + } + + Doom3Group(const Doom3Group &other, scene::Node &node, const Callback &transformChanged, + const Callback &boundsChanged, const Callback &evaluateTransform) : + m_entity(other.m_entity), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_rotationKey(RotationChangedCaller(*this)), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_funcStaticOrigin(m_traverse, m_origin), + m_renderName(m_named, g_vector3_identity), + m_skin(SkinChangedCaller(*this)), + m_curveNURBS(boundsChanged), + m_curveCatmullRom(boundsChanged), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform), + m_traversable(0) + { + construct(); + } + + ~Doom3Group() + { + destroy(); + } + + InstanceCounter m_instanceCounter; + + void instanceAttach(const scene::Path &path) + { + if (++m_instanceCounter.m_count == 1) { + m_filter.instanceAttach(); + m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end())); + m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end())); + + m_funcStaticOrigin.enable(); + } + } + + void instanceDetach(const scene::Path &path) + { + if (--m_instanceCounter.m_count == 0) { + m_funcStaticOrigin.disable(); + + m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end())); + m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end())); + m_filter.instanceDetach(); + } + } + + EntityKeyValues &getEntity() + { + return m_entity; + } + + const EntityKeyValues &getEntity() const + { + return m_entity; + } + + scene::Traversable &getTraversable() + { + return *m_traversable; + } + + Namespaced &getNamespaced() + { + return m_nameKeys; + } + + Nameable &getNameable() + { + return m_named; + } + + TransformNode &getTransformNode() + { + return m_transform; + } + + ModelSkin &getModelSkin() + { + return m_skin.get(); + } + + void attach(scene::Traversable::Observer *observer) + { + m_traverseObservers.attach(*observer); + } + + void detach(scene::Traversable::Observer *observer) + { + m_traverseObservers.detach(*observer); + } + + const AABB &localAABB() const + { + m_curveBounds = m_curveNURBS.m_bounds; + aabb_extend_by_aabb_safe(m_curveBounds, m_curveCatmullRom.m_bounds); + return m_curveBounds; + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, bool selected) const + { + if (isModel() && selected) { + m_renderOrigin.render(renderer, volume, localToWorld); + } + + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly); + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials); + + if (!m_curveNURBS.m_renderCurve.m_vertices.empty()) { + renderer.addRenderable(m_curveNURBS.m_renderCurve, localToWorld); + } + if (!m_curveCatmullRom.m_renderCurve.m_vertices.empty()) { + renderer.addRenderable(m_curveCatmullRom.m_renderCurve, localToWorld); + } + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, bool selected, + const AABB &childBounds) const + { + renderSolid(renderer, volume, localToWorld, selected); + + if (g_showNames) { + // draw models as usual + if (!isModel()) { + // don't draw the name for worldspawn + if (!strcmp(m_entity.getEntityClass().name(), "worldspawn")) { + return; + } + + // place name in the middle of the "children cloud" + m_name_origin = childBounds.origin; + } + + renderer.addRenderable(m_renderName, localToWorld); + } + } + + void testSelect(Selector &selector, SelectionTest &test, SelectionIntersection &best) + { + PointVertexArray_testSelect(&m_curveNURBS.m_renderCurve.m_vertices[0], + m_curveNURBS.m_renderCurve.m_vertices.size(), test, best); + PointVertexArray_testSelect(&m_curveCatmullRom.m_renderCurve.m_vertices[0], + m_curveCatmullRom.m_renderCurve.m_vertices.size(), test, best); + } + + void translate(const Vector3 &translation) + { + m_origin = origin_translated(m_origin, translation); + } + + void rotate(const Quaternion &rotation) + { + rotation_rotate(m_rotation, rotation); + } + + void snapto(float snap) + { + m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap); + m_originKey.write(&m_entity); + } + + void revertTransform() + { + m_origin = m_originKey.m_origin; + rotation_assign(m_rotation, m_rotationKey.m_rotation); + m_curveNURBS.m_controlPointsTransformed = m_curveNURBS.m_controlPoints; + m_curveCatmullRom.m_controlPointsTransformed = m_curveCatmullRom.m_controlPoints; + } + + void freezeTransform() + { + m_originKey.m_origin = m_origin; + m_originKey.write(&m_entity); + rotation_assign(m_rotationKey.m_rotation, m_rotation); + m_rotationKey.write(&m_entity); + m_curveNURBS.m_controlPoints = m_curveNURBS.m_controlPointsTransformed; + ControlPoints_write(m_curveNURBS.m_controlPoints, curve_Nurbs, m_entity); + m_curveCatmullRom.m_controlPoints = m_curveCatmullRom.m_controlPointsTransformed; + ControlPoints_write(m_curveCatmullRom.m_controlPoints, curve_CatmullRomSpline, m_entity); + } + + void transformChanged() + { + revertTransform(); + m_evaluateTransform(); + updateTransform(); + m_curveNURBS.curveChanged(); + m_curveCatmullRom.curveChanged(); + } + + typedef MemberCaller TransformChangedCaller; }; class Doom3GroupInstance : - public TargetableInstance, - public TransformModifier, - public Renderable, - public SelectionTestable, - public ComponentSelectionTestable, - public ComponentEditable, - public ComponentSnappable -{ -class TypeCasts -{ -InstanceTypeCastTable m_casts; -public: -TypeCasts(){ - m_casts = TargetableInstance::StaticTypeCasts::instance().get(); - InstanceContainedCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceIdentityCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} -}; - -Doom3Group& m_contained; -CurveEdit m_curveNURBS; -CurveEdit m_curveCatmullRom; -mutable AABB m_aabb_component; + public TargetableInstance, + public TransformModifier, + public Renderable, + public SelectionTestable, + public ComponentSelectionTestable, + public ComponentEditable, + public ComponentSnappable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + m_casts = TargetableInstance::StaticTypeCasts::instance().get(); + InstanceContainedCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceIdentityCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + Doom3Group &m_contained; + CurveEdit m_curveNURBS; + CurveEdit m_curveCatmullRom; + mutable AABB m_aabb_component; public: -typedef LazyStatic StaticTypeCasts; - - -Bounded& get( NullType){ - return m_contained; -} - -STRING_CONSTANT( Name, "Doom3GroupInstance" ); - -Doom3GroupInstance( const scene::Path& path, scene::Instance* parent, Doom3Group& contained ) : - TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this ), - TransformModifier( Doom3Group::TransformChangedCaller( contained ), ApplyTransformCaller( *this ) ), - m_contained( contained ), - m_curveNURBS( m_contained.m_curveNURBS.m_controlPointsTransformed, SelectionChangedComponentCaller( *this ) ), - m_curveCatmullRom( m_contained.m_curveCatmullRom.m_controlPointsTransformed, SelectionChangedComponentCaller( *this ) ){ - m_contained.instanceAttach( Instance::path() ); - m_contained.m_curveNURBSChanged = m_contained.m_curveNURBS.connect( CurveEdit::CurveChangedCaller( m_curveNURBS ) ); - m_contained.m_curveCatmullRomChanged = m_contained.m_curveCatmullRom.connect( CurveEdit::CurveChangedCaller( m_curveCatmullRom ) ); - - StaticRenderableConnectionLines::instance().attach( *this ); -} -~Doom3GroupInstance(){ - StaticRenderableConnectionLines::instance().detach( *this ); - - m_contained.m_curveCatmullRom.disconnect( m_contained.m_curveCatmullRomChanged ); - m_contained.m_curveNURBS.disconnect( m_contained.m_curveNURBSChanged ); - m_contained.instanceDetach( Instance::path() ); -} -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() ); - - m_curveNURBS.renderComponentsSelected( renderer, volume, localToWorld() ); - m_curveCatmullRom.renderComponentsSelected( renderer, volume, localToWorld() ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), Instance::childBounds() ); - - m_curveNURBS.renderComponentsSelected( renderer, volume, localToWorld() ); - m_curveCatmullRom.renderComponentsSelected( renderer, volume, localToWorld() ); -} -void renderComponents( Renderer& renderer, const VolumeTest& volume ) const { - if ( GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex ) { - m_curveNURBS.renderComponents( renderer, volume, localToWorld() ); - m_curveCatmullRom.renderComponents( renderer, volume, localToWorld() ); - } -} - -void testSelect( Selector& selector, SelectionTest& test ){ - test.BeginMesh( localToWorld() ); - SelectionIntersection best; - - m_contained.testSelect( selector, test, best ); - - if ( best.valid() ) { - Selector_add( selector, getSelectable(), best ); - } -} - -bool isSelectedComponents() const { - return m_curveNURBS.isSelected() || m_curveCatmullRom.isSelected(); -} -void setSelectedComponents( bool selected, SelectionSystem::EComponentMode mode ){ - if ( mode == SelectionSystem::eVertex ) { - m_curveNURBS.setSelected( selected ); - m_curveCatmullRom.setSelected( selected ); - } -} -void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ){ - if ( mode == SelectionSystem::eVertex ) { - test.BeginMesh( localToWorld() ); - m_curveNURBS.testSelect( selector, test ); - m_curveCatmullRom.testSelect( selector, test ); - } -} - -void transformComponents( const Matrix4& matrix ){ - if ( m_curveNURBS.isSelected() ) { - m_curveNURBS.transform( matrix ); - } - if ( m_curveCatmullRom.isSelected() ) { - m_curveCatmullRom.transform( matrix ); - } -} - -const AABB& getSelectedComponentsBounds() const { - m_aabb_component = AABB(); - m_curveNURBS.forEachSelected([&](const Vector3 &point) { - aabb_extend_by_point_safe(m_aabb_component, point); - }); - m_curveCatmullRom.forEachSelected([&](const Vector3 &point) { - aabb_extend_by_point_safe(m_aabb_component, point); - }); - return m_aabb_component; -} - -void snapComponents( float snap ){ - if ( m_curveNURBS.isSelected() ) { - m_curveNURBS.snapto( snap ); - m_curveNURBS.write( curve_Nurbs, m_contained.getEntity() ); - } - if ( m_curveCatmullRom.isSelected() ) { - m_curveCatmullRom.snapto( snap ); - m_curveCatmullRom.write( curve_CatmullRomSpline, m_contained.getEntity() ); - } -} - -void evaluateTransform(){ - if ( getType() == TRANSFORM_PRIMITIVE ) { - m_contained.translate( getTranslation() ); - m_contained.rotate( getRotation() ); - } - else - { - transformComponents( calculateTransform() ); - } -} -void applyTransform(){ - m_contained.revertTransform(); - evaluateTransform(); - m_contained.freezeTransform(); -} -typedef MemberCaller ApplyTransformCaller; - -void selectionChangedComponent( const Selectable& selectable ){ - GlobalSelectionSystem().getObserver ( SelectionSystem::eComponent )( selectable ); - GlobalSelectionSystem().onComponentSelection( *this, selectable ); -} -typedef MemberCaller SelectionChangedComponentCaller; + typedef LazyStatic StaticTypeCasts; + + + Bounded &get(NullType) + { + return m_contained; + } + + STRING_CONSTANT(Name, "Doom3GroupInstance"); + + Doom3GroupInstance(const scene::Path &path, scene::Instance *parent, Doom3Group &contained) : + TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this), + TransformModifier(Doom3Group::TransformChangedCaller(contained), ApplyTransformCaller(*this)), + m_contained(contained), + m_curveNURBS(m_contained.m_curveNURBS.m_controlPointsTransformed, SelectionChangedComponentCaller(*this)), + m_curveCatmullRom(m_contained.m_curveCatmullRom.m_controlPointsTransformed, + SelectionChangedComponentCaller(*this)) + { + m_contained.instanceAttach(Instance::path()); + m_contained.m_curveNURBSChanged = m_contained.m_curveNURBS.connect(CurveEdit::CurveChangedCaller(m_curveNURBS)); + m_contained.m_curveCatmullRomChanged = m_contained.m_curveCatmullRom.connect( + CurveEdit::CurveChangedCaller(m_curveCatmullRom)); + + StaticRenderableConnectionLines::instance().attach(*this); + } + + ~Doom3GroupInstance() + { + StaticRenderableConnectionLines::instance().detach(*this); + + m_contained.m_curveCatmullRom.disconnect(m_contained.m_curveCatmullRomChanged); + m_contained.m_curveNURBS.disconnect(m_contained.m_curveNURBSChanged); + m_contained.instanceDetach(Instance::path()); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected()); + + m_curveNURBS.renderComponentsSelected(renderer, volume, localToWorld()); + m_curveCatmullRom.renderComponentsSelected(renderer, volume, localToWorld()); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected(), + Instance::childBounds()); + + m_curveNURBS.renderComponentsSelected(renderer, volume, localToWorld()); + m_curveCatmullRom.renderComponentsSelected(renderer, volume, localToWorld()); + } + + void renderComponents(Renderer &renderer, const VolumeTest &volume) const + { + if (GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex) { + m_curveNURBS.renderComponents(renderer, volume, localToWorld()); + m_curveCatmullRom.renderComponents(renderer, volume, localToWorld()); + } + } + + void testSelect(Selector &selector, SelectionTest &test) + { + test.BeginMesh(localToWorld()); + SelectionIntersection best; + + m_contained.testSelect(selector, test, best); + + if (best.valid()) { + Selector_add(selector, getSelectable(), best); + } + } + + bool isSelectedComponents() const + { + return m_curveNURBS.isSelected() || m_curveCatmullRom.isSelected(); + } + + void setSelectedComponents(bool selected, SelectionSystem::EComponentMode mode) + { + if (mode == SelectionSystem::eVertex) { + m_curveNURBS.setSelected(selected); + m_curveCatmullRom.setSelected(selected); + } + } + + void testSelectComponents(Selector &selector, SelectionTest &test, SelectionSystem::EComponentMode mode) + { + if (mode == SelectionSystem::eVertex) { + test.BeginMesh(localToWorld()); + m_curveNURBS.testSelect(selector, test); + m_curveCatmullRom.testSelect(selector, test); + } + } + + void transformComponents(const Matrix4 &matrix) + { + if (m_curveNURBS.isSelected()) { + m_curveNURBS.transform(matrix); + } + if (m_curveCatmullRom.isSelected()) { + m_curveCatmullRom.transform(matrix); + } + } + + const AABB &getSelectedComponentsBounds() const + { + m_aabb_component = AABB(); + m_curveNURBS.forEachSelected([&](const Vector3 &point) { + aabb_extend_by_point_safe(m_aabb_component, point); + }); + m_curveCatmullRom.forEachSelected([&](const Vector3 &point) { + aabb_extend_by_point_safe(m_aabb_component, point); + }); + return m_aabb_component; + } + + void snapComponents(float snap) + { + if (m_curveNURBS.isSelected()) { + m_curveNURBS.snapto(snap); + m_curveNURBS.write(curve_Nurbs, m_contained.getEntity()); + } + if (m_curveCatmullRom.isSelected()) { + m_curveCatmullRom.snapto(snap); + m_curveCatmullRom.write(curve_CatmullRomSpline, m_contained.getEntity()); + } + } + + void evaluateTransform() + { + if (getType() == TRANSFORM_PRIMITIVE) { + m_contained.translate(getTranslation()); + m_contained.rotate(getRotation()); + } else { + transformComponents(calculateTransform()); + } + } + + void applyTransform() + { + m_contained.revertTransform(); + evaluateTransform(); + m_contained.freezeTransform(); + } + + typedef MemberCaller ApplyTransformCaller; + + void selectionChangedComponent(const Selectable &selectable) + { + GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable); + GlobalSelectionSystem().onComponentSelection(*this, selectable); + } + + typedef MemberCaller SelectionChangedComponentCaller; }; class Doom3GroupNode : - public scene::Node::Symbiot, - public scene::Instantiable, - public scene::Cloneable, - public scene::Traversable::Observer -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; -public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); - NodeStaticCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} -}; + public scene::Node::Symbiot, + public scene::Instantiable, + public scene::Cloneable, + public scene::Traversable::Observer { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + NodeStaticCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + } + + NodeTypeCastTable &get() + { + return m_casts; + } + }; + + + scene::Node m_node; + InstanceSet m_instances; + Doom3Group m_contained; + + void construct() + { + m_contained.attach(this); + } + + void destroy() + { + m_contained.detach(this); + } - -scene::Node m_node; -InstanceSet m_instances; -Doom3Group m_contained; - -void construct(){ - m_contained.attach( this ); -} -void destroy(){ - m_contained.detach( this ); -} public: -typedef LazyStatic StaticTypeCasts; - -scene::Traversable& get( NullType){ - return m_contained.getTraversable(); -} -Snappable& get( NullType){ - return m_contained; -} -TransformNode& get( NullType){ - return m_contained.getTransformNode(); -} -Entity& get( NullType){ - return m_contained.getEntity(); -} -Nameable& get( NullType){ - return m_contained.getNameable(); -} -Namespaced& get( NullType){ - return m_contained.getNamespaced(); -} -ModelSkin& get( NullType){ - return m_contained.getModelSkin(); -} - -Doom3GroupNode( EntityClass* eclass ) : - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -Doom3GroupNode( const Doom3GroupNode& other ) : - scene::Node::Symbiot( other ), - scene::Instantiable( other ), - scene::Cloneable( other ), - scene::Traversable::Observer( other ), - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -~Doom3GroupNode(){ - destroy(); -} - -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} - -scene::Node& clone() const { - return ( new Doom3GroupNode( *this ) )->node(); -} - -void insert( scene::Node& child ){ - m_instances.insert( child ); -} -void erase( scene::Node& child ){ - m_instances.erase( child ); -} - -scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new Doom3GroupInstance( path, parent, m_contained ); -} -void forEachInstance( const scene::Instantiable::Visitor& visitor ){ - m_instances.forEachInstance( visitor ); -} -void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){ - m_instances.insert( observer, path, instance ); -} -scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){ - return m_instances.erase( observer, path ); -} + typedef LazyStatic StaticTypeCasts; + + scene::Traversable &get(NullType) + { + return m_contained.getTraversable(); + } + + Snappable &get(NullType) + { + return m_contained; + } + + TransformNode &get(NullType) + { + return m_contained.getTransformNode(); + } + + Entity &get(NullType) + { + return m_contained.getEntity(); + } + + Nameable &get(NullType) + { + return m_contained.getNameable(); + } + + Namespaced &get(NullType) + { + return m_contained.getNamespaced(); + } + + ModelSkin &get(NullType) + { + return m_contained.getModelSkin(); + } + + Doom3GroupNode(EntityClass *eclass) : + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSet::BoundsChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + Doom3GroupNode(const Doom3GroupNode &other) : + scene::Node::Symbiot(other), + scene::Instantiable(other), + scene::Cloneable(other), + scene::Traversable::Observer(other), + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSet::BoundsChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + ~Doom3GroupNode() + { + destroy(); + } + + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } + + scene::Node &clone() const + { + return (new Doom3GroupNode(*this))->node(); + } + + void insert(scene::Node &child) + { + m_instances.insert(child); + } + + void erase(scene::Node &child) + { + m_instances.erase(child); + } + + scene::Instance *create(const scene::Path &path, scene::Instance *parent) + { + return new Doom3GroupInstance(path, parent, m_contained); + } + + void forEachInstance(const scene::Instantiable::Visitor &visitor) + { + m_instances.forEachInstance(visitor); + } + + void insert(scene::Instantiable::Observer *observer, const scene::Path &path, scene::Instance *instance) + { + m_instances.insert(observer, path, instance); + } + + scene::Instance *erase(scene::Instantiable::Observer *observer, const scene::Path &path) + { + return m_instances.erase(observer, path); + } }; -void Doom3Group_construct(){ - CurveEdit::Type::instance().m_controlsShader = GlobalShaderCache().capture( "$POINT" ); - CurveEdit::Type::instance().m_selectedShader = GlobalShaderCache().capture( "$SELPOINT" ); +void Doom3Group_construct() +{ + CurveEdit::Type::instance().m_controlsShader = GlobalShaderCache().capture("$POINT"); + CurveEdit::Type::instance().m_selectedShader = GlobalShaderCache().capture("$SELPOINT"); } -void Doom3Group_destroy(){ - GlobalShaderCache().release( "$SELPOINT" ); - GlobalShaderCache().release( "$POINT" ); +void Doom3Group_destroy() +{ + GlobalShaderCache().release("$SELPOINT"); + GlobalShaderCache().release("$POINT"); } -scene::Node& New_Doom3Group( EntityClass* eclass ){ - return ( new Doom3GroupNode( eclass ) )->node(); +scene::Node &New_Doom3Group(EntityClass *eclass) +{ + return (new Doom3GroupNode(eclass))->node(); } diff --git a/plugins/entity/doom3group.h b/plugins/entity/doom3group.h index 42fdfd2e..7eef3341 100644 --- a/plugins/entity/doom3group.h +++ b/plugins/entity/doom3group.h @@ -22,14 +22,15 @@ #if !defined( INCLUDED_STATIC_H ) #define INCLUDED_STATIC_H -namespace scene -{ -class Node; +namespace scene { + class Node; } class EntityClass; void Doom3Group_construct(); + void Doom3Group_destroy(); -scene::Node& New_Doom3Group( EntityClass* eclass ); + +scene::Node &New_Doom3Group(EntityClass *eclass); #endif diff --git a/plugins/entity/eclassmodel.cpp b/plugins/entity/eclassmodel.cpp index 3b91eeb0..fe910ad0 100644 --- a/plugins/entity/eclassmodel.cpp +++ b/plugins/entity/eclassmodel.cpp @@ -55,406 +55,499 @@ #include "entity.h" class EclassModel : - public Snappable -{ -MatrixTransform m_transform; -EntityKeyValues m_entity; -KeyObserverMap m_keyObservers; - -OriginKey m_originKey; -Vector3 m_origin; -AngleKey m_angleKey; -float m_angle; -RotationKey m_rotationKey; -Float9 m_rotation; -SingletonModel m_model; - -ClassnameFilter m_filter; -NamedEntity m_named; -NameKeys m_nameKeys; -RenderablePivot m_renderOrigin; -RenderableNamedEntity m_renderName; -ModelSkinKey m_skin; - -Callback m_transformChanged; -Callback m_evaluateTransform; - -void construct(){ - default_rotation( m_rotation ); - - m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) ); - m_keyObservers.insert( Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) ); - if ( g_gameType == eGameTypeDoom3 ) { - m_keyObservers.insert( "angle", RotationKey::AngleChangedCaller( m_rotationKey ) ); - m_keyObservers.insert( "rotation", RotationKey::RotationChangedCaller( m_rotationKey ) ); - } - else - { - m_keyObservers.insert( "angle", AngleKey::AngleChangedCaller( m_angleKey ) ); - } - m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) ); -} + public Snappable { + MatrixTransform m_transform; + EntityKeyValues m_entity; + KeyObserverMap m_keyObservers; + + OriginKey m_originKey; + Vector3 m_origin; + AngleKey m_angleKey; + float m_angle; + RotationKey m_rotationKey; + Float9 m_rotation; + SingletonModel m_model; + + ClassnameFilter m_filter; + NamedEntity m_named; + NameKeys m_nameKeys; + RenderablePivot m_renderOrigin; + RenderableNamedEntity m_renderName; + ModelSkinKey m_skin; + + Callback m_transformChanged; + Callback m_evaluateTransform; + + void construct() + { + default_rotation(m_rotation); + + m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter)); + m_keyObservers.insert(Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named)); + if (g_gameType == eGameTypeDoom3) { + m_keyObservers.insert("angle", RotationKey::AngleChangedCaller(m_rotationKey)); + m_keyObservers.insert("rotation", RotationKey::RotationChangedCaller(m_rotationKey)); + } else { + m_keyObservers.insert("angle", AngleKey::AngleChangedCaller(m_angleKey)); + } + m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey)); + } // vc 2k5 compiler fix #if _MSC_VER >= 1400 -public: + public: #endif -void updateTransform(){ - m_transform.localToParent() = g_matrix4_identity; - matrix4_translate_by_vec3( m_transform.localToParent(), m_origin ); + void updateTransform() + { + m_transform.localToParent() = g_matrix4_identity; + matrix4_translate_by_vec3(m_transform.localToParent(), m_origin); - if ( g_gameType == eGameTypeDoom3 ) { - matrix4_multiply_by_matrix4( m_transform.localToParent(), rotation_toMatrix( m_rotation ) ); - } - else - { - matrix4_multiply_by_matrix4( m_transform.localToParent(), matrix4_rotation_for_z_degrees( m_angle ) ); - } + if (g_gameType == eGameTypeDoom3) { + matrix4_multiply_by_matrix4(m_transform.localToParent(), rotation_toMatrix(m_rotation)); + } else { + matrix4_multiply_by_matrix4(m_transform.localToParent(), matrix4_rotation_for_z_degrees(m_angle)); + } - m_transformChanged(); -} -typedef MemberCaller UpdateTransformCaller; + m_transformChanged(); + } -void originChanged(){ - m_origin = m_originKey.m_origin; - updateTransform(); -} -typedef MemberCaller OriginChangedCaller; -void angleChanged(){ - m_angle = m_angleKey.m_angle; - updateTransform(); -} -typedef MemberCaller AngleChangedCaller; -void rotationChanged(){ - rotation_assign( m_rotation, m_rotationKey.m_rotation ); - updateTransform(); -} -typedef MemberCaller RotationChangedCaller; + typedef MemberCaller UpdateTransformCaller; -void skinChanged(){ - scene::Node* node = m_model.getNode(); - if ( node != 0 ) { - Node_modelSkinChanged( *node ); - } -} -typedef MemberCaller SkinChangedCaller; + void originChanged() + { + m_origin = m_originKey.m_origin; + updateTransform(); + } -public: + typedef MemberCaller OriginChangedCaller; -EclassModel( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) : - m_entity( eclass ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_angleKey( AngleChangedCaller( *this ) ), - m_angle( ANGLEKEY_IDENTITY ), - m_rotationKey( RotationChangedCaller( *this ) ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_renderName( m_named, g_vector3_identity ), - m_skin( SkinChangedCaller( *this ) ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} -EclassModel( const EclassModel& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) : - m_entity( other.m_entity ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_angleKey( AngleChangedCaller( *this ) ), - m_angle( ANGLEKEY_IDENTITY ), - m_rotationKey( RotationChangedCaller( *this ) ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_renderName( m_named, g_vector3_identity ), - m_skin( SkinChangedCaller( *this ) ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} + void angleChanged() + { + m_angle = m_angleKey.m_angle; + updateTransform(); + } -InstanceCounter m_instanceCounter; -void instanceAttach( const scene::Path& path ){ - if ( ++m_instanceCounter.m_count == 1 ) { - m_filter.instanceAttach(); - m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) ); - m_entity.attach( m_keyObservers ); - m_model.modelChanged( m_entity.getEntityClass().modelpath() ); - m_skin.skinChanged( m_entity.getEntityClass().skin() ); - } -} -void instanceDetach( const scene::Path& path ){ - if ( --m_instanceCounter.m_count == 0 ) { - m_skin.skinChanged( "" ); - m_model.modelChanged( "" ); - m_entity.detach( m_keyObservers ); - m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) ); - m_filter.instanceDetach(); - } -} + typedef MemberCaller AngleChangedCaller; -EntityKeyValues& getEntity(){ - return m_entity; -} -const EntityKeyValues& getEntity() const { - return m_entity; -} + void rotationChanged() + { + rotation_assign(m_rotation, m_rotationKey.m_rotation); + updateTransform(); + } -scene::Traversable& getTraversable(){ - return m_model.getTraversable(); -} -Namespaced& getNamespaced(){ - return m_nameKeys; -} -Nameable& getNameable(){ - return m_named; -} -TransformNode& getTransformNode(){ - return m_transform; -} -ModelSkin& getModelSkin(){ - return m_skin.get(); -} + typedef MemberCaller RotationChangedCaller; -void attach( scene::Traversable::Observer* observer ){ - m_model.attach( observer ); -} -void detach( scene::Traversable::Observer* observer ){ - m_model.detach( observer ); -} + void skinChanged() + { + scene::Node *node = m_model.getNode(); + if (node != 0) { + Node_modelSkinChanged(*node); + } + } -void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const { - if ( selected ) { - m_renderOrigin.render( renderer, volume, localToWorld ); - } + typedef MemberCaller SkinChangedCaller; - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const { - renderSolid( renderer, volume, localToWorld, selected ); - if ( g_showNames ) { - renderer.addRenderable( m_renderName, localToWorld ); - } -} - -void translate( const Vector3& translation ){ - m_origin = origin_translated( m_origin, translation ); -} -void rotate( const Quaternion& rotation ){ - if ( g_gameType == eGameTypeDoom3 ) { - rotation_rotate( m_rotation, rotation ); - } - else - { - m_angle = angle_rotated( m_angle, rotation ); - } -} -void snapto( float snap ){ - m_originKey.m_origin = origin_snapped( m_originKey.m_origin, snap ); - m_originKey.write( &m_entity ); -} -void revertTransform(){ - m_origin = m_originKey.m_origin; - if ( g_gameType == eGameTypeDoom3 ) { - rotation_assign( m_rotation, m_rotationKey.m_rotation ); - } - else - { - m_angle = m_angleKey.m_angle; - } -} -void freezeTransform(){ - m_originKey.m_origin = m_origin; - m_originKey.write( &m_entity ); - if ( g_gameType == eGameTypeDoom3 ) { - rotation_assign( m_rotationKey.m_rotation, m_rotation ); - m_rotationKey.write( &m_entity ); - } - else - { - m_angleKey.m_angle = m_angle; - m_angleKey.write( &m_entity ); - } -} -void transformChanged(){ - revertTransform(); - m_evaluateTransform(); - updateTransform(); -} -typedef MemberCaller TransformChangedCaller; -}; - -class EclassModelInstance : public TargetableInstance, public TransformModifier, public Renderable -{ -class TypeCasts -{ -InstanceTypeCastTable m_casts; -public: -TypeCasts(){ - m_casts = TargetableInstance::StaticTypeCasts::instance().get(); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceIdentityCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} -}; - -EclassModel& m_contained; public: -typedef LazyStatic StaticTypeCasts; - -STRING_CONSTANT( Name, "EclassModelInstance" ); -EclassModelInstance( const scene::Path& path, scene::Instance* parent, EclassModel& contained ) : - TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this ), - TransformModifier( EclassModel::TransformChangedCaller( contained ), ApplyTransformCaller( *this ) ), - m_contained( contained ){ - m_contained.instanceAttach( Instance::path() ); - - StaticRenderableConnectionLines::instance().attach( *this ); -} -~EclassModelInstance(){ - StaticRenderableConnectionLines::instance().detach( *this ); - - m_contained.instanceDetach( Instance::path() ); -} -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() ); -} - -void evaluateTransform(){ - if ( getType() == TRANSFORM_PRIMITIVE ) { - m_contained.translate( getTranslation() ); - m_contained.rotate( getRotation() ); - } -} -void applyTransform(){ - m_contained.revertTransform(); - evaluateTransform(); - m_contained.freezeTransform(); -} -typedef MemberCaller ApplyTransformCaller; + EclassModel(EntityClass *eclass, scene::Node &node, const Callback &transformChanged, + const Callback &evaluateTransform) : + m_entity(eclass), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_angleKey(AngleChangedCaller(*this)), + m_angle(ANGLEKEY_IDENTITY), + m_rotationKey(RotationChangedCaller(*this)), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_renderName(m_named, g_vector3_identity), + m_skin(SkinChangedCaller(*this)), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + EclassModel(const EclassModel &other, scene::Node &node, const Callback &transformChanged, + const Callback &evaluateTransform) : + m_entity(other.m_entity), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_angleKey(AngleChangedCaller(*this)), + m_angle(ANGLEKEY_IDENTITY), + m_rotationKey(RotationChangedCaller(*this)), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_renderName(m_named, g_vector3_identity), + m_skin(SkinChangedCaller(*this)), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + InstanceCounter m_instanceCounter; + + void instanceAttach(const scene::Path &path) + { + if (++m_instanceCounter.m_count == 1) { + m_filter.instanceAttach(); + m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end())); + m_entity.attach(m_keyObservers); + m_model.modelChanged(m_entity.getEntityClass().modelpath()); + m_skin.skinChanged(m_entity.getEntityClass().skin()); + } + } + + void instanceDetach(const scene::Path &path) + { + if (--m_instanceCounter.m_count == 0) { + m_skin.skinChanged(""); + m_model.modelChanged(""); + m_entity.detach(m_keyObservers); + m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end())); + m_filter.instanceDetach(); + } + } + + EntityKeyValues &getEntity() + { + return m_entity; + } + + const EntityKeyValues &getEntity() const + { + return m_entity; + } + + scene::Traversable &getTraversable() + { + return m_model.getTraversable(); + } + + Namespaced &getNamespaced() + { + return m_nameKeys; + } + + Nameable &getNameable() + { + return m_named; + } + + TransformNode &getTransformNode() + { + return m_transform; + } + + ModelSkin &getModelSkin() + { + return m_skin.get(); + } + + void attach(scene::Traversable::Observer *observer) + { + m_model.attach(observer); + } + + void detach(scene::Traversable::Observer *observer) + { + m_model.detach(observer); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, bool selected) const + { + if (selected) { + m_renderOrigin.render(renderer, volume, localToWorld); + } + + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, bool selected) const + { + renderSolid(renderer, volume, localToWorld, selected); + if (g_showNames) { + renderer.addRenderable(m_renderName, localToWorld); + } + } + + void translate(const Vector3 &translation) + { + m_origin = origin_translated(m_origin, translation); + } + + void rotate(const Quaternion &rotation) + { + if (g_gameType == eGameTypeDoom3) { + rotation_rotate(m_rotation, rotation); + } else { + m_angle = angle_rotated(m_angle, rotation); + } + } + + void snapto(float snap) + { + m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap); + m_originKey.write(&m_entity); + } + + void revertTransform() + { + m_origin = m_originKey.m_origin; + if (g_gameType == eGameTypeDoom3) { + rotation_assign(m_rotation, m_rotationKey.m_rotation); + } else { + m_angle = m_angleKey.m_angle; + } + } + + void freezeTransform() + { + m_originKey.m_origin = m_origin; + m_originKey.write(&m_entity); + if (g_gameType == eGameTypeDoom3) { + rotation_assign(m_rotationKey.m_rotation, m_rotation); + m_rotationKey.write(&m_entity); + } else { + m_angleKey.m_angle = m_angle; + m_angleKey.write(&m_entity); + } + } + + void transformChanged() + { + revertTransform(); + m_evaluateTransform(); + updateTransform(); + } + + typedef MemberCaller TransformChangedCaller; }; -class EclassModelNode : - public scene::Node::Symbiot, - public scene::Instantiable, - public scene::Cloneable, - public scene::Traversable::Observer -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; +class EclassModelInstance : public TargetableInstance, public TransformModifier, public Renderable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + m_casts = TargetableInstance::StaticTypeCasts::instance().get(); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceIdentityCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + EclassModel &m_contained; public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); - NodeStaticCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} + typedef LazyStatic StaticTypeCasts; + + STRING_CONSTANT(Name, "EclassModelInstance"); + + EclassModelInstance(const scene::Path &path, scene::Instance *parent, EclassModel &contained) : + TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this), + TransformModifier(EclassModel::TransformChangedCaller(contained), ApplyTransformCaller(*this)), + m_contained(contained) + { + m_contained.instanceAttach(Instance::path()); + + StaticRenderableConnectionLines::instance().attach(*this); + } + + ~EclassModelInstance() + { + StaticRenderableConnectionLines::instance().detach(*this); + + m_contained.instanceDetach(Instance::path()); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected()); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected()); + } + + void evaluateTransform() + { + if (getType() == TRANSFORM_PRIMITIVE) { + m_contained.translate(getTranslation()); + m_contained.rotate(getRotation()); + } + } + + void applyTransform() + { + m_contained.revertTransform(); + evaluateTransform(); + m_contained.freezeTransform(); + } + + typedef MemberCaller ApplyTransformCaller; }; - -scene::Node m_node; -InstanceSet m_instances; -EclassModel m_contained; - -void construct(){ - m_contained.attach( this ); -} -void destroy(){ - m_contained.detach( this ); -} +class EclassModelNode : + public scene::Node::Symbiot, + public scene::Instantiable, + public scene::Cloneable, + public scene::Traversable::Observer { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + NodeStaticCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + } + + NodeTypeCastTable &get() + { + return m_casts; + } + }; + + + scene::Node m_node; + InstanceSet m_instances; + EclassModel m_contained; + + void construct() + { + m_contained.attach(this); + } + + void destroy() + { + m_contained.detach(this); + } public: -typedef LazyStatic StaticTypeCasts; - -scene::Traversable& get( NullType){ - return m_contained.getTraversable(); -} -Snappable& get( NullType){ - return m_contained; -} -TransformNode& get( NullType){ - return m_contained.getTransformNode(); -} -Entity& get( NullType){ - return m_contained.getEntity(); -} -Nameable& get( NullType){ - return m_contained.getNameable(); -} -Namespaced& get( NullType){ - return m_contained.getNamespaced(); -} -ModelSkin& get( NullType){ - return m_contained.getModelSkin(); -} - -EclassModelNode( EntityClass* eclass ) : - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -EclassModelNode( const EclassModelNode& other ) : - scene::Node::Symbiot( other ), - scene::Instantiable( other ), - scene::Cloneable( other ), - scene::Traversable::Observer( other ), - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -~EclassModelNode(){ - destroy(); -} -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} - -void insert( scene::Node& child ){ - m_instances.insert( child ); -} -void erase( scene::Node& child ){ - m_instances.erase( child ); -} - -scene::Node& clone() const { - return ( new EclassModelNode( *this ) )->node(); -} - -scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new EclassModelInstance( path, parent, m_contained ); -} -void forEachInstance( const scene::Instantiable::Visitor& visitor ){ - m_instances.forEachInstance( visitor ); -} -void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){ - m_instances.insert( observer, path, instance ); -} -scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){ - return m_instances.erase( observer, path ); -} + typedef LazyStatic StaticTypeCasts; + + scene::Traversable &get(NullType) + { + return m_contained.getTraversable(); + } + + Snappable &get(NullType) + { + return m_contained; + } + + TransformNode &get(NullType) + { + return m_contained.getTransformNode(); + } + + Entity &get(NullType) + { + return m_contained.getEntity(); + } + + Nameable &get(NullType) + { + return m_contained.getNameable(); + } + + Namespaced &get(NullType) + { + return m_contained.getNamespaced(); + } + + ModelSkin &get(NullType) + { + return m_contained.getModelSkin(); + } + + EclassModelNode(EntityClass *eclass) : + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + EclassModelNode(const EclassModelNode &other) : + scene::Node::Symbiot(other), + scene::Instantiable(other), + scene::Cloneable(other), + scene::Traversable::Observer(other), + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + ~EclassModelNode() + { + destroy(); + } + + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } + + void insert(scene::Node &child) + { + m_instances.insert(child); + } + + void erase(scene::Node &child) + { + m_instances.erase(child); + } + + scene::Node &clone() const + { + return (new EclassModelNode(*this))->node(); + } + + scene::Instance *create(const scene::Path &path, scene::Instance *parent) + { + return new EclassModelInstance(path, parent, m_contained); + } + + void forEachInstance(const scene::Instantiable::Visitor &visitor) + { + m_instances.forEachInstance(visitor); + } + + void insert(scene::Instantiable::Observer *observer, const scene::Path &path, scene::Instance *instance) + { + m_instances.insert(observer, path, instance); + } + + scene::Instance *erase(scene::Instantiable::Observer *observer, const scene::Path &path) + { + return m_instances.erase(observer, path); + } }; -scene::Node& New_EclassModel( EntityClass* eclass ){ - return ( new EclassModelNode( eclass ) )->node(); +scene::Node &New_EclassModel(EntityClass *eclass) +{ + return (new EclassModelNode(eclass))->node(); } diff --git a/plugins/entity/eclassmodel.h b/plugins/entity/eclassmodel.h index 5dfe2fe9..38bc0ed1 100644 --- a/plugins/entity/eclassmodel.h +++ b/plugins/entity/eclassmodel.h @@ -22,13 +22,12 @@ #if !defined( INCLUDED_ECLASSMODEL_H ) #define INCLUDED_ECLASSMODEL_H -namespace scene -{ -class Node; +namespace scene { + class Node; } class EntityClass; -scene::Node& New_EclassModel( EntityClass* eclass ); +scene::Node &New_EclassModel(EntityClass *eclass); #include "entity.h" diff --git a/plugins/entity/entity.cpp b/plugins/entity/entity.cpp index dfd2a640..65452a70 100644 --- a/plugins/entity/entity.cpp +++ b/plugins/entity/entity.cpp @@ -45,319 +45,343 @@ #include "doom3group.h" - EGameType g_gameType; -inline scene::Node& entity_for_eclass( EntityClass* eclass ){ - if ( ( string_compare_nocase_n( eclass->name(), "misc_", 5 ) == 0 && string_equal_nocase( eclass->name() + string_length( eclass->name() ) - 5, "model" ) ) // misc_*model (also misc_model) // TODO make classname_* wrapper functions for this - || classname_equal( eclass->name(), "model_static" ) ) { - return New_MiscModel( eclass ); - } - else if ( classname_equal( eclass->name(), "light" ) - || classname_equal( eclass->name(), "lightJunior" ) ) { - return New_Light( eclass ); - } - if ( !eclass->fixedsize ) { - if ( g_gameType == eGameTypeDoom3 ) { - return New_Doom3Group( eclass ); - } - else - { - return New_Group( eclass ); - } - } - else if ( !string_empty( eclass->modelpath() ) ) { - return New_EclassModel( eclass ); - } - else - { - return New_GenericEntity( eclass ); - } +inline scene::Node &entity_for_eclass(EntityClass *eclass) +{ + if ((string_compare_nocase_n(eclass->name(), "misc_", 5) == 0 && + string_equal_nocase(eclass->name() + string_length(eclass->name()) - 5, + "model")) // misc_*model (also misc_model) // TODO make classname_* wrapper functions for this + || classname_equal(eclass->name(), "model_static")) { + return New_MiscModel(eclass); + } else if (classname_equal(eclass->name(), "light") + || classname_equal(eclass->name(), "lightJunior")) { + return New_Light(eclass); + } + if (!eclass->fixedsize) { + if (g_gameType == eGameTypeDoom3) { + return New_Doom3Group(eclass); + } else { + return New_Group(eclass); + } + } else if (!string_empty(eclass->modelpath())) { + return New_EclassModel(eclass); + } else { + return New_GenericEntity(eclass); + } } -void Entity_setName( Entity& entity, const char* name ){ - entity.setKeyValue( "name", name ); +void Entity_setName(Entity &entity, const char *name) +{ + entity.setKeyValue("name", name); } -typedef ReferenceCaller EntitySetNameCaller; -inline Namespaced* Node_getNamespaced( scene::Node& node ){ - return NodeTypeCast::cast( node ); +typedef ReferenceCaller EntitySetNameCaller; + +inline Namespaced *Node_getNamespaced(scene::Node &node) +{ + return NodeTypeCast::cast(node); } -inline scene::Node& node_for_eclass( EntityClass* eclass ){ - scene::Node& node = entity_for_eclass( eclass ); - Node_getEntity( node )->setKeyValue( "classname", eclass->name() ); - - if ( g_gameType == eGameTypeDoom3 - && string_not_empty( eclass->name() ) - && !string_equal( eclass->name(), "worldspawn" ) - && !string_equal( eclass->name(), "UNKNOWN_CLASS" ) ) { - char buffer[1024]; - strcpy( buffer, eclass->name() ); - strcat( buffer, "_1" ); - GlobalNamespace().makeUnique( buffer, EntitySetNameCaller( *Node_getEntity( node ) ) ); - } - - Namespaced* namespaced = Node_getNamespaced( node ); - if ( namespaced != 0 ) { - namespaced->setNamespace( GlobalNamespace() ); - } - - return node; +inline scene::Node &node_for_eclass(EntityClass *eclass) +{ + scene::Node &node = entity_for_eclass(eclass); + Node_getEntity(node)->setKeyValue("classname", eclass->name()); + + if (g_gameType == eGameTypeDoom3 + && string_not_empty(eclass->name()) + && !string_equal(eclass->name(), "worldspawn") + && !string_equal(eclass->name(), "UNKNOWN_CLASS")) { + char buffer[1024]; + strcpy(buffer, eclass->name()); + strcat(buffer, "_1"); + GlobalNamespace().makeUnique(buffer, EntitySetNameCaller(*Node_getEntity(node))); + } + + Namespaced *namespaced = Node_getNamespaced(node); + if (namespaced != 0) { + namespaced->setNamespace(GlobalNamespace()); + } + + return node; } EntityCreator::KeyValueChangedFunc EntityKeyValues::m_entityKeyValueChanged = 0; EntityCreator::KeyValueChangedFunc KeyValue::m_entityKeyValueChanged = 0; -Counter* EntityKeyValues::m_counter = 0; +Counter *EntityKeyValues::m_counter = 0; bool g_showNames = true; bool g_showAngles = true; bool g_newLightDraw = true; bool g_lightRadii = false; -class ConnectEntities -{ +class ConnectEntities { public: -Entity* m_e1; -Entity* m_e2; -int m_index; -ConnectEntities( Entity* e1, Entity* e2, int index ) : m_e1( e1 ), m_e2( e2 ), m_index( index ){ -} -const char *keyname(){ - StringOutputStream key( 16 ); - if ( m_index <= 0 ) { - return "target"; - } - if ( m_index == 1 ) { - return "killtarget"; - } - key << "target" << m_index; - return key.c_str(); -} -void connect( const char* name ){ - m_e1->setKeyValue( keyname(), name ); - m_e2->setKeyValue( "targetname", name ); -} -typedef MemberCaller ConnectCaller; + Entity *m_e1; + Entity *m_e2; + int m_index; + + ConnectEntities(Entity *e1, Entity *e2, int index) : m_e1(e1), m_e2(e2), m_index(index) + { + } + + const char *keyname() + { + StringOutputStream key(16); + if (m_index <= 0) { + return "target"; + } + if (m_index == 1) { + return "killtarget"; + } + key << "target" << m_index; + return key.c_str(); + } + + void connect(const char *name) + { + m_e1->setKeyValue(keyname(), name); + m_e2->setKeyValue("targetname", name); + } + + typedef MemberCaller ConnectCaller; }; -inline Entity* ScenePath_getEntity( const scene::Path& path ){ - Entity* entity = Node_getEntity( path.top() ); - if ( entity == 0 ) { - entity = Node_getEntity( path.parent() ); - } - return entity; -} - -class Quake3EntityCreator : public EntityCreator +inline Entity *ScenePath_getEntity(const scene::Path &path) { -public: -scene::Node& createEntity( EntityClass* eclass ){ - return node_for_eclass( eclass ); -} -void setKeyValueChangedFunc( KeyValueChangedFunc func ){ - EntityKeyValues::setKeyValueChangedFunc( func ); -} -void setCounter( Counter* counter ){ - EntityKeyValues::setCounter( counter ); -} -void connectEntities( const scene::Path& path, const scene::Path& targetPath, int index ){ - Entity* e1 = ScenePath_getEntity( path ); - Entity* e2 = ScenePath_getEntity( targetPath ); - - if ( e1 == 0 || e2 == 0 ) { - globalErrorStream() << "entityConnectSelected: both of the selected instances must be an entity\n"; - return; - } - - if ( e1 == e2 ) { - globalErrorStream() << "entityConnectSelected: the selected instances must not both be from the same entity\n"; - return; - } - - - UndoableCommand undo( "entityConnectSelected" ); - - if ( g_gameType == eGameTypeDoom3 ) { - StringOutputStream key( 16 ); - if ( index >= 0 ) { - key << "target"; - if ( index != 0 ) { - key << index; - } - e1->setKeyValue( key.c_str(), e2->getKeyValue( "name" ) ); - key.clear(); - } - else - { - for ( unsigned int i = 0; ; ++i ) - { - key << "target"; - if ( i != 0 ) { - key << i; - } - const char* value = e1->getKeyValue( key.c_str() ); - if ( string_empty( value ) ) { - e1->setKeyValue( key.c_str(), e2->getKeyValue( "name" ) ); - break; - } - key.clear(); - } - } - } - else - { - ConnectEntities connector( e1, e2, index ); - const char* value = e2->getKeyValue( "targetname" ); - if ( !string_empty( value ) ) { - connector.connect( value ); - } - else - { - const char* type = e2->getKeyValue( "classname" ); - if ( string_empty( type ) ) { - type = "t"; - } - StringOutputStream key( 64 ); - key << type << "1"; - GlobalNamespace().makeUnique( key.c_str(), ConnectEntities::ConnectCaller( connector ) ); - } - } - - SceneChangeNotify(); -} -void setLightRadii( bool lightRadii ){ - g_lightRadii = lightRadii; -} -bool getLightRadii() const { - return g_lightRadii; -} -void setShowNames( bool showNames ){ - g_showNames = showNames; -} -bool getShowNames(){ - return g_showNames; -} -void setShowAngles( bool showAngles ){ - g_showAngles = showAngles; -} -bool getShowAngles(){ - return g_showAngles; + Entity *entity = Node_getEntity(path.top()); + if (entity == 0) { + entity = Node_getEntity(path.parent()); + } + return entity; } -void printStatistics() const { - StringPool_analyse( EntityKeyValues::getPool() ); -} +class Quake3EntityCreator : public EntityCreator { +public: + scene::Node &createEntity(EntityClass *eclass) + { + return node_for_eclass(eclass); + } + + void setKeyValueChangedFunc(KeyValueChangedFunc func) + { + EntityKeyValues::setKeyValueChangedFunc(func); + } + + void setCounter(Counter *counter) + { + EntityKeyValues::setCounter(counter); + } + + void connectEntities(const scene::Path &path, const scene::Path &targetPath, int index) + { + Entity *e1 = ScenePath_getEntity(path); + Entity *e2 = ScenePath_getEntity(targetPath); + + if (e1 == 0 || e2 == 0) { + globalErrorStream() << "entityConnectSelected: both of the selected instances must be an entity\n"; + return; + } + + if (e1 == e2) { + globalErrorStream() + << "entityConnectSelected: the selected instances must not both be from the same entity\n"; + return; + } + + + UndoableCommand undo("entityConnectSelected"); + + if (g_gameType == eGameTypeDoom3) { + StringOutputStream key(16); + if (index >= 0) { + key << "target"; + if (index != 0) { + key << index; + } + e1->setKeyValue(key.c_str(), e2->getKeyValue("name")); + key.clear(); + } else { + for (unsigned int i = 0;; ++i) { + key << "target"; + if (i != 0) { + key << i; + } + const char *value = e1->getKeyValue(key.c_str()); + if (string_empty(value)) { + e1->setKeyValue(key.c_str(), e2->getKeyValue("name")); + break; + } + key.clear(); + } + } + } else { + ConnectEntities connector(e1, e2, index); + const char *value = e2->getKeyValue("targetname"); + if (!string_empty(value)) { + connector.connect(value); + } else { + const char *type = e2->getKeyValue("classname"); + if (string_empty(type)) { + type = "t"; + } + StringOutputStream key(64); + key << type << "1"; + GlobalNamespace().makeUnique(key.c_str(), ConnectEntities::ConnectCaller(connector)); + } + } + + SceneChangeNotify(); + } + + void setLightRadii(bool lightRadii) + { + g_lightRadii = lightRadii; + } + + bool getLightRadii() const + { + return g_lightRadii; + } + + void setShowNames(bool showNames) + { + g_showNames = showNames; + } + + bool getShowNames() + { + return g_showNames; + } + + void setShowAngles(bool showAngles) + { + g_showAngles = showAngles; + } + + bool getShowAngles() + { + return g_showAngles; + } + + void printStatistics() const + { + StringPool_analyse(EntityKeyValues::getPool()); + } }; Quake3EntityCreator g_Quake3EntityCreator; -EntityCreator& GetEntityCreator(){ - return g_Quake3EntityCreator; +EntityCreator &GetEntityCreator() +{ + return g_Quake3EntityCreator; } - -class filter_entity_classname : public EntityFilter -{ -const char* m_classname; +class filter_entity_classname : public EntityFilter { + const char *m_classname; public: -filter_entity_classname( const char* classname ) : m_classname( classname ){ -} -bool filter( const Entity& entity ) const { - return string_equal( entity.getKeyValue( "classname" ), m_classname ); -} + filter_entity_classname(const char *classname) : m_classname(classname) + { + } + + bool filter(const Entity &entity) const + { + return string_equal(entity.getKeyValue("classname"), m_classname); + } }; -class filter_entity_classgroup : public EntityFilter -{ -const char* m_classgroup; -std::size_t m_length; +class filter_entity_classgroup : public EntityFilter { + const char *m_classgroup; + std::size_t m_length; public: -filter_entity_classgroup( const char* classgroup ) : m_classgroup( classgroup ), m_length( string_length( m_classgroup ) ){ -} -bool filter( const Entity& entity ) const { - return string_equal_n( entity.getKeyValue( "classname" ), m_classgroup, m_length ); -} + filter_entity_classgroup(const char *classgroup) : m_classgroup(classgroup), m_length(string_length(m_classgroup)) + { + } + + bool filter(const Entity &entity) const + { + return string_equal_n(entity.getKeyValue("classname"), m_classgroup, m_length); + } }; -filter_entity_classname g_filter_entity_world( "worldspawn" ); -filter_entity_classname g_filter_entity_func_group( "func_group" ); -filter_entity_classname g_filter_entity_light( "light" ); -filter_entity_classname g_filter_entity_misc_model( "misc_model" ); -filter_entity_classname g_filter_entity_misc_gamemodel( "misc_gamemodel" ); -filter_entity_classgroup g_filter_entity_trigger( "trigger_" ); -filter_entity_classgroup g_filter_entity_path( "path_" ); +filter_entity_classname g_filter_entity_world("worldspawn"); +filter_entity_classname g_filter_entity_func_group("func_group"); +filter_entity_classname g_filter_entity_light("light"); +filter_entity_classname g_filter_entity_misc_model("misc_model"); +filter_entity_classname g_filter_entity_misc_gamemodel("misc_gamemodel"); +filter_entity_classgroup g_filter_entity_trigger("trigger_"); +filter_entity_classgroup g_filter_entity_path("path_"); -class filter_entity_doom3model : public EntityFilter -{ +class filter_entity_doom3model : public EntityFilter { public: -bool filter( const Entity& entity ) const { - return string_equal( entity.getKeyValue( "classname" ), "func_static" ) - && !string_equal( entity.getKeyValue( "model" ), entity.getKeyValue( "name" ) ); -} + bool filter(const Entity &entity) const + { + return string_equal(entity.getKeyValue("classname"), "func_static") + && !string_equal(entity.getKeyValue("model"), entity.getKeyValue("name")); + } }; filter_entity_doom3model g_filter_entity_doom3model; -void Entity_InitFilters(){ - add_entity_filter( g_filter_entity_world, EXCLUDE_WORLD ); - add_entity_filter( g_filter_entity_func_group, EXCLUDE_WORLD ); - add_entity_filter( g_filter_entity_world, EXCLUDE_ENT, true ); - add_entity_filter( g_filter_entity_trigger, EXCLUDE_TRIGGERS ); - add_entity_filter( g_filter_entity_misc_model, EXCLUDE_MODELS ); - add_entity_filter( g_filter_entity_misc_gamemodel, EXCLUDE_MODELS ); - add_entity_filter( g_filter_entity_doom3model, EXCLUDE_MODELS ); - add_entity_filter( g_filter_entity_light, EXCLUDE_LIGHTS ); - add_entity_filter( g_filter_entity_path, EXCLUDE_PATHS ); +void Entity_InitFilters() +{ + add_entity_filter(g_filter_entity_world, EXCLUDE_WORLD); + add_entity_filter(g_filter_entity_func_group, EXCLUDE_WORLD); + add_entity_filter(g_filter_entity_world, EXCLUDE_ENT, true); + add_entity_filter(g_filter_entity_trigger, EXCLUDE_TRIGGERS); + add_entity_filter(g_filter_entity_misc_model, EXCLUDE_MODELS); + add_entity_filter(g_filter_entity_misc_gamemodel, EXCLUDE_MODELS); + add_entity_filter(g_filter_entity_doom3model, EXCLUDE_MODELS); + add_entity_filter(g_filter_entity_light, EXCLUDE_LIGHTS); + add_entity_filter(g_filter_entity_path, EXCLUDE_PATHS); } #include "preferencesystem.h" -void Entity_Construct( EGameType gameType ){ - g_gameType = gameType; - if ( g_gameType == eGameTypeDoom3 ) { - g_targetable_nameKey = "name"; - - Static::instance().m_keyIsName = keyIsNameDoom3; - Static::instance().m_nameKey = "name"; - } - else - { - Static::instance().m_keyIsName = keyIsNameQuake3; - Static::instance().m_nameKey = "targetname"; - } - - GlobalPreferenceSystem().registerPreference( "SI_ShowNames", make_property_string( g_showNames ) ); - GlobalPreferenceSystem().registerPreference( "SI_ShowAngles", make_property_string( g_showAngles ) ); - GlobalPreferenceSystem().registerPreference( "NewLightStyle", make_property_string( g_newLightDraw ) ); - GlobalPreferenceSystem().registerPreference( "LightRadiuses", make_property_string( g_lightRadii ) ); - - Entity_InitFilters(); - LightType lightType = LIGHTTYPE_DEFAULT; - if ( g_gameType == eGameTypeRTCW ) { - lightType = LIGHTTYPE_RTCW; - } - else if ( g_gameType == eGameTypeDoom3 ) { - lightType = LIGHTTYPE_DOOM3; - } - Light_Construct( lightType ); - MiscModel_construct(); - Doom3Group_construct(); - - RenderablePivot::StaticShader::instance() = GlobalShaderCache().capture( "$PIVOT" ); - - GlobalShaderCache().attachRenderable( StaticRenderableConnectionLines::instance() ); +void Entity_Construct(EGameType gameType) +{ + g_gameType = gameType; + if (g_gameType == eGameTypeDoom3) { + g_targetable_nameKey = "name"; + + Static::instance().m_keyIsName = keyIsNameDoom3; + Static::instance().m_nameKey = "name"; + } else { + Static::instance().m_keyIsName = keyIsNameQuake3; + Static::instance().m_nameKey = "targetname"; + } + + GlobalPreferenceSystem().registerPreference("SI_ShowNames", make_property_string(g_showNames)); + GlobalPreferenceSystem().registerPreference("SI_ShowAngles", make_property_string(g_showAngles)); + GlobalPreferenceSystem().registerPreference("NewLightStyle", make_property_string(g_newLightDraw)); + GlobalPreferenceSystem().registerPreference("LightRadiuses", make_property_string(g_lightRadii)); + + Entity_InitFilters(); + LightType lightType = LIGHTTYPE_DEFAULT; + if (g_gameType == eGameTypeRTCW) { + lightType = LIGHTTYPE_RTCW; + } else if (g_gameType == eGameTypeDoom3) { + lightType = LIGHTTYPE_DOOM3; + } + Light_Construct(lightType); + MiscModel_construct(); + Doom3Group_construct(); + + RenderablePivot::StaticShader::instance() = GlobalShaderCache().capture("$PIVOT"); + + GlobalShaderCache().attachRenderable(StaticRenderableConnectionLines::instance()); } -void Entity_Destroy(){ - GlobalShaderCache().detachRenderable( StaticRenderableConnectionLines::instance() ); +void Entity_Destroy() +{ + GlobalShaderCache().detachRenderable(StaticRenderableConnectionLines::instance()); - GlobalShaderCache().release( "$PIVOT" ); + GlobalShaderCache().release("$PIVOT"); - Doom3Group_destroy(); - MiscModel_destroy(); - Light_Destroy(); + Doom3Group_destroy(); + MiscModel_destroy(); + Light_Destroy(); } diff --git a/plugins/entity/entity.h b/plugins/entity/entity.h index ae294ab7..e6d84246 100644 --- a/plugins/entity/entity.h +++ b/plugins/entity/entity.h @@ -23,19 +23,21 @@ #define INCLUDED_ENTITY_H class EntityCreator; -EntityCreator& GetEntityCreator(); -enum EGameType -{ - eGameTypeQuake3, - eGameTypeRTCW, - eGameTypeDoom3, +EntityCreator &GetEntityCreator(); + +enum EGameType { + eGameTypeQuake3, + eGameTypeRTCW, + eGameTypeDoom3, }; extern EGameType g_gameType; class FilterSystem; -void Entity_Construct( EGameType gameType = eGameTypeQuake3 ); + +void Entity_Construct(EGameType gameType = eGameTypeQuake3); + void Entity_Destroy(); extern bool g_showNames; diff --git a/plugins/entity/filters.cpp b/plugins/entity/filters.cpp index d18b3097..15c3787a 100644 --- a/plugins/entity/filters.cpp +++ b/plugins/entity/filters.cpp @@ -25,40 +25,47 @@ #include -class EntityFilterWrapper : public Filter -{ -bool m_active; -bool m_invert; -EntityFilter& m_filter; +class EntityFilterWrapper : public Filter { + bool m_active; + bool m_invert; + EntityFilter &m_filter; public: -EntityFilterWrapper( EntityFilter& filter, bool invert ) : m_invert( invert ), m_filter( filter ){ -} -void setActive( bool active ){ - m_active = active; -} -bool active(){ - return m_active; -} -bool filter( const Entity& entity ){ - return m_invert ^ m_filter.filter( entity ); -} + EntityFilterWrapper(EntityFilter &filter, bool invert) : m_invert(invert), m_filter(filter) + { + } + + void setActive(bool active) + { + m_active = active; + } + + bool active() + { + return m_active; + } + + bool filter(const Entity &entity) + { + return m_invert ^ m_filter.filter(entity); + } }; typedef std::list EntityFilters; EntityFilters g_entityFilters; -void add_entity_filter( EntityFilter& filter, int mask, bool invert ){ - g_entityFilters.push_back( EntityFilterWrapper( filter, invert ) ); - GlobalFilterSystem().addFilter( g_entityFilters.back(), mask ); +void add_entity_filter(EntityFilter &filter, int mask, bool invert) +{ + g_entityFilters.push_back(EntityFilterWrapper(filter, invert)); + GlobalFilterSystem().addFilter(g_entityFilters.back(), mask); } -bool entity_filtered( Entity& entity ){ - for ( EntityFilters::iterator i = g_entityFilters.begin(); i != g_entityFilters.end(); ++i ) - { - if ( ( *i ).active() && ( *i ).filter( entity ) ) { - return true; - } - } - return false; +bool entity_filtered(Entity &entity) +{ + for (EntityFilters::iterator i = g_entityFilters.begin(); i != g_entityFilters.end(); ++i) { + if ((*i).active() && (*i).filter(entity)) { + return true; + } + } + return false; } diff --git a/plugins/entity/filters.h b/plugins/entity/filters.h index 219d6de9..e77f3298 100644 --- a/plugins/entity/filters.h +++ b/plugins/entity/filters.h @@ -29,47 +29,54 @@ class Entity; -class EntityFilter -{ +class EntityFilter { public: -virtual bool filter( const Entity& entity ) const = 0; + virtual bool filter(const Entity &entity) const = 0; }; -bool entity_filtered( Entity& entity ); -void add_entity_filter( EntityFilter& filter, int mask, bool invert = false ); +bool entity_filtered(Entity &entity); -class ClassnameFilter : public Filterable -{ -scene::Node& m_node; +void add_entity_filter(EntityFilter &filter, int mask, bool invert = false); + +class ClassnameFilter : public Filterable { + scene::Node &m_node; public: -Entity& m_entity; - -ClassnameFilter( Entity& entity, scene::Node& node ) : m_node( node ), m_entity( entity ){ -} -~ClassnameFilter(){ -} - -void instanceAttach(){ - GlobalFilterSystem().registerFilterable( *this ); -} -void instanceDetach(){ - GlobalFilterSystem().unregisterFilterable( *this ); -} - -void updateFiltered(){ - if ( entity_filtered( m_entity ) ) { - m_node.enable( scene::Node::eFiltered ); - } - else - { - m_node.disable( scene::Node::eFiltered ); - } -} - -void classnameChanged( const char* value ){ - updateFiltered(); -} -typedef MemberCaller ClassnameChangedCaller; + Entity &m_entity; + + ClassnameFilter(Entity &entity, scene::Node &node) : m_node(node), m_entity(entity) + { + } + + ~ClassnameFilter() + { + } + + void instanceAttach() + { + GlobalFilterSystem().registerFilterable(*this); + } + + void instanceDetach() + { + GlobalFilterSystem().unregisterFilterable(*this); + } + + void updateFiltered() + { + if (entity_filtered(m_entity)) { + m_node.enable(scene::Node::eFiltered); + } else { + m_node.disable(scene::Node::eFiltered); + } + } + + void classnameChanged(const char *value) + { + updateFiltered(); + } + + typedef MemberCaller ClassnameChangedCaller; }; #endif diff --git a/plugins/entity/generic.cpp b/plugins/entity/generic.cpp index b80ae830..8abaf008 100644 --- a/plugins/entity/generic.cpp +++ b/plugins/entity/generic.cpp @@ -51,384 +51,476 @@ #include "entity.h" -class RenderableArrow : public OpenGLRenderable -{ -const Vector3& m_origin; -const Vector3& m_angles; +class RenderableArrow : public OpenGLRenderable { + const Vector3 &m_origin; + const Vector3 &m_angles; public: -RenderableArrow( const Vector3& origin, const Vector3& angles ) - : m_origin( origin ), m_angles( angles ){ -} - -void render( RenderStateFlags state ) const { - Matrix4 mat = matrix4_rotation_for_euler_xyz_degrees( m_angles ); - arrow_draw( m_origin, matrix4_transformed_direction( mat, Vector3( 1, 0, 0 ) ), matrix4_transformed_direction( mat, Vector3( 0, 1, 0 ) ), matrix4_transformed_direction( mat, Vector3( 0, 0, 1 ) ) ); -} + RenderableArrow(const Vector3 &origin, const Vector3 &angles) + : m_origin(origin), m_angles(angles) + { + } + + void render(RenderStateFlags state) const + { + Matrix4 mat = matrix4_rotation_for_euler_xyz_degrees(m_angles); + arrow_draw(m_origin, matrix4_transformed_direction(mat, Vector3(1, 0, 0)), + matrix4_transformed_direction(mat, Vector3(0, 1, 0)), + matrix4_transformed_direction(mat, Vector3(0, 0, 1))); + } }; -inline void read_aabb( AABB& aabb, const EntityClass& eclass ){ - aabb = aabb_for_minmax( eclass.mins, eclass.maxs ); +inline void read_aabb(AABB &aabb, const EntityClass &eclass) +{ + aabb = aabb_for_minmax(eclass.mins, eclass.maxs); } class GenericEntity : - public Cullable, - public Bounded, - public Snappable -{ -EntityKeyValues m_entity; -KeyObserverMap m_keyObservers; -MatrixTransform m_transform; - -OriginKey m_originKey; -Vector3 m_origin; -AnglesKey m_anglesKey; -Vector3 m_angles; - -ClassnameFilter m_filter; -NamedEntity m_named; -NameKeys m_nameKeys; - -AABB m_aabb_local; - -RenderableArrow m_arrow; -RenderableSolidAABB m_aabb_solid; -RenderableWireframeAABB m_aabb_wire; -RenderableNamedEntity m_renderName; - -Callback m_transformChanged; -Callback m_evaluateTransform; - -void construct(){ - read_aabb( m_aabb_local, m_entity.getEntityClass() ); - - m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) ); - m_keyObservers.insert( Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) ); - m_keyObservers.insert( "angle", AnglesKey::AngleChangedCaller( m_anglesKey ) ); - m_keyObservers.insert( "angles", AnglesKey::AnglesChangedCaller( m_anglesKey ) ); - m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) ); -} + public Cullable, + public Bounded, + public Snappable { + EntityKeyValues m_entity; + KeyObserverMap m_keyObservers; + MatrixTransform m_transform; + + OriginKey m_originKey; + Vector3 m_origin; + AnglesKey m_anglesKey; + Vector3 m_angles; + + ClassnameFilter m_filter; + NamedEntity m_named; + NameKeys m_nameKeys; + + AABB m_aabb_local; + + RenderableArrow m_arrow; + RenderableSolidAABB m_aabb_solid; + RenderableWireframeAABB m_aabb_wire; + RenderableNamedEntity m_renderName; + + Callback m_transformChanged; + Callback m_evaluateTransform; + + void construct() + { + read_aabb(m_aabb_local, m_entity.getEntityClass()); + + m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter)); + m_keyObservers.insert(Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named)); + m_keyObservers.insert("angle", AnglesKey::AngleChangedCaller(m_anglesKey)); + m_keyObservers.insert("angles", AnglesKey::AnglesChangedCaller(m_anglesKey)); + m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey)); + } // vc 2k5 compiler fix #if _MSC_VER >= 1400 -public: + public: #endif -void updateTransform(){ - m_transform.localToParent() = g_matrix4_identity; - matrix4_translate_by_vec3( m_transform.localToParent(), m_origin ); - m_transformChanged(); -} -typedef MemberCaller UpdateTransformCaller; -void originChanged(){ - m_origin = m_originKey.m_origin; - updateTransform(); -} -typedef MemberCaller OriginChangedCaller; -void anglesChanged(){ - m_angles = m_anglesKey.m_angles; - updateTransform(); -} -typedef MemberCaller AnglesChangedCaller; -public: + void updateTransform() + { + m_transform.localToParent() = g_matrix4_identity; + matrix4_translate_by_vec3(m_transform.localToParent(), m_origin); + m_transformChanged(); + } -GenericEntity( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) : - m_entity( eclass ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_anglesKey( AnglesChangedCaller( *this ) ), - m_angles( ANGLESKEY_IDENTITY ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_arrow( m_aabb_local.origin, m_angles ), - m_aabb_solid( m_aabb_local ), - m_aabb_wire( m_aabb_local ), - m_renderName( m_named, g_vector3_identity ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} -GenericEntity( const GenericEntity& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) : - m_entity( other.m_entity ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_anglesKey( AnglesChangedCaller( *this ) ), - m_angles( ANGLESKEY_IDENTITY ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_arrow( m_aabb_local.origin, m_angles ), - m_aabb_solid( m_aabb_local ), - m_aabb_wire( m_aabb_local ), - m_renderName( m_named, g_vector3_identity ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} + typedef MemberCaller UpdateTransformCaller; -InstanceCounter m_instanceCounter; -void instanceAttach( const scene::Path& path ){ - if ( ++m_instanceCounter.m_count == 1 ) { - m_filter.instanceAttach(); - m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) ); - m_entity.attach( m_keyObservers ); - } -} -void instanceDetach( const scene::Path& path ){ - if ( --m_instanceCounter.m_count == 0 ) { - m_entity.detach( m_keyObservers ); - m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) ); - m_filter.instanceDetach(); - } -} + void originChanged() + { + m_origin = m_originKey.m_origin; + updateTransform(); + } -EntityKeyValues& getEntity(){ - return m_entity; -} -const EntityKeyValues& getEntity() const { - return m_entity; -} - -Namespaced& getNamespaced(){ - return m_nameKeys; -} -Nameable& getNameable(){ - return m_named; -} -TransformNode& getTransformNode(){ - return m_transform; -} - -const AABB& localAABB() const { - return m_aabb_local; -} - -VolumeIntersectionValue intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) const { - return volume.TestAABB( localAABB(), localToWorld ); -} - -void renderArrow( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - if ( g_showAngles ) { - renderer.addRenderable( m_arrow, localToWorld ); - } -} -void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - renderer.SetState( m_entity.getEntityClass().m_state_fill, Renderer::eFullMaterials ); - renderer.addRenderable( m_aabb_solid, localToWorld ); - renderArrow( renderer, volume, localToWorld ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); - renderer.addRenderable( m_aabb_wire, localToWorld ); - renderArrow( renderer, volume, localToWorld ); - if ( g_showNames ) { - renderer.addRenderable( m_renderName, localToWorld ); - } -} + typedef MemberCaller OriginChangedCaller; + void anglesChanged() + { + m_angles = m_anglesKey.m_angles; + updateTransform(); + } -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 ); - } -} + typedef MemberCaller AnglesChangedCaller; +public: -void translate( const Vector3& translation ){ - m_origin = origin_translated( m_origin, translation ); -} -void rotate( const Quaternion& rotation ){ - m_angles = angles_rotated( m_angles, rotation ); -} -void snapto( float snap ){ - m_originKey.m_origin = origin_snapped( m_originKey.m_origin, snap ); - m_originKey.write( &m_entity ); -} -void revertTransform(){ - m_origin = m_originKey.m_origin; - m_angles = m_anglesKey.m_angles; -} -void freezeTransform(){ - m_originKey.m_origin = m_origin; - m_originKey.write( &m_entity ); - m_anglesKey.m_angles = m_angles; - m_anglesKey.write( &m_entity ); -} -void transformChanged(){ - revertTransform(); - m_evaluateTransform(); - updateTransform(); -} -typedef MemberCaller TransformChangedCaller; + GenericEntity(EntityClass *eclass, scene::Node &node, const Callback &transformChanged, + const Callback &evaluateTransform) : + m_entity(eclass), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_anglesKey(AnglesChangedCaller(*this)), + m_angles(ANGLESKEY_IDENTITY), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_arrow(m_aabb_local.origin, m_angles), + m_aabb_solid(m_aabb_local), + m_aabb_wire(m_aabb_local), + m_renderName(m_named, g_vector3_identity), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + GenericEntity(const GenericEntity &other, scene::Node &node, const Callback &transformChanged, + const Callback &evaluateTransform) : + m_entity(other.m_entity), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_anglesKey(AnglesChangedCaller(*this)), + m_angles(ANGLESKEY_IDENTITY), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_arrow(m_aabb_local.origin, m_angles), + m_aabb_solid(m_aabb_local), + m_aabb_wire(m_aabb_local), + m_renderName(m_named, g_vector3_identity), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + InstanceCounter m_instanceCounter; + + void instanceAttach(const scene::Path &path) + { + if (++m_instanceCounter.m_count == 1) { + m_filter.instanceAttach(); + m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end())); + m_entity.attach(m_keyObservers); + } + } + + void instanceDetach(const scene::Path &path) + { + if (--m_instanceCounter.m_count == 0) { + m_entity.detach(m_keyObservers); + m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end())); + m_filter.instanceDetach(); + } + } + + EntityKeyValues &getEntity() + { + return m_entity; + } + + const EntityKeyValues &getEntity() const + { + return m_entity; + } + + Namespaced &getNamespaced() + { + return m_nameKeys; + } + + Nameable &getNameable() + { + return m_named; + } + + TransformNode &getTransformNode() + { + return m_transform; + } + + const AABB &localAABB() const + { + return m_aabb_local; + } + + VolumeIntersectionValue intersectVolume(const VolumeTest &volume, const Matrix4 &localToWorld) const + { + return volume.TestAABB(localAABB(), localToWorld); + } + + void renderArrow(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + if (g_showAngles) { + renderer.addRenderable(m_arrow, localToWorld); + } + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + renderer.SetState(m_entity.getEntityClass().m_state_fill, Renderer::eFullMaterials); + renderer.addRenderable(m_aabb_solid, localToWorld); + renderArrow(renderer, volume, localToWorld); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly); + renderer.addRenderable(m_aabb_wire, localToWorld); + renderArrow(renderer, volume, localToWorld); + if (g_showNames) { + renderer.addRenderable(m_renderName, localToWorld); + } + } + + + void testSelect(Selector &selector, SelectionTest &test, const Matrix4 &localToWorld) + { + test.BeginMesh(localToWorld); + + SelectionIntersection best; + aabb_testselect(m_aabb_local, test, best); + if (best.valid()) { + selector.addIntersection(best); + } + } + + void translate(const Vector3 &translation) + { + m_origin = origin_translated(m_origin, translation); + } + + void rotate(const Quaternion &rotation) + { + m_angles = angles_rotated(m_angles, rotation); + } + + void snapto(float snap) + { + m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap); + m_originKey.write(&m_entity); + } + + void revertTransform() + { + m_origin = m_originKey.m_origin; + m_angles = m_anglesKey.m_angles; + } + + void freezeTransform() + { + m_originKey.m_origin = m_origin; + m_originKey.write(&m_entity); + m_anglesKey.m_angles = m_angles; + m_anglesKey.write(&m_entity); + } + + void transformChanged() + { + revertTransform(); + m_evaluateTransform(); + updateTransform(); + } + + typedef MemberCaller TransformChangedCaller; }; class GenericEntityInstance : - public TargetableInstance, - public TransformModifier, - public Renderable, - public SelectionTestable -{ -class TypeCasts -{ -InstanceTypeCastTable m_casts; -public: -TypeCasts(){ - m_casts = TargetableInstance::StaticTypeCasts::instance().get(); - InstanceContainedCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceIdentityCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} -}; - -GenericEntity& m_contained; -mutable AABB m_bounds; + public TargetableInstance, + public TransformModifier, + public Renderable, + public SelectionTestable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + m_casts = TargetableInstance::StaticTypeCasts::instance().get(); + InstanceContainedCast::install(m_casts); + InstanceContainedCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceIdentityCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + GenericEntity &m_contained; + mutable AABB m_bounds; public: -typedef LazyStatic StaticTypeCasts; - -Bounded& get( NullType){ - return m_contained; -} -Cullable& get( NullType){ - return m_contained; -} - -STRING_CONSTANT( Name, "GenericEntityInstance" ); - -GenericEntityInstance( const scene::Path& path, scene::Instance* parent, GenericEntity& contained ) : - TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this ), - TransformModifier( GenericEntity::TransformChangedCaller( contained ), ApplyTransformCaller( *this ) ), - m_contained( contained ){ - m_contained.instanceAttach( Instance::path() ); - - StaticRenderableConnectionLines::instance().attach( *this ); -} -~GenericEntityInstance(){ - StaticRenderableConnectionLines::instance().detach( *this ); - - m_contained.instanceDetach( Instance::path() ); -} - -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderSolid( renderer, volume, Instance::localToWorld() ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderWireframe( renderer, volume, Instance::localToWorld() ); -} - -void testSelect( Selector& selector, SelectionTest& test ){ - m_contained.testSelect( selector, test, Instance::localToWorld() ); -} - -void evaluateTransform(){ - if ( getType() == TRANSFORM_PRIMITIVE ) { - m_contained.translate( getTranslation() ); - m_contained.rotate( getRotation() ); - } -} -void applyTransform(){ - m_contained.revertTransform(); - evaluateTransform(); - m_contained.freezeTransform(); -} -typedef MemberCaller ApplyTransformCaller; + typedef LazyStatic StaticTypeCasts; + + Bounded &get(NullType) + { + return m_contained; + } + + Cullable &get(NullType) + { + return m_contained; + } + + STRING_CONSTANT(Name, "GenericEntityInstance"); + + GenericEntityInstance(const scene::Path &path, scene::Instance *parent, GenericEntity &contained) : + TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this), + TransformModifier(GenericEntity::TransformChangedCaller(contained), ApplyTransformCaller(*this)), + m_contained(contained) + { + m_contained.instanceAttach(Instance::path()); + + StaticRenderableConnectionLines::instance().attach(*this); + } + + ~GenericEntityInstance() + { + StaticRenderableConnectionLines::instance().detach(*this); + + m_contained.instanceDetach(Instance::path()); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderSolid(renderer, volume, Instance::localToWorld()); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderWireframe(renderer, volume, Instance::localToWorld()); + } + + void testSelect(Selector &selector, SelectionTest &test) + { + m_contained.testSelect(selector, test, Instance::localToWorld()); + } + + void evaluateTransform() + { + if (getType() == TRANSFORM_PRIMITIVE) { + m_contained.translate(getTranslation()); + m_contained.rotate(getRotation()); + } + } + + void applyTransform() + { + m_contained.revertTransform(); + evaluateTransform(); + m_contained.freezeTransform(); + } + + typedef MemberCaller ApplyTransformCaller; }; class GenericEntityNode : - public scene::Node::Symbiot, - public scene::Instantiable, - public scene::Cloneable -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; -public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); - NodeStaticCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} -}; - - -InstanceSet m_instances; - -scene::Node m_node; -GenericEntity m_contained; + public scene::Node::Symbiot, + public scene::Instantiable, + public scene::Cloneable { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + NodeStaticCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + } + + NodeTypeCastTable &get() + { + return m_casts; + } + }; + + + InstanceSet m_instances; + + scene::Node m_node; + GenericEntity m_contained; public: -typedef LazyStatic StaticTypeCasts; - -Snappable& get( NullType){ - return m_contained; -} -TransformNode& get( NullType){ - return m_contained.getTransformNode(); -} -Entity& get( NullType){ - return m_contained.getEntity(); -} -Nameable& get( NullType){ - return m_contained.getNameable(); -} -Namespaced& get( NullType){ - return m_contained.getNamespaced(); -} - -GenericEntityNode( EntityClass* eclass ) : - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ -} -GenericEntityNode( const GenericEntityNode& other ) : - scene::Node::Symbiot( other ), - scene::Instantiable( other ), - scene::Cloneable( other ), - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ -} -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} - -scene::Node& clone() const { - return ( new GenericEntityNode( *this ) )->node(); -} - -scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new GenericEntityInstance( path, parent, m_contained ); -} -void forEachInstance( const scene::Instantiable::Visitor& visitor ){ - m_instances.forEachInstance( visitor ); -} -void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){ - m_instances.insert( observer, path, instance ); -} -scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){ - return m_instances.erase( observer, path ); -} + typedef LazyStatic StaticTypeCasts; + + Snappable &get(NullType) + { + return m_contained; + } + + TransformNode &get(NullType) + { + return m_contained.getTransformNode(); + } + + Entity &get(NullType) + { + return m_contained.getEntity(); + } + + Nameable &get(NullType) + { + return m_contained.getNameable(); + } + + Namespaced &get(NullType) + { + return m_contained.getNamespaced(); + } + + GenericEntityNode(EntityClass *eclass) : + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + } + + GenericEntityNode(const GenericEntityNode &other) : + scene::Node::Symbiot(other), + scene::Instantiable(other), + scene::Cloneable(other), + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + } + + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } + + scene::Node &clone() const + { + return (new GenericEntityNode(*this))->node(); + } + + scene::Instance *create(const scene::Path &path, scene::Instance *parent) + { + return new GenericEntityInstance(path, parent, m_contained); + } + + void forEachInstance(const scene::Instantiable::Visitor &visitor) + { + m_instances.forEachInstance(visitor); + } + + void insert(scene::Instantiable::Observer *observer, const scene::Path &path, scene::Instance *instance) + { + m_instances.insert(observer, path, instance); + } + + scene::Instance *erase(scene::Instantiable::Observer *observer, const scene::Path &path) + { + return m_instances.erase(observer, path); + } }; -scene::Node& New_GenericEntity( EntityClass* eclass ){ - return ( new GenericEntityNode( eclass ) )->node(); +scene::Node &New_GenericEntity(EntityClass *eclass) +{ + return (new GenericEntityNode(eclass))->node(); } diff --git a/plugins/entity/generic.h b/plugins/entity/generic.h index 1f9c2cda..1a04b95f 100644 --- a/plugins/entity/generic.h +++ b/plugins/entity/generic.h @@ -22,6 +22,6 @@ #if !defined( INCLUDED_GENERIC_H ) #define INCLUDED_GENERIC_H -scene::Node& New_GenericEntity( EntityClass* eclass ); +scene::Node &New_GenericEntity(EntityClass *eclass); #endif diff --git a/plugins/entity/group.cpp b/plugins/entity/group.cpp index bad7fc54..ed8d5772 100644 --- a/plugins/entity/group.cpp +++ b/plugins/entity/group.cpp @@ -49,153 +49,190 @@ /// The "origin" key directly controls the entity's local-to-parent transform. -class Group -{ -EntityKeyValues m_entity; -KeyObserverMap m_keyObservers; -MatrixTransform m_transform; -TraversableNodeSet m_traverse; +class Group { + EntityKeyValues m_entity; + KeyObserverMap m_keyObservers; + MatrixTransform m_transform; + TraversableNodeSet m_traverse; -ClassnameFilter m_filter; -NamedEntity m_named; -NameKeys m_nameKeys; + ClassnameFilter m_filter; + NamedEntity m_named; + NameKeys m_nameKeys; -OriginKey m_originKey; -Vector3 m_origin; + OriginKey m_originKey; + Vector3 m_origin; -RenderableNamedEntity m_renderName; -mutable Vector3 m_name_origin; + RenderableNamedEntity m_renderName; + mutable Vector3 m_name_origin; -Callback m_transformChanged; -Callback m_evaluateTransform; + Callback m_transformChanged; + Callback m_evaluateTransform; -void construct(){ - m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) ); - m_keyObservers.insert( Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) ); - m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) ); -} + void construct() + { + m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter)); + m_keyObservers.insert(Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named)); + m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey)); + } public: -Group( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) : - m_entity( eclass ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_renderName( m_named, m_name_origin ), - m_name_origin( g_vector3_identity ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} -Group( const Group& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) : - m_entity( other.m_entity ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_renderName( m_named, g_vector3_identity ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} - -InstanceCounter m_instanceCounter; -void instanceAttach( const scene::Path& path ){ - if ( ++m_instanceCounter.m_count == 1 ) { - m_filter.instanceAttach(); - m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) ); - m_traverse.instanceAttach( path_find_mapfile( path.begin(), path.end() ) ); - m_entity.attach( m_keyObservers ); - } -} -void instanceDetach( const scene::Path& path ){ - if ( --m_instanceCounter.m_count == 0 ) { - m_entity.detach( m_keyObservers ); - m_traverse.instanceDetach( path_find_mapfile( path.begin(), path.end() ) ); - m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) ); - m_filter.instanceDetach(); - } -} - -EntityKeyValues& getEntity(){ - return m_entity; -} -const EntityKeyValues& getEntity() const { - return m_entity; -} - -scene::Traversable& getTraversable(){ - return m_traverse; -} -Namespaced& getNamespaced(){ - return m_nameKeys; -} -Nameable& getNameable(){ - return m_named; -} -TransformNode& getTransformNode(){ - return m_transform; -} - -void attach( scene::Traversable::Observer* observer ){ - m_traverse.attach( observer ); -} -void detach( scene::Traversable::Observer* observer ){ - m_traverse.detach( observer ); -} - -void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); -} - -void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, const AABB& childBounds ) const { - renderSolid( renderer, volume, localToWorld ); - - if ( g_showNames ) { - // don't draw the name for worldspawn - if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) { - return; - } - - // place name in the middle of the "children cloud" - m_name_origin = childBounds.origin; - - renderer.addRenderable( m_renderName, localToWorld ); - } -} - -void updateTransform(){ - m_transform.localToParent() = g_matrix4_identity; - matrix4_translate_by_vec3( m_transform.localToParent(), m_origin ); - m_transformChanged(); -} -typedef MemberCaller UpdateTransformCaller; -void originChanged(){ - m_origin = m_originKey.m_origin; - updateTransform(); -} -typedef MemberCaller OriginChangedCaller; - -void translate( const Vector3& translation ){ - m_origin = origin_translated( m_origin, translation ); -} - -void revertTransform(){ - m_origin = m_originKey.m_origin; -} -void freezeTransform(){ - m_originKey.m_origin = m_origin; - m_originKey.write( &m_entity ); -} -void transformChanged(){ - revertTransform(); - m_evaluateTransform(); - updateTransform(); -} -typedef MemberCaller TransformChangedCaller; + Group(EntityClass *eclass, scene::Node &node, const Callback &transformChanged, + const Callback &evaluateTransform) : + m_entity(eclass), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_renderName(m_named, m_name_origin), + m_name_origin(g_vector3_identity), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + Group(const Group &other, scene::Node &node, const Callback &transformChanged, + const Callback &evaluateTransform) : + m_entity(other.m_entity), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_renderName(m_named, g_vector3_identity), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + InstanceCounter m_instanceCounter; + + void instanceAttach(const scene::Path &path) + { + if (++m_instanceCounter.m_count == 1) { + m_filter.instanceAttach(); + m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end())); + m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end())); + m_entity.attach(m_keyObservers); + } + } + + void instanceDetach(const scene::Path &path) + { + if (--m_instanceCounter.m_count == 0) { + m_entity.detach(m_keyObservers); + m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end())); + m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end())); + m_filter.instanceDetach(); + } + } + + EntityKeyValues &getEntity() + { + return m_entity; + } + + const EntityKeyValues &getEntity() const + { + return m_entity; + } + + scene::Traversable &getTraversable() + { + return m_traverse; + } + + Namespaced &getNamespaced() + { + return m_nameKeys; + } + + Nameable &getNameable() + { + return m_named; + } + + TransformNode &getTransformNode() + { + return m_transform; + } + + void attach(scene::Traversable::Observer *observer) + { + m_traverse.attach(observer); + } + + void detach(scene::Traversable::Observer *observer) + { + m_traverse.detach(observer); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, + const AABB &childBounds) const + { + renderSolid(renderer, volume, localToWorld); + + if (g_showNames) { + // don't draw the name for worldspawn + if (!strcmp(m_entity.getEntityClass().name(), "worldspawn")) { + return; + } + + // place name in the middle of the "children cloud" + m_name_origin = childBounds.origin; + + renderer.addRenderable(m_renderName, localToWorld); + } + } + + void updateTransform() + { + m_transform.localToParent() = g_matrix4_identity; + matrix4_translate_by_vec3(m_transform.localToParent(), m_origin); + m_transformChanged(); + } + + typedef MemberCaller UpdateTransformCaller; + + void originChanged() + { + m_origin = m_originKey.m_origin; + updateTransform(); + } + + typedef MemberCaller OriginChangedCaller; + + void translate(const Vector3 &translation) + { + m_origin = origin_translated(m_origin, translation); + } + + void revertTransform() + { + m_origin = m_originKey.m_origin; + } + + void freezeTransform() + { + m_originKey.m_origin = m_origin; + m_originKey.write(&m_entity); + } + + void transformChanged() + { + revertTransform(); + m_evaluateTransform(); + updateTransform(); + } + + typedef MemberCaller TransformChangedCaller; }; #if 0 @@ -206,7 +243,7 @@ public: TransformableSetTranslation( const Translation& value ) : m_value( value ){ } void operator()( Transformable& transformable ) const { - transformable.setTranslation( m_value ); + transformable.setTranslation( m_value ); } }; @@ -217,7 +254,7 @@ public: TransformableSetRotation( const Rotation& value ) : m_value( value ){ } void operator()( Transformable& transformable ) const { - transformable.setRotation( m_value ); + transformable.setRotation( m_value ); } }; @@ -228,7 +265,7 @@ public: TransformableSetScale( const Scale& value ) : m_value( value ){ } void operator()( Transformable& transformable ) const { - transformable.setScale( m_value ); + transformable.setScale( m_value ); } }; @@ -239,7 +276,7 @@ public: TransformableSetType( const TransformModifierType& value ) : m_value( value ){ } void operator()( Transformable& transformable ) const { - transformable.setType( m_value ); + transformable.setType( m_value ); } }; @@ -248,204 +285,251 @@ class TransformableFreezeTransform TransformModifierType m_value; public: void operator()( Transformable& transformable ) const { - transformable.freezeTransform(); + transformable.freezeTransform(); } }; template inline void Scene_forEachChildTransformable( const Functor& functor, const scene::Path& path ){ - GlobalSceneGraph().traverse_subgraph( ChildInstanceWalker< InstanceApply >( functor ), path ); + GlobalSceneGraph().traverse_subgraph( ChildInstanceWalker< InstanceApply >( functor ), path ); } #endif class GroupInstance : - public TargetableInstance, - public TransformModifier, + public TargetableInstance, + public TransformModifier, #if 0 - public Transformable, + public Transformable, #endif - public Renderable -{ -class TypeCasts -{ -InstanceTypeCastTable m_casts; -public: -TypeCasts(){ - m_casts = TargetableInstance::StaticTypeCasts::instance().get(); - InstanceStaticCast::install( m_casts ); + public Renderable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + m_casts = TargetableInstance::StaticTypeCasts::instance().get(); + InstanceStaticCast::install(m_casts); #if 0 - InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); #endif -} -InstanceTypeCastTable& get(){ - return m_casts; -} -}; + } -Group& m_contained; -public: -typedef LazyStatic StaticTypeCasts; - -GroupInstance( const scene::Path& path, scene::Instance* parent, Group& group ) : - TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), group.getEntity(), *this ), - TransformModifier( Group::TransformChangedCaller( group ), ApplyTransformCaller( *this ) ), - m_contained( group ){ - m_contained.instanceAttach( Instance::path() ); - StaticRenderableConnectionLines::instance().attach( *this ); -} -~GroupInstance(){ - StaticRenderableConnectionLines::instance().detach( *this ); - m_contained.instanceDetach( Instance::path() ); -} -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderSolid( renderer, volume, Instance::localToWorld() ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), Instance::childBounds() ); -} + InstanceTypeCastTable &get() + { + return m_casts; + } + }; -STRING_CONSTANT( Name, "GroupInstance" ); + Group &m_contained; +public: + typedef LazyStatic StaticTypeCasts; + + GroupInstance(const scene::Path &path, scene::Instance *parent, Group &group) : + TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), group.getEntity(), *this), + TransformModifier(Group::TransformChangedCaller(group), ApplyTransformCaller(*this)), + m_contained(group) + { + m_contained.instanceAttach(Instance::path()); + StaticRenderableConnectionLines::instance().attach(*this); + } + + ~GroupInstance() + { + StaticRenderableConnectionLines::instance().detach(*this); + m_contained.instanceDetach(Instance::path()); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderSolid(renderer, volume, Instance::localToWorld()); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), Instance::childBounds()); + } + + STRING_CONSTANT(Name, "GroupInstance"); #if 0 -void setType( TransformModifierType type ){ - Scene_forEachChildTransformable( TransformableSetType( type ), Instance::path() ); -} -void setTranslation( const Translation& value ){ - Scene_forEachChildTransformable( TransformableSetTranslation( value ), Instance::path() ); -} -void setRotation( const Rotation& value ){ - Scene_forEachChildTransformable( TransformableSetRotation( value ), Instance::path() ); -} -void setScale( const Scale& value ){ - Scene_forEachChildTransformable( TransformableSetScale( value ), Instance::path() ); -} -void freezeTransform(){ - Scene_forEachChildTransformable( TransformableFreezeTransform(), Instance::path() ); -} - -void evaluateTransform(){ -} + void setType( TransformModifierType type ){ + Scene_forEachChildTransformable( TransformableSetType( type ), Instance::path() ); + } + void setTranslation( const Translation& value ){ + Scene_forEachChildTransformable( TransformableSetTranslation( value ), Instance::path() ); + } + void setRotation( const Rotation& value ){ + Scene_forEachChildTransformable( TransformableSetRotation( value ), Instance::path() ); + } + void setScale( const Scale& value ){ + Scene_forEachChildTransformable( TransformableSetScale( value ), Instance::path() ); + } + void freezeTransform(){ + Scene_forEachChildTransformable( TransformableFreezeTransform(), Instance::path() ); + } + + void evaluateTransform(){ + } #endif -void evaluateTransform(){ - if ( getType() == TRANSFORM_PRIMITIVE ) { - m_contained.translate( getTranslation() ); - } -} -void applyTransform(){ - m_contained.revertTransform(); - evaluateTransform(); - m_contained.freezeTransform(); -} -typedef MemberCaller ApplyTransformCaller; + void evaluateTransform() + { + if (getType() == TRANSFORM_PRIMITIVE) { + m_contained.translate(getTranslation()); + } + } + + void applyTransform() + { + m_contained.revertTransform(); + evaluateTransform(); + m_contained.freezeTransform(); + } + + typedef MemberCaller ApplyTransformCaller; }; class GroupNode : - public scene::Node::Symbiot, - public scene::Instantiable, - public scene::Cloneable, - public scene::Traversable::Observer -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; -public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); - NodeStaticCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} -}; - - -scene::Node m_node; -InstanceSet m_instances; -Group m_contained; - -void construct(){ - m_contained.attach( this ); -} -void destroy(){ - m_contained.detach( this ); -} + public scene::Node::Symbiot, + public scene::Instantiable, + public scene::Cloneable, + public scene::Traversable::Observer { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + NodeStaticCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + } + + NodeTypeCastTable &get() + { + return m_casts; + } + }; + + + scene::Node m_node; + InstanceSet m_instances; + Group m_contained; + + void construct() + { + m_contained.attach(this); + } + + void destroy() + { + m_contained.detach(this); + } public: -typedef LazyStatic StaticTypeCasts; - -scene::Traversable& get( NullType){ - return m_contained.getTraversable(); -} -TransformNode& get( NullType){ - return m_contained.getTransformNode(); -} -Entity& get( NullType){ - return m_contained.getEntity(); -} -Nameable& get( NullType){ - return m_contained.getNameable(); -} -Namespaced& get( NullType){ - return m_contained.getNamespaced(); -} - -GroupNode( EntityClass* eclass ) : - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -GroupNode( const GroupNode& other ) : - scene::Node::Symbiot( other ), - scene::Instantiable( other ), - scene::Cloneable( other ), - scene::Traversable::Observer( other ), - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -~GroupNode(){ - destroy(); -} - -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} - -scene::Node& clone() const { - return ( new GroupNode( *this ) )->node(); -} - -void insert( scene::Node& child ){ - m_instances.insert( child ); -} -void erase( scene::Node& child ){ - m_instances.erase( child ); -} - -scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new GroupInstance( path, parent, m_contained ); -} -void forEachInstance( const scene::Instantiable::Visitor& visitor ){ - m_instances.forEachInstance( visitor ); -} -void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){ - m_instances.insert( observer, path, instance ); -} -scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){ - return m_instances.erase( observer, path ); -} + typedef LazyStatic StaticTypeCasts; + + scene::Traversable &get(NullType) + { + return m_contained.getTraversable(); + } + + TransformNode &get(NullType) + { + return m_contained.getTransformNode(); + } + + Entity &get(NullType) + { + return m_contained.getEntity(); + } + + Nameable &get(NullType) + { + return m_contained.getNameable(); + } + + Namespaced &get(NullType) + { + return m_contained.getNamespaced(); + } + + GroupNode(EntityClass *eclass) : + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + GroupNode(const GroupNode &other) : + scene::Node::Symbiot(other), + scene::Instantiable(other), + scene::Cloneable(other), + scene::Traversable::Observer(other), + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + ~GroupNode() + { + destroy(); + } + + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } + + scene::Node &clone() const + { + return (new GroupNode(*this))->node(); + } + + void insert(scene::Node &child) + { + m_instances.insert(child); + } + + void erase(scene::Node &child) + { + m_instances.erase(child); + } + + scene::Instance *create(const scene::Path &path, scene::Instance *parent) + { + return new GroupInstance(path, parent, m_contained); + } + + void forEachInstance(const scene::Instantiable::Visitor &visitor) + { + m_instances.forEachInstance(visitor); + } + + void insert(scene::Instantiable::Observer *observer, const scene::Path &path, scene::Instance *instance) + { + m_instances.insert(observer, path, instance); + } + + scene::Instance *erase(scene::Instantiable::Observer *observer, const scene::Path &path) + { + return m_instances.erase(observer, path); + } }; -scene::Node& New_Group( EntityClass* eclass ){ - return ( new GroupNode( eclass ) )->node(); +scene::Node &New_Group(EntityClass *eclass) +{ + return (new GroupNode(eclass))->node(); } diff --git a/plugins/entity/group.h b/plugins/entity/group.h index 599b8c7a..c8c83539 100644 --- a/plugins/entity/group.h +++ b/plugins/entity/group.h @@ -22,6 +22,6 @@ #if !defined( INCLUDED_GROUP_H ) #define INCLUDED_GROUP_H -scene::Node& New_Group( EntityClass* eclass ); +scene::Node &New_Group(EntityClass *eclass); #endif diff --git a/plugins/entity/keyobservers.h b/plugins/entity/keyobservers.h index b57a0e32..78597358 100644 --- a/plugins/entity/keyobservers.h +++ b/plugins/entity/keyobservers.h @@ -25,26 +25,30 @@ #include "entitylib.h" #include -class KeyObserverMap : public Entity::Observer -{ -typedef std::multimap KeyObservers; -KeyObservers m_keyObservers; +class KeyObserverMap : public Entity::Observer { + typedef std::multimap KeyObservers; + KeyObservers m_keyObservers; public: -void insert( const char* key, const KeyObserver& observer ){ - m_keyObservers.insert( KeyObservers::value_type( key, observer ) ); -} -void insert( const char* key, EntityKeyValue& value ){ - for ( KeyObservers::const_iterator i = m_keyObservers.find( key ); i != m_keyObservers.end() && string_equal( ( *i ).first, key ); ++i ) - { - value.attach( ( *i ).second ); - } -} -void erase( const char* key, EntityKeyValue& value ){ - for ( KeyObservers::const_iterator i = m_keyObservers.find( key ); i != m_keyObservers.end() && string_equal( ( *i ).first, key ); ++i ) - { - value.detach( ( *i ).second ); - } -} + void insert(const char *key, const KeyObserver &observer) + { + m_keyObservers.insert(KeyObservers::value_type(key, observer)); + } + + void insert(const char *key, EntityKeyValue &value) + { + for (KeyObservers::const_iterator i = m_keyObservers.find(key); + i != m_keyObservers.end() && string_equal((*i).first, key); ++i) { + value.attach((*i).second); + } + } + + void erase(const char *key, EntityKeyValue &value) + { + for (KeyObservers::const_iterator i = m_keyObservers.find(key); + i != m_keyObservers.end() && string_equal((*i).first, key); ++i) { + value.detach((*i).second); + } + } }; #endif diff --git a/plugins/entity/light.cpp b/plugins/entity/light.cpp index 9d8b9247..5b1a4055 100644 --- a/plugins/entity/light.cpp +++ b/plugins/entity/light.cpp @@ -64,318 +64,318 @@ #include "rotation.h" #include "entity.h" + extern bool g_newLightDraw; -void sphere_draw_fill( const Vector3& origin, float radius, int sides ){ - if ( radius <= 0 ) { - return; - } +void sphere_draw_fill(const Vector3 &origin, float radius, int sides) +{ + if (radius <= 0) { + return; + } + + const double dt = c_2pi / static_cast( sides ); + const double dp = c_pi / static_cast( sides ); + + glBegin(GL_TRIANGLES); + for (int i = 0; i <= sides - 1; ++i) { + for (int j = 0; j <= sides - 2; ++j) { + const double t = i * dt; + const double p = (j * dp) - (c_pi / 2.0); + + { + Vector3 v(vector3_added(origin, vector3_scaled(vector3_for_spherical(t, p), radius))); + glVertex3fv(vector3_to_array(v)); + } + + { + Vector3 v(vector3_added(origin, vector3_scaled(vector3_for_spherical(t, p + dp), radius))); + glVertex3fv(vector3_to_array(v)); + } + + { + Vector3 v(vector3_added(origin, vector3_scaled(vector3_for_spherical(t + dt, p + dp), radius))); + glVertex3fv(vector3_to_array(v)); + } + + { + Vector3 v(vector3_added(origin, vector3_scaled(vector3_for_spherical(t, p), radius))); + glVertex3fv(vector3_to_array(v)); + } + + { + Vector3 v(vector3_added(origin, vector3_scaled(vector3_for_spherical(t + dt, p + dp), radius))); + glVertex3fv(vector3_to_array(v)); + } + + { + Vector3 v(vector3_added(origin, vector3_scaled(vector3_for_spherical(t + dt, p), radius))); + glVertex3fv(vector3_to_array(v)); + } + } + } + + { + const double p = (sides - 1) * dp - (c_pi / 2.0); + for (int i = 0; i <= sides - 1; ++i) { + const double t = i * dt; + + { + Vector3 v(vector3_added(origin, vector3_scaled(vector3_for_spherical(t, p), radius))); + glVertex3fv(vector3_to_array(v)); + } + + { + Vector3 v(vector3_added(origin, vector3_scaled(vector3_for_spherical(t + dt, p + dp), radius))); + glVertex3fv(vector3_to_array(v)); + } + + { + Vector3 v(vector3_added(origin, vector3_scaled(vector3_for_spherical(t + dt, p), radius))); + glVertex3fv(vector3_to_array(v)); + } + } + } + glEnd(); +} + +void sphere_draw_wire(const Vector3 &origin, float radius, int sides) +{ + { + glBegin(GL_LINE_LOOP); - const double dt = c_2pi / static_cast( sides ); - const double dp = c_pi / static_cast( sides ); + for (int i = 0; i <= sides; i++) { + double ds = sin((i * 2 * c_pi) / sides); + double dc = cos((i * 2 * c_pi) / sides); - glBegin( GL_TRIANGLES ); - for ( int i = 0; i <= sides - 1; ++i ) - { - for ( int j = 0; j <= sides - 2; ++j ) - { - const double t = i * dt; - const double p = ( j * dp ) - ( c_pi / 2.0 ); - - { - Vector3 v( vector3_added( origin, vector3_scaled( vector3_for_spherical( t, p ), radius ) ) ); - glVertex3fv( vector3_to_array( v ) ); - } - - { - Vector3 v( vector3_added( origin, vector3_scaled( vector3_for_spherical( t, p + dp ), radius ) ) ); - glVertex3fv( vector3_to_array( v ) ); - } - - { - Vector3 v( vector3_added( origin, vector3_scaled( vector3_for_spherical( t + dt, p + dp ), radius ) ) ); - glVertex3fv( vector3_to_array( v ) ); - } - - { - Vector3 v( vector3_added( origin, vector3_scaled( vector3_for_spherical( t, p ), radius ) ) ); - glVertex3fv( vector3_to_array( v ) ); - } - - { - Vector3 v( vector3_added( origin, vector3_scaled( vector3_for_spherical( t + dt, p + dp ), radius ) ) ); - glVertex3fv( vector3_to_array( v ) ); - } - - { - Vector3 v( vector3_added( origin, vector3_scaled( vector3_for_spherical( t + dt, p ), radius ) ) ); - glVertex3fv( vector3_to_array( v ) ); - } - } - } + glVertex3f( + static_cast( origin[0] + radius * dc ), + static_cast( origin[1] + radius * ds ), + origin[2] + ); + } - { - const double p = ( sides - 1 ) * dp - ( c_pi / 2.0 ); - for ( int i = 0; i <= sides - 1; ++i ) - { - const double t = i * dt; - - { - Vector3 v( vector3_added( origin, vector3_scaled( vector3_for_spherical( t, p ), radius ) ) ); - glVertex3fv( vector3_to_array( v ) ); - } - - { - Vector3 v( vector3_added( origin, vector3_scaled( vector3_for_spherical( t + dt, p + dp ), radius ) ) ); - glVertex3fv( vector3_to_array( v ) ); - } - - { - Vector3 v( vector3_added( origin, vector3_scaled( vector3_for_spherical( t + dt, p ), radius ) ) ); - glVertex3fv( vector3_to_array( v ) ); - } - } - } - glEnd(); -} + glEnd(); + } -void sphere_draw_wire( const Vector3& origin, float radius, int sides ){ - { - glBegin( GL_LINE_LOOP ); + { + glBegin(GL_LINE_LOOP); - for ( int i = 0; i <= sides; i++ ) - { - double ds = sin( ( i * 2 * c_pi ) / sides ); - double dc = cos( ( i * 2 * c_pi ) / sides ); - - glVertex3f( - static_cast( origin[0] + radius * dc ), - static_cast( origin[1] + radius * ds ), - origin[2] - ); - } + for (int i = 0; i <= sides; i++) { + double ds = sin((i * 2 * c_pi) / sides); + double dc = cos((i * 2 * c_pi) / sides); - glEnd(); - } + glVertex3f( + static_cast( origin[0] + radius * dc ), + origin[1], + static_cast( origin[2] + radius * ds ) + ); + } - { - glBegin( GL_LINE_LOOP ); + glEnd(); + } - for ( int i = 0; i <= sides; i++ ) - { - double ds = sin( ( i * 2 * c_pi ) / sides ); - double dc = cos( ( i * 2 * c_pi ) / sides ); - - glVertex3f( - static_cast( origin[0] + radius * dc ), - origin[1], - static_cast( origin[2] + radius * ds ) - ); - } + { + glBegin(GL_LINE_LOOP); - glEnd(); - } + for (int i = 0; i <= sides; i++) { + double ds = sin((i * 2 * c_pi) / sides); + double dc = cos((i * 2 * c_pi) / sides); - { - glBegin( GL_LINE_LOOP ); + glVertex3f( + origin[0], + static_cast( origin[1] + radius * dc ), + static_cast( origin[2] + radius * ds ) + ); + } - for ( int i = 0; i <= sides; i++ ) - { - double ds = sin( ( i * 2 * c_pi ) / sides ); - double dc = cos( ( i * 2 * c_pi ) / sides ); - - glVertex3f( - origin[0], - static_cast( origin[1] + radius * dc ), - static_cast( origin[2] + radius * ds ) - ); - } - - glEnd(); - } + glEnd(); + } } -void light_draw_box_lines( const Vector3& origin, const Vector3 points[8] ){ - //draw lines from the center of the bbox to the corners - glBegin( GL_LINES ); - - glVertex3fv( vector3_to_array( origin ) ); - glVertex3fv( vector3_to_array( points[1] ) ); +void light_draw_box_lines(const Vector3 &origin, const Vector3 points[8]) +{ + //draw lines from the center of the bbox to the corners + glBegin(GL_LINES); - glVertex3fv( vector3_to_array( origin ) ); - glVertex3fv( vector3_to_array( points[5] ) ); + glVertex3fv(vector3_to_array(origin)); + glVertex3fv(vector3_to_array(points[1])); - glVertex3fv( vector3_to_array( origin ) ); - glVertex3fv( vector3_to_array( points[2] ) ); + glVertex3fv(vector3_to_array(origin)); + glVertex3fv(vector3_to_array(points[5])); - glVertex3fv( vector3_to_array( origin ) ); - glVertex3fv( vector3_to_array( points[6] ) ); + glVertex3fv(vector3_to_array(origin)); + glVertex3fv(vector3_to_array(points[2])); - glVertex3fv( vector3_to_array( origin ) ); - glVertex3fv( vector3_to_array( points[0] ) ); + glVertex3fv(vector3_to_array(origin)); + glVertex3fv(vector3_to_array(points[6])); - glVertex3fv( vector3_to_array( origin ) ); - glVertex3fv( vector3_to_array( points[4] ) ); + glVertex3fv(vector3_to_array(origin)); + glVertex3fv(vector3_to_array(points[0])); - glVertex3fv( vector3_to_array( origin ) ); - glVertex3fv( vector3_to_array( points[3] ) ); + glVertex3fv(vector3_to_array(origin)); + glVertex3fv(vector3_to_array(points[4])); - glVertex3fv( vector3_to_array( origin ) ); - glVertex3fv( vector3_to_array( points[7] ) ); + glVertex3fv(vector3_to_array(origin)); + glVertex3fv(vector3_to_array(points[3])); - glEnd(); -} + glVertex3fv(vector3_to_array(origin)); + glVertex3fv(vector3_to_array(points[7])); -void light_draw_radius_wire( const Vector3& origin, const float envelope[3] ){ - if ( envelope[0] > 0 ) { - sphere_draw_wire( origin, envelope[0], 24 ); - } - if ( envelope[1] > 0 ) { - sphere_draw_wire( origin, envelope[1], 24 ); - } - if ( envelope[2] > 0 ) { - sphere_draw_wire( origin, envelope[2], 24 ); - } + glEnd(); } -void light_draw_radius_fill( const Vector3& origin, const float envelope[3] ){ - if ( envelope[0] > 0 ) { - sphere_draw_fill( origin, envelope[0], 16 ); - } - if ( envelope[1] > 0 ) { - sphere_draw_fill( origin, envelope[1], 16 ); - } - if ( envelope[2] > 0 ) { - sphere_draw_fill( origin, envelope[2], 16 ); - } -} +void light_draw_radius_wire(const Vector3 &origin, const float envelope[3]) +{ + if (envelope[0] > 0) { + sphere_draw_wire(origin, envelope[0], 24); + } + if (envelope[1] > 0) { + sphere_draw_wire(origin, envelope[1], 24); + } + if (envelope[2] > 0) { + sphere_draw_wire(origin, envelope[2], 24); + } +} + +void light_draw_radius_fill(const Vector3 &origin, const float envelope[3]) +{ + if (envelope[0] > 0) { + sphere_draw_fill(origin, envelope[0], 16); + } + if (envelope[1] > 0) { + sphere_draw_fill(origin, envelope[1], 16); + } + if (envelope[2] > 0) { + sphere_draw_fill(origin, envelope[2], 16); + } +} + +void light_vertices(const AABB &aabb_light, Vector3 points[6]) +{ + Vector3 max(vector3_added(aabb_light.origin, aabb_light.extents)); + Vector3 min(vector3_subtracted(aabb_light.origin, aabb_light.extents)); + Vector3 mid(aabb_light.origin); -void light_vertices( const AABB& aabb_light, Vector3 points[6] ){ - Vector3 max( vector3_added( aabb_light.origin, aabb_light.extents ) ); - Vector3 min( vector3_subtracted( aabb_light.origin, aabb_light.extents ) ); - Vector3 mid( aabb_light.origin ); - - // top, bottom, middle-up, middle-right, middle-down, middle-left - points[0] = Vector3( mid[0], mid[1], max[2] ); - points[1] = Vector3( mid[0], mid[1], min[2] ); - points[2] = Vector3( mid[0], max[1], mid[2] ); - points[3] = Vector3( max[0], mid[1], mid[2] ); - points[4] = Vector3( mid[0], min[1], mid[2] ); - points[5] = Vector3( min[0], mid[1], mid[2] ); + // top, bottom, middle-up, middle-right, middle-down, middle-left + points[0] = Vector3(mid[0], mid[1], max[2]); + points[1] = Vector3(mid[0], mid[1], min[2]); + points[2] = Vector3(mid[0], max[1], mid[2]); + points[3] = Vector3(max[0], mid[1], mid[2]); + points[4] = Vector3(mid[0], min[1], mid[2]); + points[5] = Vector3(min[0], mid[1], mid[2]); } -void light_draw( const AABB& aabb_light, RenderStateFlags state ){ - Vector3 points[6]; - light_vertices( aabb_light, points ); - - if ( state & RENDER_LIGHTING ) { - const float f = 0.70710678f; - // North, East, South, West - const Vector3 normals[8] = { - Vector3( 0, f, f ), - Vector3( f, 0, f ), - Vector3( 0,-f, f ), - Vector3( -f, 0, f ), - Vector3( 0, f,-f ), - Vector3( f, 0,-f ), - Vector3( 0,-f,-f ), - Vector3( -f, 0,-f ), - }; +void light_draw(const AABB &aabb_light, RenderStateFlags state) +{ + Vector3 points[6]; + light_vertices(aabb_light, points); + + if (state & RENDER_LIGHTING) { + const float f = 0.70710678f; + // North, East, South, West + const Vector3 normals[8] = { + Vector3(0, f, f), + Vector3(f, 0, f), + Vector3(0, -f, f), + Vector3(-f, 0, f), + Vector3(0, f, -f), + Vector3(f, 0, -f), + Vector3(0, -f, -f), + Vector3(-f, 0, -f), + }; #if !defined( USE_TRIANGLE_FAN ) - glBegin( GL_TRIANGLES ); + glBegin(GL_TRIANGLES); #else - glBegin( GL_TRIANGLE_FAN ); + glBegin( GL_TRIANGLE_FAN ); #endif - glVertex3fv( vector3_to_array( points[0] ) ); - glVertex3fv( vector3_to_array( points[2] ) ); - glNormal3fv( vector3_to_array( normals[0] ) ); - glVertex3fv( vector3_to_array( points[3] ) ); + glVertex3fv(vector3_to_array(points[0])); + glVertex3fv(vector3_to_array(points[2])); + glNormal3fv(vector3_to_array(normals[0])); + glVertex3fv(vector3_to_array(points[3])); #if !defined( USE_TRIANGLE_FAN ) - glVertex3fv( vector3_to_array( points[0] ) ); - glVertex3fv( vector3_to_array( points[3] ) ); + glVertex3fv(vector3_to_array(points[0])); + glVertex3fv(vector3_to_array(points[3])); #endif - glNormal3fv( vector3_to_array( normals[1] ) ); - glVertex3fv( vector3_to_array( points[4] ) ); + glNormal3fv(vector3_to_array(normals[1])); + glVertex3fv(vector3_to_array(points[4])); #if !defined( USE_TRIANGLE_FAN ) - glVertex3fv( vector3_to_array( points[0] ) ); - glVertex3fv( vector3_to_array( points[4] ) ); + glVertex3fv(vector3_to_array(points[0])); + glVertex3fv(vector3_to_array(points[4])); #endif - glNormal3fv( vector3_to_array( normals[2] ) ); - glVertex3fv( vector3_to_array( points[5] ) ); + glNormal3fv(vector3_to_array(normals[2])); + glVertex3fv(vector3_to_array(points[5])); #if !defined( USE_TRIANGLE_FAN ) - glVertex3fv( vector3_to_array( points[0] ) ); - glVertex3fv( vector3_to_array( points[5] ) ); + glVertex3fv(vector3_to_array(points[0])); + glVertex3fv(vector3_to_array(points[5])); #endif - glNormal3fv( vector3_to_array( normals[3] ) ); - glVertex3fv( vector3_to_array( points[2] ) ); + glNormal3fv(vector3_to_array(normals[3])); + glVertex3fv(vector3_to_array(points[2])); #if defined( USE_TRIANGLE_FAN ) - glEnd(); + glEnd(); glBegin( GL_TRIANGLE_FAN ); #endif - glVertex3fv( vector3_to_array( points[1] ) ); - glVertex3fv( vector3_to_array( points[2] ) ); - glNormal3fv( vector3_to_array( normals[7] ) ); - glVertex3fv( vector3_to_array( points[5] ) ); + glVertex3fv(vector3_to_array(points[1])); + glVertex3fv(vector3_to_array(points[2])); + glNormal3fv(vector3_to_array(normals[7])); + glVertex3fv(vector3_to_array(points[5])); #if !defined( USE_TRIANGLE_FAN ) - glVertex3fv( vector3_to_array( points[1] ) ); - glVertex3fv( vector3_to_array( points[5] ) ); + glVertex3fv(vector3_to_array(points[1])); + glVertex3fv(vector3_to_array(points[5])); #endif - glNormal3fv( vector3_to_array( normals[6] ) ); - glVertex3fv( vector3_to_array( points[4] ) ); + glNormal3fv(vector3_to_array(normals[6])); + glVertex3fv(vector3_to_array(points[4])); #if !defined( USE_TRIANGLE_FAN ) - glVertex3fv( vector3_to_array( points[1] ) ); - glVertex3fv( vector3_to_array( points[4] ) ); + glVertex3fv(vector3_to_array(points[1])); + glVertex3fv(vector3_to_array(points[4])); #endif - glNormal3fv( vector3_to_array( normals[5] ) ); - glVertex3fv( vector3_to_array( points[3] ) ); + glNormal3fv(vector3_to_array(normals[5])); + glVertex3fv(vector3_to_array(points[3])); #if !defined( USE_TRIANGLE_FAN ) - glVertex3fv( vector3_to_array( points[1] ) ); - glVertex3fv( vector3_to_array( points[3] ) ); + glVertex3fv(vector3_to_array(points[1])); + glVertex3fv(vector3_to_array(points[3])); #endif - glNormal3fv( vector3_to_array( normals[4] ) ); - glVertex3fv( vector3_to_array( points[2] ) ); - - glEnd(); - } - else - { - typedef unsigned int index_t; - const index_t indices[24] = { - 0, 2, 3, - 0, 3, 4, - 0, 4, 5, - 0, 5, 2, - 1, 2, 5, - 1, 5, 4, - 1, 4, 3, - 1, 3, 2 - }; + glNormal3fv(vector3_to_array(normals[4])); + glVertex3fv(vector3_to_array(points[2])); + + glEnd(); + } else { + typedef unsigned int index_t; + const index_t indices[24] = { + 0, 2, 3, + 0, 3, 4, + 0, 4, 5, + 0, 5, 2, + 1, 2, 5, + 1, 5, 4, + 1, 4, 3, + 1, 3, 2 + }; #if 1 - glVertexPointer( 3, GL_FLOAT, 0, points ); - glDrawElements( GL_TRIANGLES, sizeof( indices ) / sizeof( index_t ), RenderIndexTypeID, indices ); + glVertexPointer(3, GL_FLOAT, 0, points); + glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(index_t), RenderIndexTypeID, indices); #else - glBegin( GL_TRIANGLES ); + glBegin( GL_TRIANGLES ); for ( unsigned int i = 0; i < sizeof( indices ) / sizeof( index_t ); ++i ) { glVertex3fv( points[indices[i]] ); } glEnd(); #endif - } + } - // NOTE: prolly not relevant until some time.. - // check for DOOM lights + // NOTE: prolly not relevant until some time.. + // check for DOOM lights #if 0 - if ( strlen( ValueForKey( e, "light_right" ) ) > 0 ) { + if ( strlen( ValueForKey( e, "light_right" ) ) > 0 ) { vec3_t vRight, vUp, vTarget, vTemp; GetVectorForKey( e, "light_right", vRight ); GetVectorForKey( e, "light_up", vUp ); @@ -415,894 +415,1024 @@ void light_draw( const AABB& aabb_light, RenderStateFlags state ){ float fPointScale = 7500.f; float fLinearScale = 1.f / 8000.f; -float light_radius_linear( float fIntensity, float fFalloffTolerance ){ - return ( ( fIntensity * fPointScale * fLinearScale ) - fFalloffTolerance ); +float light_radius_linear(float fIntensity, float fFalloffTolerance) +{ + return ((fIntensity * fPointScale * fLinearScale) - fFalloffTolerance); } -float light_radius( float fIntensity, float fFalloffTolerance ){ - return sqrt( fIntensity * fPointScale / fFalloffTolerance ); +float light_radius(float fIntensity, float fFalloffTolerance) +{ + return sqrt(fIntensity * fPointScale / fFalloffTolerance); } LightType g_lightType = LIGHTTYPE_DEFAULT; -bool spawnflags_linear( int flags ){ - if ( g_lightType == LIGHTTYPE_RTCW ) { - // Spawnflags : - // 1: nonlinear - // 2: angle +bool spawnflags_linear(int flags) +{ + if (g_lightType == LIGHTTYPE_RTCW) { + // Spawnflags : + // 1: nonlinear + // 2: angle - return !( flags & 1 ); - } - else - { - // Spawnflags : - // 1: linear - // 2: no angle + return !(flags & 1); + } else { + // Spawnflags : + // 1: linear + // 2: no angle - return ( flags & 1 ); - } + return (flags & 1); + } } -class LightRadii -{ +class LightRadii { public: -float m_radii[3]; + float m_radii[3]; private: -float m_primaryIntensity; -float m_secondaryIntensity; -int m_flags; -float m_fade; -float m_scale; - -void calculateRadii(){ - float intensity = 300.0f; - - if ( m_primaryIntensity != 0.0f ) { - intensity = m_primaryIntensity; - } - else if ( m_secondaryIntensity != 0.0f ) { - intensity = m_secondaryIntensity; - } - - intensity *= m_scale; - - if ( spawnflags_linear( m_flags ) ) { - m_radii[0] = light_radius_linear( intensity, 1.0f ) / m_fade; - m_radii[1] = light_radius_linear( intensity, 48.0f ) / m_fade; - m_radii[2] = light_radius_linear( intensity, 255.0f ) / m_fade; - } - else - { - m_radii[0] = light_radius( intensity, 1.0f ); - m_radii[1] = light_radius( intensity, 48.0f ); - m_radii[2] = light_radius( intensity, 255.0f ); - } -} + float m_primaryIntensity; + float m_secondaryIntensity; + int m_flags; + float m_fade; + float m_scale; + + void calculateRadii() + { + float intensity = 300.0f; + + if (m_primaryIntensity != 0.0f) { + intensity = m_primaryIntensity; + } else if (m_secondaryIntensity != 0.0f) { + intensity = m_secondaryIntensity; + } + + intensity *= m_scale; + + if (spawnflags_linear(m_flags)) { + m_radii[0] = light_radius_linear(intensity, 1.0f) / m_fade; + m_radii[1] = light_radius_linear(intensity, 48.0f) / m_fade; + m_radii[2] = light_radius_linear(intensity, 255.0f) / m_fade; + } else { + m_radii[0] = light_radius(intensity, 1.0f); + m_radii[1] = light_radius(intensity, 48.0f); + m_radii[2] = light_radius(intensity, 255.0f); + } + } public: -LightRadii() : m_primaryIntensity( 0 ), m_secondaryIntensity( 0 ), m_flags( 0 ), m_fade( 1 ), m_scale( 1 ){ -} - - -void primaryIntensityChanged( const char* value ){ - m_primaryIntensity = string_read_float( value ); - calculateRadii(); -} -typedef MemberCaller PrimaryIntensityChangedCaller; -void secondaryIntensityChanged( const char* value ){ - m_secondaryIntensity = string_read_float( value ); - calculateRadii(); -} -typedef MemberCaller SecondaryIntensityChangedCaller; -void scaleChanged( const char* value ){ - m_scale = string_read_float( value ); - if ( m_scale <= 0.0f ) { - m_scale = 1.0f; - } - calculateRadii(); -} -typedef MemberCaller ScaleChangedCaller; -void fadeChanged( const char* value ){ - m_fade = string_read_float( value ); - if ( m_fade <= 0.0f ) { - m_fade = 1.0f; - } - calculateRadii(); -} -typedef MemberCaller FadeChangedCaller; -void flagsChanged( const char* value ){ - m_flags = string_read_int( value ); - calculateRadii(); -} -typedef MemberCaller FlagsChangedCaller; + LightRadii() : m_primaryIntensity(0), m_secondaryIntensity(0), m_flags(0), m_fade(1), m_scale(1) + { + } + + + void primaryIntensityChanged(const char *value) + { + m_primaryIntensity = string_read_float(value); + calculateRadii(); + } + + typedef MemberCaller PrimaryIntensityChangedCaller; + + void secondaryIntensityChanged(const char *value) + { + m_secondaryIntensity = string_read_float(value); + calculateRadii(); + } + + typedef MemberCaller SecondaryIntensityChangedCaller; + + void scaleChanged(const char *value) + { + m_scale = string_read_float(value); + if (m_scale <= 0.0f) { + m_scale = 1.0f; + } + calculateRadii(); + } + + typedef MemberCaller ScaleChangedCaller; + + void fadeChanged(const char *value) + { + m_fade = string_read_float(value); + if (m_fade <= 0.0f) { + m_fade = 1.0f; + } + calculateRadii(); + } + + typedef MemberCaller FadeChangedCaller; + + void flagsChanged(const char *value) + { + m_flags = string_read_int(value); + calculateRadii(); + } + + typedef MemberCaller FlagsChangedCaller; }; -class Doom3LightRadius -{ +class Doom3LightRadius { public: -Vector3 m_defaultRadius; -Vector3 m_radius; -Vector3 m_radiusTransformed; -Vector3 m_center; -Callback m_changed; -bool m_useCenterKey; - -Doom3LightRadius( const char* defaultRadius ) : m_defaultRadius( 300, 300, 300 ), m_center( 0, 0, 0 ), m_useCenterKey( false ){ - if ( !string_parse_vector3( defaultRadius, m_defaultRadius ) ) { - globalErrorStream() << "Doom3LightRadius: failed to parse default light radius\n"; - } - m_radius = m_defaultRadius; -} - -void lightRadiusChanged( const char* value ){ - if ( !string_parse_vector3( value, m_radius ) ) { - m_radius = m_defaultRadius; - } - m_radiusTransformed = m_radius; - m_changed(); - SceneChangeNotify(); -} -typedef MemberCaller LightRadiusChangedCaller; - -void lightCenterChanged( const char* value ){ - m_useCenterKey = string_parse_vector3( value, m_center ); - if ( !m_useCenterKey ) { - m_center = Vector3( 0, 0, 0 ); - } - SceneChangeNotify(); -} -typedef MemberCaller LightCenterChangedCaller; + Vector3 m_defaultRadius; + Vector3 m_radius; + Vector3 m_radiusTransformed; + Vector3 m_center; + Callback m_changed; + bool m_useCenterKey; + + Doom3LightRadius(const char *defaultRadius) : m_defaultRadius(300, 300, 300), m_center(0, 0, 0), + m_useCenterKey(false) + { + if (!string_parse_vector3(defaultRadius, m_defaultRadius)) { + globalErrorStream() << "Doom3LightRadius: failed to parse default light radius\n"; + } + m_radius = m_defaultRadius; + } + + void lightRadiusChanged(const char *value) + { + if (!string_parse_vector3(value, m_radius)) { + m_radius = m_defaultRadius; + } + m_radiusTransformed = m_radius; + m_changed(); + SceneChangeNotify(); + } + + typedef MemberCaller LightRadiusChangedCaller; + + void lightCenterChanged(const char *value) + { + m_useCenterKey = string_parse_vector3(value, m_center); + if (!m_useCenterKey) { + m_center = Vector3(0, 0, 0); + } + SceneChangeNotify(); + } + + typedef MemberCaller LightCenterChangedCaller; }; -class RenderLightRadiiWire : public OpenGLRenderable -{ -LightRadii& m_radii; -const Vector3& m_origin; +class RenderLightRadiiWire : public OpenGLRenderable { + LightRadii &m_radii; + const Vector3 &m_origin; public: -RenderLightRadiiWire( LightRadii& radii, const Vector3& origin ) : m_radii( radii ), m_origin( origin ){ -} -void render( RenderStateFlags state ) const { - light_draw_radius_wire( m_origin, m_radii.m_radii ); -} + RenderLightRadiiWire(LightRadii &radii, const Vector3 &origin) : m_radii(radii), m_origin(origin) + { + } + + void render(RenderStateFlags state) const + { + light_draw_radius_wire(m_origin, m_radii.m_radii); + } }; -class RenderLightRadiiFill : public OpenGLRenderable -{ -LightRadii& m_radii; -const Vector3& m_origin; +class RenderLightRadiiFill : public OpenGLRenderable { + LightRadii &m_radii; + const Vector3 &m_origin; public: -static Shader* m_state; + static Shader *m_state; -RenderLightRadiiFill( LightRadii& radii, const Vector3& origin ) : m_radii( radii ), m_origin( origin ){ -} -void render( RenderStateFlags state ) const { - light_draw_radius_fill( m_origin, m_radii.m_radii ); -} + RenderLightRadiiFill(LightRadii &radii, const Vector3 &origin) : m_radii(radii), m_origin(origin) + { + } + + void render(RenderStateFlags state) const + { + light_draw_radius_fill(m_origin, m_radii.m_radii); + } }; -class RenderLightRadiiBox : public OpenGLRenderable -{ -const Vector3& m_origin; +class RenderLightRadiiBox : public OpenGLRenderable { + const Vector3 &m_origin; public: -mutable Vector3 m_points[8]; -static Shader* m_state; - -RenderLightRadiiBox( const Vector3& origin ) : m_origin( origin ){ -} -void render( RenderStateFlags state ) const { - //draw the bounding box of light based on light_radius key - if ( ( state & RENDER_FILL ) != 0 ) { - aabb_draw_flatshade( m_points ); - } - else - { - aabb_draw_wire( m_points ); - } - - #if 1 //disable if you dont want lines going from the center of the light bbox to the corners - light_draw_box_lines( m_origin, m_points ); - #endif -} + mutable Vector3 m_points[8]; + static Shader *m_state; + + RenderLightRadiiBox(const Vector3 &origin) : m_origin(origin) + { + } + + void render(RenderStateFlags state) const + { + //draw the bounding box of light based on light_radius key + if ((state & RENDER_FILL) != 0) { + aabb_draw_flatshade(m_points); + } else { + aabb_draw_wire(m_points); + } + +#if 1 //disable if you dont want lines going from the center of the light bbox to the corners + light_draw_box_lines(m_origin, m_points); +#endif + } }; -Shader* RenderLightRadiiFill::m_state = 0; +Shader *RenderLightRadiiFill::m_state = 0; -class RenderLightCenter : public OpenGLRenderable -{ -const Vector3& m_center; -EntityClass& m_eclass; +class RenderLightCenter : public OpenGLRenderable { + const Vector3 &m_center; + EntityClass &m_eclass; public: -static Shader* m_state; - -RenderLightCenter( const Vector3& center, EntityClass& eclass ) : m_center( center ), m_eclass( eclass ){ -} -void render( RenderStateFlags state ) const { - glBegin( GL_POINTS ); - glColor3fv( vector3_to_array( m_eclass.color ) ); - glVertex3fv( vector3_to_array( m_center ) ); - glEnd(); -} + static Shader *m_state; + + RenderLightCenter(const Vector3 ¢er, EntityClass &eclass) : m_center(center), m_eclass(eclass) + { + } + + void render(RenderStateFlags state) const + { + glBegin(GL_POINTS); + glColor3fv(vector3_to_array(m_eclass.color)); + glVertex3fv(vector3_to_array(m_center)); + glEnd(); + } }; -Shader* RenderLightCenter::m_state = 0; +Shader *RenderLightCenter::m_state = 0; -class RenderLightProjection : public OpenGLRenderable -{ -const Matrix4& m_projection; +class RenderLightProjection : public OpenGLRenderable { + const Matrix4 &m_projection; public: -RenderLightProjection( const Matrix4& projection ) : m_projection( projection ){ -} -void render( RenderStateFlags state ) const { - Matrix4 unproject( matrix4_full_inverse( m_projection ) ); - Vector3 points[8]; - aabb_corners( AABB( Vector3( 0.5f, 0.5f, 0.5f ), Vector3( 0.5f, 0.5f, 0.5f ) ), points ); - points[0] = vector4_projected( matrix4_transformed_vector4( unproject, Vector4( points[0], 1 ) ) ); - points[1] = vector4_projected( matrix4_transformed_vector4( unproject, Vector4( points[1], 1 ) ) ); - points[2] = vector4_projected( matrix4_transformed_vector4( unproject, Vector4( points[2], 1 ) ) ); - points[3] = vector4_projected( matrix4_transformed_vector4( unproject, Vector4( points[3], 1 ) ) ); - points[4] = vector4_projected( matrix4_transformed_vector4( unproject, Vector4( points[4], 1 ) ) ); - points[5] = vector4_projected( matrix4_transformed_vector4( unproject, Vector4( points[5], 1 ) ) ); - points[6] = vector4_projected( matrix4_transformed_vector4( unproject, Vector4( points[6], 1 ) ) ); - points[7] = vector4_projected( matrix4_transformed_vector4( unproject, Vector4( points[7], 1 ) ) ); + RenderLightProjection(const Matrix4 &projection) : m_projection(projection) + { + } + + void render(RenderStateFlags state) const + { + Matrix4 unproject(matrix4_full_inverse(m_projection)); + Vector3 points[8]; + aabb_corners(AABB(Vector3(0.5f, 0.5f, 0.5f), Vector3(0.5f, 0.5f, 0.5f)), points); + points[0] = vector4_projected(matrix4_transformed_vector4(unproject, Vector4(points[0], 1))); + points[1] = vector4_projected(matrix4_transformed_vector4(unproject, Vector4(points[1], 1))); + points[2] = vector4_projected(matrix4_transformed_vector4(unproject, Vector4(points[2], 1))); + points[3] = vector4_projected(matrix4_transformed_vector4(unproject, Vector4(points[3], 1))); + points[4] = vector4_projected(matrix4_transformed_vector4(unproject, Vector4(points[4], 1))); + points[5] = vector4_projected(matrix4_transformed_vector4(unproject, Vector4(points[5], 1))); + points[6] = vector4_projected(matrix4_transformed_vector4(unproject, Vector4(points[6], 1))); + points[7] = vector4_projected(matrix4_transformed_vector4(unproject, Vector4(points[7], 1))); // Vector4 test1 = matrix4_transformed_vector4( unproject, Vector4( 0.5f, 0.5f, 0.5f, 1 ) ); // Vector3 test2 = vector4_projected( test1 ); - aabb_draw_wire( points ); -} + aabb_draw_wire(points); + } }; -inline void default_extents( Vector3& extents ){ - extents = Vector3( 8, 8, 8 ); -} - -class ShaderRef +inline void default_extents(Vector3 &extents) { -CopiedString m_name; -Shader* m_shader; -void capture(){ - m_shader = GlobalShaderCache().capture( m_name.c_str() ); -} -void release(){ - GlobalShaderCache().release( m_name.c_str() ); + extents = Vector3(8, 8, 8); } + +class ShaderRef { + CopiedString m_name; + Shader *m_shader; + + void capture() + { + m_shader = GlobalShaderCache().capture(m_name.c_str()); + } + + void release() + { + GlobalShaderCache().release(m_name.c_str()); + } + public: -ShaderRef(){ - capture(); -} -~ShaderRef(){ - release(); -} -void setName( const char* name ){ - release(); - m_name = name; - capture(); -} -Shader* get() const { - return m_shader; -} + ShaderRef() + { + capture(); + } + + ~ShaderRef() + { + release(); + } + + void setName(const char *name) + { + release(); + m_name = name; + capture(); + } + + Shader *get() const + { + return m_shader; + } }; -class LightShader -{ -ShaderRef m_shader; -void setDefault(){ - m_shader.setName( m_defaultShader ); -} -public: -static const char* m_defaultShader; +class LightShader { + ShaderRef m_shader; -LightShader(){ - setDefault(); -} -void valueChanged( const char* value ){ - if ( string_empty( value ) ) { - setDefault(); - } - else - { - m_shader.setName( value ); - } - SceneChangeNotify(); -} -typedef MemberCaller ValueChangedCaller; + void setDefault() + { + m_shader.setName(m_defaultShader); + } -Shader* get() const { - return m_shader.get(); -} +public: + static const char *m_defaultShader; + + LightShader() + { + setDefault(); + } + + void valueChanged(const char *value) + { + if (string_empty(value)) { + setDefault(); + } else { + m_shader.setName(value); + } + SceneChangeNotify(); + } + + typedef MemberCaller ValueChangedCaller; + + Shader *get() const + { + return m_shader.get(); + } }; -const char* LightShader::m_defaultShader = ""; +const char *LightShader::m_defaultShader = ""; -inline const BasicVector4& plane3_to_vector4( const Plane3& self ){ - return reinterpret_cast&>( self ); +inline const BasicVector4 &plane3_to_vector4(const Plane3 &self) +{ + return reinterpret_cast &>( self ); } -inline BasicVector4& plane3_to_vector4( Plane3& self ){ - return reinterpret_cast&>( self ); +inline BasicVector4 &plane3_to_vector4(Plane3 &self) +{ + return reinterpret_cast &>( self ); } -inline Matrix4 matrix4_from_planes( const Plane3& left, const Plane3& right, const Plane3& bottom, const Plane3& top, const Plane3& front, const Plane3& back ){ - return Matrix4( - ( right.a - left.a ) / 2, - ( top.a - bottom.a ) / 2, - ( back.a - front.a ) / 2, - right.a - ( right.a - left.a ) / 2, - ( right.b - left.b ) / 2, - ( top.b - bottom.b ) / 2, - ( back.b - front.b ) / 2, - right.b - ( right.b - left.b ) / 2, - ( right.c - left.c ) / 2, - ( top.c - bottom.c ) / 2, - ( back.c - front.c ) / 2, - right.c - ( right.c - left.c ) / 2, - ( right.d - left.d ) / 2, - ( top.d - bottom.d ) / 2, - ( back.d - front.d ) / 2, - right.d - ( right.d - left.d ) / 2 - ); +inline Matrix4 matrix4_from_planes(const Plane3 &left, const Plane3 &right, const Plane3 &bottom, const Plane3 &top, + const Plane3 &front, const Plane3 &back) +{ + return Matrix4( + (right.a - left.a) / 2, + (top.a - bottom.a) / 2, + (back.a - front.a) / 2, + right.a - (right.a - left.a) / 2, + (right.b - left.b) / 2, + (top.b - bottom.b) / 2, + (back.b - front.b) / 2, + right.b - (right.b - left.b) / 2, + (right.c - left.c) / 2, + (top.c - bottom.c) / 2, + (back.c - front.c) / 2, + right.c - (right.c - left.c) / 2, + (right.d - left.d) / 2, + (top.d - bottom.d) / 2, + (back.d - front.d) / 2, + right.d - (right.d - left.d) / 2 + ); } class Light : - public OpenGLRenderable, - public Cullable, - public Bounded, - public Editable, - public Snappable -{ -EntityKeyValues m_entity; -KeyObserverMap m_keyObservers; -TraversableNodeSet m_traverse; -IdentityTransform m_transform; - -OriginKey m_originKey; -RotationKey m_rotationKey; -Float9 m_rotation; -Colour m_colour; - -ClassnameFilter m_filter; -NamedEntity m_named; -NameKeys m_nameKeys; -TraversableObserverPairRelay m_traverseObservers; -Doom3GroupOrigin m_funcStaticOrigin; - -LightRadii m_radii; -Doom3LightRadius m_doom3Radius; - -RenderLightRadiiWire m_radii_wire; -RenderLightRadiiFill m_radii_fill; -RenderLightRadiiBox m_radii_box; -RenderLightCenter m_render_center; -RenderableNamedEntity m_renderName; - -Vector3 m_lightOrigin; -bool m_useLightOrigin; -Float9 m_lightRotation; -bool m_useLightRotation; - -Vector3 m_lightTarget; -bool m_useLightTarget; -Vector3 m_lightUp; -bool m_useLightUp; -Vector3 m_lightRight; -bool m_useLightRight; -Vector3 m_lightStart; -bool m_useLightStart; -Vector3 m_lightEnd; -bool m_useLightEnd; - -mutable AABB m_doom3AABB; -mutable Matrix4 m_doom3Rotation; -mutable Matrix4 m_doom3Projection; -mutable Frustum m_doom3Frustum; -mutable bool m_doom3ProjectionChanged; - -RenderLightProjection m_renderProjection; - -LightShader m_shader; - -AABB m_aabb_light; - -Callback m_transformChanged; -Callback m_boundsChanged; -Callback m_evaluateTransform; - -void construct(){ - default_rotation( m_rotation ); - m_aabb_light.origin = Vector3( 0, 0, 0 ); - default_extents( m_aabb_light.extents ); - - m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) ); - m_keyObservers.insert( Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) ); - m_keyObservers.insert( "_color", Colour::ColourChangedCaller( m_colour ) ); - m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) ); - m_keyObservers.insert( "_light", LightRadii::PrimaryIntensityChangedCaller( m_radii ) ); - m_keyObservers.insert( "light", LightRadii::SecondaryIntensityChangedCaller( m_radii ) ); - m_keyObservers.insert( "fade", LightRadii::FadeChangedCaller( m_radii ) ); - m_keyObservers.insert( "scale", LightRadii::ScaleChangedCaller( m_radii ) ); - m_keyObservers.insert( "spawnflags", LightRadii::FlagsChangedCaller( m_radii ) ); - - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_keyObservers.insert( "angle", RotationKey::AngleChangedCaller( m_rotationKey ) ); - m_keyObservers.insert( "rotation", RotationKey::RotationChangedCaller( m_rotationKey ) ); - m_keyObservers.insert( "light_radius", Doom3LightRadius::LightRadiusChangedCaller( m_doom3Radius ) ); - m_keyObservers.insert( "light_center", Doom3LightRadius::LightCenterChangedCaller( m_doom3Radius ) ); - m_keyObservers.insert( "light_origin", Light::LightOriginChangedCaller( *this ) ); - m_keyObservers.insert( "light_rotation", Light::LightRotationChangedCaller( *this ) ); - m_keyObservers.insert( "light_target", Light::LightTargetChangedCaller( *this ) ); - m_keyObservers.insert( "light_up", Light::LightUpChangedCaller( *this ) ); - m_keyObservers.insert( "light_right", Light::LightRightChangedCaller( *this ) ); - m_keyObservers.insert( "light_start", Light::LightStartChangedCaller( *this ) ); - m_keyObservers.insert( "light_end", Light::LightEndChangedCaller( *this ) ); - m_keyObservers.insert( "texture", LightShader::ValueChangedCaller( m_shader ) ); - m_useLightTarget = m_useLightUp = m_useLightRight = m_useLightStart = m_useLightEnd = false; - m_doom3ProjectionChanged = true; - } - - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_traverse.attach( &m_traverseObservers ); - m_traverseObservers.attach( m_funcStaticOrigin ); - - m_entity.m_isContainer = true; - } -} -void destroy(){ - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_traverseObservers.detach( m_funcStaticOrigin ); - m_traverse.detach( &m_traverseObservers ); - } -} + public OpenGLRenderable, + public Cullable, + public Bounded, + public Editable, + public Snappable { + EntityKeyValues m_entity; + KeyObserverMap m_keyObservers; + TraversableNodeSet m_traverse; + IdentityTransform m_transform; + + OriginKey m_originKey; + RotationKey m_rotationKey; + Float9 m_rotation; + Colour m_colour; + + ClassnameFilter m_filter; + NamedEntity m_named; + NameKeys m_nameKeys; + TraversableObserverPairRelay m_traverseObservers; + Doom3GroupOrigin m_funcStaticOrigin; + + LightRadii m_radii; + Doom3LightRadius m_doom3Radius; + + RenderLightRadiiWire m_radii_wire; + RenderLightRadiiFill m_radii_fill; + RenderLightRadiiBox m_radii_box; + RenderLightCenter m_render_center; + RenderableNamedEntity m_renderName; + + Vector3 m_lightOrigin; + bool m_useLightOrigin; + Float9 m_lightRotation; + bool m_useLightRotation; + + Vector3 m_lightTarget; + bool m_useLightTarget; + Vector3 m_lightUp; + bool m_useLightUp; + Vector3 m_lightRight; + bool m_useLightRight; + Vector3 m_lightStart; + bool m_useLightStart; + Vector3 m_lightEnd; + bool m_useLightEnd; + + mutable AABB m_doom3AABB; + mutable Matrix4 m_doom3Rotation; + mutable Matrix4 m_doom3Projection; + mutable Frustum m_doom3Frustum; + mutable bool m_doom3ProjectionChanged; + + RenderLightProjection m_renderProjection; + + LightShader m_shader; + + AABB m_aabb_light; + + Callback m_transformChanged; + Callback m_boundsChanged; + Callback m_evaluateTransform; + + void construct() + { + default_rotation(m_rotation); + m_aabb_light.origin = Vector3(0, 0, 0); + default_extents(m_aabb_light.extents); + + m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter)); + m_keyObservers.insert(Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named)); + m_keyObservers.insert("_color", Colour::ColourChangedCaller(m_colour)); + m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey)); + m_keyObservers.insert("_light", LightRadii::PrimaryIntensityChangedCaller(m_radii)); + m_keyObservers.insert("light", LightRadii::SecondaryIntensityChangedCaller(m_radii)); + m_keyObservers.insert("fade", LightRadii::FadeChangedCaller(m_radii)); + m_keyObservers.insert("scale", LightRadii::ScaleChangedCaller(m_radii)); + m_keyObservers.insert("spawnflags", LightRadii::FlagsChangedCaller(m_radii)); + + if (g_lightType == LIGHTTYPE_DOOM3) { + m_keyObservers.insert("angle", RotationKey::AngleChangedCaller(m_rotationKey)); + m_keyObservers.insert("rotation", RotationKey::RotationChangedCaller(m_rotationKey)); + m_keyObservers.insert("light_radius", Doom3LightRadius::LightRadiusChangedCaller(m_doom3Radius)); + m_keyObservers.insert("light_center", Doom3LightRadius::LightCenterChangedCaller(m_doom3Radius)); + m_keyObservers.insert("light_origin", Light::LightOriginChangedCaller(*this)); + m_keyObservers.insert("light_rotation", Light::LightRotationChangedCaller(*this)); + m_keyObservers.insert("light_target", Light::LightTargetChangedCaller(*this)); + m_keyObservers.insert("light_up", Light::LightUpChangedCaller(*this)); + m_keyObservers.insert("light_right", Light::LightRightChangedCaller(*this)); + m_keyObservers.insert("light_start", Light::LightStartChangedCaller(*this)); + m_keyObservers.insert("light_end", Light::LightEndChangedCaller(*this)); + m_keyObservers.insert("texture", LightShader::ValueChangedCaller(m_shader)); + m_useLightTarget = m_useLightUp = m_useLightRight = m_useLightStart = m_useLightEnd = false; + m_doom3ProjectionChanged = true; + } + + if (g_lightType == LIGHTTYPE_DOOM3) { + m_traverse.attach(&m_traverseObservers); + m_traverseObservers.attach(m_funcStaticOrigin); + + m_entity.m_isContainer = true; + } + } + + void destroy() + { + if (g_lightType == LIGHTTYPE_DOOM3) { + m_traverseObservers.detach(m_funcStaticOrigin); + m_traverse.detach(&m_traverseObservers); + } + } // vc 2k5 compiler fix #if _MSC_VER >= 1400 -public: + public: #endif -void updateOrigin(){ - m_boundsChanged(); - - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_funcStaticOrigin.originChanged(); - } - - m_doom3Radius.m_changed(); - - GlobalSelectionSystem().pivotChanged(); -} - -void originChanged(){ - m_aabb_light.origin = m_useLightOrigin ? m_lightOrigin : m_originKey.m_origin; - updateOrigin(); -} -typedef MemberCaller OriginChangedCaller; - -void lightOriginChanged( const char* value ){ - m_useLightOrigin = !string_empty( value ); - if ( m_useLightOrigin ) { - read_origin( m_lightOrigin, value ); - } - originChanged(); -} -typedef MemberCaller LightOriginChangedCaller; - -void lightTargetChanged( const char* value ){ - m_useLightTarget = !string_empty( value ); - if ( m_useLightTarget ) { - read_origin( m_lightTarget, value ); - } - projectionChanged(); -} -typedef MemberCaller LightTargetChangedCaller; -void lightUpChanged( const char* value ){ - m_useLightUp = !string_empty( value ); - if ( m_useLightUp ) { - read_origin( m_lightUp, value ); - } - projectionChanged(); -} -typedef MemberCaller LightUpChangedCaller; -void lightRightChanged( const char* value ){ - m_useLightRight = !string_empty( value ); - if ( m_useLightRight ) { - read_origin( m_lightRight, value ); - } - projectionChanged(); -} -typedef MemberCaller LightRightChangedCaller; -void lightStartChanged( const char* value ){ - m_useLightStart = !string_empty( value ); - if ( m_useLightStart ) { - read_origin( m_lightStart, value ); - } - projectionChanged(); -} -typedef MemberCaller LightStartChangedCaller; -void lightEndChanged( const char* value ){ - m_useLightEnd = !string_empty( value ); - if ( m_useLightEnd ) { - read_origin( m_lightEnd, value ); - } - projectionChanged(); -} -typedef MemberCaller LightEndChangedCaller; - -void writeLightOrigin(){ - write_origin( m_lightOrigin, &m_entity, "light_origin" ); -} - -void updateLightRadiiBox() const { - const Matrix4& rotation = rotation_toMatrix( m_rotation ); - aabb_corners( AABB( Vector3( 0, 0, 0 ), m_doom3Radius.m_radiusTransformed ), m_radii_box.m_points ); - matrix4_transform_point( rotation, m_radii_box.m_points[0] ); - vector3_add( m_radii_box.m_points[0], m_aabb_light.origin ); - matrix4_transform_point( rotation, m_radii_box.m_points[1] ); - vector3_add( m_radii_box.m_points[1], m_aabb_light.origin ); - matrix4_transform_point( rotation, m_radii_box.m_points[2] ); - vector3_add( m_radii_box.m_points[2], m_aabb_light.origin ); - matrix4_transform_point( rotation, m_radii_box.m_points[3] ); - vector3_add( m_radii_box.m_points[3], m_aabb_light.origin ); - matrix4_transform_point( rotation, m_radii_box.m_points[4] ); - vector3_add( m_radii_box.m_points[4], m_aabb_light.origin ); - matrix4_transform_point( rotation, m_radii_box.m_points[5] ); - vector3_add( m_radii_box.m_points[5], m_aabb_light.origin ); - matrix4_transform_point( rotation, m_radii_box.m_points[6] ); - vector3_add( m_radii_box.m_points[6], m_aabb_light.origin ); - matrix4_transform_point( rotation, m_radii_box.m_points[7] ); - vector3_add( m_radii_box.m_points[7], m_aabb_light.origin ); -} - -void rotationChanged(){ - rotation_assign( m_rotation, m_useLightRotation ? m_lightRotation : m_rotationKey.m_rotation ); - GlobalSelectionSystem().pivotChanged(); -} -typedef MemberCaller RotationChangedCaller; - -void lightRotationChanged( const char* value ){ - m_useLightRotation = !string_empty( value ); - if ( m_useLightRotation ) { - read_rotation( m_lightRotation, value ); - } - rotationChanged(); -} -typedef MemberCaller LightRotationChangedCaller; + void updateOrigin() + { + m_boundsChanged(); + + if (g_lightType == LIGHTTYPE_DOOM3) { + m_funcStaticOrigin.originChanged(); + } + + m_doom3Radius.m_changed(); + + GlobalSelectionSystem().pivotChanged(); + } + + void originChanged() + { + m_aabb_light.origin = m_useLightOrigin ? m_lightOrigin : m_originKey.m_origin; + updateOrigin(); + } + + typedef MemberCaller OriginChangedCaller; + + void lightOriginChanged(const char *value) + { + m_useLightOrigin = !string_empty(value); + if (m_useLightOrigin) { + read_origin(m_lightOrigin, value); + } + originChanged(); + } + + typedef MemberCaller LightOriginChangedCaller; + + void lightTargetChanged(const char *value) + { + m_useLightTarget = !string_empty(value); + if (m_useLightTarget) { + read_origin(m_lightTarget, value); + } + projectionChanged(); + } + + typedef MemberCaller LightTargetChangedCaller; + + void lightUpChanged(const char *value) + { + m_useLightUp = !string_empty(value); + if (m_useLightUp) { + read_origin(m_lightUp, value); + } + projectionChanged(); + } + + typedef MemberCaller LightUpChangedCaller; + + void lightRightChanged(const char *value) + { + m_useLightRight = !string_empty(value); + if (m_useLightRight) { + read_origin(m_lightRight, value); + } + projectionChanged(); + } + + typedef MemberCaller LightRightChangedCaller; + + void lightStartChanged(const char *value) + { + m_useLightStart = !string_empty(value); + if (m_useLightStart) { + read_origin(m_lightStart, value); + } + projectionChanged(); + } + + typedef MemberCaller LightStartChangedCaller; + + void lightEndChanged(const char *value) + { + m_useLightEnd = !string_empty(value); + if (m_useLightEnd) { + read_origin(m_lightEnd, value); + } + projectionChanged(); + } + + typedef MemberCaller LightEndChangedCaller; + + void writeLightOrigin() + { + write_origin(m_lightOrigin, &m_entity, "light_origin"); + } + + void updateLightRadiiBox() const + { + const Matrix4 &rotation = rotation_toMatrix(m_rotation); + aabb_corners(AABB(Vector3(0, 0, 0), m_doom3Radius.m_radiusTransformed), m_radii_box.m_points); + matrix4_transform_point(rotation, m_radii_box.m_points[0]); + vector3_add(m_radii_box.m_points[0], m_aabb_light.origin); + matrix4_transform_point(rotation, m_radii_box.m_points[1]); + vector3_add(m_radii_box.m_points[1], m_aabb_light.origin); + matrix4_transform_point(rotation, m_radii_box.m_points[2]); + vector3_add(m_radii_box.m_points[2], m_aabb_light.origin); + matrix4_transform_point(rotation, m_radii_box.m_points[3]); + vector3_add(m_radii_box.m_points[3], m_aabb_light.origin); + matrix4_transform_point(rotation, m_radii_box.m_points[4]); + vector3_add(m_radii_box.m_points[4], m_aabb_light.origin); + matrix4_transform_point(rotation, m_radii_box.m_points[5]); + vector3_add(m_radii_box.m_points[5], m_aabb_light.origin); + matrix4_transform_point(rotation, m_radii_box.m_points[6]); + vector3_add(m_radii_box.m_points[6], m_aabb_light.origin); + matrix4_transform_point(rotation, m_radii_box.m_points[7]); + vector3_add(m_radii_box.m_points[7], m_aabb_light.origin); + } + + void rotationChanged() + { + rotation_assign(m_rotation, m_useLightRotation ? m_lightRotation : m_rotationKey.m_rotation); + GlobalSelectionSystem().pivotChanged(); + } + + typedef MemberCaller RotationChangedCaller; + + void lightRotationChanged(const char *value) + { + m_useLightRotation = !string_empty(value); + if (m_useLightRotation) { + read_rotation(m_lightRotation, value); + } + rotationChanged(); + } + + typedef MemberCaller LightRotationChangedCaller; public: -Light( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& boundsChanged, const Callback& evaluateTransform ) : - m_entity( eclass ), - m_originKey( OriginChangedCaller( *this ) ), - m_rotationKey( RotationChangedCaller( *this ) ), - m_colour( Callback() ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_funcStaticOrigin( m_traverse, m_originKey.m_origin ), - m_doom3Radius( EntityClass_valueForKey( m_entity.getEntityClass(), "light_radius" ) ), - m_radii_wire( m_radii, m_aabb_light.origin ), - m_radii_fill( m_radii, m_aabb_light.origin ), - m_radii_box( m_aabb_light.origin ), - m_render_center( m_doom3Radius.m_center, m_entity.getEntityClass() ), - m_renderName( m_named, m_aabb_light.origin ), - m_useLightOrigin( false ), - m_useLightRotation( false ), - m_renderProjection( m_doom3Projection ), - m_transformChanged( transformChanged ), - m_boundsChanged( boundsChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} -Light( const Light& other, scene::Node& node, const Callback& transformChanged, const Callback& boundsChanged, const Callback& evaluateTransform ) : - m_entity( other.m_entity ), - m_originKey( OriginChangedCaller( *this ) ), - m_rotationKey( RotationChangedCaller( *this ) ), - m_colour( Callback() ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_funcStaticOrigin( m_traverse, m_originKey.m_origin ), - m_doom3Radius( EntityClass_valueForKey( m_entity.getEntityClass(), "light_radius" ) ), - m_radii_wire( m_radii, m_aabb_light.origin ), - m_radii_fill( m_radii, m_aabb_light.origin ), - m_radii_box( m_aabb_light.origin ), - m_render_center( m_doom3Radius.m_center, m_entity.getEntityClass() ), - m_renderName( m_named, m_aabb_light.origin ), - m_useLightOrigin( false ), - m_useLightRotation( false ), - m_renderProjection( m_doom3Projection ), - m_transformChanged( transformChanged ), - m_boundsChanged( boundsChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} -~Light(){ - destroy(); -} - -InstanceCounter m_instanceCounter; -void instanceAttach( const scene::Path& path ){ - if ( ++m_instanceCounter.m_count == 1 ) { - m_filter.instanceAttach(); - m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) ); - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_traverse.instanceAttach( path_find_mapfile( path.begin(), path.end() ) ); - } - m_entity.attach( m_keyObservers ); - - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_funcStaticOrigin.enable(); - } - } -} -void instanceDetach( const scene::Path& path ){ - if ( --m_instanceCounter.m_count == 0 ) { - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_funcStaticOrigin.disable(); - } - - m_entity.detach( m_keyObservers ); - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_traverse.instanceDetach( path_find_mapfile( path.begin(), path.end() ) ); - } - m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) ); - m_filter.instanceDetach(); - } -} - -EntityKeyValues& getEntity(){ - return m_entity; -} -const EntityKeyValues& getEntity() const { - return m_entity; -} - -scene::Traversable& getTraversable(){ - return m_traverse; -} -Namespaced& getNamespaced(){ - return m_nameKeys; -} -Nameable& getNameable(){ - return m_named; -} -TransformNode& getTransformNode(){ - return m_transform; -} - -void attach( scene::Traversable::Observer* observer ){ - m_traverseObservers.attach( *observer ); -} -void detach( scene::Traversable::Observer* observer ){ - m_traverseObservers.detach( *observer ); -} - -void render( RenderStateFlags state ) const { - if ( !g_newLightDraw ) { - aabb_draw( m_aabb_light, state ); - } - else - { - light_draw( m_aabb_light, state ); - } -} - -VolumeIntersectionValue intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) const { - return volume.TestAABB( m_aabb_light, localToWorld ); -} + Light(EntityClass *eclass, scene::Node &node, const Callback &transformChanged, + const Callback &boundsChanged, const Callback &evaluateTransform) : + m_entity(eclass), + m_originKey(OriginChangedCaller(*this)), + m_rotationKey(RotationChangedCaller(*this)), + m_colour(Callback()), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_funcStaticOrigin(m_traverse, m_originKey.m_origin), + m_doom3Radius(EntityClass_valueForKey(m_entity.getEntityClass(), "light_radius")), + m_radii_wire(m_radii, m_aabb_light.origin), + m_radii_fill(m_radii, m_aabb_light.origin), + m_radii_box(m_aabb_light.origin), + m_render_center(m_doom3Radius.m_center, m_entity.getEntityClass()), + m_renderName(m_named, m_aabb_light.origin), + m_useLightOrigin(false), + m_useLightRotation(false), + m_renderProjection(m_doom3Projection), + m_transformChanged(transformChanged), + m_boundsChanged(boundsChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + Light(const Light &other, scene::Node &node, const Callback &transformChanged, + const Callback &boundsChanged, const Callback &evaluateTransform) : + m_entity(other.m_entity), + m_originKey(OriginChangedCaller(*this)), + m_rotationKey(RotationChangedCaller(*this)), + m_colour(Callback()), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_funcStaticOrigin(m_traverse, m_originKey.m_origin), + m_doom3Radius(EntityClass_valueForKey(m_entity.getEntityClass(), "light_radius")), + m_radii_wire(m_radii, m_aabb_light.origin), + m_radii_fill(m_radii, m_aabb_light.origin), + m_radii_box(m_aabb_light.origin), + m_render_center(m_doom3Radius.m_center, m_entity.getEntityClass()), + m_renderName(m_named, m_aabb_light.origin), + m_useLightOrigin(false), + m_useLightRotation(false), + m_renderProjection(m_doom3Projection), + m_transformChanged(transformChanged), + m_boundsChanged(boundsChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + ~Light() + { + destroy(); + } + + InstanceCounter m_instanceCounter; + + void instanceAttach(const scene::Path &path) + { + if (++m_instanceCounter.m_count == 1) { + m_filter.instanceAttach(); + m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end())); + if (g_lightType == LIGHTTYPE_DOOM3) { + m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end())); + } + m_entity.attach(m_keyObservers); + + if (g_lightType == LIGHTTYPE_DOOM3) { + m_funcStaticOrigin.enable(); + } + } + } + + void instanceDetach(const scene::Path &path) + { + if (--m_instanceCounter.m_count == 0) { + if (g_lightType == LIGHTTYPE_DOOM3) { + m_funcStaticOrigin.disable(); + } + + m_entity.detach(m_keyObservers); + if (g_lightType == LIGHTTYPE_DOOM3) { + m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end())); + } + m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end())); + m_filter.instanceDetach(); + } + } + + EntityKeyValues &getEntity() + { + return m_entity; + } + + const EntityKeyValues &getEntity() const + { + return m_entity; + } + + scene::Traversable &getTraversable() + { + return m_traverse; + } + + Namespaced &getNamespaced() + { + return m_nameKeys; + } + + Nameable &getNameable() + { + return m_named; + } + + TransformNode &getTransformNode() + { + return m_transform; + } + + void attach(scene::Traversable::Observer *observer) + { + m_traverseObservers.attach(*observer); + } + + void detach(scene::Traversable::Observer *observer) + { + m_traverseObservers.detach(*observer); + } + + void render(RenderStateFlags state) const + { + if (!g_newLightDraw) { + aabb_draw(m_aabb_light, state); + } else { + light_draw(m_aabb_light, state); + } + } + + VolumeIntersectionValue intersectVolume(const VolumeTest &volume, const Matrix4 &localToWorld) const + { + return volume.TestAABB(m_aabb_light, localToWorld); + } // cache -const AABB& localAABB() const { - return m_aabb_light; -} - - -mutable Matrix4 m_projectionOrientation; - -void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const { - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); - renderer.SetState( m_colour.state(), Renderer::eFullMaterials ); - renderer.addRenderable( *this, localToWorld ); - - if ( selected && g_lightRadii && string_empty( m_entity.getKeyValue( "target" ) ) ) { - if ( renderer.getStyle() == Renderer::eFullMaterials ) { - renderer.SetState( RenderLightRadiiFill::m_state, Renderer::eFullMaterials ); - renderer.Highlight( Renderer::ePrimitive, false ); - renderer.addRenderable( m_radii_fill, localToWorld ); - } - else - { - renderer.addRenderable( m_radii_wire, localToWorld ); - } - } - - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials ); - - if ( g_lightType == LIGHTTYPE_DOOM3 && selected ) { - if ( isProjected() ) { - projection(); - m_projectionOrientation = rotation(); - vector4_to_vector3( m_projectionOrientation.t() ) = localAABB().origin; - renderer.addRenderable( m_renderProjection, m_projectionOrientation ); - } - else - { - updateLightRadiiBox(); - renderer.addRenderable( m_radii_box, localToWorld ); - } - - //draw the center of the light - if ( m_doom3Radius.m_useCenterKey ) { - renderer.Highlight( Renderer::ePrimitive, false ); - renderer.Highlight( Renderer::eFace, false ); - renderer.SetState( m_render_center.m_state, Renderer::eFullMaterials ); - renderer.SetState( m_render_center.m_state, Renderer::eWireframeOnly ); - renderer.addRenderable( m_render_center, localToWorld ); - } - } -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const { - renderSolid( renderer, volume, localToWorld, selected ); - if ( g_showNames ) { - renderer.addRenderable( m_renderName, localToWorld ); - } -} - -void testSelect( Selector& selector, SelectionTest& test, const Matrix4& localToWorld ){ - test.BeginMesh( localToWorld ); - - SelectionIntersection best; - aabb_testselect( m_aabb_light, test, best ); - if ( best.valid() ) { - selector.addIntersection( best ); - } -} - -void translate( const Vector3& translation ){ - m_aabb_light.origin = origin_translated( m_aabb_light.origin, translation ); -} -void rotate( const Quaternion& rotation ){ - rotation_rotate( m_rotation, rotation ); -} -void snapto( float snap ){ - if ( g_lightType == LIGHTTYPE_DOOM3 && !m_useLightOrigin && !m_traverse.empty() ) { - m_useLightOrigin = true; - m_lightOrigin = m_originKey.m_origin; - } - - if ( m_useLightOrigin ) { - m_lightOrigin = origin_snapped( m_lightOrigin, snap ); - writeLightOrigin(); - } - else - { - m_originKey.m_origin = origin_snapped( m_originKey.m_origin, snap ); - m_originKey.write( &m_entity ); - } -} -void setLightRadius( const AABB& aabb ){ - m_aabb_light.origin = aabb.origin; - m_doom3Radius.m_radiusTransformed = aabb.extents; -} -void transformLightRadius( const Matrix4& transform ){ - matrix4_transform_point( transform, m_aabb_light.origin ); -} -void revertTransform(){ - m_aabb_light.origin = m_useLightOrigin ? m_lightOrigin : m_originKey.m_origin; - rotation_assign( m_rotation, m_useLightRotation ? m_lightRotation : m_rotationKey.m_rotation ); - m_doom3Radius.m_radiusTransformed = m_doom3Radius.m_radius; -} -void freezeTransform(){ - if ( g_lightType == LIGHTTYPE_DOOM3 && !m_useLightOrigin && !m_traverse.empty() ) { - m_useLightOrigin = true; - } - - if ( m_useLightOrigin ) { - m_lightOrigin = m_aabb_light.origin; - writeLightOrigin(); - } - else - { - m_originKey.m_origin = m_aabb_light.origin; - m_originKey.write( &m_entity ); - } - - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - if ( !m_useLightRotation && !m_traverse.empty() ) { - m_useLightRotation = true; - } - - if ( m_useLightRotation ) { - rotation_assign( m_lightRotation, m_rotation ); - write_rotation( m_lightRotation, &m_entity, "light_rotation" ); - } - - rotation_assign( m_rotationKey.m_rotation, m_rotation ); - write_rotation( m_rotationKey.m_rotation, &m_entity ); - - m_doom3Radius.m_radius = m_doom3Radius.m_radiusTransformed; - write_origin( m_doom3Radius.m_radius, &m_entity, "light_radius" ); - } -} -void transformChanged(){ - revertTransform(); - m_evaluateTransform(); - updateOrigin(); -} -typedef MemberCaller TransformChangedCaller; - -mutable Matrix4 m_localPivot; -const Matrix4& getLocalPivot() const { - m_localPivot = rotation_toMatrix( m_rotation ); - vector4_to_vector3( m_localPivot.t() ) = m_aabb_light.origin; - return m_localPivot; -} - -void setLightChangedCallback( const Callback& callback ){ - m_doom3Radius.m_changed = callback; -} - -const AABB& aabb() const { - m_doom3AABB = AABB( m_aabb_light.origin, m_doom3Radius.m_radiusTransformed ); - return m_doom3AABB; -} -bool testAABB( const AABB& other ) const { - if ( isProjected() ) { - Matrix4 transform = rotation(); - vector4_to_vector3( transform.t() ) = localAABB().origin; - projection(); - Frustum frustum( frustum_transformed( m_doom3Frustum, transform ) ); - return frustum_test_aabb( frustum, other ) != c_volumeOutside; - } - // test against an AABB which contains the rotated bounds of this light. - const AABB& bounds = aabb(); - return aabb_intersects_aabb( other, AABB( - bounds.origin, - Vector3( - static_cast( fabs( m_rotation[0] * bounds.extents[0] ) - + fabs( m_rotation[3] * bounds.extents[1] ) - + fabs( m_rotation[6] * bounds.extents[2] ) ), - static_cast( fabs( m_rotation[1] * bounds.extents[0] ) - + fabs( m_rotation[4] * bounds.extents[1] ) - + fabs( m_rotation[7] * bounds.extents[2] ) ), - static_cast( fabs( m_rotation[2] * bounds.extents[0] ) - + fabs( m_rotation[5] * bounds.extents[1] ) - + fabs( m_rotation[8] * bounds.extents[2] ) ) - ) - ) ); -} - -const Matrix4& rotation() const { - m_doom3Rotation = rotation_toMatrix( m_rotation ); - return m_doom3Rotation; -} -const Vector3& offset() const { - return m_doom3Radius.m_center; -} -const Vector3& colour() const { - return m_colour.m_colour; -} - -bool isProjected() const { - return m_useLightTarget && m_useLightUp && m_useLightRight; -} -void projectionChanged(){ - m_doom3ProjectionChanged = true; - m_doom3Radius.m_changed(); - SceneChangeNotify(); -} - -const Matrix4& projection() const { - if ( !m_doom3ProjectionChanged ) { - return m_doom3Projection; - } - m_doom3ProjectionChanged = false; - m_doom3Projection = g_matrix4_identity; - matrix4_translate_by_vec3( m_doom3Projection, Vector3( 0.5f, 0.5f, 0 ) ); - matrix4_scale_by_vec3( m_doom3Projection, Vector3( 0.5f, 0.5f, 1 ) ); + const AABB &localAABB() const + { + return m_aabb_light; + } + + + mutable Matrix4 m_projectionOrientation; + + void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, bool selected) const + { + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly); + renderer.SetState(m_colour.state(), Renderer::eFullMaterials); + renderer.addRenderable(*this, localToWorld); + + if (selected && g_lightRadii && string_empty(m_entity.getKeyValue("target"))) { + if (renderer.getStyle() == Renderer::eFullMaterials) { + renderer.SetState(RenderLightRadiiFill::m_state, Renderer::eFullMaterials); + renderer.Highlight(Renderer::ePrimitive, false); + renderer.addRenderable(m_radii_fill, localToWorld); + } else { + renderer.addRenderable(m_radii_wire, localToWorld); + } + } + + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials); + + if (g_lightType == LIGHTTYPE_DOOM3 && selected) { + if (isProjected()) { + projection(); + m_projectionOrientation = rotation(); + vector4_to_vector3(m_projectionOrientation.t()) = localAABB().origin; + renderer.addRenderable(m_renderProjection, m_projectionOrientation); + } else { + updateLightRadiiBox(); + renderer.addRenderable(m_radii_box, localToWorld); + } + + //draw the center of the light + if (m_doom3Radius.m_useCenterKey) { + renderer.Highlight(Renderer::ePrimitive, false); + renderer.Highlight(Renderer::eFace, false); + renderer.SetState(m_render_center.m_state, Renderer::eFullMaterials); + renderer.SetState(m_render_center.m_state, Renderer::eWireframeOnly); + renderer.addRenderable(m_render_center, localToWorld); + } + } + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, bool selected) const + { + renderSolid(renderer, volume, localToWorld, selected); + if (g_showNames) { + renderer.addRenderable(m_renderName, localToWorld); + } + } + + void testSelect(Selector &selector, SelectionTest &test, const Matrix4 &localToWorld) + { + test.BeginMesh(localToWorld); + + SelectionIntersection best; + aabb_testselect(m_aabb_light, test, best); + if (best.valid()) { + selector.addIntersection(best); + } + } + + void translate(const Vector3 &translation) + { + m_aabb_light.origin = origin_translated(m_aabb_light.origin, translation); + } + + void rotate(const Quaternion &rotation) + { + rotation_rotate(m_rotation, rotation); + } + + void snapto(float snap) + { + if (g_lightType == LIGHTTYPE_DOOM3 && !m_useLightOrigin && !m_traverse.empty()) { + m_useLightOrigin = true; + m_lightOrigin = m_originKey.m_origin; + } + + if (m_useLightOrigin) { + m_lightOrigin = origin_snapped(m_lightOrigin, snap); + writeLightOrigin(); + } else { + m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap); + m_originKey.write(&m_entity); + } + } + + void setLightRadius(const AABB &aabb) + { + m_aabb_light.origin = aabb.origin; + m_doom3Radius.m_radiusTransformed = aabb.extents; + } + + void transformLightRadius(const Matrix4 &transform) + { + matrix4_transform_point(transform, m_aabb_light.origin); + } + + void revertTransform() + { + m_aabb_light.origin = m_useLightOrigin ? m_lightOrigin : m_originKey.m_origin; + rotation_assign(m_rotation, m_useLightRotation ? m_lightRotation : m_rotationKey.m_rotation); + m_doom3Radius.m_radiusTransformed = m_doom3Radius.m_radius; + } + + void freezeTransform() + { + if (g_lightType == LIGHTTYPE_DOOM3 && !m_useLightOrigin && !m_traverse.empty()) { + m_useLightOrigin = true; + } + + if (m_useLightOrigin) { + m_lightOrigin = m_aabb_light.origin; + writeLightOrigin(); + } else { + m_originKey.m_origin = m_aabb_light.origin; + m_originKey.write(&m_entity); + } + + if (g_lightType == LIGHTTYPE_DOOM3) { + if (!m_useLightRotation && !m_traverse.empty()) { + m_useLightRotation = true; + } + + if (m_useLightRotation) { + rotation_assign(m_lightRotation, m_rotation); + write_rotation(m_lightRotation, &m_entity, "light_rotation"); + } + + rotation_assign(m_rotationKey.m_rotation, m_rotation); + write_rotation(m_rotationKey.m_rotation, &m_entity); + + m_doom3Radius.m_radius = m_doom3Radius.m_radiusTransformed; + write_origin(m_doom3Radius.m_radius, &m_entity, "light_radius"); + } + } + + void transformChanged() + { + revertTransform(); + m_evaluateTransform(); + updateOrigin(); + } + + typedef MemberCaller TransformChangedCaller; + + mutable Matrix4 m_localPivot; + + const Matrix4 &getLocalPivot() const + { + m_localPivot = rotation_toMatrix(m_rotation); + vector4_to_vector3(m_localPivot.t()) = m_aabb_light.origin; + return m_localPivot; + } + + void setLightChangedCallback(const Callback &callback) + { + m_doom3Radius.m_changed = callback; + } + + const AABB &aabb() const + { + m_doom3AABB = AABB(m_aabb_light.origin, m_doom3Radius.m_radiusTransformed); + return m_doom3AABB; + } + + bool testAABB(const AABB &other) const + { + if (isProjected()) { + Matrix4 transform = rotation(); + vector4_to_vector3(transform.t()) = localAABB().origin; + projection(); + Frustum frustum(frustum_transformed(m_doom3Frustum, transform)); + return frustum_test_aabb(frustum, other) != c_volumeOutside; + } + // test against an AABB which contains the rotated bounds of this light. + const AABB &bounds = aabb(); + return aabb_intersects_aabb(other, AABB( + bounds.origin, + Vector3( + static_cast( fabs(m_rotation[0] * bounds.extents[0]) + + fabs(m_rotation[3] * bounds.extents[1]) + + fabs(m_rotation[6] * bounds.extents[2])), + static_cast( fabs(m_rotation[1] * bounds.extents[0]) + + fabs(m_rotation[4] * bounds.extents[1]) + + fabs(m_rotation[7] * bounds.extents[2])), + static_cast( fabs(m_rotation[2] * bounds.extents[0]) + + fabs(m_rotation[5] * bounds.extents[1]) + + fabs(m_rotation[8] * bounds.extents[2])) + ) + )); + } + + const Matrix4 &rotation() const + { + m_doom3Rotation = rotation_toMatrix(m_rotation); + return m_doom3Rotation; + } + + const Vector3 &offset() const + { + return m_doom3Radius.m_center; + } + + const Vector3 &colour() const + { + return m_colour.m_colour; + } + + bool isProjected() const + { + return m_useLightTarget && m_useLightUp && m_useLightRight; + } + + void projectionChanged() + { + m_doom3ProjectionChanged = true; + m_doom3Radius.m_changed(); + SceneChangeNotify(); + } + + const Matrix4 &projection() const + { + if (!m_doom3ProjectionChanged) { + return m_doom3Projection; + } + m_doom3ProjectionChanged = false; + m_doom3Projection = g_matrix4_identity; + matrix4_translate_by_vec3(m_doom3Projection, Vector3(0.5f, 0.5f, 0)); + matrix4_scale_by_vec3(m_doom3Projection, Vector3(0.5f, 0.5f, 1)); #if 0 - Vector3 right = vector3_cross( m_lightUp, vector3_normalised( m_lightTarget ) ); + Vector3 right = vector3_cross( m_lightUp, vector3_normalised( m_lightTarget ) ); Vector3 up = vector3_cross( vector3_normalised( m_lightTarget ), m_lightRight ); Vector3 target = m_lightTarget; Matrix4 test( @@ -1316,7 +1446,7 @@ const Matrix4& projection() const { matrix4_premultiply_by_matrix4( test, frustum ); matrix4_multiply_by_matrix4( m_doom3Projection, test ); #elif 0 - const float nearFar = 1 / 49.5f; + const float nearFar = 1 / 49.5f; Vector3 right = vector3_cross( m_lightUp, vector3_normalised( m_lightTarget + m_lightRight ) ); Vector3 up = vector3_cross( vector3_normalised( m_lightTarget + m_lightUp ), m_lightRight ); Vector3 target = vector3_negated( m_lightTarget * ( 1 + nearFar ) ); @@ -1329,7 +1459,7 @@ const Matrix4& projection() const { ); matrix4_multiply_by_matrix4( m_doom3Projection, test ); #elif 0 - Vector3 leftA( m_lightTarget - m_lightRight ); + Vector3 leftA( m_lightTarget - m_lightRight ); Vector3 leftB( m_lightRight + m_lightUp ); Plane3 left( vector3_normalised( vector3_cross( leftA, leftB ) ) * ( 1.0 / 128 ), 0 ); Vector3 rightA( m_lightTarget + m_lightRight ); @@ -1347,372 +1477,461 @@ const Matrix4& projection() const { matrix4_multiply_by_matrix4( m_doom3Projection, test ); #else - Plane3 lightProject[4]; - - Vector3 start = m_useLightStart && m_useLightEnd ? m_lightStart : vector3_normalised( m_lightTarget ); - Vector3 stop = m_useLightStart && m_useLightEnd ? m_lightEnd : m_lightTarget; - - float rLen = vector3_length( m_lightRight ); - Vector3 right = vector3_divided( m_lightRight, rLen ); - float uLen = vector3_length( m_lightUp ); - Vector3 up = vector3_divided( m_lightUp, uLen ); - Vector3 normal = vector3_normalised( vector3_cross( up, right ) ); - - float dist = vector3_dot( m_lightTarget, normal ); - if ( dist < 0 ) { - dist = -dist; - normal = vector3_negated( normal ); - } - - right *= ( 0.5f * dist ) / rLen; - up *= -( 0.5f * dist ) / uLen; - - lightProject[2] = Plane3( normal, 0 ); - lightProject[0] = Plane3( right, 0 ); - lightProject[1] = Plane3( up, 0 ); - - // now offset to center - Vector4 targetGlobal( m_lightTarget, 1 ); - { - float a = vector4_dot( targetGlobal, plane3_to_vector4( lightProject[0] ) ); - float b = vector4_dot( targetGlobal, plane3_to_vector4( lightProject[2] ) ); - float ofs = 0.5f - a / b; - plane3_to_vector4( lightProject[0] ) += plane3_to_vector4( lightProject[2] ) * ofs; - } - { - float a = vector4_dot( targetGlobal, plane3_to_vector4( lightProject[1] ) ); - float b = vector4_dot( targetGlobal, plane3_to_vector4( lightProject[2] ) ); - float ofs = 0.5f - a / b; - plane3_to_vector4( lightProject[1] ) += plane3_to_vector4( lightProject[2] ) * ofs; - } - - // set the falloff vector - Vector3 falloff = stop - start; - float length = vector3_length( falloff ); - falloff = vector3_divided( falloff, length ); - if ( length <= 0 ) { - length = 1; - } - falloff *= ( 1.0f / length ); - lightProject[3] = Plane3( falloff, -vector3_dot( start, falloff ) ); - - // we want the planes of s=0, s=q, t=0, and t=q - m_doom3Frustum.left = lightProject[0]; - m_doom3Frustum.bottom = lightProject[1]; - m_doom3Frustum.right = Plane3( lightProject[2].normal() - lightProject[0].normal(), lightProject[2].dist() - lightProject[0].dist() ); - m_doom3Frustum.top = Plane3( lightProject[2].normal() - lightProject[1].normal(), lightProject[2].dist() - lightProject[1].dist() ); - - // we want the planes of s=0 and s=1 for front and rear clipping planes - m_doom3Frustum.front = lightProject[3]; - - m_doom3Frustum.back = lightProject[3]; - m_doom3Frustum.back.dist() -= 1.0f; - m_doom3Frustum.back = plane3_flipped( m_doom3Frustum.back ); - - Matrix4 test( matrix4_from_planes( m_doom3Frustum.left, m_doom3Frustum.right, m_doom3Frustum.bottom, m_doom3Frustum.top, m_doom3Frustum.front, m_doom3Frustum.back ) ); - matrix4_multiply_by_matrix4( m_doom3Projection, test ); - - m_doom3Frustum.left = plane3_normalised( m_doom3Frustum.left ); - m_doom3Frustum.right = plane3_normalised( m_doom3Frustum.right ); - m_doom3Frustum.bottom = plane3_normalised( m_doom3Frustum.bottom ); - m_doom3Frustum.top = plane3_normalised( m_doom3Frustum.top ); - m_doom3Frustum.back = plane3_normalised( m_doom3Frustum.back ); - m_doom3Frustum.front = plane3_normalised( m_doom3Frustum.front ); + Plane3 lightProject[4]; + + Vector3 start = m_useLightStart && m_useLightEnd ? m_lightStart : vector3_normalised(m_lightTarget); + Vector3 stop = m_useLightStart && m_useLightEnd ? m_lightEnd : m_lightTarget; + + float rLen = vector3_length(m_lightRight); + Vector3 right = vector3_divided(m_lightRight, rLen); + float uLen = vector3_length(m_lightUp); + Vector3 up = vector3_divided(m_lightUp, uLen); + Vector3 normal = vector3_normalised(vector3_cross(up, right)); + + float dist = vector3_dot(m_lightTarget, normal); + if (dist < 0) { + dist = -dist; + normal = vector3_negated(normal); + } + + right *= (0.5f * dist) / rLen; + up *= -(0.5f * dist) / uLen; + + lightProject[2] = Plane3(normal, 0); + lightProject[0] = Plane3(right, 0); + lightProject[1] = Plane3(up, 0); + + // now offset to center + Vector4 targetGlobal(m_lightTarget, 1); + { + float a = vector4_dot(targetGlobal, plane3_to_vector4(lightProject[0])); + float b = vector4_dot(targetGlobal, plane3_to_vector4(lightProject[2])); + float ofs = 0.5f - a / b; + plane3_to_vector4(lightProject[0]) += plane3_to_vector4(lightProject[2]) * ofs; + } + { + float a = vector4_dot(targetGlobal, plane3_to_vector4(lightProject[1])); + float b = vector4_dot(targetGlobal, plane3_to_vector4(lightProject[2])); + float ofs = 0.5f - a / b; + plane3_to_vector4(lightProject[1]) += plane3_to_vector4(lightProject[2]) * ofs; + } + + // set the falloff vector + Vector3 falloff = stop - start; + float length = vector3_length(falloff); + falloff = vector3_divided(falloff, length); + if (length <= 0) { + length = 1; + } + falloff *= (1.0f / length); + lightProject[3] = Plane3(falloff, -vector3_dot(start, falloff)); + + // we want the planes of s=0, s=q, t=0, and t=q + m_doom3Frustum.left = lightProject[0]; + m_doom3Frustum.bottom = lightProject[1]; + m_doom3Frustum.right = Plane3(lightProject[2].normal() - lightProject[0].normal(), + lightProject[2].dist() - lightProject[0].dist()); + m_doom3Frustum.top = Plane3(lightProject[2].normal() - lightProject[1].normal(), + lightProject[2].dist() - lightProject[1].dist()); + + // we want the planes of s=0 and s=1 for front and rear clipping planes + m_doom3Frustum.front = lightProject[3]; + + m_doom3Frustum.back = lightProject[3]; + m_doom3Frustum.back.dist() -= 1.0f; + m_doom3Frustum.back = plane3_flipped(m_doom3Frustum.back); + + Matrix4 test(matrix4_from_planes(m_doom3Frustum.left, m_doom3Frustum.right, m_doom3Frustum.bottom, + m_doom3Frustum.top, m_doom3Frustum.front, m_doom3Frustum.back)); + matrix4_multiply_by_matrix4(m_doom3Projection, test); + + m_doom3Frustum.left = plane3_normalised(m_doom3Frustum.left); + m_doom3Frustum.right = plane3_normalised(m_doom3Frustum.right); + m_doom3Frustum.bottom = plane3_normalised(m_doom3Frustum.bottom); + m_doom3Frustum.top = plane3_normalised(m_doom3Frustum.top); + m_doom3Frustum.back = plane3_normalised(m_doom3Frustum.back); + m_doom3Frustum.front = plane3_normalised(m_doom3Frustum.front); #endif - //matrix4_scale_by_vec3(m_doom3Projection, Vector3(1.0 / 128, 1.0 / 128, 1.0 / 128)); - return m_doom3Projection; -} - -Shader* getShader() const { - return m_shader.get(); -} + //matrix4_scale_by_vec3(m_doom3Projection, Vector3(1.0 / 128, 1.0 / 128, 1.0 / 128)); + return m_doom3Projection; + } + + Shader *getShader() const + { + return m_shader.get(); + } }; class LightInstance : - public TargetableInstance, - public TransformModifier, - public Renderable, - public SelectionTestable, - public RendererLight, - public PlaneSelectable, - public ComponentSelectionTestable -{ -class TypeCasts -{ -InstanceTypeCastTable m_casts; + public TargetableInstance, + public TransformModifier, + public Renderable, + public SelectionTestable, + public RendererLight, + public PlaneSelectable, + public ComponentSelectionTestable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + m_casts = TargetableInstance::StaticTypeCasts::instance().get(); + InstanceContainedCast::install(m_casts); + //InstanceContainedCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceIdentityCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + Light &m_contained; + DragPlanes m_dragPlanes; // dragplanes for lightresizing using mousedrag public: -TypeCasts(){ - m_casts = TargetableInstance::StaticTypeCasts::instance().get(); - InstanceContainedCast::install( m_casts ); - //InstanceContainedCast::install(m_casts); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceIdentityCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} -}; - -Light& m_contained; -DragPlanes m_dragPlanes; // dragplanes for lightresizing using mousedrag -public: -typedef LazyStatic StaticTypeCasts; - -Bounded& get( NullType){ - return m_contained; -} - -STRING_CONSTANT( Name, "LightInstance" ); - -LightInstance( const scene::Path& path, scene::Instance* parent, Light& contained ) : - TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this ), - TransformModifier( Light::TransformChangedCaller( contained ), ApplyTransformCaller( *this ) ), - m_contained( contained ), - m_dragPlanes( SelectedChangedComponentCaller( *this ) ){ - m_contained.instanceAttach( Instance::path() ); - - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - GlobalShaderCache().attach( *this ); - m_contained.setLightChangedCallback( LightChangedCaller( *this ) ); - } - - StaticRenderableConnectionLines::instance().attach( *this ); -} -~LightInstance(){ - StaticRenderableConnectionLines::instance().detach( *this ); - - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_contained.setLightChangedCallback( Callback() ); - GlobalShaderCache().detach( *this ); - } - - m_contained.instanceDetach( Instance::path() ); -} -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() ); -} -void testSelect( Selector& selector, SelectionTest& test ){ - m_contained.testSelect( selector, test, Instance::localToWorld() ); -} - -void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){ - test.BeginMesh( localToWorld() ); - m_dragPlanes.selectPlanes( m_contained.aabb(), selector, test, selectedPlaneCallback, rotation() ); -} -void selectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ){ - m_dragPlanes.selectReversedPlanes( m_contained.aabb(), selector, selectedPlanes, rotation() ); -} - -bool isSelectedComponents() const { - return m_dragPlanes.isSelected(); -} -void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ){ - if ( mode == SelectionSystem::eFace ) { - m_dragPlanes.setSelected( false ); - } -} -void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ){ -} - -void selectedChangedComponent( const Selectable& selectable ){ - GlobalSelectionSystem().getObserver ( SelectionSystem::eComponent )( selectable ); - GlobalSelectionSystem().onComponentSelection( *this, selectable ); -} -typedef MemberCaller SelectedChangedComponentCaller; - -void evaluateTransform(){ - if ( getType() == TRANSFORM_PRIMITIVE ) { - m_contained.translate( getTranslation() ); - m_contained.rotate( getRotation() ); - } - else - { - //globalOutputStream() << getTranslation() << "\n"; - - m_dragPlanes.m_bounds = m_contained.aabb(); - m_contained.setLightRadius( m_dragPlanes.evaluateResize( getTranslation(), rotation() ) ); - } -} -void applyTransform(){ - m_contained.revertTransform(); - evaluateTransform(); - m_contained.freezeTransform(); -} -typedef MemberCaller ApplyTransformCaller; - -void lightChanged(){ - GlobalShaderCache().changed( *this ); -} -typedef MemberCaller LightChangedCaller; - -Shader* getShader() const { - return m_contained.getShader(); -} -const AABB& aabb() const { - return m_contained.aabb(); -} -bool testAABB( const AABB& other ) const { - return m_contained.testAABB( other ); -} -const Matrix4& rotation() const { - return m_contained.rotation(); -} -const Vector3& offset() const { - return m_contained.offset(); -} -const Vector3& colour() const { - return m_contained.colour(); -} - -bool isProjected() const { - return m_contained.isProjected(); -} -const Matrix4& projection() const { - return m_contained.projection(); -} + typedef LazyStatic StaticTypeCasts; + + Bounded &get(NullType) + { + return m_contained; + } + + STRING_CONSTANT(Name, "LightInstance"); + + LightInstance(const scene::Path &path, scene::Instance *parent, Light &contained) : + TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this), + TransformModifier(Light::TransformChangedCaller(contained), ApplyTransformCaller(*this)), + m_contained(contained), + m_dragPlanes(SelectedChangedComponentCaller(*this)) + { + m_contained.instanceAttach(Instance::path()); + + if (g_lightType == LIGHTTYPE_DOOM3) { + GlobalShaderCache().attach(*this); + m_contained.setLightChangedCallback(LightChangedCaller(*this)); + } + + StaticRenderableConnectionLines::instance().attach(*this); + } + + ~LightInstance() + { + StaticRenderableConnectionLines::instance().detach(*this); + + if (g_lightType == LIGHTTYPE_DOOM3) { + m_contained.setLightChangedCallback(Callback()); + GlobalShaderCache().detach(*this); + } + + m_contained.instanceDetach(Instance::path()); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected()); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected()); + } + + void testSelect(Selector &selector, SelectionTest &test) + { + m_contained.testSelect(selector, test, Instance::localToWorld()); + } + + void selectPlanes(Selector &selector, SelectionTest &test, const PlaneCallback &selectedPlaneCallback) + { + test.BeginMesh(localToWorld()); + m_dragPlanes.selectPlanes(m_contained.aabb(), selector, test, selectedPlaneCallback, rotation()); + } + + void selectReversedPlanes(Selector &selector, const SelectedPlanes &selectedPlanes) + { + m_dragPlanes.selectReversedPlanes(m_contained.aabb(), selector, selectedPlanes, rotation()); + } + + bool isSelectedComponents() const + { + return m_dragPlanes.isSelected(); + } + + void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) + { + if (mode == SelectionSystem::eFace) { + m_dragPlanes.setSelected(false); + } + } + + void testSelectComponents(Selector &selector, SelectionTest &test, SelectionSystem::EComponentMode mode) + { + } + + void selectedChangedComponent(const Selectable &selectable) + { + GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable); + GlobalSelectionSystem().onComponentSelection(*this, selectable); + } + + typedef MemberCaller SelectedChangedComponentCaller; + + void evaluateTransform() + { + if (getType() == TRANSFORM_PRIMITIVE) { + m_contained.translate(getTranslation()); + m_contained.rotate(getRotation()); + } else { + //globalOutputStream() << getTranslation() << "\n"; + + m_dragPlanes.m_bounds = m_contained.aabb(); + m_contained.setLightRadius(m_dragPlanes.evaluateResize(getTranslation(), rotation())); + } + } + + void applyTransform() + { + m_contained.revertTransform(); + evaluateTransform(); + m_contained.freezeTransform(); + } + + typedef MemberCaller ApplyTransformCaller; + + void lightChanged() + { + GlobalShaderCache().changed(*this); + } + + typedef MemberCaller LightChangedCaller; + + Shader *getShader() const + { + return m_contained.getShader(); + } + + const AABB &aabb() const + { + return m_contained.aabb(); + } + + bool testAABB(const AABB &other) const + { + return m_contained.testAABB(other); + } + + const Matrix4 &rotation() const + { + return m_contained.rotation(); + } + + const Vector3 &offset() const + { + return m_contained.offset(); + } + + const Vector3 &colour() const + { + return m_contained.colour(); + } + + bool isProjected() const + { + return m_contained.isProjected(); + } + + const Matrix4 &projection() const + { + return m_contained.projection(); + } }; class LightNode : - public scene::Node::Symbiot, - public scene::Instantiable, - public scene::Cloneable, - public scene::Traversable::Observer -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; -public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); - NodeStaticCast::install( m_casts ); - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - NodeContainedCast::install( m_casts ); - } - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} -}; - - -scene::Node m_node; -InstanceSet m_instances; -Light m_contained; + public scene::Node::Symbiot, + public scene::Instantiable, + public scene::Cloneable, + public scene::Traversable::Observer { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + NodeStaticCast::install(m_casts); + if (g_lightType == LIGHTTYPE_DOOM3) { + NodeContainedCast::install(m_casts); + } + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + } + + NodeTypeCastTable &get() + { + return m_casts; + } + }; + + + scene::Node m_node; + InstanceSet m_instances; + Light m_contained; + + void construct() + { + if (g_lightType == LIGHTTYPE_DOOM3) { + m_contained.attach(this); + } + } + + void destroy() + { + if (g_lightType == LIGHTTYPE_DOOM3) { + m_contained.detach(this); + } + } -void construct(){ - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_contained.attach( this ); - } -} -void destroy(){ - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - m_contained.detach( this ); - } -} public: -typedef LazyStatic StaticTypeCasts; - -scene::Traversable& get( NullType){ - return m_contained.getTraversable(); -} -Editable& get( NullType){ - return m_contained; -} -Snappable& get( NullType){ - return m_contained; -} -TransformNode& get( NullType){ - return m_contained.getTransformNode(); -} -Entity& get( NullType){ - return m_contained.getEntity(); -} -Nameable& get( NullType){ - return m_contained.getNameable(); -} -Namespaced& get( NullType){ - return m_contained.getNamespaced(); -} - -LightNode( EntityClass* eclass ) : - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -LightNode( const LightNode& other ) : - scene::Node::Symbiot( other ), - scene::Instantiable( other ), - scene::Cloneable( other ), - scene::Traversable::Observer( other ), - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -~LightNode(){ - destroy(); -} - -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} - -scene::Node& clone() const { - return ( new LightNode( *this ) )->node(); -} - -void insert( scene::Node& child ){ - m_instances.insert( child ); -} -void erase( scene::Node& child ){ - m_instances.erase( child ); -} - -scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new LightInstance( path, parent, m_contained ); -} -void forEachInstance( const scene::Instantiable::Visitor& visitor ){ - m_instances.forEachInstance( visitor ); -} -void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){ - m_instances.insert( observer, path, instance ); -} -scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){ - return m_instances.erase( observer, path ); -} + typedef LazyStatic StaticTypeCasts; + + scene::Traversable &get(NullType) + { + return m_contained.getTraversable(); + } + + Editable &get(NullType) + { + return m_contained; + } + + Snappable &get(NullType) + { + return m_contained; + } + + TransformNode &get(NullType) + { + return m_contained.getTransformNode(); + } + + Entity &get(NullType) + { + return m_contained.getEntity(); + } + + Nameable &get(NullType) + { + return m_contained.getNameable(); + } + + Namespaced &get(NullType) + { + return m_contained.getNamespaced(); + } + + LightNode(EntityClass *eclass) : + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSet::BoundsChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + LightNode(const LightNode &other) : + scene::Node::Symbiot(other), + scene::Instantiable(other), + scene::Cloneable(other), + scene::Traversable::Observer(other), + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSet::BoundsChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + ~LightNode() + { + destroy(); + } + + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } + + scene::Node &clone() const + { + return (new LightNode(*this))->node(); + } + + void insert(scene::Node &child) + { + m_instances.insert(child); + } + + void erase(scene::Node &child) + { + m_instances.erase(child); + } + + scene::Instance *create(const scene::Path &path, scene::Instance *parent) + { + return new LightInstance(path, parent, m_contained); + } + + void forEachInstance(const scene::Instantiable::Visitor &visitor) + { + m_instances.forEachInstance(visitor); + } + + void insert(scene::Instantiable::Observer *observer, const scene::Path &path, scene::Instance *instance) + { + m_instances.insert(observer, path, instance); + } + + scene::Instance *erase(scene::Instantiable::Observer *observer, const scene::Path &path) + { + return m_instances.erase(observer, path); + } }; -void Light_Construct( LightType lightType ){ - g_lightType = lightType; - if ( g_lightType == LIGHTTYPE_DOOM3 ) { - LightShader::m_defaultShader = "lights/defaultPointLight"; +void Light_Construct(LightType lightType) +{ + g_lightType = lightType; + if (g_lightType == LIGHTTYPE_DOOM3) { + LightShader::m_defaultShader = "lights/defaultPointLight"; #if 0 - LightShader::m_defaultShader = "lights/defaultProjectedLight"; + LightShader::m_defaultShader = "lights/defaultProjectedLight"; #endif - } - RenderLightRadiiFill::m_state = GlobalShaderCache().capture( "$Q3MAP2_LIGHT_SPHERE" ); - RenderLightCenter::m_state = GlobalShaderCache().capture( "$BIGPOINT" ); + } + RenderLightRadiiFill::m_state = GlobalShaderCache().capture("$Q3MAP2_LIGHT_SPHERE"); + RenderLightCenter::m_state = GlobalShaderCache().capture("$BIGPOINT"); } -void Light_Destroy(){ - GlobalShaderCache().release( "$Q3MAP2_LIGHT_SPHERE" ); - GlobalShaderCache().release( "$BIGPOINT" ); + +void Light_Destroy() +{ + GlobalShaderCache().release("$Q3MAP2_LIGHT_SPHERE"); + GlobalShaderCache().release("$BIGPOINT"); } -scene::Node& New_Light( EntityClass* eclass ){ - return ( new LightNode( eclass ) )->node(); +scene::Node &New_Light(EntityClass *eclass) +{ + return (new LightNode(eclass))->node(); } diff --git a/plugins/entity/light.h b/plugins/entity/light.h index 5c807ab2..ac46a3b5 100644 --- a/plugins/entity/light.h +++ b/plugins/entity/light.h @@ -22,20 +22,21 @@ #if !defined( INCLUDED_LIGHT_H ) #define INCLUDED_LIGHT_H -namespace scene -{ -class Node; +namespace scene { + class Node; } class EntityClass; -scene::Node& New_Light( EntityClass* eclass ); -enum LightType -{ - LIGHTTYPE_DEFAULT, - LIGHTTYPE_RTCW, - LIGHTTYPE_DOOM3 +scene::Node &New_Light(EntityClass *eclass); + +enum LightType { + LIGHTTYPE_DEFAULT, + LIGHTTYPE_RTCW, + LIGHTTYPE_DOOM3 }; -void Light_Construct( LightType lightType ); + +void Light_Construct(LightType lightType); + void Light_Destroy(); #endif diff --git a/plugins/entity/miscmodel.cpp b/plugins/entity/miscmodel.cpp index ac541a6f..76bf6598 100644 --- a/plugins/entity/miscmodel.cpp +++ b/plugins/entity/miscmodel.cpp @@ -51,362 +51,463 @@ #include "entity.h" class MiscModel : - public Snappable -{ -EntityKeyValues m_entity; -KeyObserverMap m_keyObservers; -MatrixTransform m_transform; - -OriginKey m_originKey; -Vector3 m_origin; -AnglesKey m_anglesKey; -Vector3 m_angles; -ScaleKey m_scaleKey; -Vector3 m_scale; - -SingletonModel m_model; - -ClassnameFilter m_filter; -NamedEntity m_named; -NameKeys m_nameKeys; -RenderablePivot m_renderOrigin; -RenderableNamedEntity m_renderName; - -Callback m_transformChanged; -Callback m_evaluateTransform; - -void construct(){ - m_keyObservers.insert( "classname", ClassnameFilter::ClassnameChangedCaller( m_filter ) ); - m_keyObservers.insert( Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller( m_named ) ); - m_keyObservers.insert( "model", SingletonModel::ModelChangedCaller( m_model ) ); - m_keyObservers.insert( "origin", OriginKey::OriginChangedCaller( m_originKey ) ); - m_keyObservers.insert( "angle", AnglesKey::AngleChangedCaller( m_anglesKey ) ); - m_keyObservers.insert( "angles", AnglesKey::AnglesChangedCaller( m_anglesKey ) ); - m_keyObservers.insert( "modelscale", ScaleKey::UniformScaleChangedCaller( m_scaleKey ) ); - m_keyObservers.insert( "modelscale_vec", ScaleKey::ScaleChangedCaller( m_scaleKey ) ); -} - -void updateTransform(){ - m_transform.localToParent() = g_matrix4_identity; - matrix4_transform_by_euler_xyz_degrees( m_transform.localToParent(), m_origin, m_angles, m_scale ); - m_transformChanged(); -} + public Snappable { + EntityKeyValues m_entity; + KeyObserverMap m_keyObservers; + MatrixTransform m_transform; + + OriginKey m_originKey; + Vector3 m_origin; + AnglesKey m_anglesKey; + Vector3 m_angles; + ScaleKey m_scaleKey; + Vector3 m_scale; + + SingletonModel m_model; + + ClassnameFilter m_filter; + NamedEntity m_named; + NameKeys m_nameKeys; + RenderablePivot m_renderOrigin; + RenderableNamedEntity m_renderName; + + Callback m_transformChanged; + Callback m_evaluateTransform; + + void construct() + { + m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter)); + m_keyObservers.insert(Static::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named)); + m_keyObservers.insert("model", SingletonModel::ModelChangedCaller(m_model)); + m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey)); + m_keyObservers.insert("angle", AnglesKey::AngleChangedCaller(m_anglesKey)); + m_keyObservers.insert("angles", AnglesKey::AnglesChangedCaller(m_anglesKey)); + m_keyObservers.insert("modelscale", ScaleKey::UniformScaleChangedCaller(m_scaleKey)); + m_keyObservers.insert("modelscale_vec", ScaleKey::ScaleChangedCaller(m_scaleKey)); + } + + void updateTransform() + { + m_transform.localToParent() = g_matrix4_identity; + matrix4_transform_by_euler_xyz_degrees(m_transform.localToParent(), m_origin, m_angles, m_scale); + m_transformChanged(); + } // vc 2k5 compiler fix #if _MSC_VER >= 1400 -public: + public: #endif -void originChanged(){ - m_origin = m_originKey.m_origin; - updateTransform(); -} -typedef MemberCaller OriginChangedCaller; -void anglesChanged(){ - m_angles = m_anglesKey.m_angles; - updateTransform(); -} -typedef MemberCaller AnglesChangedCaller; -void scaleChanged(){ - m_scale = m_scaleKey.m_scale; - updateTransform(); -} -typedef MemberCaller ScaleChangedCaller; -public: - -MiscModel( EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) : - m_entity( eclass ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_anglesKey( AnglesChangedCaller( *this ) ), - m_angles( ANGLESKEY_IDENTITY ), - m_scaleKey( ScaleChangedCaller( *this ) ), - m_scale( SCALEKEY_IDENTITY ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_renderName( m_named, g_vector3_identity ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} -MiscModel( const MiscModel& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) : - m_entity( other.m_entity ), - m_originKey( OriginChangedCaller( *this ) ), - m_origin( ORIGINKEY_IDENTITY ), - m_anglesKey( AnglesChangedCaller( *this ) ), - m_angles( ANGLESKEY_IDENTITY ), - m_scaleKey( ScaleChangedCaller( *this ) ), - m_scale( SCALEKEY_IDENTITY ), - m_filter( m_entity, node ), - m_named( m_entity ), - m_nameKeys( m_entity ), - m_renderName( m_named, g_vector3_identity ), - m_transformChanged( transformChanged ), - m_evaluateTransform( evaluateTransform ){ - construct(); -} - -InstanceCounter m_instanceCounter; -void instanceAttach( const scene::Path& path ){ - if ( ++m_instanceCounter.m_count == 1 ) { - m_filter.instanceAttach(); - m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) ); - m_entity.attach( m_keyObservers ); - } -} -void instanceDetach( const scene::Path& path ){ - if ( --m_instanceCounter.m_count == 0 ) { - m_entity.detach( m_keyObservers ); - m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) ); - m_filter.instanceDetach(); - } -} - -EntityKeyValues& getEntity(){ - return m_entity; -} -const EntityKeyValues& getEntity() const { - return m_entity; -} - -scene::Traversable& getTraversable(){ - return m_model.getTraversable(); -} -Namespaced& getNamespaced(){ - return m_nameKeys; -} -Nameable& getNameable(){ - return m_named; -} -TransformNode& getTransformNode(){ - return m_transform; -} - -void attach( scene::Traversable::Observer* observer ){ - m_model.attach( observer ); -} -void detach( scene::Traversable::Observer* observer ){ - m_model.detach( observer ); -} + void originChanged() + { + m_origin = m_originKey.m_origin; + updateTransform(); + } -void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const { - if ( selected ) { - m_renderOrigin.render( renderer, volume, localToWorld ); - } + typedef MemberCaller OriginChangedCaller; - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const { - renderSolid( renderer, volume, localToWorld, selected ); - if ( g_showNames ) { - renderer.addRenderable( m_renderName, localToWorld ); - } -} + void anglesChanged() + { + m_angles = m_anglesKey.m_angles; + updateTransform(); + } -void translate( const Vector3& translation ){ - m_origin = origin_translated( m_origin, translation ); -} -void rotate( const Quaternion& rotation ){ - m_angles = angles_rotated( m_angles, rotation ); -} -void scale( const Vector3& scaling ){ - m_scale = scale_scaled( m_scale, scaling ); -} -void snapto( float snap ){ - m_originKey.m_origin = origin_snapped( m_originKey.m_origin, snap ); - m_originKey.write( &m_entity ); -} -void revertTransform(){ - m_origin = m_originKey.m_origin; - m_angles = m_anglesKey.m_angles; - m_scale = m_scaleKey.m_scale; -} -void freezeTransform(){ - m_originKey.m_origin = m_origin; - m_originKey.write( &m_entity ); - m_anglesKey.m_angles = m_angles; - m_anglesKey.write( &m_entity ); - m_scaleKey.m_scale = m_scale; - m_scaleKey.write( &m_entity ); -} -void transformChanged(){ - revertTransform(); - m_evaluateTransform(); - updateTransform(); -} -typedef MemberCaller TransformChangedCaller; -}; + typedef MemberCaller AnglesChangedCaller; -class MiscModelInstance : public TargetableInstance, public TransformModifier, public Renderable -{ -class TypeCasts -{ -InstanceTypeCastTable m_casts; -public: -TypeCasts(){ - m_casts = TargetableInstance::StaticTypeCasts::instance().get(); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceIdentityCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} -}; + void scaleChanged() + { + m_scale = m_scaleKey.m_scale; + updateTransform(); + } -MiscModel& m_contained; + typedef MemberCaller ScaleChangedCaller; public: -typedef LazyStatic StaticTypeCasts; -STRING_CONSTANT( Name, "MiscModelInstance" ); - -MiscModelInstance( const scene::Path& path, scene::Instance* parent, MiscModel& miscmodel ) : - TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), miscmodel.getEntity(), *this ), - TransformModifier( MiscModel::TransformChangedCaller( miscmodel ), ApplyTransformCaller( *this ) ), - m_contained( miscmodel ){ - m_contained.instanceAttach( Instance::path() ); - StaticRenderableConnectionLines::instance().attach( *this ); -} -~MiscModelInstance(){ - StaticRenderableConnectionLines::instance().detach( *this ); - m_contained.instanceDetach( Instance::path() ); -} -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderSolid( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), getSelectable().isSelected() ); -} -void evaluateTransform(){ - if ( getType() == TRANSFORM_PRIMITIVE ) { - m_contained.translate( getTranslation() ); - m_contained.rotate( getRotation() ); - m_contained.scale( getScale() ); - } -} -void applyTransform(){ - m_contained.revertTransform(); - evaluateTransform(); - m_contained.freezeTransform(); -} -typedef MemberCaller ApplyTransformCaller; + MiscModel(EntityClass *eclass, scene::Node &node, const Callback &transformChanged, + const Callback &evaluateTransform) : + m_entity(eclass), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_anglesKey(AnglesChangedCaller(*this)), + m_angles(ANGLESKEY_IDENTITY), + m_scaleKey(ScaleChangedCaller(*this)), + m_scale(SCALEKEY_IDENTITY), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_renderName(m_named, g_vector3_identity), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + MiscModel(const MiscModel &other, scene::Node &node, const Callback &transformChanged, + const Callback &evaluateTransform) : + m_entity(other.m_entity), + m_originKey(OriginChangedCaller(*this)), + m_origin(ORIGINKEY_IDENTITY), + m_anglesKey(AnglesChangedCaller(*this)), + m_angles(ANGLESKEY_IDENTITY), + m_scaleKey(ScaleChangedCaller(*this)), + m_scale(SCALEKEY_IDENTITY), + m_filter(m_entity, node), + m_named(m_entity), + m_nameKeys(m_entity), + m_renderName(m_named, g_vector3_identity), + m_transformChanged(transformChanged), + m_evaluateTransform(evaluateTransform) + { + construct(); + } + + InstanceCounter m_instanceCounter; + + void instanceAttach(const scene::Path &path) + { + if (++m_instanceCounter.m_count == 1) { + m_filter.instanceAttach(); + m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end())); + m_entity.attach(m_keyObservers); + } + } + + void instanceDetach(const scene::Path &path) + { + if (--m_instanceCounter.m_count == 0) { + m_entity.detach(m_keyObservers); + m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end())); + m_filter.instanceDetach(); + } + } + + EntityKeyValues &getEntity() + { + return m_entity; + } + + const EntityKeyValues &getEntity() const + { + return m_entity; + } + + scene::Traversable &getTraversable() + { + return m_model.getTraversable(); + } + + Namespaced &getNamespaced() + { + return m_nameKeys; + } + + Nameable &getNameable() + { + return m_named; + } + + TransformNode &getTransformNode() + { + return m_transform; + } + + void attach(scene::Traversable::Observer *observer) + { + m_model.attach(observer); + } + + void detach(scene::Traversable::Observer *observer) + { + m_model.detach(observer); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, bool selected) const + { + if (selected) { + m_renderOrigin.render(renderer, volume, localToWorld); + } + + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, bool selected) const + { + renderSolid(renderer, volume, localToWorld, selected); + if (g_showNames) { + renderer.addRenderable(m_renderName, localToWorld); + } + } + + void translate(const Vector3 &translation) + { + m_origin = origin_translated(m_origin, translation); + } + + void rotate(const Quaternion &rotation) + { + m_angles = angles_rotated(m_angles, rotation); + } + + void scale(const Vector3 &scaling) + { + m_scale = scale_scaled(m_scale, scaling); + } + + void snapto(float snap) + { + m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap); + m_originKey.write(&m_entity); + } + + void revertTransform() + { + m_origin = m_originKey.m_origin; + m_angles = m_anglesKey.m_angles; + m_scale = m_scaleKey.m_scale; + } + + void freezeTransform() + { + m_originKey.m_origin = m_origin; + m_originKey.write(&m_entity); + m_anglesKey.m_angles = m_angles; + m_anglesKey.write(&m_entity); + m_scaleKey.m_scale = m_scale; + m_scaleKey.write(&m_entity); + } + + void transformChanged() + { + revertTransform(); + m_evaluateTransform(); + updateTransform(); + } + + typedef MemberCaller TransformChangedCaller; }; -class MiscModelNode : - public scene::Node::Symbiot, - public scene::Instantiable, - public scene::Cloneable, - public scene::Traversable::Observer -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; +class MiscModelInstance : public TargetableInstance, public TransformModifier, public Renderable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + m_casts = TargetableInstance::StaticTypeCasts::instance().get(); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceIdentityCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + MiscModel &m_contained; public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); - NodeStaticCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} + typedef LazyStatic StaticTypeCasts; + + STRING_CONSTANT(Name, "MiscModelInstance"); + + MiscModelInstance(const scene::Path &path, scene::Instance *parent, MiscModel &miscmodel) : + TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), miscmodel.getEntity(), *this), + TransformModifier(MiscModel::TransformChangedCaller(miscmodel), ApplyTransformCaller(*this)), + m_contained(miscmodel) + { + m_contained.instanceAttach(Instance::path()); + StaticRenderableConnectionLines::instance().attach(*this); + } + + ~MiscModelInstance() + { + StaticRenderableConnectionLines::instance().detach(*this); + m_contained.instanceDetach(Instance::path()); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected()); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected()); + } + + void evaluateTransform() + { + if (getType() == TRANSFORM_PRIMITIVE) { + m_contained.translate(getTranslation()); + m_contained.rotate(getRotation()); + m_contained.scale(getScale()); + } + } + + void applyTransform() + { + m_contained.revertTransform(); + evaluateTransform(); + m_contained.freezeTransform(); + } + + typedef MemberCaller ApplyTransformCaller; }; - -scene::Node m_node; -InstanceSet m_instances; -MiscModel m_contained; - -void construct(){ - m_contained.attach( this ); -} -void destroy(){ - m_contained.detach( this ); -} +class MiscModelNode : + public scene::Node::Symbiot, + public scene::Instantiable, + public scene::Cloneable, + public scene::Traversable::Observer { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + NodeStaticCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + } + + NodeTypeCastTable &get() + { + return m_casts; + } + }; + + + scene::Node m_node; + InstanceSet m_instances; + MiscModel m_contained; + + void construct() + { + m_contained.attach(this); + } + + void destroy() + { + m_contained.detach(this); + } public: -typedef LazyStatic StaticTypeCasts; - -scene::Traversable& get( NullType){ - return m_contained.getTraversable(); -} -Snappable& get( NullType){ - return m_contained; -} -TransformNode& get( NullType){ - return m_contained.getTransformNode(); -} -Entity& get( NullType){ - return m_contained.getEntity(); -} -Nameable& get( NullType){ - return m_contained.getNameable(); -} -Namespaced& get( NullType){ - return m_contained.getNamespaced(); -} - -MiscModelNode( EntityClass* eclass ) : - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -MiscModelNode( const MiscModelNode& other ) : - scene::Node::Symbiot( other ), - scene::Instantiable( other ), - scene::Cloneable( other ), - scene::Traversable::Observer( other ), - m_node( this, this, StaticTypeCasts::instance().get() ), - m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform::Caller( m_instances ) ){ - construct(); -} -~MiscModelNode(){ - destroy(); -} - -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} - -scene::Node& clone() const { - return ( new MiscModelNode( *this ) )->node(); -} - -void insert( scene::Node& child ){ - m_instances.insert( child ); -} -void erase( scene::Node& child ){ - m_instances.erase( child ); -} - -scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new MiscModelInstance( path, parent, m_contained ); -} -void forEachInstance( const scene::Instantiable::Visitor& visitor ){ - m_instances.forEachInstance( visitor ); -} -void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){ - m_instances.insert( observer, path, instance ); -} -scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){ - return m_instances.erase( observer, path ); -} + typedef LazyStatic StaticTypeCasts; + + scene::Traversable &get(NullType) + { + return m_contained.getTraversable(); + } + + Snappable &get(NullType) + { + return m_contained; + } + + TransformNode &get(NullType) + { + return m_contained.getTransformNode(); + } + + Entity &get(NullType) + { + return m_contained.getEntity(); + } + + Nameable &get(NullType) + { + return m_contained.getNameable(); + } + + Namespaced &get(NullType) + { + return m_contained.getNamespaced(); + } + + MiscModelNode(EntityClass *eclass) : + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + MiscModelNode(const MiscModelNode &other) : + scene::Node::Symbiot(other), + scene::Instantiable(other), + scene::Cloneable(other), + scene::Traversable::Observer(other), + m_node(this, this, StaticTypeCasts::instance().get()), + m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), + InstanceSetEvaluateTransform::Caller(m_instances)) + { + construct(); + } + + ~MiscModelNode() + { + destroy(); + } + + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } + + scene::Node &clone() const + { + return (new MiscModelNode(*this))->node(); + } + + void insert(scene::Node &child) + { + m_instances.insert(child); + } + + void erase(scene::Node &child) + { + m_instances.erase(child); + } + + scene::Instance *create(const scene::Path &path, scene::Instance *parent) + { + return new MiscModelInstance(path, parent, m_contained); + } + + void forEachInstance(const scene::Instantiable::Visitor &visitor) + { + m_instances.forEachInstance(visitor); + } + + void insert(scene::Instantiable::Observer *observer, const scene::Path &path, scene::Instance *instance) + { + m_instances.insert(observer, path, instance); + } + + scene::Instance *erase(scene::Instantiable::Observer *observer, const scene::Path &path) + { + return m_instances.erase(observer, path); + } }; -scene::Node& New_MiscModel( EntityClass* eclass ){ - return ( new MiscModelNode( eclass ) )->node(); +scene::Node &New_MiscModel(EntityClass *eclass) +{ + return (new MiscModelNode(eclass))->node(); } -void MiscModel_construct(){ +void MiscModel_construct() +{ } -void MiscModel_destroy(){ + +void MiscModel_destroy() +{ } diff --git a/plugins/entity/miscmodel.h b/plugins/entity/miscmodel.h index a6fba44c..228aeca2 100644 --- a/plugins/entity/miscmodel.h +++ b/plugins/entity/miscmodel.h @@ -22,8 +22,10 @@ #if !defined( INCLUDED_MISCMODEL_H ) #define INCLUDED_MISCMODEL_H -scene::Node& New_MiscModel( EntityClass* eclass ); +scene::Node &New_MiscModel(EntityClass *eclass); + void MiscModel_construct(); + void MiscModel_destroy(); #endif diff --git a/plugins/entity/model.h b/plugins/entity/model.h index 75e442f1..5e5dc116 100644 --- a/plugins/entity/model.h +++ b/plugins/entity/model.h @@ -29,81 +29,98 @@ #include "os/path.h" #include "moduleobserver.h" -class EModel : public ModuleObserver -{ -ResourceReference m_resource; -scene::Traversable& m_traverse; -scene::Node* m_node; -Callback m_modelChanged; +class EModel : public ModuleObserver { + ResourceReference m_resource; + scene::Traversable &m_traverse; + scene::Node *m_node; + Callback m_modelChanged; public: -EModel( scene::Traversable& traversable, const Callback& modelChanged ) - : m_resource( "" ), m_traverse( traversable ), m_node( 0 ), m_modelChanged( modelChanged ){ - m_resource.attach( *this ); -} -~EModel(){ - m_resource.detach( *this ); -} - -void realise(){ - m_resource.get()->load(); - m_node = m_resource.get()->getNode(); - if ( m_node != 0 ) { - m_traverse.insert( *m_node ); - } -} -void unrealise(){ - if ( m_node != 0 ) { - m_traverse.erase( *m_node ); - } -} - -void modelChanged( const char* value ){ - StringOutputStream cleaned( string_length( value ) ); - cleaned << PathCleaned( value ); - m_resource.detach( *this ); - m_resource.setName( cleaned.c_str() ); - m_resource.attach( *this ); - m_modelChanged(); -} -typedef MemberCaller ModelChangedCaller; - -const char* getName() const { - return m_resource.getName(); -} -scene::Node* getNode() const { - return m_node; -} + EModel(scene::Traversable &traversable, const Callback &modelChanged) + : m_resource(""), m_traverse(traversable), m_node(0), m_modelChanged(modelChanged) + { + m_resource.attach(*this); + } + + ~EModel() + { + m_resource.detach(*this); + } + + void realise() + { + m_resource.get()->load(); + m_node = m_resource.get()->getNode(); + if (m_node != 0) { + m_traverse.insert(*m_node); + } + } + + void unrealise() + { + if (m_node != 0) { + m_traverse.erase(*m_node); + } + } + + void modelChanged(const char *value) + { + StringOutputStream cleaned(string_length(value)); + cleaned << PathCleaned(value); + m_resource.detach(*this); + m_resource.setName(cleaned.c_str()); + m_resource.attach(*this); + m_modelChanged(); + } + + typedef MemberCaller ModelChangedCaller; + + const char *getName() const + { + return m_resource.getName(); + } + + scene::Node *getNode() const + { + return m_node; + } }; -class SingletonModel -{ -TraversableNode m_traverse; -EModel m_model; +class SingletonModel { + TraversableNode m_traverse; + EModel m_model; public: -SingletonModel() - : m_model( m_traverse, Callback() ){ -} - -void attach( scene::Traversable::Observer* observer ){ - m_traverse.attach( observer ); -} -void detach( scene::Traversable::Observer* observer ){ - m_traverse.detach( observer ); -} - -scene::Traversable& getTraversable(){ - return m_traverse; -} - -void modelChanged( const char* value ){ - m_model.modelChanged( value ); -} -typedef MemberCaller ModelChangedCaller; - -scene::Node* getNode() const { - return m_model.getNode(); -} + SingletonModel() + : m_model(m_traverse, Callback()) + { + } + + void attach(scene::Traversable::Observer *observer) + { + m_traverse.attach(observer); + } + + void detach(scene::Traversable::Observer *observer) + { + m_traverse.detach(observer); + } + + scene::Traversable &getTraversable() + { + return m_traverse; + } + + void modelChanged(const char *value) + { + m_model.modelChanged(value); + } + + typedef MemberCaller ModelChangedCaller; + + scene::Node *getNode() const + { + return m_model.getNode(); + } }; #endif diff --git a/plugins/entity/modelskinkey.h b/plugins/entity/modelskinkey.h index 96364015..f1c1cca2 100644 --- a/plugins/entity/modelskinkey.h +++ b/plugins/entity/modelskinkey.h @@ -30,70 +30,86 @@ #include "entitylib.h" #include "traverselib.h" -inline void parseTextureName( CopiedString& name, const char* token ){ - StringOutputStream cleaned( 256 ); - cleaned << PathCleaned( token ); - name = StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ); // remove extension +inline void parseTextureName(CopiedString &name, const char *token) +{ + StringOutputStream cleaned(256); + cleaned << PathCleaned(token); + name = StringRange(cleaned.c_str(), path_get_filename_base_end(cleaned.c_str())); // remove extension } -class ModelSkinKey : public ModuleObserver -{ -CopiedString m_name; -ModelSkin* m_skin; -Callback m_skinChangedCallback; +class ModelSkinKey : public ModuleObserver { + CopiedString m_name; + ModelSkin *m_skin; + Callback m_skinChangedCallback; -ModelSkinKey( const ModelSkinKey& ); -ModelSkinKey operator=( const ModelSkinKey& ); + ModelSkinKey(const ModelSkinKey &); -void construct(){ - m_skin = &GlobalModelSkinCache().capture( m_name.c_str() ); - m_skin->attach( *this ); -} -void destroy(){ - m_skin->detach( *this ); - GlobalModelSkinCache().release( m_name.c_str() ); -} + ModelSkinKey operator=(const ModelSkinKey &); -public: -ModelSkinKey( const Callback& skinChangedCallback ) : m_skinChangedCallback( skinChangedCallback ){ - construct(); -} -~ModelSkinKey(){ - destroy(); -} -ModelSkin& get() const { - return *m_skin; -} -void skinChanged( const char* value ){ - destroy(); - parseTextureName( m_name, value ); - construct(); -} -typedef MemberCaller SkinChangedCaller; + void construct() + { + m_skin = &GlobalModelSkinCache().capture(m_name.c_str()); + m_skin->attach(*this); + } -void realise(){ - m_skinChangedCallback(); -} -void unrealise(){ -} + void destroy() + { + m_skin->detach(*this); + GlobalModelSkinCache().release(m_name.c_str()); + } + +public: + ModelSkinKey(const Callback &skinChangedCallback) : m_skinChangedCallback(skinChangedCallback) + { + construct(); + } + + ~ModelSkinKey() + { + destroy(); + } + + ModelSkin &get() const + { + return *m_skin; + } + + void skinChanged(const char *value) + { + destroy(); + parseTextureName(m_name, value); + construct(); + } + + typedef MemberCaller SkinChangedCaller; + + void realise() + { + m_skinChangedCallback(); + } + + void unrealise() + { + } }; -class InstanceSkinChanged : public scene::Instantiable::Visitor -{ +class InstanceSkinChanged : public scene::Instantiable::Visitor { public: -void visit( scene::Instance& instance ) const { - //\todo don't do this for instances that are not children of the entity setting the skin - SkinnedModel* skinned = InstanceTypeCast::cast( instance ); - if ( skinned != 0 ) { - skinned->skinChanged(); - } -} + void visit(scene::Instance &instance) const + { + //\todo don't do this for instances that are not children of the entity setting the skin + SkinnedModel *skinned = InstanceTypeCast::cast(instance); + if (skinned != 0) { + skinned->skinChanged(); + } + } }; -inline void Node_modelSkinChanged( scene::Node& node ){ - scene::Instantiable* instantiable = Node_getInstantiable( node ); - ASSERT_NOTNULL( instantiable ); - instantiable->forEachInstance( InstanceSkinChanged() ); +inline void Node_modelSkinChanged(scene::Node &node) +{ + scene::Instantiable *instantiable = Node_getInstantiable(node); + ASSERT_NOTNULL(instantiable); + instantiable->forEachInstance(InstanceSkinChanged()); } #endif diff --git a/plugins/entity/namedentity.h b/plugins/entity/namedentity.h index 857b10b4..6d40380a 100644 --- a/plugins/entity/namedentity.h +++ b/plugins/entity/namedentity.h @@ -29,73 +29,83 @@ #include -class NameCallbackSet -{ -typedef std::set NameCallbacks; -NameCallbacks m_callbacks; +class NameCallbackSet { + typedef std::set NameCallbacks; + NameCallbacks m_callbacks; public: -void insert( const NameCallback& callback ){ - m_callbacks.insert( callback ); -} -void erase( const NameCallback& callback ){ - m_callbacks.erase( callback ); -} -void changed( const char* name ) const { - for ( NameCallbacks::const_iterator i = m_callbacks.begin(); i != m_callbacks.end(); ++i ) - { - ( *i )( name ); - } -} + void insert(const NameCallback &callback) + { + m_callbacks.insert(callback); + } + + void erase(const NameCallback &callback) + { + m_callbacks.erase(callback); + } + + void changed(const char *name) const + { + for (NameCallbacks::const_iterator i = m_callbacks.begin(); i != m_callbacks.end(); ++i) { + (*i)(name); + } + } }; -class NamedEntity : public Nameable -{ -EntityKeyValues& m_entity; -NameCallbackSet m_changed; -CopiedString m_name; +class NamedEntity : public Nameable { + EntityKeyValues &m_entity; + NameCallbackSet m_changed; + CopiedString m_name; public: -NamedEntity( EntityKeyValues& entity ) : m_entity( entity ){ -} -const char* name() const { - if ( string_empty( m_name.c_str() ) ) { - return m_entity.getEntityClass().name(); - } - return m_name.c_str(); -} -void attach( const NameCallback& callback ){ - m_changed.insert( callback ); -} -void detach( const NameCallback& callback ){ - m_changed.erase( callback ); -} - -void identifierChanged( const char* value ){ - if ( string_empty( value ) ) { - m_changed.changed( m_entity.getEntityClass().name() ); - } - else - { - m_changed.changed( value ); - } - m_name = value; -} -typedef MemberCaller IdentifierChangedCaller; + NamedEntity(EntityKeyValues &entity) : m_entity(entity) + { + } + + const char *name() const + { + if (string_empty(m_name.c_str())) { + return m_entity.getEntityClass().name(); + } + return m_name.c_str(); + } + + void attach(const NameCallback &callback) + { + m_changed.insert(callback); + } + + void detach(const NameCallback &callback) + { + m_changed.erase(callback); + } + + void identifierChanged(const char *value) + { + if (string_empty(value)) { + m_changed.changed(m_entity.getEntityClass().name()); + } else { + m_changed.changed(value); + } + m_name = value; + } + + typedef MemberCaller IdentifierChangedCaller; }; -class RenderableNamedEntity : public OpenGLRenderable -{ -const NamedEntity& m_named; -const Vector3& m_position; +class RenderableNamedEntity : public OpenGLRenderable { + const NamedEntity &m_named; + const Vector3 &m_position; public: -RenderableNamedEntity( const NamedEntity& named, const Vector3& position ) - : m_named( named ), m_position( position ){ -} -void render( RenderStateFlags state ) const { - glRasterPos3fv( vector3_to_array( m_position ) ); - GlobalOpenGL().drawString( m_named.name() ); -} -}; + RenderableNamedEntity(const NamedEntity &named, const Vector3 &position) + : m_named(named), m_position(position) + { + } + void render(RenderStateFlags state) const + { + glRasterPos3fv(vector3_to_array(m_position)); + GlobalOpenGL().drawString(m_named.name()); + } +}; #endif diff --git a/plugins/entity/namekeys.h b/plugins/entity/namekeys.h index 45943f1f..f298674c 100644 --- a/plugins/entity/namekeys.h +++ b/plugins/entity/namekeys.h @@ -28,106 +28,129 @@ #include "entitylib.h" #include "namespace.h" -inline bool string_is_integer( const char* string ){ - strtol( string, const_cast( &string ), 10 ); - return *string == '\0'; +inline bool string_is_integer(const char *string) +{ + strtol(string, const_cast( &string ), 10); + return *string == '\0'; } -typedef bool ( *KeyIsNameFunc )( const char* key ); +typedef bool ( *KeyIsNameFunc )(const char *key); -class KeyIsName -{ +class KeyIsName { public: -KeyIsNameFunc m_keyIsName; -const char* m_nameKey; + KeyIsNameFunc m_keyIsName; + const char *m_nameKey; -KeyIsName(){ -} + KeyIsName() + { + } }; -typedef MemberCaller KeyValueAssignCaller; -typedef MemberCaller KeyValueAttachCaller; -typedef MemberCaller KeyValueDetachCaller; +typedef MemberCaller KeyValueAssignCaller; +typedef MemberCaller KeyValueAttachCaller; +typedef MemberCaller KeyValueDetachCaller; + +class NameKeys : public Entity::Observer, public Namespaced { + Namespace *m_namespace; + EntityKeyValues &m_entity; + KeyIsNameFunc m_keyIsName; + + NameKeys(const NameKeys &other); + + NameKeys &operator=(const NameKeys &other); + + typedef std::map KeyValues; + KeyValues m_keyValues; + + void insertName(const char *key, EntityKeyValue &value) + { + if (m_namespace != 0 && m_keyIsName(key)) { + //globalOutputStream() << "insert " << key << "\n"; + m_namespace->attach(KeyValueAssignCaller(value), KeyValueAttachCaller(value)); + } + } + + void eraseName(const char *key, EntityKeyValue &value) + { + if (m_namespace != 0 && m_keyIsName(key)) { + //globalOutputStream() << "erase " << key << "\n"; + m_namespace->detach(KeyValueAssignCaller(value), KeyValueDetachCaller(value)); + } + } + + void insertAll() + { + for (KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i) { + insertName((*i).first.c_str(), *(*i).second); + } + } + + void eraseAll() + { + for (KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i) { + eraseName((*i).first.c_str(), *(*i).second); + } + } -class NameKeys : public Entity::Observer, public Namespaced -{ -Namespace* m_namespace; -EntityKeyValues& m_entity; -KeyIsNameFunc m_keyIsName; -NameKeys( const NameKeys& other ); -NameKeys& operator=( const NameKeys& other ); - -typedef std::map KeyValues; -KeyValues m_keyValues; - -void insertName( const char* key, EntityKeyValue& value ){ - if ( m_namespace != 0 && m_keyIsName( key ) ) { - //globalOutputStream() << "insert " << key << "\n"; - m_namespace->attach( KeyValueAssignCaller( value ), KeyValueAttachCaller( value ) ); - } -} -void eraseName( const char* key, EntityKeyValue& value ){ - if ( m_namespace != 0 && m_keyIsName( key ) ) { - //globalOutputStream() << "erase " << key << "\n"; - m_namespace->detach( KeyValueAssignCaller( value ), KeyValueDetachCaller( value ) ); - } -} -void insertAll(){ - for ( KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i ) - { - insertName( ( *i ).first.c_str(), *( *i ).second ); - } -} -void eraseAll(){ - for ( KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i ) - { - eraseName( ( *i ).first.c_str(), *( *i ).second ); - } -} public: -NameKeys( EntityKeyValues& entity ) : m_namespace( 0 ), m_entity( entity ), m_keyIsName( Static::instance().m_keyIsName ){ - m_entity.attach( *this ); -} -~NameKeys(){ - m_entity.detach( *this ); -} -void setNamespace( Namespace& space ){ - eraseAll(); - m_namespace = &space; - insertAll(); -} -void setKeyIsName( KeyIsNameFunc keyIsName ){ - eraseAll(); - m_keyIsName = keyIsName; - insertAll(); -} -void insert( const char* key, EntityKeyValue& value ){ - m_keyValues.insert( KeyValues::value_type( key, &value ) ); - insertName( key, value ); -} -void erase( const char* key, EntityKeyValue& value ){ - eraseName( key, value ); - m_keyValues.erase( key ); -} + NameKeys(EntityKeyValues &entity) : m_namespace(0), m_entity(entity), + m_keyIsName(Static::instance().m_keyIsName) + { + m_entity.attach(*this); + } + + ~NameKeys() + { + m_entity.detach(*this); + } + + void setNamespace(Namespace &space) + { + eraseAll(); + m_namespace = &space; + insertAll(); + } + + void setKeyIsName(KeyIsNameFunc keyIsName) + { + eraseAll(); + m_keyIsName = keyIsName; + insertAll(); + } + + void insert(const char *key, EntityKeyValue &value) + { + m_keyValues.insert(KeyValues::value_type(key, &value)); + insertName(key, value); + } + + void erase(const char *key, EntityKeyValue &value) + { + eraseName(key, value); + m_keyValues.erase(key); + } }; -inline bool keyIsNameDoom3( const char* key ){ - return string_equal( key, "target" ) - || ( string_equal_n( key, "target", 6 ) && string_is_integer( key + 6 ) ) - || string_equal( key, "name" ); +inline bool keyIsNameDoom3(const char *key) +{ + return string_equal(key, "target") + || (string_equal_n(key, "target", 6) && string_is_integer(key + 6)) + || string_equal(key, "name"); } -inline bool keyIsNameDoom3Doom3Group( const char* key ){ - return keyIsNameDoom3( key ) - || string_equal( key, "model" ); +inline bool keyIsNameDoom3Doom3Group(const char *key) +{ + return keyIsNameDoom3(key) + || string_equal(key, "model"); } -inline bool keyIsNameQuake3( const char* key ){ - return string_equal( key, "target" ) - || string_equal( key, "targetname" ) - || string_equal( key, "killtarget" ) - || ( string_equal_n( key, "target", 6 ) && string_is_integer( key + 6 ) ); // Nexuiz +inline bool keyIsNameQuake3(const char *key) +{ + return string_equal(key, "target") + || string_equal(key, "targetname") + || string_equal(key, "killtarget") + || (string_equal_n(key, "target", 6) && string_is_integer(key + 6)); // Nexuiz } #endif diff --git a/plugins/entity/origin.h b/plugins/entity/origin.h index 84bb7462..1259b9b0 100644 --- a/plugins/entity/origin.h +++ b/plugins/entity/origin.h @@ -28,118 +28,139 @@ #include "generic/callback.h" #include "stringio.h" -const Vector3 ORIGINKEY_IDENTITY = Vector3( 0, 0, 0 ); +const Vector3 ORIGINKEY_IDENTITY = Vector3(0, 0, 0); -inline void default_origin( Vector3& origin ){ - origin = ORIGINKEY_IDENTITY; -} -inline void read_origin( Vector3& origin, const char* value ){ - if ( !string_parse_vector3( value, origin ) ) { - default_origin( origin ); - } +inline void default_origin(Vector3 &origin) +{ + origin = ORIGINKEY_IDENTITY; } -inline void write_origin( const Vector3& origin, Entity* entity, const char* key ){ - char value[64]; - sprintf( value, "%f %f %f", origin[0], origin[1], origin[2] ); - entity->setKeyValue( key, value ); + +inline void read_origin(Vector3 &origin, const char *value) +{ + if (!string_parse_vector3(value, origin)) { + default_origin(origin); + } } -inline Vector3 origin_translated( const Vector3& origin, const Vector3& translation ){ - return matrix4_get_translation_vec3( - matrix4_multiplied_by_matrix4( - matrix4_translation_for_vec3( origin ), - matrix4_translation_for_vec3( translation ) - ) - ); +inline void write_origin(const Vector3 &origin, Entity *entity, const char *key) +{ + char value[64]; + sprintf(value, "%f %f %f", origin[0], origin[1], origin[2]); + entity->setKeyValue(key, value); } -inline Vector3 origin_snapped( const Vector3& origin, float snap ){ - return vector3_snapped( origin, snap ); +inline Vector3 origin_translated(const Vector3 &origin, const Vector3 &translation) +{ + return matrix4_get_translation_vec3( + matrix4_multiplied_by_matrix4( + matrix4_translation_for_vec3(origin), + matrix4_translation_for_vec3(translation) + ) + ); } -class OriginKey +inline Vector3 origin_snapped(const Vector3 &origin, float snap) { -Callback m_originChanged; + return vector3_snapped(origin, snap); +} + +class OriginKey { + Callback m_originChanged; public: -Vector3 m_origin; + Vector3 m_origin; -OriginKey( const Callback& originChanged ) - : m_originChanged( originChanged ), m_origin( ORIGINKEY_IDENTITY ){ -} + OriginKey(const Callback &originChanged) + : m_originChanged(originChanged), m_origin(ORIGINKEY_IDENTITY) + { + } -void originChanged( const char* value ){ - read_origin( m_origin, value ); - m_originChanged(); -} -typedef MemberCaller OriginChangedCaller; + void originChanged(const char *value) + { + read_origin(m_origin, value); + m_originChanged(); + } + typedef MemberCaller OriginChangedCaller; -void write( Entity* entity ) const { - write_origin( m_origin, entity, "origin" ); -} + + void write(Entity *entity) const + { + write_origin(m_origin, entity, "origin"); + } }; #include "scenelib.h" -inline BrushDoom3* Node_getBrushDoom3( scene::Node& node ){ - return NodeTypeCast::cast( node ); +inline BrushDoom3 *Node_getBrushDoom3(scene::Node &node) +{ + return NodeTypeCast::cast(node); } -inline void BrushDoom3_setDoom3GroupOrigin( scene::Node& node, const Vector3& origin ){ - BrushDoom3* brush = Node_getBrushDoom3( node ); - if ( brush != 0 ) { - brush->setDoom3GroupOrigin( origin ); - } +inline void BrushDoom3_setDoom3GroupOrigin(scene::Node &node, const Vector3 &origin) +{ + BrushDoom3 *brush = Node_getBrushDoom3(node); + if (brush != 0) { + brush->setDoom3GroupOrigin(origin); + } } -class SetDoom3GroupOriginWalker : public scene::Traversable::Walker -{ -const Vector3& m_origin; +class SetDoom3GroupOriginWalker : public scene::Traversable::Walker { + const Vector3 &m_origin; public: -SetDoom3GroupOriginWalker( const Vector3& origin ) : m_origin( origin ){ -} -bool pre( scene::Node& node ) const { - BrushDoom3_setDoom3GroupOrigin( node, m_origin ); - return true; -} + SetDoom3GroupOriginWalker(const Vector3 &origin) : m_origin(origin) + { + } + + bool pre(scene::Node &node) const + { + BrushDoom3_setDoom3GroupOrigin(node, m_origin); + return true; + } }; -class Doom3GroupOrigin : public scene::Traversable::Observer -{ -scene::Traversable& m_set; -const Vector3& m_origin; -bool m_enabled; +class Doom3GroupOrigin : public scene::Traversable::Observer { + scene::Traversable &m_set; + const Vector3 &m_origin; + bool m_enabled; public: -Doom3GroupOrigin( scene::Traversable& set, const Vector3& origin ) : m_set( set ), m_origin( origin ), m_enabled( false ){ -} - -void enable(){ - m_enabled = true; - originChanged(); -} -void disable(){ - m_enabled = false; -} - -void originChanged(){ - if ( m_enabled ) { - m_set.traverse( SetDoom3GroupOriginWalker( m_origin ) ); - } -} - -void insert( scene::Node& node ){ - if ( m_enabled ) { - BrushDoom3_setDoom3GroupOrigin( node, m_origin ); - } -} -void erase( scene::Node& node ){ - if ( m_enabled ) { - BrushDoom3_setDoom3GroupOrigin( node, Vector3( 0, 0, 0 ) ); - } -} + Doom3GroupOrigin(scene::Traversable &set, const Vector3 &origin) : m_set(set), m_origin(origin), m_enabled(false) + { + } + + void enable() + { + m_enabled = true; + originChanged(); + } + + void disable() + { + m_enabled = false; + } + + void originChanged() + { + if (m_enabled) { + m_set.traverse(SetDoom3GroupOriginWalker(m_origin)); + } + } + + void insert(scene::Node &node) + { + if (m_enabled) { + BrushDoom3_setDoom3GroupOrigin(node, m_origin); + } + } + + void erase(scene::Node &node) + { + if (m_enabled) { + BrushDoom3_setDoom3GroupOrigin(node, Vector3(0, 0, 0)); + } + } }; diff --git a/plugins/entity/plugin.cpp b/plugins/entity/plugin.cpp index 58b6fb37..d67ad14c 100644 --- a/plugins/entity/plugin.cpp +++ b/plugins/entity/plugin.cpp @@ -43,40 +43,44 @@ #include "modulesystem/singletonmodule.h" class EntityDependencies : - public GlobalRadiantModuleRef, - public GlobalOpenGLModuleRef, - public GlobalUndoModuleRef, - public GlobalSceneGraphModuleRef, - public GlobalShaderCacheModuleRef, - public GlobalSelectionModuleRef, - public GlobalReferenceModuleRef, - public GlobalFilterModuleRef, - public GlobalPreferenceSystemModuleRef, - public GlobalNamespaceModuleRef, - public GlobalModelSkinCacheModuleRef -{ + public GlobalRadiantModuleRef, + public GlobalOpenGLModuleRef, + public GlobalUndoModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalSelectionModuleRef, + public GlobalReferenceModuleRef, + public GlobalFilterModuleRef, + public GlobalPreferenceSystemModuleRef, + public GlobalNamespaceModuleRef, + public GlobalModelSkinCacheModuleRef { }; -class EntityQ3API : public TypeSystemRef -{ -EntityCreator* m_entityq3; +class EntityQ3API : public TypeSystemRef { + EntityCreator *m_entityq3; public: -typedef EntityCreator Type; -STRING_CONSTANT( Name, "quake3" ); + typedef EntityCreator Type; -EntityQ3API(){ - Entity_Construct(); + STRING_CONSTANT(Name, "quake3"); - m_entityq3 = &GetEntityCreator(); + EntityQ3API() + { + Entity_Construct(); - GlobalReferenceCache().setEntityCreator( *m_entityq3 ); -} -~EntityQ3API(){ - Entity_Destroy(); -} -EntityCreator* getTable(){ - return m_entityq3; -} + m_entityq3 = &GetEntityCreator(); + + GlobalReferenceCache().setEntityCreator(*m_entityq3); + } + + ~EntityQ3API() + { + Entity_Destroy(); + } + + EntityCreator *getTable() + { + return m_entityq3; + } }; typedef SingletonModule EntityQ3Module; @@ -84,26 +88,31 @@ typedef SingletonModule EntityQ3Module; EntityQ3Module g_EntityQ3Module; -class EntityWolfAPI : public TypeSystemRef -{ -EntityCreator* m_entitywolf; +class EntityWolfAPI : public TypeSystemRef { + EntityCreator *m_entitywolf; public: -typedef EntityCreator Type; -STRING_CONSTANT( Name, "wolf" ); + typedef EntityCreator Type; -EntityWolfAPI(){ - Entity_Construct( eGameTypeRTCW ); + STRING_CONSTANT(Name, "wolf"); - m_entitywolf = &GetEntityCreator(); + EntityWolfAPI() + { + Entity_Construct(eGameTypeRTCW); - GlobalReferenceCache().setEntityCreator( *m_entitywolf ); -} -~EntityWolfAPI(){ - Entity_Destroy(); -} -EntityCreator* getTable(){ - return m_entitywolf; -} + m_entitywolf = &GetEntityCreator(); + + GlobalReferenceCache().setEntityCreator(*m_entitywolf); + } + + ~EntityWolfAPI() + { + Entity_Destroy(); + } + + EntityCreator *getTable() + { + return m_entitywolf; + } }; typedef SingletonModule EntityWolfModule; @@ -111,26 +120,31 @@ typedef SingletonModule EntityWolfModule; EntityWolfModule g_EntityWolfModule; -class EntityDoom3API : public TypeSystemRef -{ -EntityCreator* m_entitydoom3; +class EntityDoom3API : public TypeSystemRef { + EntityCreator *m_entitydoom3; public: -typedef EntityCreator Type; -STRING_CONSTANT( Name, "doom3" ); + typedef EntityCreator Type; -EntityDoom3API(){ - Entity_Construct( eGameTypeDoom3 ); + STRING_CONSTANT(Name, "doom3"); - m_entitydoom3 = &GetEntityCreator(); + EntityDoom3API() + { + Entity_Construct(eGameTypeDoom3); - GlobalReferenceCache().setEntityCreator( *m_entitydoom3 ); -} -~EntityDoom3API(){ - Entity_Destroy(); -} -EntityCreator* getTable(){ - return m_entitydoom3; -} + m_entitydoom3 = &GetEntityCreator(); + + GlobalReferenceCache().setEntityCreator(*m_entitydoom3); + } + + ~EntityDoom3API() + { + Entity_Destroy(); + } + + EntityCreator *getTable() + { + return m_entitydoom3; + } }; typedef SingletonModule EntityDoom3Module; @@ -138,11 +152,12 @@ typedef SingletonModule EntityDoom3Module; EntityDoom3Module g_EntityDoom3Module; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_EntityQ3Module.selfRegister(); - g_EntityWolfModule.selfRegister(); - g_EntityDoom3Module.selfRegister(); - Doom3ModelSkinCacheModule_selfRegister( server ); + g_EntityQ3Module.selfRegister(); + g_EntityWolfModule.selfRegister(); + g_EntityDoom3Module.selfRegister(); + Doom3ModelSkinCacheModule_selfRegister(server); } diff --git a/plugins/entity/rotation.h b/plugins/entity/rotation.h index 4c566d96..c11bb987 100644 --- a/plugins/entity/rotation.h +++ b/plugins/entity/rotation.h @@ -33,151 +33,160 @@ typedef float Float9[9]; -inline void default_rotation( Float9 rotation ){ - rotation[0] = 1; - rotation[1] = 0; - rotation[2] = 0; - rotation[3] = 0; - rotation[4] = 1; - rotation[5] = 0; - rotation[6] = 0; - rotation[7] = 0; - rotation[8] = 1; -} -inline void write_rotation( const Float9 rotation, Entity* entity, const char* key = "rotation" ){ - if ( rotation[0] == 1 - && rotation[1] == 0 - && rotation[2] == 0 - && rotation[3] == 0 - && rotation[4] == 1 - && rotation[5] == 0 - && rotation[6] == 0 - && rotation[7] == 0 - && rotation[8] == 1 ) { - entity->setKeyValue( key, "" ); - } - else - { - StringOutputStream value( 256 ); - value << rotation[0] << ' ' - << rotation[1] << ' ' - << rotation[2] << ' ' - << rotation[3] << ' ' - << rotation[4] << ' ' - << rotation[5] << ' ' - << rotation[6] << ' ' - << rotation[7] << ' ' - << rotation[8]; - entity->setKeyValue( key, value.c_str() ); - } -} -inline void read_rotation( Float9 rotation, const char* value ){ - if ( !string_parse_vector( value, rotation, rotation + 9 ) ) { - default_rotation( rotation ); - } +inline void default_rotation(Float9 rotation) +{ + rotation[0] = 1; + rotation[1] = 0; + rotation[2] = 0; + rotation[3] = 0; + rotation[4] = 1; + rotation[5] = 0; + rotation[6] = 0; + rotation[7] = 0; + rotation[8] = 1; } -inline Matrix4 rotation_toMatrix( const Float9 rotation ){ - return Matrix4( - rotation[0], - rotation[1], - rotation[2], - 0, - rotation[3], - rotation[4], - rotation[5], - 0, - rotation[6], - rotation[7], - rotation[8], - 0, - 0, - 0, - 0, - 1 - ); +inline void write_rotation(const Float9 rotation, Entity *entity, const char *key = "rotation") +{ + if (rotation[0] == 1 + && rotation[1] == 0 + && rotation[2] == 0 + && rotation[3] == 0 + && rotation[4] == 1 + && rotation[5] == 0 + && rotation[6] == 0 + && rotation[7] == 0 + && rotation[8] == 1) { + entity->setKeyValue(key, ""); + } else { + StringOutputStream value(256); + value << rotation[0] << ' ' + << rotation[1] << ' ' + << rotation[2] << ' ' + << rotation[3] << ' ' + << rotation[4] << ' ' + << rotation[5] << ' ' + << rotation[6] << ' ' + << rotation[7] << ' ' + << rotation[8]; + entity->setKeyValue(key, value.c_str()); + } } -inline void rotation_fromMatrix( Float9 rotation, const Matrix4& matrix ){ - rotation[0] = matrix.xx(); - rotation[1] = matrix.xy(); - rotation[2] = matrix.xz(); - rotation[3] = matrix.yx(); - rotation[4] = matrix.yy(); - rotation[5] = matrix.yz(); - rotation[6] = matrix.zx(); - rotation[7] = matrix.zy(); - rotation[8] = matrix.zz(); +inline void read_rotation(Float9 rotation, const char *value) +{ + if (!string_parse_vector(value, rotation, rotation + 9)) { + default_rotation(rotation); + } } -inline void rotation_assign( Float9 rotation, const Float9 other ){ - rotation[0] = other[0]; - rotation[1] = other[1]; - rotation[2] = other[2]; - rotation[3] = other[3]; - rotation[4] = other[4]; - rotation[5] = other[5]; - rotation[6] = other[6]; - rotation[7] = other[7]; - rotation[8] = other[8]; +inline Matrix4 rotation_toMatrix(const Float9 rotation) +{ + return Matrix4( + rotation[0], + rotation[1], + rotation[2], + 0, + rotation[3], + rotation[4], + rotation[5], + 0, + rotation[6], + rotation[7], + rotation[8], + 0, + 0, + 0, + 0, + 1 + ); } -inline void rotation_rotate( Float9 rotation, const Quaternion& rotate ){ - rotation_fromMatrix( rotation, - matrix4_multiplied_by_matrix4( - rotation_toMatrix( rotation ), - matrix4_rotation_for_quaternion_quantised( rotate ) - ) - ); +inline void rotation_fromMatrix(Float9 rotation, const Matrix4 &matrix) +{ + rotation[0] = matrix.xx(); + rotation[1] = matrix.xy(); + rotation[2] = matrix.xz(); + rotation[3] = matrix.yx(); + rotation[4] = matrix.yy(); + rotation[5] = matrix.yz(); + rotation[6] = matrix.zx(); + rotation[7] = matrix.zy(); + rotation[8] = matrix.zz(); } -inline void read_angle( Float9 rotation, const char* value ){ - float angle; - if ( !string_parse_float( value, angle ) ) { - default_rotation( rotation ); - } - else - { - rotation_fromMatrix( rotation, matrix4_rotation_for_z_degrees( angle ) ); - } +inline void rotation_assign(Float9 rotation, const Float9 other) +{ + rotation[0] = other[0]; + rotation[1] = other[1]; + rotation[2] = other[2]; + rotation[3] = other[3]; + rotation[4] = other[4]; + rotation[5] = other[5]; + rotation[6] = other[6]; + rotation[7] = other[7]; + rotation[8] = other[8]; } -class RotationKey +inline void rotation_rotate(Float9 rotation, const Quaternion &rotate) { -Callback m_rotationChanged; -public: -Float9 m_rotation; - - -RotationKey( const Callback& rotationChanged ) - : m_rotationChanged( rotationChanged ){ - default_rotation( m_rotation ); + rotation_fromMatrix(rotation, + matrix4_multiplied_by_matrix4( + rotation_toMatrix(rotation), + matrix4_rotation_for_quaternion_quantised(rotate) + ) + ); } -void angleChanged( const char* value ){ - read_angle( m_rotation, value ); - m_rotationChanged(); +inline void read_angle(Float9 rotation, const char *value) +{ + float angle; + if (!string_parse_float(value, angle)) { + default_rotation(rotation); + } else { + rotation_fromMatrix(rotation, matrix4_rotation_for_z_degrees(angle)); + } } -typedef MemberCaller AngleChangedCaller; -void rotationChanged( const char* value ){ - read_rotation( m_rotation, value ); - m_rotationChanged(); -} -typedef MemberCaller RotationChangedCaller; - -void write( Entity* entity ) const { - Vector3 euler = matrix4_get_rotation_euler_xyz_degrees( rotation_toMatrix( m_rotation ) ); - if ( euler[0] == 0 && euler[1] == 0 ) { - entity->setKeyValue( "rotation", "" ); - write_angle( euler[2], entity ); - } - else - { - entity->setKeyValue( "angle", "" ); - write_rotation( m_rotation, entity ); - } -} +class RotationKey { + Callback m_rotationChanged; +public: + Float9 m_rotation; + + + RotationKey(const Callback &rotationChanged) + : m_rotationChanged(rotationChanged) + { + default_rotation(m_rotation); + } + + void angleChanged(const char *value) + { + read_angle(m_rotation, value); + m_rotationChanged(); + } + + typedef MemberCaller AngleChangedCaller; + + void rotationChanged(const char *value) + { + read_rotation(m_rotation, value); + m_rotationChanged(); + } + + typedef MemberCaller RotationChangedCaller; + + void write(Entity *entity) const + { + Vector3 euler = matrix4_get_rotation_euler_xyz_degrees(rotation_toMatrix(m_rotation)); + if (euler[0] == 0 && euler[1] == 0) { + entity->setKeyValue("rotation", ""); + write_angle(euler[2], entity); + } else { + entity->setKeyValue("angle", ""); + write_rotation(m_rotation, entity); + } + } }; #endif diff --git a/plugins/entity/scale.h b/plugins/entity/scale.h index dfb2884a..a6115bd1 100644 --- a/plugins/entity/scale.h +++ b/plugins/entity/scale.h @@ -28,89 +28,96 @@ #include "generic/callback.h" #include "stringio.h" -const Vector3 SCALEKEY_IDENTITY = Vector3( 1, 1, 1 ); +const Vector3 SCALEKEY_IDENTITY = Vector3(1, 1, 1); -inline void default_scale( Vector3& scale ){ - scale = SCALEKEY_IDENTITY; +inline void default_scale(Vector3 &scale) +{ + scale = SCALEKEY_IDENTITY; } -inline void read_scale( Vector3& scalevec, const char* value ){ - float scale; - if ( !string_parse_float( value, scale ) - || scale == 0 ) { - default_scale( scalevec ); - } - else - { - scalevec = Vector3( scale, scale, scale ); - } + +inline void read_scale(Vector3 &scalevec, const char *value) +{ + float scale; + if (!string_parse_float(value, scale) + || scale == 0) { + default_scale(scalevec); + } else { + scalevec = Vector3(scale, scale, scale); + } } -inline void read_scalevec( Vector3& scale, const char* value ){ - if ( !string_parse_vector3( value, scale ) - || scale[0] == 0 - || scale[1] == 0 - || scale[2] == 0 ) { - default_scale( scale ); - } + +inline void read_scalevec(Vector3 &scale, const char *value) +{ + if (!string_parse_vector3(value, scale) + || scale[0] == 0 + || scale[1] == 0 + || scale[2] == 0) { + default_scale(scale); + } } -inline void write_scale( const Vector3& scale, Entity* entity ){ - if ( scale[0] == 1 && scale[1] == 1 && scale[2] == 1 ) { - entity->setKeyValue( "modelscale", "" ); - entity->setKeyValue( "modelscale_vec", "" ); - } - else - { - char value[64]; - - if ( scale[0] == scale[1] && scale[0] == scale[2] ) { - sprintf( value, "%f", scale[0] ); - entity->setKeyValue( "modelscale_vec", "" ); - entity->setKeyValue( "modelscale", value ); - } - else - { - sprintf( value, "%f %f %f", scale[0], scale[1], scale[2] ); - entity->setKeyValue( "modelscale", "" ); - entity->setKeyValue( "modelscale_vec", value ); - } - } + +inline void write_scale(const Vector3 &scale, Entity *entity) +{ + if (scale[0] == 1 && scale[1] == 1 && scale[2] == 1) { + entity->setKeyValue("modelscale", ""); + entity->setKeyValue("modelscale_vec", ""); + } else { + char value[64]; + + if (scale[0] == scale[1] && scale[0] == scale[2]) { + sprintf(value, "%f", scale[0]); + entity->setKeyValue("modelscale_vec", ""); + entity->setKeyValue("modelscale", value); + } else { + sprintf(value, "%f %f %f", scale[0], scale[1], scale[2]); + entity->setKeyValue("modelscale", ""); + entity->setKeyValue("modelscale_vec", value); + } + } } -inline Vector3 scale_scaled( const Vector3& scale, const Vector3& scaling ){ - return matrix4_get_scale_vec3( - matrix4_multiplied_by_matrix4( - matrix4_scale_for_vec3( scale ), - matrix4_scale_for_vec3( scaling ) - ) - ); +inline Vector3 scale_scaled(const Vector3 &scale, const Vector3 &scaling) +{ + return matrix4_get_scale_vec3( + matrix4_multiplied_by_matrix4( + matrix4_scale_for_vec3(scale), + matrix4_scale_for_vec3(scaling) + ) + ); } -class ScaleKey -{ -Callback m_scaleChanged; +class ScaleKey { + Callback m_scaleChanged; public: -Vector3 m_scale; + Vector3 m_scale; -ScaleKey( const Callback& scaleChanged ) - : m_scaleChanged( scaleChanged ), m_scale( SCALEKEY_IDENTITY ){ -} + ScaleKey(const Callback &scaleChanged) + : m_scaleChanged(scaleChanged), m_scale(SCALEKEY_IDENTITY) + { + } -void uniformScaleChanged( const char* value ){ - read_scale( m_scale, value ); - m_scaleChanged(); -} -typedef MemberCaller UniformScaleChangedCaller; + void uniformScaleChanged(const char *value) + { + read_scale(m_scale, value); + m_scaleChanged(); + } -void scaleChanged( const char* value ){ - read_scalevec( m_scale, value ); - m_scaleChanged(); -} -typedef MemberCaller ScaleChangedCaller; + typedef MemberCaller UniformScaleChangedCaller; -void write( Entity* entity ) const { - write_scale( m_scale, entity ); -} + void scaleChanged(const char *value) + { + read_scalevec(m_scale, value); + m_scaleChanged(); + } + + typedef MemberCaller ScaleChangedCaller; + + void write(Entity *entity) const + { + write_scale(m_scale, entity); + } }; diff --git a/plugins/entity/skincache.cpp b/plugins/entity/skincache.cpp index 645e8a28..5486aad5 100644 --- a/plugins/entity/skincache.cpp +++ b/plugins/entity/skincache.cpp @@ -37,266 +37,299 @@ #include "modulesystem/singletonmodule.h" #include "stringio.h" -void parseShaderName( CopiedString& name, const char* token ){ - StringOutputStream cleaned( 256 ); - cleaned << PathCleaned( token ); - name = cleaned.c_str(); +void parseShaderName(CopiedString &name, const char *token) +{ + StringOutputStream cleaned(256); + cleaned << PathCleaned(token); + name = cleaned.c_str(); } -class Doom3ModelSkin -{ -typedef std::map Remaps; -Remaps m_remaps; +class Doom3ModelSkin { + typedef std::map Remaps; + Remaps m_remaps; public: -bool parseTokens( Tokeniser& tokeniser ){ - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); - for (;; ) - { - const char* token = tokeniser.getToken(); - if ( token == 0 ) { - return false; - } - if ( string_equal( token, "}" ) ) { - tokeniser.nextLine(); - return true; - } - else if ( string_equal( token, "model" ) ) { - //const char* model = - tokeniser.getToken(); - } - else - { - CopiedString from, to; - parseShaderName( from, token ); - - tokeniser.nextLine(); // hack to handle badly formed skins - - parseShaderName( to, tokeniser.getToken() ); - - if ( !string_equal( from.c_str(), to.c_str() ) ) { - m_remaps.insert( Remaps::value_type( from, to ) ); - } - } - tokeniser.nextLine(); - } -} -const char* getRemap( const char* name ) const { - Remaps::const_iterator i = m_remaps.find( name ); - if ( i != m_remaps.end() ) { - return ( *i ).second.c_str(); - } - return ""; -} -void forEachRemap( const SkinRemapCallback& callback ) const { - for ( Remaps::const_iterator i = m_remaps.begin(); i != m_remaps.end(); ++i ) - { - callback( SkinRemap( ( *i ).first.c_str(), ( *i ).second.c_str() ) ); - } -} + bool parseTokens(Tokeniser &tokeniser) + { + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "{")); + tokeniser.nextLine(); + for (;;) { + const char *token = tokeniser.getToken(); + if (token == 0) { + return false; + } + if (string_equal(token, "}")) { + tokeniser.nextLine(); + return true; + } else if (string_equal(token, "model")) { + //const char* model = + tokeniser.getToken(); + } else { + CopiedString from, to; + parseShaderName(from, token); + + tokeniser.nextLine(); // hack to handle badly formed skins + + parseShaderName(to, tokeniser.getToken()); + + if (!string_equal(from.c_str(), to.c_str())) { + m_remaps.insert(Remaps::value_type(from, to)); + } + } + tokeniser.nextLine(); + } + } + + const char *getRemap(const char *name) const + { + Remaps::const_iterator i = m_remaps.find(name); + if (i != m_remaps.end()) { + return (*i).second.c_str(); + } + return ""; + } + + void forEachRemap(const SkinRemapCallback &callback) const + { + for (Remaps::const_iterator i = m_remaps.begin(); i != m_remaps.end(); ++i) { + callback(SkinRemap((*i).first.c_str(), (*i).second.c_str())); + } + } }; -class GlobalSkins -{ +class GlobalSkins { public: -typedef std::map SkinMap; -SkinMap m_skins; -Doom3ModelSkin g_nullSkin; - -Doom3ModelSkin& getSkin( const char* name ){ - SkinMap::iterator i = m_skins.find( name ); - if ( i != m_skins.end() ) { - return ( *i ).second; - } - - return g_nullSkin; -} - -bool parseTokens( Tokeniser& tokeniser ){ - tokeniser.nextLine(); - for (;; ) - { - const char* token = tokeniser.getToken(); - if ( token == 0 ) { - // end of token stream - return true; - } - if ( !string_equal( token, "skin" ) ) { - Tokeniser_unexpectedError( tokeniser, token, "skin" ); - return false; - } - const char* other = tokeniser.getToken(); - if ( other == 0 ) { - Tokeniser_unexpectedError( tokeniser, token, "#string" ); - return false; - } - CopiedString name; - parseShaderName( name, other ); - Doom3ModelSkin& skin = m_skins[name]; - RETURN_FALSE_IF_FAIL( skin.parseTokens( tokeniser ) ); - } -} - -void parseFile( const char* name ){ - StringOutputStream relativeName( 64 ); - relativeName << "skins/" << name; - ArchiveTextFile* file = GlobalFileSystem().openTextFile( relativeName.c_str() ); - if ( file != 0 ) { - globalOutputStream() << "parsing skins from " << makeQuoted( name ) << "\n"; - { - Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser( file->getInputStream() ); - parseTokens( tokeniser ); - tokeniser.release(); - } - file->release(); - } - else - { - globalErrorStream() << "failed to open " << makeQuoted( name ) << "\n"; - } -} - -typedef MemberCaller ParseFileCaller; - -void construct(){ - GlobalFileSystem().forEachFile( "skins/", "skin", ParseFileCaller( *this ) ); -} - -void destroy(){ - m_skins.clear(); -} - -void realise(){ - construct(); -} -void unrealise(){ - destroy(); -} + typedef std::map SkinMap; + SkinMap m_skins; + Doom3ModelSkin g_nullSkin; + + Doom3ModelSkin &getSkin(const char *name) + { + SkinMap::iterator i = m_skins.find(name); + if (i != m_skins.end()) { + return (*i).second; + } + + return g_nullSkin; + } + + bool parseTokens(Tokeniser &tokeniser) + { + tokeniser.nextLine(); + for (;;) { + const char *token = tokeniser.getToken(); + if (token == 0) { + // end of token stream + return true; + } + if (!string_equal(token, "skin")) { + Tokeniser_unexpectedError(tokeniser, token, "skin"); + return false; + } + const char *other = tokeniser.getToken(); + if (other == 0) { + Tokeniser_unexpectedError(tokeniser, token, "#string"); + return false; + } + CopiedString name; + parseShaderName(name, other); + Doom3ModelSkin &skin = m_skins[name]; + RETURN_FALSE_IF_FAIL(skin.parseTokens(tokeniser)); + } + } + + void parseFile(const char *name) + { + StringOutputStream relativeName(64); + relativeName << "skins/" << name; + ArchiveTextFile *file = GlobalFileSystem().openTextFile(relativeName.c_str()); + if (file != 0) { + globalOutputStream() << "parsing skins from " << makeQuoted(name) << "\n"; + { + Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(file->getInputStream()); + parseTokens(tokeniser); + tokeniser.release(); + } + file->release(); + } else { + globalErrorStream() << "failed to open " << makeQuoted(name) << "\n"; + } + } + + typedef MemberCaller ParseFileCaller; + + void construct() + { + GlobalFileSystem().forEachFile("skins/", "skin", ParseFileCaller(*this)); + } + + void destroy() + { + m_skins.clear(); + } + + void realise() + { + construct(); + } + + void unrealise() + { + destroy(); + } }; GlobalSkins g_skins; -class Doom3ModelSkinCacheElement : public ModelSkin -{ -ModuleObservers m_observers; -Doom3ModelSkin* m_skin; +class Doom3ModelSkinCacheElement : public ModelSkin { + ModuleObservers m_observers; + Doom3ModelSkin *m_skin; public: -Doom3ModelSkinCacheElement() : m_skin( 0 ){ -} -void attach( ModuleObserver& observer ){ - m_observers.attach( observer ); - if ( realised() ) { - observer.realise(); - } -} -void detach( ModuleObserver& observer ){ - if ( realised() ) { - observer.unrealise(); - } - m_observers.detach( observer ); -} -bool realised() const { - return m_skin != 0; -} -void realise( const char* name ){ - ASSERT_MESSAGE( !realised(), "Doom3ModelSkinCacheElement::realise: already realised" ); - m_skin = &g_skins.getSkin( name ); - m_observers.realise(); -} -void unrealise(){ - ASSERT_MESSAGE( realised(), "Doom3ModelSkinCacheElement::unrealise: not realised" ); - m_observers.unrealise(); - m_skin = 0; -} -const char* getRemap( const char* name ) const { - ASSERT_MESSAGE( realised(), "Doom3ModelSkinCacheElement::getRemap: not realised" ); - return m_skin->getRemap( name ); -} -void forEachRemap( const SkinRemapCallback& callback ) const { - ASSERT_MESSAGE( realised(), "Doom3ModelSkinCacheElement::forEachRemap: not realised" ); - m_skin->forEachRemap( callback ); -} + Doom3ModelSkinCacheElement() : m_skin(0) + { + } + + void attach(ModuleObserver &observer) + { + m_observers.attach(observer); + if (realised()) { + observer.realise(); + } + } + + void detach(ModuleObserver &observer) + { + if (realised()) { + observer.unrealise(); + } + m_observers.detach(observer); + } + + bool realised() const + { + return m_skin != 0; + } + + void realise(const char *name) + { + ASSERT_MESSAGE(!realised(), "Doom3ModelSkinCacheElement::realise: already realised"); + m_skin = &g_skins.getSkin(name); + m_observers.realise(); + } + + void unrealise() + { + ASSERT_MESSAGE(realised(), "Doom3ModelSkinCacheElement::unrealise: not realised"); + m_observers.unrealise(); + m_skin = 0; + } + + const char *getRemap(const char *name) const + { + ASSERT_MESSAGE(realised(), "Doom3ModelSkinCacheElement::getRemap: not realised"); + return m_skin->getRemap(name); + } + + void forEachRemap(const SkinRemapCallback &callback) const + { + ASSERT_MESSAGE(realised(), "Doom3ModelSkinCacheElement::forEachRemap: not realised"); + m_skin->forEachRemap(callback); + } }; -class Doom3ModelSkinCache : public ModelSkinCache, public ModuleObserver -{ -class CreateDoom3ModelSkin -{ -Doom3ModelSkinCache& m_cache; -public: -explicit CreateDoom3ModelSkin( Doom3ModelSkinCache& cache ) - : m_cache( cache ){ -} -Doom3ModelSkinCacheElement* construct( const CopiedString& name ){ - Doom3ModelSkinCacheElement* skin = new Doom3ModelSkinCacheElement; - if ( m_cache.realised() ) { - skin->realise( name.c_str() ); - } - return skin; -} -void destroy( Doom3ModelSkinCacheElement* skin ){ - if ( m_cache.realised() ) { - skin->unrealise(); - } - delete skin; -} -}; - -typedef HashedCache, CreateDoom3ModelSkin> Cache; -Cache m_cache; -bool m_realised; +class Doom3ModelSkinCache : public ModelSkinCache, public ModuleObserver { + class CreateDoom3ModelSkin { + Doom3ModelSkinCache &m_cache; + public: + explicit CreateDoom3ModelSkin(Doom3ModelSkinCache &cache) + : m_cache(cache) + { + } + + Doom3ModelSkinCacheElement *construct(const CopiedString &name) + { + Doom3ModelSkinCacheElement *skin = new Doom3ModelSkinCacheElement; + if (m_cache.realised()) { + skin->realise(name.c_str()); + } + return skin; + } + + void destroy(Doom3ModelSkinCacheElement *skin) + { + if (m_cache.realised()) { + skin->unrealise(); + } + delete skin; + } + }; + + typedef HashedCache, CreateDoom3ModelSkin> Cache; + Cache m_cache; + bool m_realised; public: -typedef ModelSkinCache Type; -STRING_CONSTANT( Name, "*" ); -ModelSkinCache* getTable(){ - return this; -} - -Doom3ModelSkinCache() : m_cache( CreateDoom3ModelSkin( *this ) ), m_realised( false ){ - GlobalFileSystem().attach( *this ); -} -~Doom3ModelSkinCache(){ - GlobalFileSystem().detach( *this ); -} - -ModelSkin& capture( const char* name ){ - return *m_cache.capture( name ); -} -void release( const char* name ){ - m_cache.release( name ); -} - -bool realised() const { - return m_realised; -} -void realise(){ - g_skins.realise(); - m_realised = true; - for ( Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i ) - { - ( *i ).value->realise( ( *i ).key.c_str() ); - } -} -void unrealise(){ - m_realised = false; - for ( Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i ) - { - ( *i ).value->unrealise(); - } - g_skins.unrealise(); -} + typedef ModelSkinCache Type; + + STRING_CONSTANT(Name, "*"); + + ModelSkinCache *getTable() + { + return this; + } + + Doom3ModelSkinCache() : m_cache(CreateDoom3ModelSkin(*this)), m_realised(false) + { + GlobalFileSystem().attach(*this); + } + + ~Doom3ModelSkinCache() + { + GlobalFileSystem().detach(*this); + } + + ModelSkin &capture(const char *name) + { + return *m_cache.capture(name); + } + + void release(const char *name) + { + m_cache.release(name); + } + + bool realised() const + { + return m_realised; + } + + void realise() + { + g_skins.realise(); + m_realised = true; + for (Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i) { + (*i).value->realise((*i).key.c_str()); + } + } + + void unrealise() + { + m_realised = false; + for (Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i) { + (*i).value->unrealise(); + } + g_skins.unrealise(); + } }; -class Doom3ModelSkinCacheDependencies : public GlobalFileSystemModuleRef, public GlobalScripLibModuleRef -{ +class Doom3ModelSkinCacheDependencies : public GlobalFileSystemModuleRef, public GlobalScripLibModuleRef { }; typedef SingletonModule Doom3ModelSkinCacheModule; Doom3ModelSkinCacheModule g_Doom3ModelSkinCacheModule; -void Doom3ModelSkinCacheModule_selfRegister( ModuleServer& server ){ - g_Doom3ModelSkinCacheModule.selfRegister(); +void Doom3ModelSkinCacheModule_selfRegister(ModuleServer &server) +{ + g_Doom3ModelSkinCacheModule.selfRegister(); } diff --git a/plugins/entity/skincache.h b/plugins/entity/skincache.h index 9a8e836f..79708439 100644 --- a/plugins/entity/skincache.h +++ b/plugins/entity/skincache.h @@ -23,6 +23,7 @@ #define INCLUDED_SKINCACHE_H class ModuleServer; -void Doom3ModelSkinCacheModule_selfRegister( ModuleServer& server ); + +void Doom3ModelSkinCacheModule_selfRegister(ModuleServer &server); #endif diff --git a/plugins/entity/targetable.cpp b/plugins/entity/targetable.cpp index e041ee99..a20b2912 100644 --- a/plugins/entity/targetable.cpp +++ b/plugins/entity/targetable.cpp @@ -23,15 +23,16 @@ typedef std::map targetnames_t; -const char* g_targetable_nameKey = "targetname"; +const char *g_targetable_nameKey = "targetname"; targetnames_t g_targetnames; -targetables_t* getTargetables( const char* targetname ){ - if ( targetname[0] == '\0' ) { - return 0; - } - return &g_targetnames[targetname]; +targetables_t *getTargetables(const char *targetname) +{ + if (targetname[0] == '\0') { + return 0; + } + return &g_targetnames[targetname]; } -Shader* RenderableTargetingEntity::m_state; +Shader *RenderableTargetingEntity::m_state; diff --git a/plugins/entity/targetable.h b/plugins/entity/targetable.h index 99046a50..dc0270f6 100644 --- a/plugins/entity/targetable.h +++ b/plugins/entity/targetable.h @@ -36,363 +36,414 @@ #include "eclasslib.h" #include "stringio.h" -class Targetable -{ +class Targetable { public: -virtual const Vector3& world_position() const = 0; + virtual const Vector3 &world_position() const = 0; }; -typedef std::set targetables_t; +typedef std::set targetables_t; -extern const char* g_targetable_nameKey; +extern const char *g_targetable_nameKey; -targetables_t* getTargetables( const char* targetname ); +targetables_t *getTargetables(const char *targetname); -class EntityConnectionLine : public OpenGLRenderable -{ +class EntityConnectionLine : public OpenGLRenderable { public: -Vector3 start; -Vector3 end; - -void render( RenderStateFlags state ) const { - float s1[2], s2[2]; - Vector3 dir( vector3_subtracted( end, start ) ); - double len = vector3_length( dir ); - vector3_scale( dir, 8.0 * ( 1.0 / len ) ); - s1[0] = dir[0] - dir[1]; - s1[1] = dir[0] + dir[1]; - s2[0] = dir[0] + dir[1]; - s2[1] = -dir[0] + dir[1]; - - glBegin( GL_LINES ); - - glVertex3fv( vector3_to_array( start ) ); - glVertex3fv( vector3_to_array( end ) ); - - len *= 0.0625; // half / 8 - - Vector3 arrow( start ); - for ( unsigned int i = 0, count = ( len < 32 ) ? 1 : static_cast( len * 0.0625 ); i < count; i++ ) - { - vector3_add( arrow, vector3_scaled( dir, ( len < 32 ) ? len : 32 ) ); - glVertex3fv( vector3_to_array( arrow ) ); - glVertex3f( arrow[0] + s1[0], arrow[1] + s1[1], arrow[2] + dir[2] ); - glVertex3fv( vector3_to_array( arrow ) ); - glVertex3f( arrow[0] + s2[0], arrow[1] + s2[1], arrow[2] + dir[2] ); - } - - glEnd(); -} + Vector3 start; + Vector3 end; + + void render(RenderStateFlags state) const + { + float s1[2], s2[2]; + Vector3 dir(vector3_subtracted(end, start)); + double len = vector3_length(dir); + vector3_scale(dir, 8.0 * (1.0 / len)); + s1[0] = dir[0] - dir[1]; + s1[1] = dir[0] + dir[1]; + s2[0] = dir[0] + dir[1]; + s2[1] = -dir[0] + dir[1]; + + glBegin(GL_LINES); + + glVertex3fv(vector3_to_array(start)); + glVertex3fv(vector3_to_array(end)); + + len *= 0.0625; // half / 8 + + Vector3 arrow(start); + for (unsigned int i = 0, count = (len < 32) ? 1 : static_cast( len * 0.0625 ); i < count; i++) { + vector3_add(arrow, vector3_scaled(dir, (len < 32) ? len : 32)); + glVertex3fv(vector3_to_array(arrow)); + glVertex3f(arrow[0] + s1[0], arrow[1] + s1[1], arrow[2] + dir[2]); + glVertex3fv(vector3_to_array(arrow)); + glVertex3f(arrow[0] + s2[0], arrow[1] + s2[1], arrow[2] + dir[2]); + } + + glEnd(); + } }; -class TargetedEntity -{ -Targetable& m_targetable; -targetables_t* m_targets; +class TargetedEntity { + Targetable &m_targetable; + targetables_t *m_targets; -void construct(){ - if ( m_targets != 0 ) { - m_targets->insert( &m_targetable ); - } -} -void destroy(){ - if ( m_targets != 0 ) { - m_targets->erase( &m_targetable ); - } -} -public: -TargetedEntity( Targetable& targetable ) - : m_targetable( targetable ), m_targets( getTargetables( "" ) ){ - construct(); -} -~TargetedEntity(){ - destroy(); -} -void targetnameChanged( const char* name ){ - destroy(); - m_targets = getTargetables( name ); - construct(); -} -typedef MemberCaller TargetnameChangedCaller; -}; + void construct() + { + if (m_targets != 0) { + m_targets->insert(&m_targetable); + } + } + void destroy() + { + if (m_targets != 0) { + m_targets->erase(&m_targetable); + } + } -class TargetingEntity -{ -targetables_t* m_targets; public: -TargetingEntity() : - m_targets( getTargetables( "" ) ){ -} -void targetChanged( const char* target ){ - m_targets = getTargetables( target ); -} -typedef MemberCaller TargetChangedCaller; + TargetedEntity(Targetable &targetable) + : m_targetable(targetable), m_targets(getTargetables("")) + { + construct(); + } + + ~TargetedEntity() + { + destroy(); + } + + void targetnameChanged(const char *name) + { + destroy(); + m_targets = getTargetables(name); + construct(); + } + + typedef MemberCaller TargetnameChangedCaller; +}; -typedef targetables_t::iterator iterator; -iterator begin() const { - if ( m_targets == 0 ) { - return iterator(); - } - return m_targets->begin(); -} -iterator end() const { - if ( m_targets == 0 ) { - return iterator(); - } - return m_targets->end(); -} -size_t size() const { - if ( m_targets == 0 ) { - return 0; - } - return m_targets->size(); -} -bool empty() const { - return m_targets == 0 || m_targets->empty(); -} +class TargetingEntity { + targetables_t *m_targets; +public: + TargetingEntity() : + m_targets(getTargetables("")) + { + } + + void targetChanged(const char *target) + { + m_targets = getTargetables(target); + } + + typedef MemberCaller TargetChangedCaller; + + typedef targetables_t::iterator iterator; + + iterator begin() const + { + if (m_targets == 0) { + return iterator(); + } + return m_targets->begin(); + } + + iterator end() const + { + if (m_targets == 0) { + return iterator(); + } + return m_targets->end(); + } + + size_t size() const + { + if (m_targets == 0) { + return 0; + } + return m_targets->size(); + } + + bool empty() const + { + return m_targets == 0 || m_targets->empty(); + } }; - template -void TargetingEntity_forEach( const TargetingEntity& targets, const Functor& functor ){ - for ( TargetingEntity::iterator i = targets.begin(); i != targets.end(); ++i ) - { - functor( ( *i )->world_position() ); - } +void TargetingEntity_forEach(const TargetingEntity &targets, const Functor &functor) +{ + for (TargetingEntity::iterator i = targets.begin(); i != targets.end(); ++i) { + functor((*i)->world_position()); + } } typedef std::map TargetingEntities; template -void TargetingEntities_forEach( const TargetingEntities& targetingEntities, const Functor& functor ){ - for ( TargetingEntities::const_iterator i = targetingEntities.begin(); i != targetingEntities.end(); ++i ) - { - TargetingEntity_forEach( ( *i ).second, functor ); - } +void TargetingEntities_forEach(const TargetingEntities &targetingEntities, const Functor &functor) +{ + for (TargetingEntities::const_iterator i = targetingEntities.begin(); i != targetingEntities.end(); ++i) { + TargetingEntity_forEach((*i).second, functor); + } } -class TargetLinesPushBack -{ -RenderablePointVector& m_targetLines; -const Vector3& m_worldPosition; -const VolumeTest& m_volume; +class TargetLinesPushBack { + RenderablePointVector &m_targetLines; + const Vector3 &m_worldPosition; + const VolumeTest &m_volume; public: -TargetLinesPushBack( RenderablePointVector& targetLines, const Vector3& worldPosition, const VolumeTest& volume ) : - m_targetLines( targetLines ), m_worldPosition( worldPosition ), m_volume( volume ){ -} -void operator()( const Vector3& worldPosition ) const { - if ( m_volume.TestLine( segment_for_startend( m_worldPosition, worldPosition ) ) ) { - m_targetLines.push_back( PointVertex( reinterpret_cast( m_worldPosition ) ) ); - m_targetLines.push_back( PointVertex( reinterpret_cast( worldPosition ) ) ); - } -} + TargetLinesPushBack(RenderablePointVector &targetLines, const Vector3 &worldPosition, const VolumeTest &volume) : + m_targetLines(targetLines), m_worldPosition(worldPosition), m_volume(volume) + { + } + + void operator()(const Vector3 &worldPosition) const + { + if (m_volume.TestLine(segment_for_startend(m_worldPosition, worldPosition))) { + m_targetLines.push_back(PointVertex(reinterpret_cast( m_worldPosition ))); + m_targetLines.push_back(PointVertex(reinterpret_cast( worldPosition ))); + } + } }; -class TargetKeys : public Entity::Observer -{ -TargetingEntities m_targetingEntities; -Callback m_targetsChanged; - -bool readTargetKey( const char* key, std::size_t& index ){ - if ( string_equal_n( key, "target", 6 ) ) { - index = 0; - if ( string_empty( key + 6 ) || string_parse_size( key + 6, index ) ) { - return true; - } - } - if ( string_equal( key, "killtarget" ) ) { - index = -1; - return true; - } - return false; -} -public: -void setTargetsChanged( const Callback& targetsChanged ){ - m_targetsChanged = targetsChanged; -} -void targetsChanged(){ - m_targetsChanged(); -} +class TargetKeys : public Entity::Observer { + TargetingEntities m_targetingEntities; + Callback m_targetsChanged; + + bool readTargetKey(const char *key, std::size_t &index) + { + if (string_equal_n(key, "target", 6)) { + index = 0; + if (string_empty(key + 6) || string_parse_size(key + 6, index)) { + return true; + } + } + if (string_equal(key, "killtarget")) { + index = -1; + return true; + } + return false; + } -void insert( const char* key, EntityKeyValue& value ){ - std::size_t index; - if ( readTargetKey( key, index ) ) { - TargetingEntities::iterator i = m_targetingEntities.insert( TargetingEntities::value_type( index, TargetingEntity() ) ).first; - value.attach( TargetingEntity::TargetChangedCaller( ( *i ).second ) ); - targetsChanged(); - } -} -void erase( const char* key, EntityKeyValue& value ){ - std::size_t index; - if ( readTargetKey( key, index ) ) { - TargetingEntities::iterator i = m_targetingEntities.find( index ); - value.detach( TargetingEntity::TargetChangedCaller( ( *i ).second ) ); - m_targetingEntities.erase( i ); - targetsChanged(); - } -} -const TargetingEntities& get() const { - return m_targetingEntities; -} +public: + void setTargetsChanged(const Callback &targetsChanged) + { + m_targetsChanged = targetsChanged; + } + + void targetsChanged() + { + m_targetsChanged(); + } + + void insert(const char *key, EntityKeyValue &value) + { + std::size_t index; + if (readTargetKey(key, index)) { + TargetingEntities::iterator i = m_targetingEntities.insert( + TargetingEntities::value_type(index, TargetingEntity())).first; + value.attach(TargetingEntity::TargetChangedCaller((*i).second)); + targetsChanged(); + } + } + + void erase(const char *key, EntityKeyValue &value) + { + std::size_t index; + if (readTargetKey(key, index)) { + TargetingEntities::iterator i = m_targetingEntities.find(index); + value.detach(TargetingEntity::TargetChangedCaller((*i).second)); + m_targetingEntities.erase(i); + targetsChanged(); + } + } + + const TargetingEntities &get() const + { + return m_targetingEntities; + } }; - -class RenderableTargetingEntity -{ -TargetingEntity& m_targets; -mutable RenderablePointVector m_target_lines; +class RenderableTargetingEntity { + TargetingEntity &m_targets; + mutable RenderablePointVector m_target_lines; public: -static Shader* m_state; - -RenderableTargetingEntity( TargetingEntity& targets ) - : m_targets( targets ), m_target_lines( GL_LINES ){ -} -void compile( const VolumeTest& volume, const Vector3& world_position ) const { - m_target_lines.clear(); - m_target_lines.reserve( m_targets.size() * 2 ); - TargetingEntity_forEach( m_targets, TargetLinesPushBack( m_target_lines, world_position, volume ) ); -} -void render( Renderer& renderer, const VolumeTest& volume, const Vector3& world_position ) const { - if ( !m_targets.empty() ) { - compile( volume, world_position ); - if ( !m_target_lines.empty() ) { - renderer.addRenderable( m_target_lines, g_matrix4_identity ); - } - } -} + static Shader *m_state; + + RenderableTargetingEntity(TargetingEntity &targets) + : m_targets(targets), m_target_lines(GL_LINES) + { + } + + void compile(const VolumeTest &volume, const Vector3 &world_position) const + { + m_target_lines.clear(); + m_target_lines.reserve(m_targets.size() * 2); + TargetingEntity_forEach(m_targets, TargetLinesPushBack(m_target_lines, world_position, volume)); + } + + void render(Renderer &renderer, const VolumeTest &volume, const Vector3 &world_position) const + { + if (!m_targets.empty()) { + compile(volume, world_position); + if (!m_target_lines.empty()) { + renderer.addRenderable(m_target_lines, g_matrix4_identity); + } + } + } }; -class RenderableTargetingEntities -{ -const TargetingEntities& m_targets; -mutable RenderablePointVector m_target_lines; +class RenderableTargetingEntities { + const TargetingEntities &m_targets; + mutable RenderablePointVector m_target_lines; public: -static Shader* m_state; - -RenderableTargetingEntities( const TargetingEntities& targets ) - : m_targets( targets ), m_target_lines( GL_LINES ){ -} -void compile( const VolumeTest& volume, const Vector3& world_position ) const { - m_target_lines.clear(); - TargetingEntities_forEach( m_targets, TargetLinesPushBack( m_target_lines, world_position, volume ) ); -} -void render( Renderer& renderer, const VolumeTest& volume, const Vector3& world_position ) const { - if ( !m_targets.empty() ) { - compile( volume, world_position ); - if ( !m_target_lines.empty() ) { - renderer.addRenderable( m_target_lines, g_matrix4_identity ); - } - } -} + static Shader *m_state; + + RenderableTargetingEntities(const TargetingEntities &targets) + : m_targets(targets), m_target_lines(GL_LINES) + { + } + + void compile(const VolumeTest &volume, const Vector3 &world_position) const + { + m_target_lines.clear(); + TargetingEntities_forEach(m_targets, TargetLinesPushBack(m_target_lines, world_position, volume)); + } + + void render(Renderer &renderer, const VolumeTest &volume, const Vector3 &world_position) const + { + if (!m_targets.empty()) { + compile(volume, world_position); + if (!m_target_lines.empty()) { + renderer.addRenderable(m_target_lines, g_matrix4_identity); + } + } + } }; class TargetableInstance : - public SelectableInstance, - public Targetable, - public Entity::Observer -{ -mutable Vertex3f m_position; -EntityKeyValues& m_entity; -TargetKeys m_targeting; -TargetedEntity m_targeted; -RenderableTargetingEntities m_renderable; + public SelectableInstance, + public Targetable, + public Entity::Observer { + mutable Vertex3f m_position; + EntityKeyValues &m_entity; + TargetKeys m_targeting; + TargetedEntity m_targeted; + RenderableTargetingEntities m_renderable; public: -TargetableInstance( - const scene::Path& path, - scene::Instance* parent, - void* instance, - InstanceTypeCastTable& casts, - EntityKeyValues& entity, - Targetable& targetable - ) : - SelectableInstance( path, parent, instance, casts ), - m_entity( entity ), - m_targeted( targetable ), - m_renderable( m_targeting.get() ){ - m_entity.attach( *this ); - m_entity.attach( m_targeting ); -} -~TargetableInstance(){ - m_entity.detach( m_targeting ); - m_entity.detach( *this ); -} - -void setTargetsChanged( const Callback& targetsChanged ){ - m_targeting.setTargetsChanged( targetsChanged ); -} -void targetsChanged(){ - m_targeting.targetsChanged(); -} - -void insert( const char* key, EntityKeyValue& value ){ - if ( string_equal( key, g_targetable_nameKey ) ) { - value.attach( TargetedEntity::TargetnameChangedCaller( m_targeted ) ); - } -} -void erase( const char* key, EntityKeyValue& value ){ - if ( string_equal( key, g_targetable_nameKey ) ) { - value.detach( TargetedEntity::TargetnameChangedCaller( m_targeted ) ); - } -} - -const Vector3& world_position() const { + TargetableInstance( + const scene::Path &path, + scene::Instance *parent, + void *instance, + InstanceTypeCastTable &casts, + EntityKeyValues &entity, + Targetable &targetable + ) : + SelectableInstance(path, parent, instance, casts), + m_entity(entity), + m_targeted(targetable), + m_renderable(m_targeting.get()) + { + m_entity.attach(*this); + m_entity.attach(m_targeting); + } + + ~TargetableInstance() + { + m_entity.detach(m_targeting); + m_entity.detach(*this); + } + + void setTargetsChanged(const Callback &targetsChanged) + { + m_targeting.setTargetsChanged(targetsChanged); + } + + void targetsChanged() + { + m_targeting.targetsChanged(); + } + + void insert(const char *key, EntityKeyValue &value) + { + if (string_equal(key, g_targetable_nameKey)) { + value.attach(TargetedEntity::TargetnameChangedCaller(m_targeted)); + } + } + + void erase(const char *key, EntityKeyValue &value) + { + if (string_equal(key, g_targetable_nameKey)) { + value.detach(TargetedEntity::TargetnameChangedCaller(m_targeted)); + } + } + + const Vector3 &world_position() const + { #if 1 - const AABB& bounds = Instance::worldAABB(); - if ( aabb_valid( bounds ) ) { - return bounds.origin; - } + const AABB &bounds = Instance::worldAABB(); + if (aabb_valid(bounds)) { + return bounds.origin; + } #else - const AABB& childBounds = Instance::childBounds(); - if ( aabb_valid( childBounds ) ) { - return childBounds.origin; - } + const AABB& childBounds = Instance::childBounds(); + if ( aabb_valid( childBounds ) ) { + return childBounds.origin; + } #endif - return vector4_to_vector3( localToWorld().t() ); -} - -void render( Renderer& renderer, const VolumeTest& volume ) const { - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); - renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials ); - m_renderable.render( renderer, volume, world_position() ); -} - -const TargetingEntities& getTargeting() const { - return m_targeting.get(); -} + return vector4_to_vector3(localToWorld().t()); + } + + void render(Renderer &renderer, const VolumeTest &volume) const + { + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly); + renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials); + m_renderable.render(renderer, volume, world_position()); + } + + const TargetingEntities &getTargeting() const + { + return m_targeting.get(); + } }; -class RenderableConnectionLines : public Renderable -{ -typedef std::set TargetableInstances; -TargetableInstances m_instances; +class RenderableConnectionLines : public Renderable { + typedef std::set TargetableInstances; + TargetableInstances m_instances; public: -void attach( TargetableInstance& instance ){ - ASSERT_MESSAGE( m_instances.find( &instance ) == m_instances.end(), "cannot attach instance" ); - m_instances.insert( &instance ); -} -void detach( TargetableInstance& instance ){ - ASSERT_MESSAGE( m_instances.find( &instance ) != m_instances.end(), "cannot detach instance" ); - m_instances.erase( &instance ); -} - -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - for ( TargetableInstances::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i ) - { - if ( ( *i )->path().top().get().visible() ) { - ( *i )->render( renderer, volume ); - } - } -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - renderSolid( renderer, volume ); -} + void attach(TargetableInstance &instance) + { + ASSERT_MESSAGE(m_instances.find(&instance) == m_instances.end(), "cannot attach instance"); + m_instances.insert(&instance); + } + + void detach(TargetableInstance &instance) + { + ASSERT_MESSAGE(m_instances.find(&instance) != m_instances.end(), "cannot detach instance"); + m_instances.erase(&instance); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + for (TargetableInstances::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i) { + if ((*i)->path().top().get().visible()) { + (*i)->render(renderer, volume); + } + } + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + renderSolid(renderer, volume); + } }; typedef Static StaticRenderableConnectionLines; diff --git a/plugins/image/bmp.cpp b/plugins/image/bmp.cpp index 63ce4a05..4b27227b 100644 --- a/plugins/image/bmp.cpp +++ b/plugins/image/bmp.cpp @@ -30,166 +30,168 @@ typedef unsigned char byte; typedef unsigned char PaletteEntry[4]; -typedef struct -{ - char id[2]; - unsigned long fileSize; - unsigned long reserved0; - unsigned long bitmapDataOffset; - unsigned long bitmapHeaderSize; - unsigned long width; - unsigned long height; - unsigned short planes; - unsigned short bitsPerPixel; - unsigned long compression; - unsigned long bitmapDataSize; - unsigned long hRes; - unsigned long vRes; - unsigned long colors; - unsigned long importantColors; - PaletteEntry palette[256]; +typedef struct { + char id[2]; + unsigned long fileSize; + unsigned long reserved0; + unsigned long bitmapDataOffset; + unsigned long bitmapHeaderSize; + unsigned long width; + unsigned long height; + unsigned short planes; + unsigned short bitsPerPixel; + unsigned long compression; + unsigned long bitmapDataSize; + unsigned long hRes; + unsigned long vRes; + unsigned long colors; + unsigned long importantColors; + PaletteEntry palette[256]; } BMPHeader_t; -class ReadPixel8 -{ -PaletteEntry* m_palette; +class ReadPixel8 { + PaletteEntry *m_palette; public: -ReadPixel8( PaletteEntry* palette ) : m_palette( palette ){ -} -void operator()( PointerInputStream& inputStream, byte*& pixbuf ) const { - byte palIndex; - inputStream.read( &palIndex, 1 ); - *pixbuf++ = m_palette[palIndex][2]; - *pixbuf++ = m_palette[palIndex][1]; - *pixbuf++ = m_palette[palIndex][0]; - *pixbuf++ = 0xff; -} + ReadPixel8(PaletteEntry *palette) : m_palette(palette) + { + } + + void operator()(PointerInputStream &inputStream, byte *&pixbuf) const + { + byte palIndex; + inputStream.read(&palIndex, 1); + *pixbuf++ = m_palette[palIndex][2]; + *pixbuf++ = m_palette[palIndex][1]; + *pixbuf++ = m_palette[palIndex][0]; + *pixbuf++ = 0xff; + } }; -class ReadPixel16 -{ +class ReadPixel16 { public: -void operator()( PointerInputStream& inputStream, byte*& pixbuf ) const { - unsigned short shortPixel; - inputStream.read( reinterpret_cast( &shortPixel ), sizeof( unsigned short ) ); //!\todo Is this endian safe? - *pixbuf++ = static_cast( shortPixel & ( 31 << 10 ) ) >> 7; - *pixbuf++ = static_cast( shortPixel & ( 31 << 5 ) ) >> 2; - *pixbuf++ = static_cast( shortPixel & ( 31 ) ) << 3; - *pixbuf++ = 0xff; -} + void operator()(PointerInputStream &inputStream, byte *&pixbuf) const + { + unsigned short shortPixel; + inputStream.read(reinterpret_cast( &shortPixel ), sizeof(unsigned short)); //!\todo Is this endian safe? + *pixbuf++ = static_cast( shortPixel & (31 << 10)) >> 7; + *pixbuf++ = static_cast( shortPixel & (31 << 5)) >> 2; + *pixbuf++ = static_cast( shortPixel & (31)) << 3; + *pixbuf++ = 0xff; + } }; -class ReadPixel24 -{ +class ReadPixel24 { public: -void operator()( PointerInputStream& inputStream, byte*& pixbuf ) const { - byte bgr[3]; - inputStream.read( bgr, 3 ); - *pixbuf++ = bgr[2]; - *pixbuf++ = bgr[1]; - *pixbuf++ = bgr[0]; - *pixbuf++ = 255; -} + void operator()(PointerInputStream &inputStream, byte *&pixbuf) const + { + byte bgr[3]; + inputStream.read(bgr, 3); + *pixbuf++ = bgr[2]; + *pixbuf++ = bgr[1]; + *pixbuf++ = bgr[0]; + *pixbuf++ = 255; + } }; -class ReadPixel32 -{ +class ReadPixel32 { public: -void operator()( PointerInputStream& inputStream, byte*& pixbuf ) const { - byte bgra[4]; - inputStream.read( bgra, 4 ); - *pixbuf++ = bgra[2]; - *pixbuf++ = bgra[1]; - *pixbuf++ = bgra[0]; - *pixbuf++ = bgra[3]; -} + void operator()(PointerInputStream &inputStream, byte *&pixbuf) const + { + byte bgra[4]; + inputStream.read(bgra, 4); + *pixbuf++ = bgra[2]; + *pixbuf++ = bgra[1]; + *pixbuf++ = bgra[0]; + *pixbuf++ = bgra[3]; + } }; template -void ReadBMP( PointerInputStream& inputStream, byte* bmpRGBA, int rows, int columns, ReadPixel readPixel ){ - for ( int row = rows - 1; row >= 0; row-- ) - { - byte* pixbuf = bmpRGBA + row * columns * 4; - - for ( int column = 0; column < columns; column++ ) - { - readPixel( inputStream, pixbuf ); - } - } +void ReadBMP(PointerInputStream &inputStream, byte *bmpRGBA, int rows, int columns, ReadPixel readPixel) +{ + for (int row = rows - 1; row >= 0; row--) { + byte *pixbuf = bmpRGBA + row * columns * 4; + + for (int column = 0; column < columns; column++) { + readPixel(inputStream, pixbuf); + } + } } -Image* LoadBMPBuff( PointerInputStream& inputStream, std::size_t length ){ - BMPHeader_t bmpHeader; - inputStream.read( reinterpret_cast( bmpHeader.id ), 2 ); - bmpHeader.fileSize = istream_read_uint32_le( inputStream ); - bmpHeader.reserved0 = istream_read_uint32_le( inputStream ); - bmpHeader.bitmapDataOffset = istream_read_uint32_le( inputStream ); - bmpHeader.bitmapHeaderSize = istream_read_uint32_le( inputStream ); - bmpHeader.width = istream_read_uint32_le( inputStream ); - bmpHeader.height = istream_read_uint32_le( inputStream ); - bmpHeader.planes = istream_read_uint16_le( inputStream ); - bmpHeader.bitsPerPixel = istream_read_uint16_le( inputStream ); - bmpHeader.compression = istream_read_uint32_le( inputStream ); - bmpHeader.bitmapDataSize = istream_read_uint32_le( inputStream ); - bmpHeader.hRes = istream_read_uint32_le( inputStream ); - bmpHeader.vRes = istream_read_uint32_le( inputStream ); - bmpHeader.colors = istream_read_uint32_le( inputStream ); - bmpHeader.importantColors = istream_read_uint32_le( inputStream ); - - if ( bmpHeader.bitsPerPixel == 8 ) { - int paletteSize = bmpHeader.colors * 4; - inputStream.read( reinterpret_cast( bmpHeader.palette ), paletteSize ); - } - - if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' ) { - globalErrorStream() << "LoadBMP: only Windows-style BMP files supported\n"; - return 0; - } - if ( bmpHeader.fileSize != length ) { - globalErrorStream() << "LoadBMP: header size does not match file size (" << Unsigned( bmpHeader.fileSize ) << " vs. " << Unsigned( length ) << ")\n"; - return 0; - } - if ( bmpHeader.compression != 0 ) { - globalErrorStream() << "LoadBMP: only uncompressed BMP files supported\n"; - return 0; - } - if ( bmpHeader.bitsPerPixel < 8 ) { - globalErrorStream() << "LoadBMP: monochrome and 4-bit BMP files not supported\n"; - return 0; - } - - int columns = bmpHeader.width; - int rows = bmpHeader.height; - if ( rows < 0 ) { - rows = -rows; - } - - RGBAImage* image = new RGBAImage( columns, rows ); - - switch ( bmpHeader.bitsPerPixel ) - { - case 8: - ReadBMP( inputStream, image->getRGBAPixels(), rows, columns, ReadPixel8( bmpHeader.palette ) ); - break; - case 16: - ReadBMP( inputStream, image->getRGBAPixels(), rows, columns, ReadPixel16() ); - break; - case 24: - ReadBMP( inputStream, image->getRGBAPixels(), rows, columns, ReadPixel24() ); - break; - case 32: - ReadBMP( inputStream, image->getRGBAPixels(), rows, columns, ReadPixel32() ); - break; - default: - globalErrorStream() << "LoadBMP: illegal pixel_size '" << bmpHeader.bitsPerPixel << "'\n"; - image->release(); - return 0; - } - return image; +Image *LoadBMPBuff(PointerInputStream &inputStream, std::size_t length) +{ + BMPHeader_t bmpHeader; + inputStream.read(reinterpret_cast( bmpHeader.id ), 2); + bmpHeader.fileSize = istream_read_uint32_le(inputStream); + bmpHeader.reserved0 = istream_read_uint32_le(inputStream); + bmpHeader.bitmapDataOffset = istream_read_uint32_le(inputStream); + bmpHeader.bitmapHeaderSize = istream_read_uint32_le(inputStream); + bmpHeader.width = istream_read_uint32_le(inputStream); + bmpHeader.height = istream_read_uint32_le(inputStream); + bmpHeader.planes = istream_read_uint16_le(inputStream); + bmpHeader.bitsPerPixel = istream_read_uint16_le(inputStream); + bmpHeader.compression = istream_read_uint32_le(inputStream); + bmpHeader.bitmapDataSize = istream_read_uint32_le(inputStream); + bmpHeader.hRes = istream_read_uint32_le(inputStream); + bmpHeader.vRes = istream_read_uint32_le(inputStream); + bmpHeader.colors = istream_read_uint32_le(inputStream); + bmpHeader.importantColors = istream_read_uint32_le(inputStream); + + if (bmpHeader.bitsPerPixel == 8) { + int paletteSize = bmpHeader.colors * 4; + inputStream.read(reinterpret_cast( bmpHeader.palette ), paletteSize); + } + + if (bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M') { + globalErrorStream() << "LoadBMP: only Windows-style BMP files supported\n"; + return 0; + } + if (bmpHeader.fileSize != length) { + globalErrorStream() << "LoadBMP: header size does not match file size (" << Unsigned(bmpHeader.fileSize) + << " vs. " << Unsigned(length) << ")\n"; + return 0; + } + if (bmpHeader.compression != 0) { + globalErrorStream() << "LoadBMP: only uncompressed BMP files supported\n"; + return 0; + } + if (bmpHeader.bitsPerPixel < 8) { + globalErrorStream() << "LoadBMP: monochrome and 4-bit BMP files not supported\n"; + return 0; + } + + int columns = bmpHeader.width; + int rows = bmpHeader.height; + if (rows < 0) { + rows = -rows; + } + + RGBAImage *image = new RGBAImage(columns, rows); + + switch (bmpHeader.bitsPerPixel) { + case 8: + ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel8(bmpHeader.palette)); + break; + case 16: + ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel16()); + break; + case 24: + ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel24()); + break; + case 32: + ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel32()); + break; + default: + globalErrorStream() << "LoadBMP: illegal pixel_size '" << bmpHeader.bitsPerPixel << "'\n"; + image->release(); + return 0; + } + return image; } -Image* LoadBMP( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - PointerInputStream inputStream( buffer.buffer ); - return LoadBMPBuff( inputStream, buffer.length ); +Image *LoadBMP(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + PointerInputStream inputStream(buffer.buffer); + return LoadBMPBuff(inputStream, buffer.length); } diff --git a/plugins/image/bmp.h b/plugins/image/bmp.h index bbb0714e..043c289f 100644 --- a/plugins/image/bmp.h +++ b/plugins/image/bmp.h @@ -23,8 +23,9 @@ #define INCLUDED_BMP_H class Image; + class ArchiveFile; -Image* LoadBMP( ArchiveFile& file ); +Image *LoadBMP(ArchiveFile &file); #endif diff --git a/plugins/image/dds.cpp b/plugins/image/dds.cpp index 0da0d3a2..79941e87 100644 --- a/plugins/image/dds.cpp +++ b/plugins/image/dds.cpp @@ -30,23 +30,26 @@ #include "ddslib.h" #include "imagelib.h" -Image* LoadDDSBuff( const byte* buffer ){ - int width, height; - ddsPF_t pixelFormat; - if ( DDSGetInfo( reinterpret_cast( const_cast( buffer ) ), &width, &height, &pixelFormat ) == -1 ) { - return 0; - } - - RGBAImage* image = new RGBAImage( width, height ); - - if ( DDSDecompress( reinterpret_cast( const_cast( buffer ) ), image->getRGBAPixels() ) == -1 ) { - image->release(); - return 0; - } - return image; +Image *LoadDDSBuff(const byte *buffer) +{ + int width, height; + ddsPF_t pixelFormat; + if (DDSGetInfo(reinterpret_cast( const_cast( buffer )), &width, &height, &pixelFormat) == + -1) { + return 0; + } + + RGBAImage *image = new RGBAImage(width, height); + + if (DDSDecompress(reinterpret_cast( const_cast( buffer )), image->getRGBAPixels()) == -1) { + image->release(); + return 0; + } + return image; } -Image* LoadDDS( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadDDSBuff( buffer.buffer ); +Image *LoadDDS(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadDDSBuff(buffer.buffer); } diff --git a/plugins/image/dds.h b/plugins/image/dds.h index 1847edb9..5e658313 100644 --- a/plugins/image/dds.h +++ b/plugins/image/dds.h @@ -23,8 +23,9 @@ #define INCLUDED_DDS_H class Image; + class ArchiveFile; -Image* LoadDDS( ArchiveFile& file ); +Image *LoadDDS(ArchiveFile &file); #endif diff --git a/plugins/image/image.cpp b/plugins/image/image.cpp index 7d767f22..f7f73522 100644 --- a/plugins/image/image.cpp +++ b/plugins/image/image.cpp @@ -32,23 +32,25 @@ #include "modulesystem/singletonmodule.h" -class ImageDependencies : public GlobalFileSystemModuleRef -{ +class ImageDependencies : public GlobalFileSystemModuleRef { }; -class ImageTGAAPI -{ -_QERPlugImageTable m_imagetga; +class ImageTGAAPI { + _QERPlugImageTable m_imagetga; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "tga" ); + typedef _QERPlugImageTable Type; -ImageTGAAPI(){ - m_imagetga.loadImage = LoadTGA; -} -_QERPlugImageTable* getTable(){ - return &m_imagetga; -} + STRING_CONSTANT(Name, "tga"); + + ImageTGAAPI() + { + m_imagetga.loadImage = LoadTGA; + } + + _QERPlugImageTable *getTable() + { + return &m_imagetga; + } }; typedef SingletonModule ImageTGAModule; @@ -56,19 +58,22 @@ typedef SingletonModule ImageTGAModule; ImageTGAModule g_ImageTGAModule; -class ImageJPGAPI -{ -_QERPlugImageTable m_imagejpg; +class ImageJPGAPI { + _QERPlugImageTable m_imagejpg; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "jpg" ); + typedef _QERPlugImageTable Type; -ImageJPGAPI(){ - m_imagejpg.loadImage = LoadJPG; -} -_QERPlugImageTable* getTable(){ - return &m_imagejpg; -} + STRING_CONSTANT(Name, "jpg"); + + ImageJPGAPI() + { + m_imagejpg.loadImage = LoadJPG; + } + + _QERPlugImageTable *getTable() + { + return &m_imagejpg; + } }; typedef SingletonModule ImageJPGModule; @@ -76,19 +81,22 @@ typedef SingletonModule ImageJPGModule; ImageJPGModule g_ImageJPGModule; -class ImageBMPAPI -{ -_QERPlugImageTable m_imagebmp; +class ImageBMPAPI { + _QERPlugImageTable m_imagebmp; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "bmp" ); + typedef _QERPlugImageTable Type; -ImageBMPAPI(){ - m_imagebmp.loadImage = LoadBMP; -} -_QERPlugImageTable* getTable(){ - return &m_imagebmp; -} + STRING_CONSTANT(Name, "bmp"); + + ImageBMPAPI() + { + m_imagebmp.loadImage = LoadBMP; + } + + _QERPlugImageTable *getTable() + { + return &m_imagebmp; + } }; typedef SingletonModule ImageBMPModule; @@ -96,19 +104,22 @@ typedef SingletonModule ImageBMPModule; ImageBMPModule g_ImageBMPModule; -class ImagePCXAPI -{ -_QERPlugImageTable m_imagepcx; +class ImagePCXAPI { + _QERPlugImageTable m_imagepcx; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "pcx" ); + typedef _QERPlugImageTable Type; -ImagePCXAPI(){ - m_imagepcx.loadImage = LoadPCX32; -} -_QERPlugImageTable* getTable(){ - return &m_imagepcx; -} + STRING_CONSTANT(Name, "pcx"); + + ImagePCXAPI() + { + m_imagepcx.loadImage = LoadPCX32; + } + + _QERPlugImageTable *getTable() + { + return &m_imagepcx; + } }; typedef SingletonModule ImagePCXModule; @@ -116,19 +127,22 @@ typedef SingletonModule ImagePCXModule; ImagePCXModule g_ImagePCXModule; -class ImageDDSAPI -{ -_QERPlugImageTable m_imagedds; +class ImageDDSAPI { + _QERPlugImageTable m_imagedds; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "dds" ); + typedef _QERPlugImageTable Type; -ImageDDSAPI(){ - m_imagedds.loadImage = LoadDDS; -} -_QERPlugImageTable* getTable(){ - return &m_imagedds; -} + STRING_CONSTANT(Name, "dds"); + + ImageDDSAPI() + { + m_imagedds.loadImage = LoadDDS; + } + + _QERPlugImageTable *getTable() + { + return &m_imagedds; + } }; typedef SingletonModule ImageDDSModule; @@ -136,19 +150,22 @@ typedef SingletonModule ImageDDSModule; ImageDDSModule g_ImageDDSModule; -class ImageKTXAPI -{ -_QERPlugImageTable m_imagektx; +class ImageKTXAPI { + _QERPlugImageTable m_imagektx; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "ktx" ); + typedef _QERPlugImageTable Type; -ImageKTXAPI(){ - m_imagektx.loadImage = LoadKTX; -} -_QERPlugImageTable* getTable(){ - return &m_imagektx; -} + STRING_CONSTANT(Name, "ktx"); + + ImageKTXAPI() + { + m_imagektx.loadImage = LoadKTX; + } + + _QERPlugImageTable *getTable() + { + return &m_imagektx; + } }; typedef SingletonModule ImageKTXModule; @@ -156,13 +173,14 @@ typedef SingletonModule ImageKTXModule; ImageKTXModule g_ImageKTXModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); - - g_ImageTGAModule.selfRegister(); - g_ImageJPGModule.selfRegister(); - g_ImageBMPModule.selfRegister(); - g_ImagePCXModule.selfRegister(); - g_ImageDDSModule.selfRegister(); - g_ImageKTXModule.selfRegister(); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); + + g_ImageTGAModule.selfRegister(); + g_ImageJPGModule.selfRegister(); + g_ImageBMPModule.selfRegister(); + g_ImagePCXModule.selfRegister(); + g_ImageDDSModule.selfRegister(); + g_ImageKTXModule.selfRegister(); } diff --git a/plugins/image/jpeg.cpp b/plugins/image/jpeg.cpp index 91fdf18e..fdc1ef04 100644 --- a/plugins/image/jpeg.cpp +++ b/plugins/image/jpeg.cpp @@ -55,16 +55,16 @@ typedef unsigned char byte; /* Expanded data source object for stdio input */ typedef struct { - struct jpeg_source_mgr pub; /* public fields */ + struct jpeg_source_mgr pub; /* public fields */ - int src_size; - JOCTET * src_buffer; + int src_size; + JOCTET *src_buffer; - JOCTET * buffer; /* start of buffer */ - boolean start_of_file; /* have we gotten any data yet? */ + JOCTET *buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ } my_source_mgr; -typedef my_source_mgr * my_src_ptr; +typedef my_source_mgr *my_src_ptr; const int INPUT_BUF_SIZE = 4096; /* choose an efficiently fread'able size */ @@ -74,14 +74,15 @@ const int INPUT_BUF_SIZE = 4096; /* choose an efficiently fread'able size */ * before any data is actually read. */ -static void my_init_source( j_decompress_ptr cinfo ){ - my_src_ptr src = (my_src_ptr) cinfo->src; +static void my_init_source(j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ - src->start_of_file = TRUE; + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; } @@ -118,37 +119,37 @@ static void my_init_source( j_decompress_ptr cinfo ){ * the front of the buffer rather than discarding it. */ -static boolean my_fill_input_buffer( j_decompress_ptr cinfo ){ - my_src_ptr src = (my_src_ptr) cinfo->src; - size_t nbytes; - - if ( src->src_size > INPUT_BUF_SIZE ) { - nbytes = INPUT_BUF_SIZE; - } - else{ - nbytes = src->src_size; - } - - memcpy( src->buffer, src->src_buffer, nbytes ); - src->src_buffer += nbytes; - src->src_size -= nbytes; - - if ( nbytes <= 0 ) { - if ( src->start_of_file ) { /* Treat empty input file as fatal error */ - ERREXIT( cinfo, JERR_INPUT_EMPTY ); - } - WARNMS( cinfo, JWRN_JPEG_EOF ); - /* Insert a fake EOI marker */ - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - nbytes = 2; - } - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_file = FALSE; - - return TRUE; +static boolean my_fill_input_buffer(j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; + + if (src->src_size > INPUT_BUF_SIZE) { + nbytes = INPUT_BUF_SIZE; + } else { + nbytes = src->src_size; + } + + memcpy(src->buffer, src->src_buffer, nbytes); + src->src_buffer += nbytes; + src->src_size -= nbytes; + + if (nbytes <= 0) { + if (src->start_of_file) { /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + } + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; } @@ -164,24 +165,25 @@ static boolean my_fill_input_buffer( j_decompress_ptr cinfo ){ * buffer is the application writer's problem. */ -static void my_skip_input_data( j_decompress_ptr cinfo, long num_bytes ){ - my_src_ptr src = (my_src_ptr) cinfo->src; - - /* Just a dumb implementation for now. Could use fseek() except - * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - if ( num_bytes > 0 ) { - while ( num_bytes > (long) src->pub.bytes_in_buffer ) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) my_fill_input_buffer( cinfo ); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } +static void my_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) my_fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } } @@ -203,8 +205,9 @@ static void my_skip_input_data( j_decompress_ptr cinfo, long num_bytes ){ * for error exit. */ -static void my_term_source( j_decompress_ptr cinfo ){ - /* no work necessary here */ +static void my_term_source(j_decompress_ptr cinfo) +{ + /* no work necessary here */ } @@ -214,187 +217,187 @@ static void my_term_source( j_decompress_ptr cinfo ){ * for closing it after finishing decompression. */ -static void jpeg_buffer_src( j_decompress_ptr cinfo, void* buffer, int bufsize ){ - my_src_ptr src; - - /* The source object and input buffer are made permanent so that a series - * of JPEG images can be read from the same file by calling jpeg_stdio_src - * only before the first one. (If we discarded the buffer at the end of - * one image, we'd likely lose the start of the next one.) - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ - if ( cinfo->src == NULL ) { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_PERMANENT, - sizeof( my_source_mgr ) ); - src = (my_src_ptr) cinfo->src; - src->buffer = (JOCTET *) - ( *cinfo->mem->alloc_small )( (j_common_ptr) cinfo, JPOOL_PERMANENT, - INPUT_BUF_SIZE * sizeof( JOCTET ) ); - } - - src = (my_src_ptr) cinfo->src; - src->pub.init_source = my_init_source; - src->pub.fill_input_buffer = my_fill_input_buffer; - src->pub.skip_input_data = my_skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = my_term_source; - src->src_buffer = (JOCTET *)buffer; - src->src_size = bufsize; - src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ - src->pub.next_input_byte = NULL; /* until buffer loaded */ +static void jpeg_buffer_src(j_decompress_ptr cinfo, void *buffer, int bufsize) +{ + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * sizeof(JOCTET)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = my_init_source; + src->pub.fill_input_buffer = my_fill_input_buffer; + src->pub.skip_input_data = my_skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = my_term_source; + src->src_buffer = (JOCTET *) buffer; + src->src_size = bufsize; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ } // ============================================================================= static char errormsg[JMSG_LENGTH_MAX]; -typedef struct my_jpeg_error_mgr -{ - struct jpeg_error_mgr pub; // "public" fields - jmp_buf setjmp_buffer; // for return to caller +typedef struct my_jpeg_error_mgr { + struct jpeg_error_mgr pub; // "public" fields + jmp_buf setjmp_buffer; // for return to caller } bt_jpeg_error_mgr; -static void my_jpeg_error_exit( j_common_ptr cinfo ){ - my_jpeg_error_mgr* myerr = (bt_jpeg_error_mgr*) cinfo->err; +static void my_jpeg_error_exit(j_common_ptr cinfo) +{ + my_jpeg_error_mgr *myerr = (bt_jpeg_error_mgr *) cinfo->err; - ( *cinfo->err->format_message )( cinfo, errormsg ); + (*cinfo->err->format_message)(cinfo, errormsg); - longjmp( myerr->setjmp_buffer, 1 ); + longjmp(myerr->setjmp_buffer, 1); } // stash a scanline -static void j_putRGBScanline( unsigned char* jpegline, int widthPix, unsigned char* outBuf, int row ){ - int offset = row * widthPix * 4; - int count; - - for ( count = 0; count < widthPix; count++ ) - { - unsigned char iRed, iBlu, iGrn; - unsigned char *oRed, *oBlu, *oGrn, *oAlp; - - iRed = *( jpegline + count * 3 + 0 ); - iGrn = *( jpegline + count * 3 + 1 ); - iBlu = *( jpegline + count * 3 + 2 ); - - oRed = outBuf + offset + count * 4 + 0; - oGrn = outBuf + offset + count * 4 + 1; - oBlu = outBuf + offset + count * 4 + 2; - oAlp = outBuf + offset + count * 4 + 3; - - *oRed = iRed; - *oGrn = iGrn; - *oBlu = iBlu; - *oAlp = 255; - } +static void j_putRGBScanline(unsigned char *jpegline, int widthPix, unsigned char *outBuf, int row) +{ + int offset = row * widthPix * 4; + int count; + + for (count = 0; count < widthPix; count++) { + unsigned char iRed, iBlu, iGrn; + unsigned char *oRed, *oBlu, *oGrn, *oAlp; + + iRed = *(jpegline + count * 3 + 0); + iGrn = *(jpegline + count * 3 + 1); + iBlu = *(jpegline + count * 3 + 2); + + oRed = outBuf + offset + count * 4 + 0; + oGrn = outBuf + offset + count * 4 + 1; + oBlu = outBuf + offset + count * 4 + 2; + oAlp = outBuf + offset + count * 4 + 3; + + *oRed = iRed; + *oGrn = iGrn; + *oBlu = iBlu; + *oAlp = 255; + } } // stash a scanline -static void j_putRGBAScanline( unsigned char* jpegline, int widthPix, unsigned char* outBuf, int row ){ - int offset = row * widthPix * 4; - int count; - - for ( count = 0; count < widthPix; count++ ) - { - unsigned char iRed, iBlu, iGrn, iAlp; - unsigned char *oRed, *oBlu, *oGrn, *oAlp; - - iRed = *( jpegline + count * 4 + 0 ); - iGrn = *( jpegline + count * 4 + 1 ); - iBlu = *( jpegline + count * 4 + 2 ); - iAlp = *( jpegline + count * 4 + 3 ); - - oRed = outBuf + offset + count * 4 + 0; - oGrn = outBuf + offset + count * 4 + 1; - oBlu = outBuf + offset + count * 4 + 2; - oAlp = outBuf + offset + count * 4 + 3; - - *oRed = iRed; - *oGrn = iGrn; - *oBlu = iBlu; - - //!\todo fix jpeglib, it leaves alpha channel uninitialised +static void j_putRGBAScanline(unsigned char *jpegline, int widthPix, unsigned char *outBuf, int row) +{ + int offset = row * widthPix * 4; + int count; + + for (count = 0; count < widthPix; count++) { + unsigned char iRed, iBlu, iGrn, iAlp; + unsigned char *oRed, *oBlu, *oGrn, *oAlp; + + iRed = *(jpegline + count * 4 + 0); + iGrn = *(jpegline + count * 4 + 1); + iBlu = *(jpegline + count * 4 + 2); + iAlp = *(jpegline + count * 4 + 3); + + oRed = outBuf + offset + count * 4 + 0; + oGrn = outBuf + offset + count * 4 + 1; + oBlu = outBuf + offset + count * 4 + 2; + oAlp = outBuf + offset + count * 4 + 3; + + *oRed = iRed; + *oGrn = iGrn; + *oBlu = iBlu; + + //!\todo fix jpeglib, it leaves alpha channel uninitialised #if 1 - (void) iAlp; - *oAlp = 255; + (void) iAlp; + *oAlp = 255; #else - *oAlp = iAlp; + *oAlp = iAlp; #endif - } + } } // stash a gray scanline -static void j_putGrayScanlineToRGB( unsigned char* jpegline, int widthPix, unsigned char* outBuf, int row ){ - int offset = row * widthPix * 4; - int count; - - for ( count = 0; count < widthPix; count++ ) - { - unsigned char iGray; - unsigned char *oRed, *oBlu, *oGrn, *oAlp; - - // get our grayscale value - iGray = *( jpegline + count ); - - oRed = outBuf + offset + count * 4; - oGrn = outBuf + offset + count * 4 + 1; - oBlu = outBuf + offset + count * 4 + 2; - oAlp = outBuf + offset + count * 4 + 3; - - *oRed = iGray; - *oGrn = iGray; - *oBlu = iGray; - *oAlp = 255; - } +static void j_putGrayScanlineToRGB(unsigned char *jpegline, int widthPix, unsigned char *outBuf, int row) +{ + int offset = row * widthPix * 4; + int count; + + for (count = 0; count < widthPix; count++) { + unsigned char iGray; + unsigned char *oRed, *oBlu, *oGrn, *oAlp; + + // get our grayscale value + iGray = *(jpegline + count); + + oRed = outBuf + offset + count * 4; + oGrn = outBuf + offset + count * 4 + 1; + oBlu = outBuf + offset + count * 4 + 2; + oAlp = outBuf + offset + count * 4 + 3; + + *oRed = iGray; + *oGrn = iGray; + *oBlu = iGray; + *oAlp = 255; + } } -static Image* LoadJPGBuff_( const void *src_buffer, int src_size ){ - struct jpeg_decompress_struct cinfo; - struct my_jpeg_error_mgr jerr; +static Image *LoadJPGBuff_(const void *src_buffer, int src_size) +{ + struct jpeg_decompress_struct cinfo; + struct my_jpeg_error_mgr jerr; - cinfo.err = jpeg_std_error( &jerr.pub ); - jerr.pub.error_exit = my_jpeg_error_exit; + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_jpeg_error_exit; - if ( setjmp( jerr.setjmp_buffer ) ) { //< TODO: use c++ exceptions instead of setjmp/longjmp to handle errors - globalErrorStream() << "WARNING: JPEG library error: " << errormsg << "\n"; - jpeg_destroy_decompress( &cinfo ); - return 0; - } + if (setjmp(jerr.setjmp_buffer)) { //< TODO: use c++ exceptions instead of setjmp/longjmp to handle errors + globalErrorStream() << "WARNING: JPEG library error: " << errormsg << "\n"; + jpeg_destroy_decompress(&cinfo); + return 0; + } - jpeg_create_decompress( &cinfo ); - jpeg_buffer_src( &cinfo, const_cast( src_buffer ), src_size ); - jpeg_read_header( &cinfo, TRUE ); - jpeg_start_decompress( &cinfo ); + jpeg_create_decompress(&cinfo); + jpeg_buffer_src(&cinfo, const_cast( src_buffer ), src_size); + jpeg_read_header(&cinfo, TRUE); + jpeg_start_decompress(&cinfo); - int row_stride = cinfo.output_width * cinfo.output_components; + int row_stride = cinfo.output_width * cinfo.output_components; - RGBAImage* image = new RGBAImage( cinfo.output_width, cinfo.output_height ); + RGBAImage *image = new RGBAImage(cinfo.output_width, cinfo.output_height); - JSAMPARRAY buffer = ( *cinfo.mem->alloc_sarray )( ( j_common_ptr ) & cinfo, JPOOL_IMAGE, row_stride, 1 ); + JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - while ( cinfo.output_scanline < cinfo.output_height ) - { - jpeg_read_scanlines( &cinfo, buffer, 1 ); + while (cinfo.output_scanline < cinfo.output_height) { + jpeg_read_scanlines(&cinfo, buffer, 1); - if ( cinfo.out_color_components == 4 ) { - j_putRGBAScanline( buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline - 1 ); - } - else if ( cinfo.out_color_components == 3 ) { - j_putRGBScanline( buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline - 1 ); - } - else if ( cinfo.out_color_components == 1 ) { - j_putGrayScanlineToRGB( buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline - 1 ); - } - } + if (cinfo.out_color_components == 4) { + j_putRGBAScanline(buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline - 1); + } else if (cinfo.out_color_components == 3) { + j_putRGBScanline(buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline - 1); + } else if (cinfo.out_color_components == 1) { + j_putGrayScanlineToRGB(buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline - 1); + } + } - jpeg_finish_decompress( &cinfo ); - jpeg_destroy_decompress( &cinfo ); + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); - return image; + return image; } -Image* LoadJPG( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadJPGBuff_( buffer.buffer, static_cast( buffer.length ) ); +Image *LoadJPG(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadJPGBuff_(buffer.buffer, static_cast( buffer.length )); } diff --git a/plugins/image/jpeg.h b/plugins/image/jpeg.h index 110f9ad6..22952971 100644 --- a/plugins/image/jpeg.h +++ b/plugins/image/jpeg.h @@ -32,8 +32,9 @@ #define INCLUDED_JPEG_H class Image; + class ArchiveFile; -Image* LoadJPG( ArchiveFile& file ); +Image *LoadJPG(ArchiveFile &file); #endif diff --git a/plugins/image/ktx.cpp b/plugins/image/ktx.cpp index 696ede55..9d220535 100644 --- a/plugins/image/ktx.cpp +++ b/plugins/image/ktx.cpp @@ -29,388 +29,403 @@ #include "imagelib.h" -const int KTX_TYPE_UNSIGNED_BYTE = 0x1401; -const int KTX_TYPE_UNSIGNED_SHORT_4_4_4_4 = 0x8033; -const int KTX_TYPE_UNSIGNED_SHORT_5_5_5_1 = 0x8034; -const int KTX_TYPE_UNSIGNED_SHORT_5_6_5 = 0x8363; - -const int KTX_FORMAT_ALPHA = 0x1906; -const int KTX_FORMAT_RGB = 0x1907; -const int KTX_FORMAT_RGBA = 0x1908; -const int KTX_FORMAT_LUMINANCE = 0x1909; -const int KTX_FORMAT_LUMINANCE_ALPHA = 0x190A; -const int KTX_FORMAT_BGR = 0x80E0; -const int KTX_FORMAT_BGRA = 0x80E1; - -const int KTX_FORMAT_ETC1_RGB8 = 0x8D64; - -class KTX_Decoder -{ +const int KTX_TYPE_UNSIGNED_BYTE = 0x1401; +const int KTX_TYPE_UNSIGNED_SHORT_4_4_4_4 = 0x8033; +const int KTX_TYPE_UNSIGNED_SHORT_5_5_5_1 = 0x8034; +const int KTX_TYPE_UNSIGNED_SHORT_5_6_5 = 0x8363; + +const int KTX_FORMAT_ALPHA = 0x1906; +const int KTX_FORMAT_RGB = 0x1907; +const int KTX_FORMAT_RGBA = 0x1908; +const int KTX_FORMAT_LUMINANCE = 0x1909; +const int KTX_FORMAT_LUMINANCE_ALPHA = 0x190A; +const int KTX_FORMAT_BGR = 0x80E0; +const int KTX_FORMAT_BGRA = 0x80E1; + +const int KTX_FORMAT_ETC1_RGB8 = 0x8D64; + +class KTX_Decoder { public: - virtual ~KTX_Decoder() = default; - virtual void Decode( PointerInputStream& istream, byte* out ) = 0; - virtual unsigned int GetPixelSize() = 0; + virtual ~KTX_Decoder() = default; + + virtual void Decode(PointerInputStream &istream, byte *out) = 0; + + virtual unsigned int GetPixelSize() = 0; }; -class KTX_Decoder_A8 : public KTX_Decoder -{ +class KTX_Decoder_A8 : public KTX_Decoder { public: - virtual void Decode( PointerInputStream& istream, byte* out ){ - out[0] = out[1] = out[2] = 0; - out[3] = istream_read_byte( istream ); - } - virtual unsigned int GetPixelSize(){ - return 1; - } + virtual void Decode(PointerInputStream &istream, byte *out) + { + out[0] = out[1] = out[2] = 0; + out[3] = istream_read_byte(istream); + } + + virtual unsigned int GetPixelSize() + { + return 1; + } }; -class KTX_Decoder_RGB8 : public KTX_Decoder -{ +class KTX_Decoder_RGB8 : public KTX_Decoder { public: - virtual void Decode( PointerInputStream& istream, byte* out ){ - istream.read( out, 3 ); - out[3] = 255; - } - virtual unsigned int GetPixelSize(){ - return 3; - } + virtual void Decode(PointerInputStream &istream, byte *out) + { + istream.read(out, 3); + out[3] = 255; + } + + virtual unsigned int GetPixelSize() + { + return 3; + } }; -class KTX_Decoder_RGBA8 : public KTX_Decoder -{ +class KTX_Decoder_RGBA8 : public KTX_Decoder { public: - virtual void Decode( PointerInputStream& istream, byte* out ){ - istream.read( out, 4 ); - } - virtual unsigned int GetPixelSize(){ - return 4; - } + virtual void Decode(PointerInputStream &istream, byte *out) + { + istream.read(out, 4); + } + + virtual unsigned int GetPixelSize() + { + return 4; + } }; -class KTX_Decoder_L8 : public KTX_Decoder -{ +class KTX_Decoder_L8 : public KTX_Decoder { public: - virtual void Decode( PointerInputStream& istream, byte* out ){ - byte l = istream_read_byte( istream ); - out[0] = out[1] = out[2] = l; - out[3] = 255; - } - virtual unsigned int GetPixelSize(){ - return 1; - } + virtual void Decode(PointerInputStream &istream, byte *out) + { + byte l = istream_read_byte(istream); + out[0] = out[1] = out[2] = l; + out[3] = 255; + } + + virtual unsigned int GetPixelSize() + { + return 1; + } }; -class KTX_Decoder_LA8 : public KTX_Decoder -{ +class KTX_Decoder_LA8 : public KTX_Decoder { public: - virtual void Decode( PointerInputStream& istream, byte* out ){ - byte la[2]; - istream.read( la, 2 ); - out[0] = out[1] = out[2] = la[0]; - out[3] = la[1]; - } - virtual unsigned int GetPixelSize(){ - return 2; - } + virtual void Decode(PointerInputStream &istream, byte *out) + { + byte la[2]; + istream.read(la, 2); + out[0] = out[1] = out[2] = la[0]; + out[3] = la[1]; + } + + virtual unsigned int GetPixelSize() + { + return 2; + } }; -class KTX_Decoder_BGR8 : public KTX_Decoder -{ +class KTX_Decoder_BGR8 : public KTX_Decoder { public: - virtual void Decode( PointerInputStream& istream, byte* out ){ - byte bgr[3]; - istream.read( bgr, 3 ); - out[0] = bgr[2]; - out[1] = bgr[1]; - out[2] = bgr[0]; - out[3] = 255; - } - virtual unsigned int GetPixelSize(){ - return 3; - } + virtual void Decode(PointerInputStream &istream, byte *out) + { + byte bgr[3]; + istream.read(bgr, 3); + out[0] = bgr[2]; + out[1] = bgr[1]; + out[2] = bgr[0]; + out[3] = 255; + } + + virtual unsigned int GetPixelSize() + { + return 3; + } }; -class KTX_Decoder_BGRA8 : public KTX_Decoder -{ +class KTX_Decoder_BGRA8 : public KTX_Decoder { public: - virtual void Decode( PointerInputStream& istream, byte* out ){ - byte bgra[4]; - istream.read( bgra, 4 ); - out[0] = bgra[2]; - out[1] = bgra[1]; - out[2] = bgra[0]; - out[3] = bgra[3]; - } - virtual unsigned int GetPixelSize(){ - return 4; - } + virtual void Decode(PointerInputStream &istream, byte *out) + { + byte bgra[4]; + istream.read(bgra, 4); + out[0] = bgra[2]; + out[1] = bgra[1]; + out[2] = bgra[0]; + out[3] = bgra[3]; + } + + virtual unsigned int GetPixelSize() + { + return 4; + } }; -class KTX_Decoder_RGBA4 : public KTX_Decoder -{ +class KTX_Decoder_RGBA4 : public KTX_Decoder { protected: - bool m_bigEndian; + bool m_bigEndian; public: - KTX_Decoder_RGBA4( bool bigEndian ) : m_bigEndian( bigEndian ){} - virtual void Decode( PointerInputStream& istream, byte* out ){ - uint16_t rgba; - if ( m_bigEndian ) { - rgba = istream_read_uint16_be( istream ); - } - else { - rgba = istream_read_uint16_le( istream ); - } - int r = ( rgba >> 12 ) & 0xf; - int g = ( rgba >> 8 ) & 0xf; - int b = ( rgba >> 4 ) & 0xf; - int a = rgba & 0xf; - out[0] = ( r << 4 ) | r; - out[1] = ( g << 4 ) | g; - out[2] = ( b << 4 ) | b; - out[3] = ( a << 4 ) | a; - } - virtual unsigned int GetPixelSize(){ - return 2; - } + KTX_Decoder_RGBA4(bool bigEndian) : m_bigEndian(bigEndian) + {} + + virtual void Decode(PointerInputStream &istream, byte *out) + { + uint16_t rgba; + if (m_bigEndian) { + rgba = istream_read_uint16_be(istream); + } else { + rgba = istream_read_uint16_le(istream); + } + int r = (rgba >> 12) & 0xf; + int g = (rgba >> 8) & 0xf; + int b = (rgba >> 4) & 0xf; + int a = rgba & 0xf; + out[0] = (r << 4) | r; + out[1] = (g << 4) | g; + out[2] = (b << 4) | b; + out[3] = (a << 4) | a; + } + + virtual unsigned int GetPixelSize() + { + return 2; + } }; -class KTX_Decoder_RGBA5 : public KTX_Decoder -{ +class KTX_Decoder_RGBA5 : public KTX_Decoder { protected: - bool m_bigEndian; + bool m_bigEndian; public: - KTX_Decoder_RGBA5( bool bigEndian ) : m_bigEndian( bigEndian ){} - virtual void Decode( PointerInputStream& istream, byte* out ){ - uint16_t rgba; - if ( m_bigEndian ) { - rgba = istream_read_uint16_be( istream ); - } - else { - rgba = istream_read_uint16_le( istream ); - } - int r = ( rgba >> 11 ) & 0x1f; - int g = ( rgba >> 6 ) & 0x1f; - int b = ( rgba >> 1 ) & 0x1f; - out[0] = ( r << 3 ) | ( r >> 2 ); - out[1] = ( g << 3 ) | ( g >> 2 ); - out[2] = ( b << 3 ) | ( b >> 2 ); - out[3] = ( rgba & 1 ) * 255; - } - virtual unsigned int GetPixelSize(){ - return 2; - } + KTX_Decoder_RGBA5(bool bigEndian) : m_bigEndian(bigEndian) + {} + + virtual void Decode(PointerInputStream &istream, byte *out) + { + uint16_t rgba; + if (m_bigEndian) { + rgba = istream_read_uint16_be(istream); + } else { + rgba = istream_read_uint16_le(istream); + } + int r = (rgba >> 11) & 0x1f; + int g = (rgba >> 6) & 0x1f; + int b = (rgba >> 1) & 0x1f; + out[0] = (r << 3) | (r >> 2); + out[1] = (g << 3) | (g >> 2); + out[2] = (b << 3) | (b >> 2); + out[3] = (rgba & 1) * 255; + } + + virtual unsigned int GetPixelSize() + { + return 2; + } }; -class KTX_Decoder_RGB5 : public KTX_Decoder -{ +class KTX_Decoder_RGB5 : public KTX_Decoder { protected: - bool m_bigEndian; + bool m_bigEndian; public: - KTX_Decoder_RGB5( bool bigEndian ) : m_bigEndian( bigEndian ){} - virtual void Decode( PointerInputStream& istream, byte* out ){ - uint16_t rgb; - if ( m_bigEndian ) { - rgb = istream_read_uint16_be( istream ); - } - else { - rgb = istream_read_uint16_le( istream ); - } - int r = ( rgb >> 11 ) & 0x1f; - int g = ( rgb >> 5 ) & 0x3f; - int b = rgb & 0x1f; - out[0] = ( r << 3 ) | ( r >> 2 ); - out[1] = ( g << 2 ) | ( g >> 4 ); - out[2] = ( b << 3 ) | ( b >> 2 ); - out[3] = 255; - } - virtual unsigned int GetPixelSize(){ - return 2; - } + KTX_Decoder_RGB5(bool bigEndian) : m_bigEndian(bigEndian) + {} + + virtual void Decode(PointerInputStream &istream, byte *out) + { + uint16_t rgb; + if (m_bigEndian) { + rgb = istream_read_uint16_be(istream); + } else { + rgb = istream_read_uint16_le(istream); + } + int r = (rgb >> 11) & 0x1f; + int g = (rgb >> 5) & 0x3f; + int b = rgb & 0x1f; + out[0] = (r << 3) | (r >> 2); + out[1] = (g << 2) | (g >> 4); + out[2] = (b << 3) | (b >> 2); + out[3] = 255; + } + + virtual unsigned int GetPixelSize() + { + return 2; + } }; -static void KTX_DecodeETC1( PointerInputStream& istream, Image& image ){ - unsigned int width = image.getWidth(), height = image.getHeight(); - unsigned int stride = width * 4; - byte* pixbuf = image.getRGBAPixels(); - byte etc[8], rgba[64]; - - for ( unsigned int y = 0; y < height; y += 4, pixbuf += stride * 4 ) - { - unsigned int blockrows = height - y; - if ( blockrows > 4 ) { - blockrows = 4; - } - - byte* p = pixbuf; - for ( unsigned int x = 0; x < width; x += 4, p += 16 ) - { - istream.read( etc, 8 ); - ETC_DecodeETC1Block( etc, rgba, qtrue ); - - unsigned int blockrowsize = width - x; - if ( blockrowsize > 4 ) { - blockrowsize = 4; - } - blockrowsize *= 4; - for ( unsigned int blockrow = 0; blockrow < blockrows; blockrow++ ) - { - memcpy( p + blockrow * stride, rgba + blockrow * 16, blockrowsize ); - } - } - } +static void KTX_DecodeETC1(PointerInputStream &istream, Image &image) +{ + unsigned int width = image.getWidth(), height = image.getHeight(); + unsigned int stride = width * 4; + byte *pixbuf = image.getRGBAPixels(); + byte etc[8], rgba[64]; + + for (unsigned int y = 0; y < height; y += 4, pixbuf += stride * 4) { + unsigned int blockrows = height - y; + if (blockrows > 4) { + blockrows = 4; + } + + byte *p = pixbuf; + for (unsigned int x = 0; x < width; x += 4, p += 16) { + istream.read(etc, 8); + ETC_DecodeETC1Block(etc, rgba, qtrue); + + unsigned int blockrowsize = width - x; + if (blockrowsize > 4) { + blockrowsize = 4; + } + blockrowsize *= 4; + for (unsigned int blockrow = 0; blockrow < blockrows; blockrow++) { + memcpy(p + blockrow * stride, rgba + blockrow * 16, blockrowsize); + } + } + } } -Image* LoadKTXBuff( PointerInputStream& istream ){ - byte identifier[12]; - istream.read( identifier, 12 ); - if ( memcmp( identifier, "\xABKTX 11\xBB\r\n\x1A\n", 12 ) ) { - globalErrorStream() << "LoadKTX: Image has the wrong identifier\n"; - return 0; - } - - bool bigEndian = ( istream_read_uint32_le( istream ) == 0x01020304 ); - - unsigned int type; - if ( bigEndian ) { - type = istream_read_uint32_be( istream ); - } - else { - type = istream_read_uint32_le( istream ); - } - - // For compressed textures, the format is in glInternalFormat. - // For uncompressed textures, it's in glBaseInternalFormat. - istream.seek( ( type ? 3 : 2 ) * sizeof( uint32_t ) ); - unsigned int format; - if ( bigEndian ) { - format = istream_read_uint32_be( istream ); - } - else { - format = istream_read_uint32_le( istream ); - } - if ( !type ) { - istream.seek( sizeof( uint32_t ) ); - } - - unsigned int width, height; - if ( bigEndian ) { - width = istream_read_uint32_be( istream ); - height = istream_read_uint32_be( istream ); - } - else { - width = istream_read_uint32_le( istream ); - height = istream_read_uint32_le( istream ); - } - if ( !width ) { - globalErrorStream() << "LoadKTX: Image has zero width\n"; - return 0; - } - if ( !height ) { - height = 1; - } - - // Skip the key/values and load the first 2D image in the texture. - // Since KTXorientation is only a hint and has no effect on the texture data and coordinates, it must be ignored. - istream.seek( 4 * sizeof( uint32_t ) ); - unsigned int bytesOfKeyValueData; - if ( bigEndian ) { - bytesOfKeyValueData = istream_read_uint32_be( istream ); - } - else { - bytesOfKeyValueData = istream_read_uint32_le( istream ); - } - istream.seek( bytesOfKeyValueData + sizeof( uint32_t ) ); - - RGBAImage* image = new RGBAImage( width, height ); - - if ( type ) { - KTX_Decoder* decoder = NULL; - switch ( type ) - { - case KTX_TYPE_UNSIGNED_BYTE: - switch ( format ) - { - case KTX_FORMAT_ALPHA: - decoder = new KTX_Decoder_A8(); - break; - case KTX_FORMAT_RGB: - decoder = new KTX_Decoder_RGB8(); - break; - case KTX_FORMAT_RGBA: - decoder = new KTX_Decoder_RGBA8(); - break; - case KTX_FORMAT_LUMINANCE: - decoder = new KTX_Decoder_L8(); - break; - case KTX_FORMAT_LUMINANCE_ALPHA: - decoder = new KTX_Decoder_LA8(); - break; - case KTX_FORMAT_BGR: - decoder = new KTX_Decoder_BGR8(); - break; - case KTX_FORMAT_BGRA: - decoder = new KTX_Decoder_BGRA8(); - break; - } - break; - case KTX_TYPE_UNSIGNED_SHORT_4_4_4_4: - if ( format == KTX_FORMAT_RGBA ) { - decoder = new KTX_Decoder_RGBA4( bigEndian ); - } - break; - case KTX_TYPE_UNSIGNED_SHORT_5_5_5_1: - if ( format == KTX_FORMAT_RGBA ) { - decoder = new KTX_Decoder_RGBA5( bigEndian ); - } - break; - case KTX_TYPE_UNSIGNED_SHORT_5_6_5: - if ( format == KTX_FORMAT_RGB ) { - decoder = new KTX_Decoder_RGB5( bigEndian ); - } - break; - } - - if ( !decoder ) { - globalErrorStream() << "LoadKTX: Image has an unsupported pixel type " << type << " or format " << format << "\n"; - image->release(); - return 0; - } - - unsigned int inRowLength = width * decoder->GetPixelSize(); - unsigned int inPadding = ( ( inRowLength + 3 ) & ~3 ) - inRowLength; - byte* out = image->getRGBAPixels(); - for ( unsigned int y = 0; y < height; y++ ) - { - for ( unsigned int x = 0; x < width; x++, out += 4 ) - { - decoder->Decode( istream, out ); - } - - if ( inPadding ) { - istream.seek( inPadding ); - } - } - - delete decoder; - } - else { - switch ( format ) - { - case KTX_FORMAT_ETC1_RGB8: - KTX_DecodeETC1( istream, *image ); - break; - default: - globalErrorStream() << "LoadKTX: Image has an unsupported compressed format " << format << "\n"; - image->release(); - return 0; - } - } - - return image; +Image *LoadKTXBuff(PointerInputStream &istream) +{ + byte identifier[12]; + istream.read(identifier, 12); + if (memcmp(identifier, "\xABKTX 11\xBB\r\n\x1A\n", 12)) { + globalErrorStream() << "LoadKTX: Image has the wrong identifier\n"; + return 0; + } + + bool bigEndian = (istream_read_uint32_le(istream) == 0x01020304); + + unsigned int type; + if (bigEndian) { + type = istream_read_uint32_be(istream); + } else { + type = istream_read_uint32_le(istream); + } + + // For compressed textures, the format is in glInternalFormat. + // For uncompressed textures, it's in glBaseInternalFormat. + istream.seek((type ? 3 : 2) * sizeof(uint32_t)); + unsigned int format; + if (bigEndian) { + format = istream_read_uint32_be(istream); + } else { + format = istream_read_uint32_le(istream); + } + if (!type) { + istream.seek(sizeof(uint32_t)); + } + + unsigned int width, height; + if (bigEndian) { + width = istream_read_uint32_be(istream); + height = istream_read_uint32_be(istream); + } else { + width = istream_read_uint32_le(istream); + height = istream_read_uint32_le(istream); + } + if (!width) { + globalErrorStream() << "LoadKTX: Image has zero width\n"; + return 0; + } + if (!height) { + height = 1; + } + + // Skip the key/values and load the first 2D image in the texture. + // Since KTXorientation is only a hint and has no effect on the texture data and coordinates, it must be ignored. + istream.seek(4 * sizeof(uint32_t)); + unsigned int bytesOfKeyValueData; + if (bigEndian) { + bytesOfKeyValueData = istream_read_uint32_be(istream); + } else { + bytesOfKeyValueData = istream_read_uint32_le(istream); + } + istream.seek(bytesOfKeyValueData + sizeof(uint32_t)); + + RGBAImage *image = new RGBAImage(width, height); + + if (type) { + KTX_Decoder *decoder = NULL; + switch (type) { + case KTX_TYPE_UNSIGNED_BYTE: + switch (format) { + case KTX_FORMAT_ALPHA: + decoder = new KTX_Decoder_A8(); + break; + case KTX_FORMAT_RGB: + decoder = new KTX_Decoder_RGB8(); + break; + case KTX_FORMAT_RGBA: + decoder = new KTX_Decoder_RGBA8(); + break; + case KTX_FORMAT_LUMINANCE: + decoder = new KTX_Decoder_L8(); + break; + case KTX_FORMAT_LUMINANCE_ALPHA: + decoder = new KTX_Decoder_LA8(); + break; + case KTX_FORMAT_BGR: + decoder = new KTX_Decoder_BGR8(); + break; + case KTX_FORMAT_BGRA: + decoder = new KTX_Decoder_BGRA8(); + break; + } + break; + case KTX_TYPE_UNSIGNED_SHORT_4_4_4_4: + if (format == KTX_FORMAT_RGBA) { + decoder = new KTX_Decoder_RGBA4(bigEndian); + } + break; + case KTX_TYPE_UNSIGNED_SHORT_5_5_5_1: + if (format == KTX_FORMAT_RGBA) { + decoder = new KTX_Decoder_RGBA5(bigEndian); + } + break; + case KTX_TYPE_UNSIGNED_SHORT_5_6_5: + if (format == KTX_FORMAT_RGB) { + decoder = new KTX_Decoder_RGB5(bigEndian); + } + break; + } + + if (!decoder) { + globalErrorStream() << "LoadKTX: Image has an unsupported pixel type " << type << " or format " << format + << "\n"; + image->release(); + return 0; + } + + unsigned int inRowLength = width * decoder->GetPixelSize(); + unsigned int inPadding = ((inRowLength + 3) & ~3) - inRowLength; + byte *out = image->getRGBAPixels(); + for (unsigned int y = 0; y < height; y++) { + for (unsigned int x = 0; x < width; x++, out += 4) { + decoder->Decode(istream, out); + } + + if (inPadding) { + istream.seek(inPadding); + } + } + + delete decoder; + } else { + switch (format) { + case KTX_FORMAT_ETC1_RGB8: + KTX_DecodeETC1(istream, *image); + break; + default: + globalErrorStream() << "LoadKTX: Image has an unsupported compressed format " << format << "\n"; + image->release(); + return 0; + } + } + + return image; } -Image* LoadKTX( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - PointerInputStream istream( buffer.buffer ); - return LoadKTXBuff( istream ); +Image *LoadKTX(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + PointerInputStream istream(buffer.buffer); + return LoadKTXBuff(istream); } diff --git a/plugins/image/ktx.h b/plugins/image/ktx.h index 6070077b..f9b05535 100644 --- a/plugins/image/ktx.h +++ b/plugins/image/ktx.h @@ -23,8 +23,9 @@ #define INCLUDED_KTX_H class Image; + class ArchiveFile; -Image* LoadKTX( ArchiveFile& file ); +Image *LoadKTX(ArchiveFile &file); #endif diff --git a/plugins/image/pcx.cpp b/plugins/image/pcx.cpp index 46bffc05..8d658a79 100644 --- a/plugins/image/pcx.cpp +++ b/plugins/image/pcx.cpp @@ -38,21 +38,20 @@ typedef unsigned char byte; ================================================================= */ -typedef struct -{ - unsigned char manufacturer; - unsigned char version; - unsigned char encoding; - unsigned char bits_per_pixel; - unsigned short xmin, ymin, xmax, ymax; - unsigned short hres, vres; - unsigned char palette[48]; - unsigned char reserved; - unsigned char color_planes; - unsigned short bytes_per_line; - unsigned short palette_type; - unsigned char filler[58]; - unsigned char data; // unbounded +typedef struct { + unsigned char manufacturer; + unsigned char version; + unsigned char encoding; + unsigned char bits_per_pixel; + unsigned short xmin, ymin, xmax, ymax; + unsigned short hres, vres; + unsigned char palette[48]; + unsigned char reserved; + unsigned char color_planes; + unsigned short bytes_per_line; + unsigned short palette_type; + unsigned char filler[58]; + unsigned char data; // unbounded } pcx_t; /* @@ -61,119 +60,113 @@ typedef struct ============== */ -struct PCXRLEPacket -{ - byte data; - int length; +struct PCXRLEPacket { + byte data; + int length; }; -inline void ByteStream_readPCXRLEPacket( PointerInputStream& inputStream, PCXRLEPacket& packet ){ - byte d; - inputStream.read( &d, 1 ); - if ( ( d & 0xC0 ) == 0xC0 ) { - packet.length = d & 0x3F; - inputStream.read( &packet.data, 1 ); - } - else - { - packet.length = 1; - packet.data = d; - } +inline void ByteStream_readPCXRLEPacket(PointerInputStream &inputStream, PCXRLEPacket &packet) +{ + byte d; + inputStream.read(&d, 1); + if ((d & 0xC0) == 0xC0) { + packet.length = d & 0x3F; + inputStream.read(&packet.data, 1); + } else { + packet.length = 1; + packet.data = d; + } } -void LoadPCXBuff( byte* buffer, std::size_t len, byte **pic, byte **palette, int *width, int *height ){ - *pic = 0; - - pcx_t pcx; - int x, y, lsize; - byte *out, *pix; - - /* parse the PCX file */ - - PointerInputStream inputStream( buffer ); - - pcx.manufacturer = istream_read_byte( inputStream ); - pcx.version = istream_read_byte( inputStream ); - pcx.encoding = istream_read_byte( inputStream ); - pcx.bits_per_pixel = istream_read_byte( inputStream ); - pcx.xmin = istream_read_int16_le( inputStream ); - pcx.ymin = istream_read_int16_le( inputStream ); - pcx.xmax = istream_read_int16_le( inputStream ); - pcx.ymax = istream_read_int16_le( inputStream ); - pcx.hres = istream_read_int16_le( inputStream ); - pcx.vres = istream_read_int16_le( inputStream ); - inputStream.read( pcx.palette, 48 ); - pcx.reserved = istream_read_byte( inputStream ); - pcx.color_planes = istream_read_byte( inputStream ); - pcx.bytes_per_line = istream_read_int16_le( inputStream ); - pcx.palette_type = istream_read_int16_le( inputStream ); - inputStream.read( pcx.filler, 58 ); - - - if ( pcx.manufacturer != 0x0a - || pcx.version != 5 - || pcx.encoding != 1 - || pcx.bits_per_pixel != 8 ) { - return; - } - - if ( width ) { - *width = pcx.xmax + 1; - } - if ( height ) { - *height = pcx.ymax + 1; - } - - if ( !pic ) { - return; - } - - out = (byte *)malloc( ( pcx.ymax + 1 ) * ( pcx.xmax + 1 ) ); - - *pic = out; - pix = out; - - /* RR2DO2: pcx fix */ - lsize = pcx.color_planes * pcx.bytes_per_line; - - /* go scanline by scanline */ - for ( y = 0; y <= pcx.ymax; y++, pix += pcx.xmax + 1 ) - { - /* do a scanline */ - for ( x = 0; x <= pcx.xmax; ) - { - /* RR2DO2 */ - PCXRLEPacket packet; - ByteStream_readPCXRLEPacket( inputStream, packet ); - - while ( packet.length-- > 0 ) - { - pix[ x++ ] = packet.data; - } - } - - /* RR2DO2: discard any other data */ - PCXRLEPacket packet; - while ( x < lsize ) - { - ByteStream_readPCXRLEPacket( inputStream, packet ); - x++; - } - while ( packet.length-- > 0 ) - { - x++; - } - } - - /* validity check */ - if ( std::size_t( inputStream.get() - buffer ) > len ) { - *pic = 0; - } - - if ( palette ) { - *palette = (byte *)malloc( 768 ); - memcpy( *palette, buffer + len - 768, 768 ); - } +void LoadPCXBuff(byte *buffer, std::size_t len, byte **pic, byte **palette, int *width, int *height) +{ + *pic = 0; + + pcx_t pcx; + int x, y, lsize; + byte *out, *pix; + + /* parse the PCX file */ + + PointerInputStream inputStream(buffer); + + pcx.manufacturer = istream_read_byte(inputStream); + pcx.version = istream_read_byte(inputStream); + pcx.encoding = istream_read_byte(inputStream); + pcx.bits_per_pixel = istream_read_byte(inputStream); + pcx.xmin = istream_read_int16_le(inputStream); + pcx.ymin = istream_read_int16_le(inputStream); + pcx.xmax = istream_read_int16_le(inputStream); + pcx.ymax = istream_read_int16_le(inputStream); + pcx.hres = istream_read_int16_le(inputStream); + pcx.vres = istream_read_int16_le(inputStream); + inputStream.read(pcx.palette, 48); + pcx.reserved = istream_read_byte(inputStream); + pcx.color_planes = istream_read_byte(inputStream); + pcx.bytes_per_line = istream_read_int16_le(inputStream); + pcx.palette_type = istream_read_int16_le(inputStream); + inputStream.read(pcx.filler, 58); + + + if (pcx.manufacturer != 0x0a + || pcx.version != 5 + || pcx.encoding != 1 + || pcx.bits_per_pixel != 8) { + return; + } + + if (width) { + *width = pcx.xmax + 1; + } + if (height) { + *height = pcx.ymax + 1; + } + + if (!pic) { + return; + } + + out = (byte *) malloc((pcx.ymax + 1) * (pcx.xmax + 1)); + + *pic = out; + pix = out; + + /* RR2DO2: pcx fix */ + lsize = pcx.color_planes * pcx.bytes_per_line; + + /* go scanline by scanline */ + for (y = 0; y <= pcx.ymax; y++, pix += pcx.xmax + 1) { + /* do a scanline */ + for (x = 0; x <= pcx.xmax;) { + /* RR2DO2 */ + PCXRLEPacket packet; + ByteStream_readPCXRLEPacket(inputStream, packet); + + while (packet.length-- > 0) { + pix[x++] = packet.data; + } + } + + /* RR2DO2: discard any other data */ + PCXRLEPacket packet; + while (x < lsize) { + ByteStream_readPCXRLEPacket(inputStream, packet); + x++; + } + while (packet.length-- > 0) { + x++; + } + } + + /* validity check */ + if (std::size_t(inputStream.get() - buffer) > len) { + *pic = 0; + } + + if (palette) { + *palette = (byte *) malloc(768); + memcpy(*palette, buffer + len - 768, 768); + } } /* @@ -181,37 +174,38 @@ void LoadPCXBuff( byte* buffer, std::size_t len, byte **pic, byte **palette, int LoadPCX32 ============== */ -Image* LoadPCX32Buff( byte* buffer, std::size_t length ){ - byte *palette; - byte *pic8; - int i, c, p, width, height; - byte *pic32; - - LoadPCXBuff( buffer, length, &pic8, &palette, &width, &height ); - if ( !pic8 ) { - return 0; - } - - RGBAImage* image = new RGBAImage( width, height ); - c = ( width ) * ( height ); - pic32 = image->getRGBAPixels(); - for ( i = 0; i < c; i++ ) - { - p = pic8[i]; - pic32[0] = palette[p * 3]; - pic32[1] = palette[p * 3 + 1]; - pic32[2] = palette[p * 3 + 2]; - pic32[3] = 255; - pic32 += 4; - } - - free( pic8 ); - free( palette ); - - return image; +Image *LoadPCX32Buff(byte *buffer, std::size_t length) +{ + byte *palette; + byte *pic8; + int i, c, p, width, height; + byte *pic32; + + LoadPCXBuff(buffer, length, &pic8, &palette, &width, &height); + if (!pic8) { + return 0; + } + + RGBAImage *image = new RGBAImage(width, height); + c = (width) * (height); + pic32 = image->getRGBAPixels(); + for (i = 0; i < c; i++) { + p = pic8[i]; + pic32[0] = palette[p * 3]; + pic32[1] = palette[p * 3 + 1]; + pic32[2] = palette[p * 3 + 2]; + pic32[3] = 255; + pic32 += 4; + } + + free(pic8); + free(palette); + + return image; } -Image* LoadPCX32( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadPCX32Buff( buffer.buffer, buffer.length ); +Image *LoadPCX32(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadPCX32Buff(buffer.buffer, buffer.length); } diff --git a/plugins/image/pcx.h b/plugins/image/pcx.h index 63d2753a..81f10e43 100644 --- a/plugins/image/pcx.h +++ b/plugins/image/pcx.h @@ -23,8 +23,9 @@ #define INCLUDED_PCX_H class Image; + class ArchiveFile; -Image* LoadPCX32( ArchiveFile& file ); +Image *LoadPCX32(ArchiveFile &file); #endif diff --git a/plugins/image/tga.cpp b/plugins/image/tga.cpp index 4fa8731f..c430700d 100644 --- a/plugins/image/tga.cpp +++ b/plugins/image/tga.cpp @@ -40,377 +40,394 @@ class Flip10 {}; // horizontal flip only class Flip11 {}; // both template -void image_decode( PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip00& ){ - RGBAPixel* end = image.pixels + ( image.height * image.width ); - for ( RGBAPixel* row = end; row != image.pixels; row -= image.width ) - { - for ( RGBAPixel* pixel = row - image.width; pixel != row; ++pixel ) - { - decode( istream, *pixel ); - } - } +void image_decode(PointerInputStream &istream, PixelDecoder &decode, RGBAImage &image, const Flip00 &) +{ + RGBAPixel *end = image.pixels + (image.height * image.width); + for (RGBAPixel *row = end; row != image.pixels; row -= image.width) { + for (RGBAPixel *pixel = row - image.width; pixel != row; ++pixel) { + decode(istream, *pixel); + } + } } template -void image_decode( PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip01& ){ - RGBAPixel* end = image.pixels + ( image.height * image.width ); - for ( RGBAPixel* row = image.pixels; row != end; row += image.width ) - { - for ( RGBAPixel* pixel = row; pixel != row + image.width; ++pixel ) - { - decode( istream, *pixel ); - } - } +void image_decode(PointerInputStream &istream, PixelDecoder &decode, RGBAImage &image, const Flip01 &) +{ + RGBAPixel *end = image.pixels + (image.height * image.width); + for (RGBAPixel *row = image.pixels; row != end; row += image.width) { + for (RGBAPixel *pixel = row; pixel != row + image.width; ++pixel) { + decode(istream, *pixel); + } + } } template -void image_decode( PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip10& ){ - RGBAPixel* end = image.pixels + ( image.height * image.width ); - for ( RGBAPixel* row = end; row != image.pixels; row -= image.width ) - { - for ( RGBAPixel* pixel = row; pixel != row - image.width; ) - { - decode( istream, *--pixel ); - } - } +void image_decode(PointerInputStream &istream, PixelDecoder &decode, RGBAImage &image, const Flip10 &) +{ + RGBAPixel *end = image.pixels + (image.height * image.width); + for (RGBAPixel *row = end; row != image.pixels; row -= image.width) { + for (RGBAPixel *pixel = row; pixel != row - image.width;) { + decode(istream, *--pixel); + } + } } template -void image_decode( PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip11& ){ - RGBAPixel* end = image.pixels + ( image.height * image.width ); - for ( RGBAPixel* row = image.pixels; row != end; row += image.width ) - { - for ( RGBAPixel* pixel = row + image.width; pixel != row; ) - { - decode( istream, *--pixel ); - } - } +void image_decode(PointerInputStream &istream, PixelDecoder &decode, RGBAImage &image, const Flip11 &) +{ + RGBAPixel *end = image.pixels + (image.height * image.width); + for (RGBAPixel *row = image.pixels; row != end; row += image.width) { + for (RGBAPixel *pixel = row + image.width; pixel != row;) { + decode(istream, *--pixel); + } + } } -inline void istream_read_gray( PointerInputStream& istream, RGBAPixel& pixel ){ - istream.read( &pixel.blue, 1 ); - pixel.red = pixel.green = pixel.blue; - pixel.alpha = 0xff; +inline void istream_read_gray(PointerInputStream &istream, RGBAPixel &pixel) +{ + istream.read(&pixel.blue, 1); + pixel.red = pixel.green = pixel.blue; + pixel.alpha = 0xff; } -inline void istream_read_rgb( PointerInputStream& istream, RGBAPixel& pixel ){ - istream.read( &pixel.blue, 1 ); - istream.read( &pixel.green, 1 ); - istream.read( &pixel.red, 1 ); - pixel.alpha = 0xff; +inline void istream_read_rgb(PointerInputStream &istream, RGBAPixel &pixel) +{ + istream.read(&pixel.blue, 1); + istream.read(&pixel.green, 1); + istream.read(&pixel.red, 1); + pixel.alpha = 0xff; } -inline void istream_read_rgba( PointerInputStream& istream, RGBAPixel& pixel ){ - istream.read( &pixel.blue, 1 ); - istream.read( &pixel.green, 1 ); - istream.read( &pixel.red, 1 ); - istream.read( &pixel.alpha, 1 ); +inline void istream_read_rgba(PointerInputStream &istream, RGBAPixel &pixel) +{ + istream.read(&pixel.blue, 1); + istream.read(&pixel.green, 1); + istream.read(&pixel.red, 1); + istream.read(&pixel.alpha, 1); } -class TargaDecodeGrayPixel -{ +class TargaDecodeGrayPixel { public: -void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ - istream_read_gray( istream, pixel ); -} + void operator()(PointerInputStream &istream, RGBAPixel &pixel) + { + istream_read_gray(istream, pixel); + } }; template -void targa_decode_grayscale( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ - TargaDecodeGrayPixel decode; - image_decode( istream, decode, image, flip ); +void targa_decode_grayscale(PointerInputStream &istream, RGBAImage &image, const Flip &flip) +{ + TargaDecodeGrayPixel decode; + image_decode(istream, decode, image, flip); } -class TargaDecodeRGBPixel -{ +class TargaDecodeRGBPixel { public: -void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ - istream_read_rgb( istream, pixel ); -} + void operator()(PointerInputStream &istream, RGBAPixel &pixel) + { + istream_read_rgb(istream, pixel); + } }; template -void targa_decode_rgb( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ - TargaDecodeRGBPixel decode; - image_decode( istream, decode, image, flip ); +void targa_decode_rgb(PointerInputStream &istream, RGBAImage &image, const Flip &flip) +{ + TargaDecodeRGBPixel decode; + image_decode(istream, decode, image, flip); } -class TargaDecodeRGBAPixel -{ +class TargaDecodeRGBAPixel { public: -void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ - istream_read_rgba( istream, pixel ); -} + void operator()(PointerInputStream &istream, RGBAPixel &pixel) + { + istream_read_rgba(istream, pixel); + } }; template -void targa_decode_rgba( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ - TargaDecodeRGBAPixel decode; - image_decode( istream, decode, image, flip ); +void targa_decode_rgba(PointerInputStream &istream, RGBAImage &image, const Flip &flip) +{ + TargaDecodeRGBAPixel decode; + image_decode(istream, decode, image, flip); } typedef byte TargaPacket; typedef byte TargaPacketSize; -inline void targa_packet_read_istream( TargaPacket& packet, PointerInputStream& istream ){ - istream.read( &packet, 1 ); +inline void targa_packet_read_istream(TargaPacket &packet, PointerInputStream &istream) +{ + istream.read(&packet, 1); } -inline bool targa_packet_is_rle( const TargaPacket& packet ){ - return ( packet & 0x80 ) != 0; +inline bool targa_packet_is_rle(const TargaPacket &packet) +{ + return (packet & 0x80) != 0; } -inline TargaPacketSize targa_packet_size( const TargaPacket& packet ){ - return 1 + ( packet & 0x7f ); +inline TargaPacketSize targa_packet_size(const TargaPacket &packet) +{ + return 1 + (packet & 0x7f); } -class TargaDecodeGrayPixelRLE -{ -TargaPacketSize m_packetSize; -RGBAPixel m_pixel; -TargaPacket m_packet; +class TargaDecodeGrayPixelRLE { + TargaPacketSize m_packetSize; + RGBAPixel m_pixel; + TargaPacket m_packet; public: -TargaDecodeGrayPixelRLE() : m_packetSize( 0 ){ -} -void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ - if ( m_packetSize == 0 ) { - targa_packet_read_istream( m_packet, istream ); - m_packetSize = targa_packet_size( m_packet ); - - if ( targa_packet_is_rle( m_packet ) ) { - istream_read_gray( istream, m_pixel ); - } - } - - if ( targa_packet_is_rle( m_packet ) ) { - pixel = m_pixel; - } - else - { - istream_read_gray( istream, pixel ); - } - - --m_packetSize; -} + TargaDecodeGrayPixelRLE() : m_packetSize(0) + { + } + + void operator()(PointerInputStream &istream, RGBAPixel &pixel) + { + if (m_packetSize == 0) { + targa_packet_read_istream(m_packet, istream); + m_packetSize = targa_packet_size(m_packet); + + if (targa_packet_is_rle(m_packet)) { + istream_read_gray(istream, m_pixel); + } + } + + if (targa_packet_is_rle(m_packet)) { + pixel = m_pixel; + } else { + istream_read_gray(istream, pixel); + } + + --m_packetSize; + } }; template -void targa_decode_rle_grayscale( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ - TargaDecodeGrayPixelRLE decode; - image_decode( istream, decode, image, flip ); +void targa_decode_rle_grayscale(PointerInputStream &istream, RGBAImage &image, const Flip &flip) +{ + TargaDecodeGrayPixelRLE decode; + image_decode(istream, decode, image, flip); } -class TargaDecodeRGBPixelRLE -{ -TargaPacketSize m_packetSize; -RGBAPixel m_pixel; -TargaPacket m_packet; +class TargaDecodeRGBPixelRLE { + TargaPacketSize m_packetSize; + RGBAPixel m_pixel; + TargaPacket m_packet; public: -TargaDecodeRGBPixelRLE() : m_packetSize( 0 ){ -} -void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ - if ( m_packetSize == 0 ) { - targa_packet_read_istream( m_packet, istream ); - m_packetSize = targa_packet_size( m_packet ); - - if ( targa_packet_is_rle( m_packet ) ) { - istream_read_rgb( istream, m_pixel ); - } - } - - if ( targa_packet_is_rle( m_packet ) ) { - pixel = m_pixel; - } - else - { - istream_read_rgb( istream, pixel ); - } - - --m_packetSize; -} + TargaDecodeRGBPixelRLE() : m_packetSize(0) + { + } + + void operator()(PointerInputStream &istream, RGBAPixel &pixel) + { + if (m_packetSize == 0) { + targa_packet_read_istream(m_packet, istream); + m_packetSize = targa_packet_size(m_packet); + + if (targa_packet_is_rle(m_packet)) { + istream_read_rgb(istream, m_pixel); + } + } + + if (targa_packet_is_rle(m_packet)) { + pixel = m_pixel; + } else { + istream_read_rgb(istream, pixel); + } + + --m_packetSize; + } }; template -void targa_decode_rle_rgb( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ - TargaDecodeRGBPixelRLE decode; - image_decode( istream, decode, image, flip ); +void targa_decode_rle_rgb(PointerInputStream &istream, RGBAImage &image, const Flip &flip) +{ + TargaDecodeRGBPixelRLE decode; + image_decode(istream, decode, image, flip); } -class TargaDecodeRGBAPixelRLE -{ -TargaPacketSize m_packetSize; -RGBAPixel m_pixel; -TargaPacket m_packet; +class TargaDecodeRGBAPixelRLE { + TargaPacketSize m_packetSize; + RGBAPixel m_pixel; + TargaPacket m_packet; public: -TargaDecodeRGBAPixelRLE() : m_packetSize( 0 ){ -} -void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ - if ( m_packetSize == 0 ) { - targa_packet_read_istream( m_packet, istream ); - m_packetSize = targa_packet_size( m_packet ); - - if ( targa_packet_is_rle( m_packet ) ) { - istream_read_rgba( istream, m_pixel ); - } - } - - if ( targa_packet_is_rle( m_packet ) ) { - pixel = m_pixel; - } - else - { - istream_read_rgba( istream, pixel ); - } - - --m_packetSize; -} + TargaDecodeRGBAPixelRLE() : m_packetSize(0) + { + } + + void operator()(PointerInputStream &istream, RGBAPixel &pixel) + { + if (m_packetSize == 0) { + targa_packet_read_istream(m_packet, istream); + m_packetSize = targa_packet_size(m_packet); + + if (targa_packet_is_rle(m_packet)) { + istream_read_rgba(istream, m_pixel); + } + } + + if (targa_packet_is_rle(m_packet)) { + pixel = m_pixel; + } else { + istream_read_rgba(istream, pixel); + } + + --m_packetSize; + } }; template -void targa_decode_rle_rgba( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ - TargaDecodeRGBAPixelRLE decode; - image_decode( istream, decode, image, flip ); +void targa_decode_rle_rgba(PointerInputStream &istream, RGBAImage &image, const Flip &flip) +{ + TargaDecodeRGBAPixelRLE decode; + image_decode(istream, decode, image, flip); } -struct TargaHeader -{ - unsigned char id_length, colormap_type, image_type; - unsigned short colormap_index, colormap_length; - unsigned char colormap_size; - unsigned short x_origin, y_origin, width, height; - unsigned char pixel_size, attributes; +struct TargaHeader { + unsigned char id_length, colormap_type, image_type; + unsigned short colormap_index, colormap_length; + unsigned char colormap_size; + unsigned short x_origin, y_origin, width, height; + unsigned char pixel_size, attributes; }; -inline void targa_header_read_istream( TargaHeader& targa_header, PointerInputStream& istream ){ - targa_header.id_length = istream_read_byte( istream ); - targa_header.colormap_type = istream_read_byte( istream ); - targa_header.image_type = istream_read_byte( istream ); - - targa_header.colormap_index = istream_read_int16_le( istream ); - targa_header.colormap_length = istream_read_int16_le( istream ); - targa_header.colormap_size = istream_read_byte( istream ); - targa_header.x_origin = istream_read_int16_le( istream ); - targa_header.y_origin = istream_read_int16_le( istream ); - targa_header.width = istream_read_int16_le( istream ); - targa_header.height = istream_read_int16_le( istream ); - targa_header.pixel_size = istream_read_byte( istream ); - targa_header.attributes = istream_read_byte( istream ); - - if ( targa_header.id_length != 0 ) { - istream.seek( targa_header.id_length ); // skip TARGA image comment - } +inline void targa_header_read_istream(TargaHeader &targa_header, PointerInputStream &istream) +{ + targa_header.id_length = istream_read_byte(istream); + targa_header.colormap_type = istream_read_byte(istream); + targa_header.image_type = istream_read_byte(istream); + + targa_header.colormap_index = istream_read_int16_le(istream); + targa_header.colormap_length = istream_read_int16_le(istream); + targa_header.colormap_size = istream_read_byte(istream); + targa_header.x_origin = istream_read_int16_le(istream); + targa_header.y_origin = istream_read_int16_le(istream); + targa_header.width = istream_read_int16_le(istream); + targa_header.height = istream_read_int16_le(istream); + targa_header.pixel_size = istream_read_byte(istream); + targa_header.attributes = istream_read_byte(istream); + + if (targa_header.id_length != 0) { + istream.seek(targa_header.id_length); // skip TARGA image comment + } } template -class ScopeDelete -{ -Type* m_value; -ScopeDelete( const ScopeDelete& ); -ScopeDelete& operator=( const ScopeDelete& ); +class ScopeDelete { + Type *m_value; + + ScopeDelete(const ScopeDelete &); + + ScopeDelete &operator=(const ScopeDelete &); + public: -ScopeDelete( Type* value ) : m_value( value ){ -} -~ScopeDelete(){ - delete m_value; -} -Type* get_pointer() const { - return m_value; -} + ScopeDelete(Type *value) : m_value(value) + { + } + + ~ScopeDelete() + { + delete m_value; + } + + Type *get_pointer() const + { + return m_value; + } }; template -Image* Targa_decodeImageData( const TargaHeader& targa_header, PointerInputStream& istream, const Flip& flip ){ - RGBAImage* image = new RGBAImage( targa_header.width, targa_header.height ); - - if ( targa_header.image_type == 2 || targa_header.image_type == 3 ) { - switch ( targa_header.pixel_size ) - { - case 8: - targa_decode_grayscale( istream, *image, flip ); - break; - case 24: - targa_decode_rgb( istream, *image, flip ); - break; - case 32: - targa_decode_rgba( istream, *image, flip ); - break; - default: - globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; - image->release(); - return 0; - } - } - else if ( targa_header.image_type == 10 || targa_header.image_type == 11 ) { - switch ( targa_header.pixel_size ) - { - case 8: - targa_decode_rle_grayscale( istream, *image, flip ); - break; - case 24: - targa_decode_rle_rgb( istream, *image, flip ); - break; - case 32: - targa_decode_rle_rgba( istream, *image, flip ); - break; - default: - globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; - image->release(); - return 0; - } - } - - return image; +Image *Targa_decodeImageData(const TargaHeader &targa_header, PointerInputStream &istream, const Flip &flip) +{ + RGBAImage *image = new RGBAImage(targa_header.width, targa_header.height); + + if (targa_header.image_type == 2 || targa_header.image_type == 3) { + switch (targa_header.pixel_size) { + case 8: + targa_decode_grayscale(istream, *image, flip); + break; + case 24: + targa_decode_rgb(istream, *image, flip); + break; + case 32: + targa_decode_rgba(istream, *image, flip); + break; + default: + globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; + image->release(); + return 0; + } + } else if (targa_header.image_type == 10 || targa_header.image_type == 11) { + switch (targa_header.pixel_size) { + case 8: + targa_decode_rle_grayscale(istream, *image, flip); + break; + case 24: + targa_decode_rle_rgb(istream, *image, flip); + break; + case 32: + targa_decode_rle_rgba(istream, *image, flip); + break; + default: + globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; + image->release(); + return 0; + } + } + + return image; } const unsigned int TGA_FLIP_HORIZONTAL = 0x10; const unsigned int TGA_FLIP_VERTICAL = 0x20; -Image* LoadTGABuff( const byte* buffer ){ - PointerInputStream istream( buffer ); - TargaHeader targa_header; - - targa_header_read_istream( targa_header, istream ); - - if ( targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3 && targa_header.image_type != 11 ) { - globalErrorStream() << "LoadTGA: TGA type " << targa_header.image_type << " not supported\n"; - globalErrorStream() << "LoadTGA: Only type 2 (RGB), 3 (gray), 10 (RGB), and 11 (gray) TGA images supported\n"; - return 0; - } - - if ( targa_header.colormap_type != 0 ) { - globalErrorStream() << "LoadTGA: colormaps not supported\n"; - return 0; - } - - if ( ( ( targa_header.image_type == 2 || targa_header.image_type == 10 ) && targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) || - ( ( targa_header.image_type == 3 || targa_header.image_type == 11 ) && targa_header.pixel_size != 8 ) ) { - globalErrorStream() << "LoadTGA: Only 32, 24 or 8 bit images supported\n"; - return 0; - } - - if ( !bitfield_enabled( targa_header.attributes, TGA_FLIP_HORIZONTAL ) - && !bitfield_enabled( targa_header.attributes, TGA_FLIP_VERTICAL ) ) { - return Targa_decodeImageData( targa_header, istream, Flip00() ); - } - if ( !bitfield_enabled( targa_header.attributes, TGA_FLIP_HORIZONTAL ) - && bitfield_enabled( targa_header.attributes, TGA_FLIP_VERTICAL ) ) { - return Targa_decodeImageData( targa_header, istream, Flip01() ); - } - if ( bitfield_enabled( targa_header.attributes, TGA_FLIP_HORIZONTAL ) - && !bitfield_enabled( targa_header.attributes, TGA_FLIP_VERTICAL ) ) { - return Targa_decodeImageData( targa_header, istream, Flip10() ); - } - if ( bitfield_enabled( targa_header.attributes, TGA_FLIP_HORIZONTAL ) - && bitfield_enabled( targa_header.attributes, TGA_FLIP_VERTICAL ) ) { - return Targa_decodeImageData( targa_header, istream, Flip11() ); - } - - // unreachable - return 0; -} - -Image* LoadTGA( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadTGABuff( buffer.buffer ); +Image *LoadTGABuff(const byte *buffer) +{ + PointerInputStream istream(buffer); + TargaHeader targa_header; + + targa_header_read_istream(targa_header, istream); + + if (targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3 && + targa_header.image_type != 11) { + globalErrorStream() << "LoadTGA: TGA type " << targa_header.image_type << " not supported\n"; + globalErrorStream() << "LoadTGA: Only type 2 (RGB), 3 (gray), 10 (RGB), and 11 (gray) TGA images supported\n"; + return 0; + } + + if (targa_header.colormap_type != 0) { + globalErrorStream() << "LoadTGA: colormaps not supported\n"; + return 0; + } + + if (((targa_header.image_type == 2 || targa_header.image_type == 10) && targa_header.pixel_size != 32 && + targa_header.pixel_size != 24) || + ((targa_header.image_type == 3 || targa_header.image_type == 11) && targa_header.pixel_size != 8)) { + globalErrorStream() << "LoadTGA: Only 32, 24 or 8 bit images supported\n"; + return 0; + } + + if (!bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL) + && !bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL)) { + return Targa_decodeImageData(targa_header, istream, Flip00()); + } + if (!bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL) + && bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL)) { + return Targa_decodeImageData(targa_header, istream, Flip01()); + } + if (bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL) + && !bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL)) { + return Targa_decodeImageData(targa_header, istream, Flip10()); + } + if (bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL) + && bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL)) { + return Targa_decodeImageData(targa_header, istream, Flip11()); + } + + // unreachable + return 0; +} + +Image *LoadTGA(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadTGABuff(buffer.buffer); } diff --git a/plugins/image/tga.h b/plugins/image/tga.h index c67fea30..226a997c 100644 --- a/plugins/image/tga.h +++ b/plugins/image/tga.h @@ -23,8 +23,9 @@ #define INCLUDED_TGA_H class Image; + class ArchiveFile; -Image* LoadTGA( ArchiveFile& file ); +Image *LoadTGA(ArchiveFile &file); #endif diff --git a/plugins/imagehl/hlw.cpp b/plugins/imagehl/hlw.cpp index 73275547..00d1fc80 100644 --- a/plugins/imagehl/hlw.cpp +++ b/plugins/imagehl/hlw.cpp @@ -61,13 +61,12 @@ typedef unsigned char byte; ============================================================================ */ -#define GET_MIP_DATA_SIZE( WIDTH, HEIGHT ) ( sizeof( WAD3_MIP ) + ( WIDTH * HEIGHT ) + ( WIDTH * HEIGHT / 4 ) + ( WIDTH * HEIGHT / 16 ) + ( WIDTH * HEIGHT / 64 ) ) +#define GET_MIP_DATA_SIZE(WIDTH, HEIGHT) ( sizeof( WAD3_MIP ) + ( WIDTH * HEIGHT ) + ( WIDTH * HEIGHT / 4 ) + ( WIDTH * HEIGHT / 16 ) + ( WIDTH * HEIGHT / 64 ) ) -typedef struct -{ - char name[16]; - unsigned int width, height; - unsigned int offsets[4]; // four mip maps stored +typedef struct { + char name[16]; + unsigned int width, height; + unsigned int offsets[4]; // four mip maps stored } WAD3_MIP, *LPWAD3_MIP; /* @@ -88,66 +87,64 @@ typedef struct ============= */ -Image* LoadHLWBuff( byte* buffer ){ - byte *buf_p; - unsigned long mipdatasize; - int columns, rows; - byte *pixbuf; - int row, column; - byte *palette; - LPWAD3_MIP lpMip; - unsigned char red, green, blue, alphabyte; +Image *LoadHLWBuff(byte *buffer) +{ + byte *buf_p; + unsigned long mipdatasize; + int columns, rows; + byte *pixbuf; + int row, column; + byte *palette; + LPWAD3_MIP lpMip; + unsigned char red, green, blue, alphabyte; - lpMip = (LPWAD3_MIP)buffer; //!\todo Make endian-safe. + lpMip = (LPWAD3_MIP) buffer; //!\todo Make endian-safe. - mipdatasize = GET_MIP_DATA_SIZE( lpMip->width,lpMip->height ); + mipdatasize = GET_MIP_DATA_SIZE(lpMip->width, lpMip->height); - palette = buffer + mipdatasize + 2; + palette = buffer + mipdatasize + 2; - buf_p = buffer + lpMip->offsets[0]; + buf_p = buffer + lpMip->offsets[0]; - columns = lpMip->width; - rows = lpMip->height; + columns = lpMip->width; + rows = lpMip->height; - RGBAImage* image = new RGBAImage( columns, rows ); + RGBAImage *image = new RGBAImage(columns, rows); - for ( row = 0; row < rows; row++ ) - { - pixbuf = image->getRGBAPixels() + row * columns * 4; + for (row = 0; row < rows; row++) { + pixbuf = image->getRGBAPixels() + row * columns * 4; - for ( column = 0; column < columns; column++ ) - { - int palIndex; + for (column = 0; column < columns; column++) { + int palIndex; - palIndex = *buf_p++; + palIndex = *buf_p++; - red = *( palette + ( palIndex * 3 ) ); - green = *( palette + ( palIndex * 3 ) + 1 ); - blue = *( palette + ( palIndex * 3 ) + 2 ); + red = *(palette + (palIndex * 3)); + green = *(palette + (palIndex * 3) + 1); + blue = *(palette + (palIndex * 3) + 2); - // HalfLife engine makes pixels that are BLUE transparent. - // So show them that way in the editor. - if ( blue == 0xff && red == 0x00 && green == 0x00 ) { - alphabyte = 0x00; - blue = 0x00; // don't set the resulting pixel to blue - } - else - { - alphabyte = 0xff; - } + // HalfLife engine makes pixels that are BLUE transparent. + // So show them that way in the editor. + if (blue == 0xff && red == 0x00 && green == 0x00) { + alphabyte = 0x00; + blue = 0x00; // don't set the resulting pixel to blue + } else { + alphabyte = 0xff; + } - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; + *pixbuf++ = red; + *pixbuf++ = green; + *pixbuf++ = blue; - *pixbuf++ = alphabyte; - } - } + *pixbuf++ = alphabyte; + } + } - return image; + return image; } -Image* LoadHLW( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadHLWBuff( buffer.buffer ); +Image *LoadHLW(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadHLWBuff(buffer.buffer); } diff --git a/plugins/imagehl/hlw.h b/plugins/imagehl/hlw.h index 33138237..bfd0e764 100644 --- a/plugins/imagehl/hlw.h +++ b/plugins/imagehl/hlw.h @@ -23,8 +23,9 @@ #define INCLUDED_HLW_H class Image; + class ArchiveFile; -Image* LoadHLW( ArchiveFile& file ); +Image *LoadHLW(ArchiveFile &file); #endif diff --git a/plugins/imagehl/imagehl.cpp b/plugins/imagehl/imagehl.cpp index dfdf98b9..5d40d35e 100644 --- a/plugins/imagehl/imagehl.cpp +++ b/plugins/imagehl/imagehl.cpp @@ -30,23 +30,25 @@ #include "modulesystem/singletonmodule.h" -class ImageDependencies : public GlobalFileSystemModuleRef -{ +class ImageDependencies : public GlobalFileSystemModuleRef { }; -class ImageHLWAPI -{ -_QERPlugImageTable m_imagehlw; +class ImageHLWAPI { + _QERPlugImageTable m_imagehlw; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "hlw" ); + typedef _QERPlugImageTable Type; -ImageHLWAPI(){ - m_imagehlw.loadImage = LoadHLW; -} -_QERPlugImageTable* getTable(){ - return &m_imagehlw; -} + STRING_CONSTANT(Name, "hlw"); + + ImageHLWAPI() + { + m_imagehlw.loadImage = LoadHLW; + } + + _QERPlugImageTable *getTable() + { + return &m_imagehlw; + } }; typedef SingletonModule ImageHLWModule; @@ -54,19 +56,22 @@ typedef SingletonModule ImageHLWModule; ImageHLWModule g_ImageHLWModule; -class ImageMipAPI -{ -_QERPlugImageTable m_imagemip; +class ImageMipAPI { + _QERPlugImageTable m_imagemip; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "mip" ); + typedef _QERPlugImageTable Type; -ImageMipAPI(){ - m_imagemip.loadImage = LoadMIP; -} -_QERPlugImageTable* getTable(){ - return &m_imagemip; -} + STRING_CONSTANT(Name, "mip"); + + ImageMipAPI() + { + m_imagemip.loadImage = LoadMIP; + } + + _QERPlugImageTable *getTable() + { + return &m_imagemip; + } }; typedef SingletonModule ImageMipModule; @@ -74,19 +79,22 @@ typedef SingletonModule ImageMipModule; ImageMipModule g_ImageMipModule; -class ImageSpriteAPI -{ -_QERPlugImageTable m_imagesprite; +class ImageSpriteAPI { + _QERPlugImageTable m_imagesprite; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "spr" ); + typedef _QERPlugImageTable Type; -ImageSpriteAPI(){ - m_imagesprite.loadImage = LoadIDSP; -} -_QERPlugImageTable* getTable(){ - return &m_imagesprite; -} + STRING_CONSTANT(Name, "spr"); + + ImageSpriteAPI() + { + m_imagesprite.loadImage = LoadIDSP; + } + + _QERPlugImageTable *getTable() + { + return &m_imagesprite; + } }; typedef SingletonModule ImageSpriteModule; @@ -94,11 +102,11 @@ typedef SingletonModule ImageSpriteModule; ImageSpriteModule g_ImageSpriteModule; +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); - - g_ImageHLWModule.selfRegister(); - g_ImageMipModule.selfRegister(); - g_ImageSpriteModule.selfRegister(); + g_ImageHLWModule.selfRegister(); + g_ImageMipModule.selfRegister(); + g_ImageSpriteModule.selfRegister(); } diff --git a/plugins/imagehl/mip.cpp b/plugins/imagehl/mip.cpp index a9d5a71b..c46cd0a5 100644 --- a/plugins/imagehl/mip.cpp +++ b/plugins/imagehl/mip.cpp @@ -50,84 +50,83 @@ typedef unsigned char byte; ============================================================================ */ -#define GET_MIP_DATA_SIZE( WIDTH, HEIGHT ) ( sizeof( WAD3_MIP ) + ( WIDTH * HEIGHT ) + ( WIDTH * HEIGHT / 4 ) + ( WIDTH * HEIGHT / 16 ) + ( WIDTH * HEIGHT / 64 ) ) +#define GET_MIP_DATA_SIZE(WIDTH, HEIGHT) ( sizeof( WAD3_MIP ) + ( WIDTH * HEIGHT ) + ( WIDTH * HEIGHT / 4 ) + ( WIDTH * HEIGHT / 16 ) + ( WIDTH * HEIGHT / 64 ) ) const int MIP_NAME_LENGTH = 16; const int MIP_MIPMAP_COUNT = 4; -typedef struct -{ - char name[MIP_NAME_LENGTH]; - unsigned int width, height; - unsigned int offsets[MIP_MIPMAP_COUNT]; // four mip maps stored +typedef struct { + char name[MIP_NAME_LENGTH]; + unsigned int width, height; + unsigned int offsets[MIP_MIPMAP_COUNT]; // four mip maps stored } WAD3_MIP, *LPWAD3_MIP; static const byte quakepalette[768] = -{ - 0x00,0x00,0x00, 0x0f,0x0f,0x0f, 0x1f,0x1f,0x1f, 0x2f,0x2f,0x2f, - 0x3f,0x3f,0x3f, 0x4b,0x4b,0x4b, 0x5b,0x5b,0x5b, 0x6b,0x6b,0x6b, - 0x7b,0x7b,0x7b, 0x8b,0x8b,0x8b, 0x9b,0x9b,0x9b, 0xab,0xab,0xab, - 0xbb,0xbb,0xbb, 0xcb,0xcb,0xcb, 0xdb,0xdb,0xdb, 0xeb,0xeb,0xeb, - 0x0f,0x0b,0x07, 0x17,0x0f,0x0b, 0x1f,0x17,0x0b, 0x27,0x1b,0x0f, - 0x2f,0x23,0x13, 0x37,0x2b,0x17, 0x3f,0x2f,0x17, 0x4b,0x37,0x1b, - 0x53,0x3b,0x1b, 0x5b,0x43,0x1f, 0x63,0x4b,0x1f, 0x6b,0x53,0x1f, - 0x73,0x57,0x1f, 0x7b,0x5f,0x23, 0x83,0x67,0x23, 0x8f,0x6f,0x23, - 0x0b,0x0b,0x0f, 0x13,0x13,0x1b, 0x1b,0x1b,0x27, 0x27,0x27,0x33, - 0x2f,0x2f,0x3f, 0x37,0x37,0x4b, 0x3f,0x3f,0x57, 0x47,0x47,0x67, - 0x4f,0x4f,0x73, 0x5b,0x5b,0x7f, 0x63,0x63,0x8b, 0x6b,0x6b,0x97, - 0x73,0x73,0xa3, 0x7b,0x7b,0xaf, 0x83,0x83,0xbb, 0x8b,0x8b,0xcb, - 0x00,0x00,0x00, 0x07,0x07,0x00, 0x0b,0x0b,0x00, 0x13,0x13,0x00, - 0x1b,0x1b,0x00, 0x23,0x23,0x00, 0x2b,0x2b,0x07, 0x2f,0x2f,0x07, - 0x37,0x37,0x07, 0x3f,0x3f,0x07, 0x47,0x47,0x07, 0x4b,0x4b,0x0b, - 0x53,0x53,0x0b, 0x5b,0x5b,0x0b, 0x63,0x63,0x0b, 0x6b,0x6b,0x0f, - 0x07,0x00,0x00, 0x0f,0x00,0x00, 0x17,0x00,0x00, 0x1f,0x00,0x00, - 0x27,0x00,0x00, 0x2f,0x00,0x00, 0x37,0x00,0x00, 0x3f,0x00,0x00, - 0x47,0x00,0x00, 0x4f,0x00,0x00, 0x57,0x00,0x00, 0x5f,0x00,0x00, - 0x67,0x00,0x00, 0x6f,0x00,0x00, 0x77,0x00,0x00, 0x7f,0x00,0x00, - 0x13,0x13,0x00, 0x1b,0x1b,0x00, 0x23,0x23,0x00, 0x2f,0x2b,0x00, - 0x37,0x2f,0x00, 0x43,0x37,0x00, 0x4b,0x3b,0x07, 0x57,0x43,0x07, - 0x5f,0x47,0x07, 0x6b,0x4b,0x0b, 0x77,0x53,0x0f, 0x83,0x57,0x13, - 0x8b,0x5b,0x13, 0x97,0x5f,0x1b, 0xa3,0x63,0x1f, 0xaf,0x67,0x23, - 0x23,0x13,0x07, 0x2f,0x17,0x0b, 0x3b,0x1f,0x0f, 0x4b,0x23,0x13, - 0x57,0x2b,0x17, 0x63,0x2f,0x1f, 0x73,0x37,0x23, 0x7f,0x3b,0x2b, - 0x8f,0x43,0x33, 0x9f,0x4f,0x33, 0xaf,0x63,0x2f, 0xbf,0x77,0x2f, - 0xcf,0x8f,0x2b, 0xdf,0xab,0x27, 0xef,0xcb,0x1f, 0xff,0xf3,0x1b, - 0x0b,0x07,0x00, 0x1b,0x13,0x00, 0x2b,0x23,0x0f, 0x37,0x2b,0x13, - 0x47,0x33,0x1b, 0x53,0x37,0x23, 0x63,0x3f,0x2b, 0x6f,0x47,0x33, - 0x7f,0x53,0x3f, 0x8b,0x5f,0x47, 0x9b,0x6b,0x53, 0xa7,0x7b,0x5f, - 0xb7,0x87,0x6b, 0xc3,0x93,0x7b, 0xd3,0xa3,0x8b, 0xe3,0xb3,0x97, - 0xab,0x8b,0xa3, 0x9f,0x7f,0x97, 0x93,0x73,0x87, 0x8b,0x67,0x7b, - 0x7f,0x5b,0x6f, 0x77,0x53,0x63, 0x6b,0x4b,0x57, 0x5f,0x3f,0x4b, - 0x57,0x37,0x43, 0x4b,0x2f,0x37, 0x43,0x27,0x2f, 0x37,0x1f,0x23, - 0x2b,0x17,0x1b, 0x23,0x13,0x13, 0x17,0x0b,0x0b, 0x0f,0x07,0x07, - 0xbb,0x73,0x9f, 0xaf,0x6b,0x8f, 0xa3,0x5f,0x83, 0x97,0x57,0x77, - 0x8b,0x4f,0x6b, 0x7f,0x4b,0x5f, 0x73,0x43,0x53, 0x6b,0x3b,0x4b, - 0x5f,0x33,0x3f, 0x53,0x2b,0x37, 0x47,0x23,0x2b, 0x3b,0x1f,0x23, - 0x2f,0x17,0x1b, 0x23,0x13,0x13, 0x17,0x0b,0x0b, 0x0f,0x07,0x07, - 0xdb,0xc3,0xbb, 0xcb,0xb3,0xa7, 0xbf,0xa3,0x9b, 0xaf,0x97,0x8b, - 0xa3,0x87,0x7b, 0x97,0x7b,0x6f, 0x87,0x6f,0x5f, 0x7b,0x63,0x53, - 0x6b,0x57,0x47, 0x5f,0x4b,0x3b, 0x53,0x3f,0x33, 0x43,0x33,0x27, - 0x37,0x2b,0x1f, 0x27,0x1f,0x17, 0x1b,0x13,0x0f, 0x0f,0x0b,0x07, - 0x6f,0x83,0x7b, 0x67,0x7b,0x6f, 0x5f,0x73,0x67, 0x57,0x6b,0x5f, - 0x4f,0x63,0x57, 0x47,0x5b,0x4f, 0x3f,0x53,0x47, 0x37,0x4b,0x3f, - 0x2f,0x43,0x37, 0x2b,0x3b,0x2f, 0x23,0x33,0x27, 0x1f,0x2b,0x1f, - 0x17,0x23,0x17, 0x0f,0x1b,0x13, 0x0b,0x13,0x0b, 0x07,0x0b,0x07, - 0xff,0xf3,0x1b, 0xef,0xdf,0x17, 0xdb,0xcb,0x13, 0xcb,0xb7,0x0f, - 0xbb,0xa7,0x0f, 0xab,0x97,0x0b, 0x9b,0x83,0x07, 0x8b,0x73,0x07, - 0x7b,0x63,0x07, 0x6b,0x53,0x00, 0x5b,0x47,0x00, 0x4b,0x37,0x00, - 0x3b,0x2b,0x00, 0x2b,0x1f,0x00, 0x1b,0x0f,0x00, 0x0b,0x07,0x00, - 0x00,0x00,0xff, 0x0b,0x0b,0xef, 0x13,0x13,0xdf, 0x1b,0x1b,0xcf, - 0x23,0x23,0xbf, 0x2b,0x2b,0xaf, 0x2f,0x2f,0x9f, 0x2f,0x2f,0x8f, - 0x2f,0x2f,0x7f, 0x2f,0x2f,0x6f, 0x2f,0x2f,0x5f, 0x2b,0x2b,0x4f, - 0x23,0x23,0x3f, 0x1b,0x1b,0x2f, 0x13,0x13,0x1f, 0x0b,0x0b,0x0f, - 0x2b,0x00,0x00, 0x3b,0x00,0x00, 0x4b,0x07,0x00, 0x5f,0x07,0x00, - 0x6f,0x0f,0x00, 0x7f,0x17,0x07, 0x93,0x1f,0x07, 0xa3,0x27,0x0b, - 0xb7,0x33,0x0f, 0xc3,0x4b,0x1b, 0xcf,0x63,0x2b, 0xdb,0x7f,0x3b, - 0xe3,0x97,0x4f, 0xe7,0xab,0x5f, 0xef,0xbf,0x77, 0xf7,0xd3,0x8b, - 0xa7,0x7b,0x3b, 0xb7,0x9b,0x37, 0xc7,0xc3,0x37, 0xe7,0xe3,0x57, - 0x7f,0xbf,0xff, 0xab,0xe7,0xff, 0xd7,0xff,0xff, 0x67,0x00,0x00, - 0x8b,0x00,0x00, 0xb3,0x00,0x00, 0xd7,0x00,0x00, 0xff,0x00,0x00, - 0xff,0xf3,0x93, 0xff,0xf7,0xc7, 0xff,0xff,0xff, 0x9f,0x5b,0x53 -}; + { + 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x1f, 0x1f, 0x1f, 0x2f, 0x2f, 0x2f, + 0x3f, 0x3f, 0x3f, 0x4b, 0x4b, 0x4b, 0x5b, 0x5b, 0x5b, 0x6b, 0x6b, 0x6b, + 0x7b, 0x7b, 0x7b, 0x8b, 0x8b, 0x8b, 0x9b, 0x9b, 0x9b, 0xab, 0xab, 0xab, + 0xbb, 0xbb, 0xbb, 0xcb, 0xcb, 0xcb, 0xdb, 0xdb, 0xdb, 0xeb, 0xeb, 0xeb, + 0x0f, 0x0b, 0x07, 0x17, 0x0f, 0x0b, 0x1f, 0x17, 0x0b, 0x27, 0x1b, 0x0f, + 0x2f, 0x23, 0x13, 0x37, 0x2b, 0x17, 0x3f, 0x2f, 0x17, 0x4b, 0x37, 0x1b, + 0x53, 0x3b, 0x1b, 0x5b, 0x43, 0x1f, 0x63, 0x4b, 0x1f, 0x6b, 0x53, 0x1f, + 0x73, 0x57, 0x1f, 0x7b, 0x5f, 0x23, 0x83, 0x67, 0x23, 0x8f, 0x6f, 0x23, + 0x0b, 0x0b, 0x0f, 0x13, 0x13, 0x1b, 0x1b, 0x1b, 0x27, 0x27, 0x27, 0x33, + 0x2f, 0x2f, 0x3f, 0x37, 0x37, 0x4b, 0x3f, 0x3f, 0x57, 0x47, 0x47, 0x67, + 0x4f, 0x4f, 0x73, 0x5b, 0x5b, 0x7f, 0x63, 0x63, 0x8b, 0x6b, 0x6b, 0x97, + 0x73, 0x73, 0xa3, 0x7b, 0x7b, 0xaf, 0x83, 0x83, 0xbb, 0x8b, 0x8b, 0xcb, + 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x0b, 0x0b, 0x00, 0x13, 0x13, 0x00, + 0x1b, 0x1b, 0x00, 0x23, 0x23, 0x00, 0x2b, 0x2b, 0x07, 0x2f, 0x2f, 0x07, + 0x37, 0x37, 0x07, 0x3f, 0x3f, 0x07, 0x47, 0x47, 0x07, 0x4b, 0x4b, 0x0b, + 0x53, 0x53, 0x0b, 0x5b, 0x5b, 0x0b, 0x63, 0x63, 0x0b, 0x6b, 0x6b, 0x0f, + 0x07, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x17, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x37, 0x00, 0x00, 0x3f, 0x00, 0x00, + 0x47, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x57, 0x00, 0x00, 0x5f, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x77, 0x00, 0x00, 0x7f, 0x00, 0x00, + 0x13, 0x13, 0x00, 0x1b, 0x1b, 0x00, 0x23, 0x23, 0x00, 0x2f, 0x2b, 0x00, + 0x37, 0x2f, 0x00, 0x43, 0x37, 0x00, 0x4b, 0x3b, 0x07, 0x57, 0x43, 0x07, + 0x5f, 0x47, 0x07, 0x6b, 0x4b, 0x0b, 0x77, 0x53, 0x0f, 0x83, 0x57, 0x13, + 0x8b, 0x5b, 0x13, 0x97, 0x5f, 0x1b, 0xa3, 0x63, 0x1f, 0xaf, 0x67, 0x23, + 0x23, 0x13, 0x07, 0x2f, 0x17, 0x0b, 0x3b, 0x1f, 0x0f, 0x4b, 0x23, 0x13, + 0x57, 0x2b, 0x17, 0x63, 0x2f, 0x1f, 0x73, 0x37, 0x23, 0x7f, 0x3b, 0x2b, + 0x8f, 0x43, 0x33, 0x9f, 0x4f, 0x33, 0xaf, 0x63, 0x2f, 0xbf, 0x77, 0x2f, + 0xcf, 0x8f, 0x2b, 0xdf, 0xab, 0x27, 0xef, 0xcb, 0x1f, 0xff, 0xf3, 0x1b, + 0x0b, 0x07, 0x00, 0x1b, 0x13, 0x00, 0x2b, 0x23, 0x0f, 0x37, 0x2b, 0x13, + 0x47, 0x33, 0x1b, 0x53, 0x37, 0x23, 0x63, 0x3f, 0x2b, 0x6f, 0x47, 0x33, + 0x7f, 0x53, 0x3f, 0x8b, 0x5f, 0x47, 0x9b, 0x6b, 0x53, 0xa7, 0x7b, 0x5f, + 0xb7, 0x87, 0x6b, 0xc3, 0x93, 0x7b, 0xd3, 0xa3, 0x8b, 0xe3, 0xb3, 0x97, + 0xab, 0x8b, 0xa3, 0x9f, 0x7f, 0x97, 0x93, 0x73, 0x87, 0x8b, 0x67, 0x7b, + 0x7f, 0x5b, 0x6f, 0x77, 0x53, 0x63, 0x6b, 0x4b, 0x57, 0x5f, 0x3f, 0x4b, + 0x57, 0x37, 0x43, 0x4b, 0x2f, 0x37, 0x43, 0x27, 0x2f, 0x37, 0x1f, 0x23, + 0x2b, 0x17, 0x1b, 0x23, 0x13, 0x13, 0x17, 0x0b, 0x0b, 0x0f, 0x07, 0x07, + 0xbb, 0x73, 0x9f, 0xaf, 0x6b, 0x8f, 0xa3, 0x5f, 0x83, 0x97, 0x57, 0x77, + 0x8b, 0x4f, 0x6b, 0x7f, 0x4b, 0x5f, 0x73, 0x43, 0x53, 0x6b, 0x3b, 0x4b, + 0x5f, 0x33, 0x3f, 0x53, 0x2b, 0x37, 0x47, 0x23, 0x2b, 0x3b, 0x1f, 0x23, + 0x2f, 0x17, 0x1b, 0x23, 0x13, 0x13, 0x17, 0x0b, 0x0b, 0x0f, 0x07, 0x07, + 0xdb, 0xc3, 0xbb, 0xcb, 0xb3, 0xa7, 0xbf, 0xa3, 0x9b, 0xaf, 0x97, 0x8b, + 0xa3, 0x87, 0x7b, 0x97, 0x7b, 0x6f, 0x87, 0x6f, 0x5f, 0x7b, 0x63, 0x53, + 0x6b, 0x57, 0x47, 0x5f, 0x4b, 0x3b, 0x53, 0x3f, 0x33, 0x43, 0x33, 0x27, + 0x37, 0x2b, 0x1f, 0x27, 0x1f, 0x17, 0x1b, 0x13, 0x0f, 0x0f, 0x0b, 0x07, + 0x6f, 0x83, 0x7b, 0x67, 0x7b, 0x6f, 0x5f, 0x73, 0x67, 0x57, 0x6b, 0x5f, + 0x4f, 0x63, 0x57, 0x47, 0x5b, 0x4f, 0x3f, 0x53, 0x47, 0x37, 0x4b, 0x3f, + 0x2f, 0x43, 0x37, 0x2b, 0x3b, 0x2f, 0x23, 0x33, 0x27, 0x1f, 0x2b, 0x1f, + 0x17, 0x23, 0x17, 0x0f, 0x1b, 0x13, 0x0b, 0x13, 0x0b, 0x07, 0x0b, 0x07, + 0xff, 0xf3, 0x1b, 0xef, 0xdf, 0x17, 0xdb, 0xcb, 0x13, 0xcb, 0xb7, 0x0f, + 0xbb, 0xa7, 0x0f, 0xab, 0x97, 0x0b, 0x9b, 0x83, 0x07, 0x8b, 0x73, 0x07, + 0x7b, 0x63, 0x07, 0x6b, 0x53, 0x00, 0x5b, 0x47, 0x00, 0x4b, 0x37, 0x00, + 0x3b, 0x2b, 0x00, 0x2b, 0x1f, 0x00, 0x1b, 0x0f, 0x00, 0x0b, 0x07, 0x00, + 0x00, 0x00, 0xff, 0x0b, 0x0b, 0xef, 0x13, 0x13, 0xdf, 0x1b, 0x1b, 0xcf, + 0x23, 0x23, 0xbf, 0x2b, 0x2b, 0xaf, 0x2f, 0x2f, 0x9f, 0x2f, 0x2f, 0x8f, + 0x2f, 0x2f, 0x7f, 0x2f, 0x2f, 0x6f, 0x2f, 0x2f, 0x5f, 0x2b, 0x2b, 0x4f, + 0x23, 0x23, 0x3f, 0x1b, 0x1b, 0x2f, 0x13, 0x13, 0x1f, 0x0b, 0x0b, 0x0f, + 0x2b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x4b, 0x07, 0x00, 0x5f, 0x07, 0x00, + 0x6f, 0x0f, 0x00, 0x7f, 0x17, 0x07, 0x93, 0x1f, 0x07, 0xa3, 0x27, 0x0b, + 0xb7, 0x33, 0x0f, 0xc3, 0x4b, 0x1b, 0xcf, 0x63, 0x2b, 0xdb, 0x7f, 0x3b, + 0xe3, 0x97, 0x4f, 0xe7, 0xab, 0x5f, 0xef, 0xbf, 0x77, 0xf7, 0xd3, 0x8b, + 0xa7, 0x7b, 0x3b, 0xb7, 0x9b, 0x37, 0xc7, 0xc3, 0x37, 0xe7, 0xe3, 0x57, + 0x7f, 0xbf, 0xff, 0xab, 0xe7, 0xff, 0xd7, 0xff, 0xff, 0x67, 0x00, 0x00, + 0x8b, 0x00, 0x00, 0xb3, 0x00, 0x00, 0xd7, 0x00, 0x00, 0xff, 0x00, 0x00, + 0xff, 0xf3, 0x93, 0xff, 0xf7, 0xc7, 0xff, 0xff, 0xff, 0x9f, 0x5b, 0x53 + }; /* ============= @@ -135,69 +134,68 @@ static const byte quakepalette[768] = ============= */ -Image* LoadMIPBuff( byte* buffer ){ - byte *buf_p; - int palettelength; - int columns, rows, numPixels; - byte *pixbuf; - int i; - byte *loadedpalette; - const byte *palette; +Image *LoadMIPBuff(byte *buffer) +{ + byte *buf_p; + int palettelength; + int columns, rows, numPixels; + byte *pixbuf; + int i; + byte *loadedpalette; + const byte *palette; - loadedpalette = 0; + loadedpalette = 0; - PointerInputStream inputStream( buffer ); + PointerInputStream inputStream(buffer); - inputStream.seek( MIP_NAME_LENGTH ); - columns = istream_read_int32_le( inputStream ); - rows = istream_read_int32_le( inputStream ); - int offset = istream_read_int32_le( inputStream ); + inputStream.seek(MIP_NAME_LENGTH); + columns = istream_read_int32_le(inputStream); + rows = istream_read_int32_le(inputStream); + int offset = istream_read_int32_le(inputStream); - if ( std::size_t( columns ) > 65536 && std::size_t( rows ) > 65536 ) { - return 0; - } + if (std::size_t(columns) > 65536 && std::size_t(rows) > 65536) { + return 0; + } // unsigned long mipdatasize = GET_MIP_DATA_SIZE( columns, rows ); - palettelength = vfsLoadFile( "gfx/palette.lmp", (void **) &loadedpalette ); - if ( palettelength == 768 ) { - palette = loadedpalette; - } - else - { - loadedpalette = 0; - palette = quakepalette; - } + palettelength = vfsLoadFile("gfx/palette.lmp", (void **) &loadedpalette); + if (palettelength == 768) { + palette = loadedpalette; + } else { + loadedpalette = 0; + palette = quakepalette; + } - buf_p = buffer + offset; + buf_p = buffer + offset; - numPixels = columns * rows; + numPixels = columns * rows; - RGBAImage* image = new RGBAImage( columns, rows ); + RGBAImage *image = new RGBAImage(columns, rows); - //Sys_Printf("lpMip->width = %i, lpMip->height = %i, lpMip->offsets[0] = %i, lpMip->offsets[1] = %i, lpMip->offsets[2] = %i, lpMip->offsets[3] = %i, numPixels = %i\n", lpMip->width, lpMip->height, lpMip->offsets[0], lpMip->offsets[1], lpMip->offsets[2], lpMip->offsets[3], numPixels); - //for (i = 0; i < sizeof(*lpMip); i++) - // Sys_Printf("%02x", (int) ((unsigned char *)lpMip)[i]); + //Sys_Printf("lpMip->width = %i, lpMip->height = %i, lpMip->offsets[0] = %i, lpMip->offsets[1] = %i, lpMip->offsets[2] = %i, lpMip->offsets[3] = %i, numPixels = %i\n", lpMip->width, lpMip->height, lpMip->offsets[0], lpMip->offsets[1], lpMip->offsets[2], lpMip->offsets[3], numPixels); + //for (i = 0; i < sizeof(*lpMip); i++) + // Sys_Printf("%02x", (int) ((unsigned char *)lpMip)[i]); - pixbuf = image->getRGBAPixels(); + pixbuf = image->getRGBAPixels(); - for ( i = 0; i < numPixels; i++ ) - { - int palIndex = *buf_p++; - *pixbuf++ = palette[palIndex * 3]; - *pixbuf++ = palette[palIndex * 3 + 1]; - *pixbuf++ = palette[palIndex * 3 + 2]; - *pixbuf++ = 0xff; - } + for (i = 0; i < numPixels; i++) { + int palIndex = *buf_p++; + *pixbuf++ = palette[palIndex * 3]; + *pixbuf++ = palette[palIndex * 3 + 1]; + *pixbuf++ = palette[palIndex * 3 + 2]; + *pixbuf++ = 0xff; + } - if ( loadedpalette != 0 ) { - vfsFreeFile( loadedpalette ); - } + if (loadedpalette != 0) { + vfsFreeFile(loadedpalette); + } - return image; + return image; } -Image* LoadMIP( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadMIPBuff( buffer.buffer ); +Image *LoadMIP(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadMIPBuff(buffer.buffer); } diff --git a/plugins/imagehl/mip.h b/plugins/imagehl/mip.h index ea11d8ff..9b134ec9 100644 --- a/plugins/imagehl/mip.h +++ b/plugins/imagehl/mip.h @@ -23,8 +23,9 @@ #define INCLUDED_MIP_H class Image; + class ArchiveFile; -Image* LoadMIP( ArchiveFile& file ); +Image *LoadMIP(ArchiveFile &file); #endif diff --git a/plugins/imagehl/sprite.cpp b/plugins/imagehl/sprite.cpp index 195d9528..613b90a5 100644 --- a/plugins/imagehl/sprite.cpp +++ b/plugins/imagehl/sprite.cpp @@ -44,45 +44,45 @@ typedef unsigned char byte; ============================================================================ */ -typedef enum {ST_SYNC = 0, ST_RAND } synctype_t; +typedef enum { ST_SYNC = 0, ST_RAND } synctype_t; typedef enum { SPR_SINGLE = 0, SPR_GROUP } spriteframetype_t; typedef struct dspriteheader_s { - int ident; - int version; + int ident; + int version; } dspriteheader_t; // Quake1 typedef struct { - int type; - float boundingradius; - int width; - int height; - int numframes; - float beamlength; - synctype_t synctype; + int type; + float boundingradius; + int width; + int height; + int numframes; + float beamlength; + synctype_t synctype; } dspritev1_t; // Halflife typedef struct { - int type; - int texFormat; - float boundingradius; - int width; - int height; - int numframes; - float beamlength; - synctype_t synctype; + int type; + int texFormat; + float boundingradius; + int width; + int height; + int numframes; + float beamlength; + synctype_t synctype; } dspritev2_t; typedef struct { - int origin[2]; - int width; - int height; + int origin[2]; + int width; + int height; } dspriteframe_t; typedef struct { - short type; + short type; } dspriteframetype_t; /* @@ -91,7 +91,7 @@ typedef struct { } dpalette_t; */ -const int IDSPRITEHEADER = ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'D' << 8 ) + 'I' ); +const int IDSPRITEHEADER = (('P' << 24) + ('S' << 16) + ('D' << 8) + 'I'); // little-endian "IDSP" /* @@ -100,122 +100,119 @@ const int IDSPRITEHEADER = ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'D' << 8 ) + 'I' ============= */ -Image* LoadIDSPBuff( byte *buffer ){ - byte *buf_p; - int columns, rows; - byte *pixbuf; - - int row, column; - byte *palette; - unsigned char red, green, blue, alphabyte; - - dspriteheader_t *header; - dspritev1_t *pinv1; - dspritev2_t *pinv2; - dspriteframetype_t *pframetype; - int version; - int numframes; - dspriteframe_t *spriteframe; - - header = (dspriteheader_t *)buffer; - - if ( header->ident != IDSPRITEHEADER ) { - globalErrorStream() << "WARNING: IDSP file has wrong header\n"; - return 0; - } - - version = header->version; - if ( version != 1 && version != 2 ) { - globalErrorStream() << "WARNING: IDSP file has wrong version number " - "(" << version << " should be 1 or 2)\n"; - return 0; - } - - // initialise variables depending on the sprite version. - switch ( version ) - { - case 1: - pinv1 = (dspritev1_t *)( header + 1 ); - numframes = pinv1->numframes; - columns = pinv1->width; - rows = pinv1->height; - pframetype = (dspriteframetype_t *)( pinv1 + 1 ); - break; - case 2: - pinv2 = (dspritev2_t *)( header + 1 ); - numframes = pinv2->numframes; - columns = pinv2->width; - rows = pinv2->height; - pframetype = (dspriteframetype_t *)( pinv2 + 1 ); - break; - default: - globalErrorStream() << "WARNING: IDSP file has unsupported version\n"; - return 0; - } - if ( numframes > 1 ) { - globalErrorStream() << "WARNING: IDSP file has multiple frames, only the first frame will be used.\n"; - } - - // palette = buffer+mipdatasize+2; - // buf_p = buffer+lpMip->offsets[0]; - - RGBAImage* image = new RGBAImage( columns, rows ); +Image *LoadIDSPBuff(byte *buffer) +{ + byte *buf_p; + int columns, rows; + byte *pixbuf; + + int row, column; + byte *palette; + unsigned char red, green, blue, alphabyte; + + dspriteheader_t *header; + dspritev1_t *pinv1; + dspritev2_t *pinv2; + dspriteframetype_t *pframetype; + int version; + int numframes; + dspriteframe_t *spriteframe; + + header = (dspriteheader_t *) buffer; + + if (header->ident != IDSPRITEHEADER) { + globalErrorStream() << "WARNING: IDSP file has wrong header\n"; + return 0; + } + + version = header->version; + if (version != 1 && version != 2) { + globalErrorStream() << "WARNING: IDSP file has wrong version number " + "(" << version << " should be 1 or 2)\n"; + return 0; + } + + // initialise variables depending on the sprite version. + switch (version) { + case 1: + pinv1 = (dspritev1_t *) (header + 1); + numframes = pinv1->numframes; + columns = pinv1->width; + rows = pinv1->height; + pframetype = (dspriteframetype_t *) (pinv1 + 1); + break; + case 2: + pinv2 = (dspritev2_t *) (header + 1); + numframes = pinv2->numframes; + columns = pinv2->width; + rows = pinv2->height; + pframetype = (dspriteframetype_t *) (pinv2 + 1); + break; + default: + globalErrorStream() << "WARNING: IDSP file has unsupported version\n"; + return 0; + } + if (numframes > 1) { + globalErrorStream() << "WARNING: IDSP file has multiple frames, only the first frame will be used.\n"; + } + + // palette = buffer+mipdatasize+2; + // buf_p = buffer+lpMip->offsets[0]; + + RGBAImage *image = new RGBAImage(columns, rows); #ifdef DEBUG - frametype = spriteframetype_t( pframetype->type ); - if ( frametype == SPR_SINGLE ) { - globalOutputStream() << "Single Frame\n"; - } - else if ( frametype == SPR_GROUP ) { - globalOutputStream() << "Group of Frames\n"; - } - else - { - globalOutputStream() << "Bleh!\n"; // <-- we always get this, wtf! - } + frametype = spriteframetype_t( pframetype->type ); + if ( frametype == SPR_SINGLE ) { + globalOutputStream() << "Single Frame\n"; + } + else if ( frametype == SPR_GROUP ) { + globalOutputStream() << "Group of Frames\n"; + } + else + { + globalOutputStream() << "Bleh!\n"; // <-- we always get this, wtf! + } #endif - palette = (byte *)( pframetype + 1 ); - spriteframe = (dspriteframe_t *)( palette + ( 256 * 3 ) + 4 ); // what are those 4 extra bytes ? what's missing ? - buf_p = (byte *)( spriteframe + 1 ); + palette = (byte *) (pframetype + 1); + spriteframe = (dspriteframe_t *) (palette + (256 * 3) + 4); // what are those 4 extra bytes ? what's missing ? + buf_p = (byte *) (spriteframe + 1); - for ( row = 0; row < rows; row++ ) - { - pixbuf = image->getRGBAPixels() + row * columns * 4; + for (row = 0; row < rows; row++) { + pixbuf = image->getRGBAPixels() + row * columns * 4; - for ( column = 0; column < columns; column++ ) - { - int palIndex; + for (column = 0; column < columns; column++) { + int palIndex; - palIndex = *buf_p++; + palIndex = *buf_p++; - red = *( palette + ( palIndex * 3 ) ); - green = *( palette + ( palIndex * 3 ) + 1 ); - blue = *( palette + ( palIndex * 3 ) + 2 ); + red = *(palette + (palIndex * 3)); + green = *(palette + (palIndex * 3) + 1); + blue = *(palette + (palIndex * 3) + 2); - // HalfLife engine makes pixels that are BLUE transparent. (RGB = 0x0000FF) - // So show them that way in the editor. - if ( blue == 0xff && red == 0x00 && green == 0x00 ) { - alphabyte = 0xff; //FIXME: backwards? (so sprite models to render correctly) - blue = 0x00; // don't set the resulting pixel to blue - } - else - { - alphabyte = 0x00; //FIXME: backwards? (so sprite models to render correctly) - } + // HalfLife engine makes pixels that are BLUE transparent. (RGB = 0x0000FF) + // So show them that way in the editor. + if (blue == 0xff && red == 0x00 && green == 0x00) { + alphabyte = 0xff; //FIXME: backwards? (so sprite models to render correctly) + blue = 0x00; // don't set the resulting pixel to blue + } else { + alphabyte = 0x00; //FIXME: backwards? (so sprite models to render correctly) + } - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; + *pixbuf++ = red; + *pixbuf++ = green; + *pixbuf++ = blue; - *pixbuf++ = alphabyte; - } - } + *pixbuf++ = alphabyte; + } + } - return image; + return image; } -Image* LoadIDSP( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadIDSPBuff( buffer.buffer ); +Image *LoadIDSP(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadIDSPBuff(buffer.buffer); } diff --git a/plugins/imagehl/sprite.h b/plugins/imagehl/sprite.h index d6635d94..a8936855 100644 --- a/plugins/imagehl/sprite.h +++ b/plugins/imagehl/sprite.h @@ -23,8 +23,9 @@ #define INCLUDED_SPRITE_H class Image; + class ArchiveFile; -Image* LoadIDSP( ArchiveFile& file ); +Image *LoadIDSP(ArchiveFile &file); #endif diff --git a/plugins/imagepng/plugin.cpp b/plugins/imagepng/plugin.cpp index 36a4fd05..8a9f582d 100644 --- a/plugins/imagepng/plugin.cpp +++ b/plugins/imagepng/plugin.cpp @@ -31,163 +31,169 @@ #include "png.h" #include -void user_warning_fn( png_structp png_ptr, png_const_charp warning_msg ){ - globalErrorStream() << "libpng warning: " << warning_msg << "\n"; +void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) +{ + globalErrorStream() << "libpng warning: " << warning_msg << "\n"; } -void user_error_fn( png_structp png_ptr, png_const_charp error_msg ){ - globalErrorStream() << "libpng error: " << error_msg << "\n"; - longjmp( png_jmpbuf(png_ptr), 0 ); +void user_error_fn(png_structp png_ptr, png_const_charp error_msg) +{ + globalErrorStream() << "libpng error: " << error_msg << "\n"; + longjmp(png_jmpbuf(png_ptr), 0); } -void user_read_data( png_structp png_ptr, png_bytep data, png_uint_32 length ){ - png_bytep *p_p_fbuffer = (png_bytep*)png_get_io_ptr( png_ptr ); - memcpy( data, *p_p_fbuffer, length ); - *p_p_fbuffer += length; +void user_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length) +{ + png_bytep *p_p_fbuffer = (png_bytep *) png_get_io_ptr(png_ptr); + memcpy(data, *p_p_fbuffer, length); + *p_p_fbuffer += length; } -Image* LoadPNGBuff( unsigned char* fbuffer ){ - png_byte** row_pointers; - png_bytep p_fbuffer; - - p_fbuffer = fbuffer; - - // the reading glue - // http://www.libpng.org/pub/png/libpng-manual.html - - png_structp png_ptr = png_create_read_struct - ( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, - user_error_fn, user_warning_fn ); - if ( !png_ptr ) { - globalErrorStream() << "libpng error: png_create_read_struct\n"; - return 0; - } - - png_infop info_ptr = png_create_info_struct( png_ptr ); - if ( !info_ptr ) { - png_destroy_read_struct( &png_ptr, - (png_infopp)NULL, (png_infopp)NULL ); - globalErrorStream() << "libpng error: png_create_info_struct (info_ptr)\n"; - return 0; - } - - png_infop end_info = png_create_info_struct( png_ptr ); - if ( !end_info ) { - png_destroy_read_struct( &png_ptr, &info_ptr, - (png_infopp)NULL ); - globalErrorStream() << "libpng error: png_create_info_struct (end_info)\n"; - return 0; - } - - // configure the read function - png_set_read_fn( png_ptr, ( png_voidp ) & p_fbuffer, ( png_rw_ptr ) & user_read_data ); - - if ( setjmp( png_jmpbuf(png_ptr) ) ) { - png_destroy_read_struct( &png_ptr, &info_ptr, - &end_info ); - return 0; - } - - png_read_info( png_ptr, info_ptr ); - - int bit_depth = png_get_bit_depth( png_ptr, info_ptr ); - int color_type = png_get_color_type( png_ptr, info_ptr ); - - // we want to treat all images the same way - // The following code transforms grayscale images of less than 8 to 8 bits, - // changes paletted images to RGB, and adds a full alpha channel if there is - // transparency information in a tRNS chunk. - - if ( color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) { - png_set_gray_to_rgb( png_ptr ); - } - else if ( color_type == PNG_COLOR_TYPE_PALETTE ) { - png_set_palette_to_rgb( png_ptr ); - } - - if ( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 ) { - png_set_expand_gray_1_2_4_to_8( png_ptr ); - } - - if ( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) { - png_set_tRNS_to_alpha( png_ptr ); - } - - if ( !( color_type & PNG_COLOR_MASK_ALPHA ) ) { - // Set the background color to draw transparent and alpha images over. - png_color_16 my_background, *image_background; - - if ( png_get_bKGD( png_ptr, info_ptr, &image_background ) ) { - png_set_background( png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0 ); - } - else{ - png_set_background( png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0 ); - } - - // Add alpha byte after each RGB triplet - png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER ); - } - - // read the sucker in one chunk - png_read_update_info( png_ptr, info_ptr ); - - color_type = png_get_color_type( png_ptr, info_ptr ); - bit_depth = png_get_bit_depth( png_ptr, info_ptr ); - - int width = png_get_image_width( png_ptr, info_ptr ); - int height = png_get_image_height( png_ptr, info_ptr ); - - // allocate the pixel buffer, and the row pointers - RGBAImage* image = new RGBAImage( width, height ); - - row_pointers = (png_byte**) malloc( ( height ) * sizeof( png_byte* ) ); +Image *LoadPNGBuff(unsigned char *fbuffer) +{ + png_byte **row_pointers; + png_bytep p_fbuffer; + + p_fbuffer = fbuffer; + + // the reading glue + // http://www.libpng.org/pub/png/libpng-manual.html + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, + user_error_fn, user_warning_fn); + if (!png_ptr) { + globalErrorStream() << "libpng error: png_create_read_struct\n"; + return 0; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, + (png_infopp) NULL, (png_infopp) NULL); + globalErrorStream() << "libpng error: png_create_info_struct (info_ptr)\n"; + return 0; + } + + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp) NULL); + globalErrorStream() << "libpng error: png_create_info_struct (end_info)\n"; + return 0; + } + + // configure the read function + png_set_read_fn(png_ptr, (png_voidp) &p_fbuffer, (png_rw_ptr) &user_read_data); + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + return 0; + } + + png_read_info(png_ptr, info_ptr); + + int bit_depth = png_get_bit_depth(png_ptr, info_ptr); + int color_type = png_get_color_type(png_ptr, info_ptr); + + // we want to treat all images the same way + // The following code transforms grayscale images of less than 8 to 8 bits, + // changes paletted images to RGB, and adds a full alpha channel if there is + // transparency information in a tRNS chunk. + + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + } else if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + } + + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { + png_set_expand_gray_1_2_4_to_8(png_ptr); + } + + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png_ptr); + } + + if (!(color_type & PNG_COLOR_MASK_ALPHA)) { + // Set the background color to draw transparent and alpha images over. + png_color_16 my_background, *image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) { + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + } else { + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + } + + // Add alpha byte after each RGB triplet + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + } + + // read the sucker in one chunk + png_read_update_info(png_ptr, info_ptr); + + color_type = png_get_color_type(png_ptr, info_ptr); + bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + int width = png_get_image_width(png_ptr, info_ptr); + int height = png_get_image_height(png_ptr, info_ptr); + + // allocate the pixel buffer, and the row pointers + RGBAImage *image = new RGBAImage(width, height); + + row_pointers = (png_byte **) malloc((height) * sizeof(png_byte *)); + + int i; + for (i = 0; i < (height); i++) { + row_pointers[i] = (png_byte *) (image->getRGBAPixels()) + i * 4 * (width); + } + + // actual read + png_read_image(png_ptr, row_pointers); - int i; - for ( i = 0; i < ( height ); i++ ) - row_pointers[i] = (png_byte*)( image->getRGBAPixels() ) + i * 4 * ( width ); - - // actual read - png_read_image( png_ptr, row_pointers ); - - /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ - png_read_end( png_ptr, info_ptr ); - - /* free up the memory structure */ - png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); - - free( row_pointers ); - - return image; + /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + /* free up the memory structure */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + free(row_pointers); + + return image; } -Image* LoadPNG( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadPNGBuff( buffer.buffer ); +Image *LoadPNG(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadPNGBuff(buffer.buffer); } #include "modulesystem/singletonmodule.h" -class ImageDependencies : public GlobalFileSystemModuleRef -{ +class ImageDependencies : public GlobalFileSystemModuleRef { }; -class ImagePNGAPI -{ -_QERPlugImageTable m_imagepng; +class ImagePNGAPI { + _QERPlugImageTable m_imagepng; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "png" ); + typedef _QERPlugImageTable Type; -ImagePNGAPI(){ - m_imagepng.loadImage = LoadPNG; -} -_QERPlugImageTable* getTable(){ - return &m_imagepng; -} + STRING_CONSTANT(Name, "png"); + + ImagePNGAPI() + { + m_imagepng.loadImage = LoadPNG; + } + + _QERPlugImageTable *getTable() + { + return &m_imagepng; + } }; typedef SingletonModule ImagePNGModule; @@ -195,8 +201,9 @@ typedef SingletonModule ImagePNGModule; ImagePNGModule g_ImagePNGModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_ImagePNGModule.selfRegister(); + g_ImagePNGModule.selfRegister(); } diff --git a/plugins/imageq2/imageq2.cpp b/plugins/imageq2/imageq2.cpp index 9ea5c635..28258932 100644 --- a/plugins/imageq2/imageq2.cpp +++ b/plugins/imageq2/imageq2.cpp @@ -29,23 +29,25 @@ #include "modulesystem/singletonmodule.h" -class ImageDependencies : public GlobalFileSystemModuleRef -{ +class ImageDependencies : public GlobalFileSystemModuleRef { }; -class ImageWalAPI -{ -_QERPlugImageTable m_imagewal; +class ImageWalAPI { + _QERPlugImageTable m_imagewal; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "wal" ); + typedef _QERPlugImageTable Type; -ImageWalAPI(){ - m_imagewal.loadImage = LoadWal; -} -_QERPlugImageTable* getTable(){ - return &m_imagewal; -} + STRING_CONSTANT(Name, "wal"); + + ImageWalAPI() + { + m_imagewal.loadImage = LoadWal; + } + + _QERPlugImageTable *getTable() + { + return &m_imagewal; + } }; typedef SingletonModule ImageWalModule; @@ -54,19 +56,22 @@ ImageWalModule g_ImageWalModule; //////////////////////////////////////////////////// -class ImageM8API -{ -_QERPlugImageTable m_imagem8; +class ImageM8API { + _QERPlugImageTable m_imagem8; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "m8" ); + typedef _QERPlugImageTable Type; -ImageM8API(){ - m_imagem8.loadImage = LoadM8; -} -_QERPlugImageTable* getTable(){ - return &m_imagem8; -} + STRING_CONSTANT(Name, "m8"); + + ImageM8API() + { + m_imagem8.loadImage = LoadM8; + } + + _QERPlugImageTable *getTable() + { + return &m_imagem8; + } }; typedef SingletonModule ImageM8Module; @@ -75,19 +80,22 @@ ImageM8Module g_ImageM8Module; //////////////////////////////////////////////////////// -class ImageM32API -{ -_QERPlugImageTable m_imagem32; +class ImageM32API { + _QERPlugImageTable m_imagem32; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "m32" ); + typedef _QERPlugImageTable Type; -ImageM32API(){ - m_imagem32.loadImage = LoadM32; -} -_QERPlugImageTable* getTable(){ - return &m_imagem32; -} + STRING_CONSTANT(Name, "m32"); + + ImageM32API() + { + m_imagem32.loadImage = LoadM32; + } + + _QERPlugImageTable *getTable() + { + return &m_imagem32; + } }; typedef SingletonModule ImageM32Module; @@ -96,10 +104,11 @@ ImageM32Module g_ImageM32Module; //////////////////////////////////////////////////////// -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); - g_ImageWalModule.selfRegister(); - g_ImageM8Module.selfRegister(); - g_ImageM32Module.selfRegister(); + g_ImageWalModule.selfRegister(); + g_ImageM8Module.selfRegister(); + g_ImageM32Module.selfRegister(); } diff --git a/plugins/imageq2/wal.cpp b/plugins/imageq2/wal.cpp index 5994e508..162a0667 100644 --- a/plugins/imageq2/wal.cpp +++ b/plugins/imageq2/wal.cpp @@ -28,127 +28,125 @@ #include "bytestreamutils.h" #include "imagelib.h" -const int QUAKE2_WAL = 0; -const int HERETIC2_M8 = 1; +const int QUAKE2_WAL = 0; +const int HERETIC2_M8 = 1; typedef unsigned char byte; -struct pcx_header_t -{ - char manufacturer; - char version; - char encoding; - char bits_per_pixel; +struct pcx_header_t { + char manufacturer; + char version; + char encoding; + char bits_per_pixel; }; -void LoadPCXPalette( const char *filename, byte palette[768] ){ - byte* buffer; - int length = vfsLoadFile( filename, (void **)&buffer ); - if ( buffer == 0 ) { - return; - } +void LoadPCXPalette(const char *filename, byte palette[768]) +{ + byte *buffer; + int length = vfsLoadFile(filename, (void **) &buffer); + if (buffer == 0) { + return; + } - const pcx_header_t* pcx = reinterpret_cast( buffer ); + const pcx_header_t *pcx = reinterpret_cast( buffer ); - if ( pcx->manufacturer != 0x0a - || pcx->version != 5 - || pcx->encoding != 1 - || pcx->bits_per_pixel != 8 ) { - return; - } + if (pcx->manufacturer != 0x0a + || pcx->version != 5 + || pcx->encoding != 1 + || pcx->bits_per_pixel != 8) { + return; + } - memcpy( palette, buffer + length - 768, 768 ); + memcpy(palette, buffer + length - 768, 768); - vfsFreeFile( buffer ); + vfsFreeFile(buffer); } const int WAL_NAME_LENGTH = 32; const int WAL_MIPMAP_COUNT = 4; -struct wal_header_t -{ - char name[WAL_NAME_LENGTH]; - unsigned width, height; - unsigned offsets[WAL_MIPMAP_COUNT]; // four mip maps stored - char animname[WAL_NAME_LENGTH]; // next frame in animation chain - int flags; - int contents; - int value; +struct wal_header_t { + char name[WAL_NAME_LENGTH]; + unsigned width, height; + unsigned offsets[WAL_MIPMAP_COUNT]; // four mip maps stored + char animname[WAL_NAME_LENGTH]; // next frame in animation chain + int flags; + int contents; + int value; }; const int M8_NAME_LENGTH = 32; const int M8_MIPMAP_COUNT = 16; -struct m8_header_t -{ - int version; - char name[M8_NAME_LENGTH]; - unsigned width[M8_MIPMAP_COUNT], height[M8_MIPMAP_COUNT]; // width and height of each mipmap - unsigned offsets[M8_MIPMAP_COUNT]; // 16 mip maps stored - char animname[M8_NAME_LENGTH]; // next frame in animation chain - byte palette[768]; // palette stored in m8 - int flags; - int contents; - int value; +struct m8_header_t { + int version; + char name[M8_NAME_LENGTH]; + unsigned width[M8_MIPMAP_COUNT], height[M8_MIPMAP_COUNT]; // width and height of each mipmap + unsigned offsets[M8_MIPMAP_COUNT]; // 16 mip maps stored + char animname[M8_NAME_LENGTH]; // next frame in animation chain + byte palette[768]; // palette stored in m8 + int flags; + int contents; + int value; }; -Image* LoadMipTex( byte* buffer, byte TypeofTex ){ - int w, h, offset, flags, contents, value; - byte palette[768]; - byte* source; - - PointerInputStream inputStream( buffer ); - - if ( TypeofTex == HERETIC2_M8 ) { - inputStream.seek( 4 + M8_NAME_LENGTH ); // version, name - w = istream_read_int32_le( inputStream ); - inputStream.seek( 4 * ( M8_MIPMAP_COUNT - 1 ) ); // remaining widths - h = istream_read_int32_le( inputStream ); - inputStream.seek( 4 * ( M8_MIPMAP_COUNT - 1 ) ); // remaining heights - offset = istream_read_int32_le( inputStream ); - inputStream.seek( 4 * ( M8_MIPMAP_COUNT - 1 ) ); // remaining offsets - inputStream.seek( M8_NAME_LENGTH ); // animname - inputStream.read( palette, 768 ); - flags = istream_read_int32_le( inputStream ); - contents = istream_read_int32_le( inputStream ); - value = istream_read_int32_le( inputStream ); - source = buffer + offset; - } - else - { - LoadPCXPalette( "pics/colormap.pcx", palette ); - - inputStream.seek( WAL_NAME_LENGTH ); // name - w = istream_read_int32_le( inputStream ); - h = istream_read_int32_le( inputStream ); - offset = istream_read_int32_le( inputStream ); - inputStream.seek( 4 * ( WAL_MIPMAP_COUNT - 1 ) ); // remaining offsets - inputStream.seek( WAL_NAME_LENGTH ); // animname - flags = istream_read_int32_le( inputStream ); - contents = istream_read_int32_le( inputStream ); - value = istream_read_int32_le( inputStream ); - source = buffer + offset; - } - - RGBAImageFlags* image = new RGBAImageFlags( w, h, flags, contents, value ); - - byte* dest = image->getRGBAPixels(); - byte* end = source + ( w * h ); - for (; source != end; ++source, dest += 4 ) - { - *( dest + 0 ) = palette[*source * 3 + 0]; - *( dest + 1 ) = palette[*source * 3 + 1]; - *( dest + 2 ) = palette[*source * 3 + 2]; - *( dest + 3 ) = 255; - } - - return image; +Image *LoadMipTex(byte *buffer, byte TypeofTex) +{ + int w, h, offset, flags, contents, value; + byte palette[768]; + byte *source; + + PointerInputStream inputStream(buffer); + + if (TypeofTex == HERETIC2_M8) { + inputStream.seek(4 + M8_NAME_LENGTH); // version, name + w = istream_read_int32_le(inputStream); + inputStream.seek(4 * (M8_MIPMAP_COUNT - 1)); // remaining widths + h = istream_read_int32_le(inputStream); + inputStream.seek(4 * (M8_MIPMAP_COUNT - 1)); // remaining heights + offset = istream_read_int32_le(inputStream); + inputStream.seek(4 * (M8_MIPMAP_COUNT - 1)); // remaining offsets + inputStream.seek(M8_NAME_LENGTH); // animname + inputStream.read(palette, 768); + flags = istream_read_int32_le(inputStream); + contents = istream_read_int32_le(inputStream); + value = istream_read_int32_le(inputStream); + source = buffer + offset; + } else { + LoadPCXPalette("pics/colormap.pcx", palette); + + inputStream.seek(WAL_NAME_LENGTH); // name + w = istream_read_int32_le(inputStream); + h = istream_read_int32_le(inputStream); + offset = istream_read_int32_le(inputStream); + inputStream.seek(4 * (WAL_MIPMAP_COUNT - 1)); // remaining offsets + inputStream.seek(WAL_NAME_LENGTH); // animname + flags = istream_read_int32_le(inputStream); + contents = istream_read_int32_le(inputStream); + value = istream_read_int32_le(inputStream); + source = buffer + offset; + } + + RGBAImageFlags *image = new RGBAImageFlags(w, h, flags, contents, value); + + byte *dest = image->getRGBAPixels(); + byte *end = source + (w * h); + for (; source != end; ++source, dest += 4) { + *(dest + 0) = palette[*source * 3 + 0]; + *(dest + 1) = palette[*source * 3 + 1]; + *(dest + 2) = palette[*source * 3 + 2]; + *(dest + 3) = 255; + } + + return image; } -Image* LoadWal( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadMipTex( buffer.buffer, QUAKE2_WAL ); +Image *LoadWal(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadMipTex(buffer.buffer, QUAKE2_WAL); } -Image* LoadM8( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadMipTex( buffer.buffer, HERETIC2_M8 ); +Image *LoadM8(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadMipTex(buffer.buffer, HERETIC2_M8); } diff --git a/plugins/imageq2/wal.h b/plugins/imageq2/wal.h index dac84d12..a1980d37 100644 --- a/plugins/imageq2/wal.h +++ b/plugins/imageq2/wal.h @@ -23,9 +23,11 @@ #define INCLUDED_WAL_H class Image; + class ArchiveFile; -Image* LoadWal( ArchiveFile& file ); -Image* LoadM8( ArchiveFile& file ); +Image *LoadWal(ArchiveFile &file); + +Image *LoadM8(ArchiveFile &file); #endif diff --git a/plugins/imageq2/wal32.cpp b/plugins/imageq2/wal32.cpp index b202137a..cadd845e 100644 --- a/plugins/imageq2/wal32.cpp +++ b/plugins/imageq2/wal32.cpp @@ -31,59 +31,60 @@ typedef unsigned char byte; const int M32_NAME_LENGTH = 128; const int M32_MIPMAP_COUNT = 16; -typedef struct m32_header_t -{ - int version; - char name[M32_NAME_LENGTH]; - char altname[M32_NAME_LENGTH]; // texture substitution - char animname[M32_NAME_LENGTH]; // next frame in animation chain - char damagename[M32_NAME_LENGTH]; // image that should be shown when damaged - unsigned width[M32_MIPMAP_COUNT], height[M32_MIPMAP_COUNT]; - unsigned offsets[M32_MIPMAP_COUNT]; - int flags; - int contents; - int value; - float scale_x, scale_y; - int mip_scale; - - // detail texturing info - char dt_name[M32_NAME_LENGTH]; // detailed texture name - float dt_scale_x, dt_scale_y; - float dt_u, dt_v; - float dt_alpha; - int dt_src_blend_mode, dt_dst_blend_mode; - - int unused[20]; // future expansion to maintain compatibility with h2 +typedef struct m32_header_t { + int version; + char name[M32_NAME_LENGTH]; + char altname[M32_NAME_LENGTH]; // texture substitution + char animname[M32_NAME_LENGTH]; // next frame in animation chain + char damagename[M32_NAME_LENGTH]; // image that should be shown when damaged + unsigned width[M32_MIPMAP_COUNT], height[M32_MIPMAP_COUNT]; + unsigned offsets[M32_MIPMAP_COUNT]; + int flags; + int contents; + int value; + float scale_x, scale_y; + int mip_scale; + + // detail texturing info + char dt_name[M32_NAME_LENGTH]; // detailed texture name + float dt_scale_x, dt_scale_y; + float dt_u, dt_v; + float dt_alpha; + int dt_src_blend_mode, dt_dst_blend_mode; + + int unused[20]; // future expansion to maintain compatibility with h2 } m32_header_t; -Image* LoadM32Buff( byte* buffer ){ - PointerInputStream inputStream( buffer ); - - inputStream.seek( 4 // version - + M32_NAME_LENGTH // name - + M32_NAME_LENGTH // altname - + M32_NAME_LENGTH // animname - + M32_NAME_LENGTH ); // damagename - int w = istream_read_uint32_le( inputStream ); - inputStream.seek( 4 * ( M32_MIPMAP_COUNT - 1 ) ); // remaining widths - int h = istream_read_uint32_le( inputStream ); - inputStream.seek( 4 * ( M32_MIPMAP_COUNT - 1 ) ); // remaining heights - int offset = istream_read_uint32_le( inputStream ); - inputStream.seek( 4 * ( M32_MIPMAP_COUNT - 1 ) ); // remaining offsets - int flags = istream_read_uint32_le( inputStream ); - int contents = istream_read_uint32_le( inputStream ); - int value = istream_read_uint32_le( inputStream ); - - RGBAImageFlags* image = new RGBAImageFlags( w, h, flags, contents, value ); - - const byte* source = buffer + offset; - std::copy( source, source + ( w * h * 4 ), image->getRGBAPixels() ); - - return image; +Image *LoadM32Buff(byte *buffer) +{ + PointerInputStream inputStream(buffer); + + inputStream.seek(4 // version + + M32_NAME_LENGTH // name + + M32_NAME_LENGTH // altname + + M32_NAME_LENGTH // animname + + M32_NAME_LENGTH); // damagename + int w = istream_read_uint32_le(inputStream); + inputStream.seek(4 * (M32_MIPMAP_COUNT - 1)); // remaining widths + int h = istream_read_uint32_le(inputStream); + inputStream.seek(4 * (M32_MIPMAP_COUNT - 1)); // remaining heights + int offset = istream_read_uint32_le(inputStream); + inputStream.seek(4 * (M32_MIPMAP_COUNT - 1)); // remaining offsets + int flags = istream_read_uint32_le(inputStream); + int contents = istream_read_uint32_le(inputStream); + int value = istream_read_uint32_le(inputStream); + + RGBAImageFlags *image = new RGBAImageFlags(w, h, flags, contents, value); + + const byte *source = buffer + offset; + std::copy(source, source + (w * h * 4), image->getRGBAPixels()); + + return image; } -Image* LoadM32( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadM32Buff( buffer.buffer ); +Image *LoadM32(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadM32Buff(buffer.buffer); } diff --git a/plugins/imageq2/wal32.h b/plugins/imageq2/wal32.h index 25f6dac6..7cd31d3c 100644 --- a/plugins/imageq2/wal32.h +++ b/plugins/imageq2/wal32.h @@ -23,8 +23,9 @@ #define INCLUDED_WAL32_H class Image; + class ArchiveFile; -Image* LoadM32( ArchiveFile& file ); +Image *LoadM32(ArchiveFile &file); #endif diff --git a/plugins/iqmmodel/iqm.cpp b/plugins/iqmmodel/iqm.cpp index 7dca7897..96883c68 100644 --- a/plugins/iqmmodel/iqm.cpp +++ b/plugins/iqmmodel/iqm.cpp @@ -39,256 +39,246 @@ typedef unsigned char byte; ======================================================================== */ -typedef struct -{ - float s; - float t; +typedef struct { + float s; + float t; } iqmSt_t; -void istream_read_iqmSt(PointerInputStream& inputStream, iqmSt_t& st) +void istream_read_iqmSt(PointerInputStream &inputStream, iqmSt_t &st) { - st.s = istream_read_float32_le(inputStream); - st.t = istream_read_float32_le(inputStream); + st.s = istream_read_float32_le(inputStream); + st.t = istream_read_float32_le(inputStream); } -typedef struct -{ - unsigned int indices[3]; +typedef struct { + unsigned int indices[3]; } iqmTriangle_t; -void istream_read_iqmTriangle(PointerInputStream& inputStream, iqmTriangle_t& triangle) +void istream_read_iqmTriangle(PointerInputStream &inputStream, iqmTriangle_t &triangle) { - triangle.indices[0] = istream_read_int32_le(inputStream); - triangle.indices[1] = istream_read_int32_le(inputStream); - triangle.indices[2] = istream_read_int32_le(inputStream); + triangle.indices[0] = istream_read_int32_le(inputStream); + triangle.indices[1] = istream_read_int32_le(inputStream); + triangle.indices[2] = istream_read_int32_le(inputStream); } -typedef struct -{ - float v[3]; +typedef struct { + float v[3]; } iqmPos_t; -void istream_read_iqmPos(PointerInputStream& inputStream, iqmPos_t& iqmPos) +void istream_read_iqmPos(PointerInputStream &inputStream, iqmPos_t &iqmPos) { - iqmPos.v[0] = istream_read_float32_le(inputStream); - iqmPos.v[1] = istream_read_float32_le(inputStream); - iqmPos.v[2] = istream_read_float32_le(inputStream); + iqmPos.v[0] = istream_read_float32_le(inputStream); + iqmPos.v[1] = istream_read_float32_le(inputStream); + iqmPos.v[2] = istream_read_float32_le(inputStream); } -const int IQM_POSITION = 0; -const int IQM_TEXCOORD = 1; -const int IQM_NORMAL = 2; -const int IQM_TANGENT = 3; -const int IQM_BLENDINDEXES = 4; -const int IQM_BLENDWEIGHTS = 5; -const int IQM_COLOR = 6; -const int IQM_CUSTOM = 0x10; - -const int IQM_BYTE = 0; -const int IQM_UBYTE = 1; -const int IQM_SHORT = 2; -const int IQM_USHORT = 3; -const int IQM_INT = 4; -const int IQM_UINT = 5; -const int IQM_HALF = 6; -const int IQM_FLOAT = 7; -const int IQM_DOUBLE = 8; +const int IQM_POSITION = 0; +const int IQM_TEXCOORD = 1; +const int IQM_NORMAL = 2; +const int IQM_TANGENT = 3; +const int IQM_BLENDINDEXES = 4; +const int IQM_BLENDWEIGHTS = 5; +const int IQM_COLOR = 6; +const int IQM_CUSTOM = 0x10; + +const int IQM_BYTE = 0; +const int IQM_UBYTE = 1; +const int IQM_SHORT = 2; +const int IQM_USHORT = 3; +const int IQM_INT = 4; +const int IQM_UINT = 5; +const int IQM_HALF = 6; +const int IQM_FLOAT = 7; +const int IQM_DOUBLE = 8; // animflags const int IQM_LOOP = 1; -typedef struct iqmHeader_s -{ - byte id[16]; - unsigned int version; - unsigned int filesize; - unsigned int flags; - unsigned int num_text, ofs_text; - unsigned int num_meshes, ofs_meshes; - unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays; - unsigned int num_triangles, ofs_triangles, ofs_neighbors; - unsigned int num_joints, ofs_joints; - unsigned int num_poses, ofs_poses; - unsigned int num_anims, ofs_anims; - unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds; - unsigned int num_comment, ofs_comment; - unsigned int num_extensions, ofs_extensions; +typedef struct iqmHeader_s { + byte id[16]; + unsigned int version; + unsigned int filesize; + unsigned int flags; + unsigned int num_text, ofs_text; + unsigned int num_meshes, ofs_meshes; + unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays; + unsigned int num_triangles, ofs_triangles, ofs_neighbors; + unsigned int num_joints, ofs_joints; + unsigned int num_poses, ofs_poses; + unsigned int num_anims, ofs_anims; + unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds; + unsigned int num_comment, ofs_comment; + unsigned int num_extensions, ofs_extensions; } iqmHeader_t; -void istream_read_iqmHeader(PointerInputStream& inputStream, iqmHeader_t& header) +void istream_read_iqmHeader(PointerInputStream &inputStream, iqmHeader_t &header) { - inputStream.read(header.id, 16); + inputStream.read(header.id, 16); #define READINT(x) header.x = istream_read_int32_le(inputStream); - READINT (version) - READINT (filesize) - READINT (flags) - READINT (num_text) - READINT (ofs_text) - READINT (num_meshes) - READINT (ofs_meshes) - READINT (num_vertexarrays) - READINT (num_vertexes) - READINT (ofs_vertexarrays) - READINT (num_triangles) - READINT (ofs_triangles) - READINT (ofs_neighbors) - READINT (num_joints) - READINT (ofs_joints) - READINT (num_frames) - READINT (num_framechannels) - READINT (ofs_frames) - READINT (ofs_bounds) - READINT (num_comment) - READINT (ofs_comment) - READINT (num_extensions) - READINT (ofs_extensions) + READINT (version) + READINT (filesize) + READINT (flags) + READINT (num_text) + READINT (ofs_text) + READINT (num_meshes) + READINT (ofs_meshes) + READINT (num_vertexarrays) + READINT (num_vertexes) + READINT (ofs_vertexarrays) + READINT (num_triangles) + READINT (ofs_triangles) + READINT (ofs_neighbors) + READINT (num_joints) + READINT (ofs_joints) + READINT (num_frames) + READINT (num_framechannels) + READINT (ofs_frames) + READINT (ofs_bounds) + READINT (num_comment) + READINT (ofs_comment) + READINT (num_extensions) + READINT (ofs_extensions) #undef READINT } -typedef struct iqmvertexarray_s -{ - unsigned int type; - unsigned int flags; - unsigned int format; - unsigned int size; - unsigned int offset; +typedef struct iqmvertexarray_s { + unsigned int type; + unsigned int flags; + unsigned int format; + unsigned int size; + unsigned int offset; } -iqmvertexarray_t; + iqmvertexarray_t; -void istream_read_iqmVertexarray(PointerInputStream& inputStream, iqmvertexarray_t& out) +void istream_read_iqmVertexarray(PointerInputStream &inputStream, iqmvertexarray_t &out) { #define READINT(x) out.x = istream_read_int32_le(inputStream); - READINT (type) - READINT (flags) - READINT (format) - READINT (size) - READINT (offset) + READINT (type) + READINT (flags) + READINT (format) + READINT (size) + READINT (offset) #undef READINT } -ArbitraryMeshVertex IQMVertex_construct(const iqmPos_t* pos, const iqmPos_t* norm, const iqmSt_t* st) +ArbitraryMeshVertex IQMVertex_construct(const iqmPos_t *pos, const iqmPos_t *norm, const iqmSt_t *st) { - return ArbitraryMeshVertex( - Vertex3f (pos->v[0], pos->v[1], pos->v[2]), - Normal3f (norm->v[0], norm->v[1], norm->v[2]), - TexCoord2f (st->s, st->t) - ); + return ArbitraryMeshVertex( + Vertex3f(pos->v[0], pos->v[1], pos->v[2]), + Normal3f(norm->v[0], norm->v[1], norm->v[2]), + TexCoord2f(st->s, st->t) + ); } -void IQMSurface_read(Model& model, const byte* buffer, ArchiveFile& file) +void IQMSurface_read(Model &model, const byte *buffer, ArchiveFile &file) { - Surface& surface = model.newSurface(); - iqmHeader_t header; - { - PointerInputStream inputStream(buffer); - istream_read_iqmHeader(inputStream, header); - } - - { - - UniqueVertexBuffer inserter(surface.vertices()); - inserter.reserve(header.num_vertexes); - - int ofs_position = -1, ofs_st = -1, ofs_normal = -1; - PointerInputStream vaStream (buffer + header.ofs_vertexarrays); - for (unsigned int i = 0; i < header.num_vertexarrays; i++) + Surface &surface = model.newSurface(); + iqmHeader_t header; { - iqmvertexarray_t va; - istream_read_iqmVertexarray (vaStream, va); - - switch (va.type) - { - case IQM_POSITION: - if (va.format == IQM_FLOAT && va.size == 3) - ofs_position = va.offset; - break; - case IQM_TEXCOORD: - if (va.format == IQM_FLOAT && va.size == 2) - ofs_st = va.offset; - break; - case IQM_NORMAL: - if (va.format == IQM_FLOAT && va.size == 3) - ofs_normal = va.offset; - break; - } + PointerInputStream inputStream(buffer); + istream_read_iqmHeader(inputStream, header); } - - surface.indices().reserve(header.num_vertexes); - PointerInputStream posStream(buffer + ofs_position); - Array iqmPos(header.num_vertexes); - for(Array::iterator i = iqmPos.begin(); i != iqmPos.end(); ++i) { - istream_read_iqmPos(posStream, *i); - } - - PointerInputStream normStream(buffer + ofs_normal); - Array iqmNorm(header.num_vertexes); - for(Array::iterator i = iqmNorm.begin(); i != iqmNorm.end(); ++i) - { - istream_read_iqmPos(normStream, *i); - } - Array iqmSt(header.num_vertexes); - PointerInputStream stStream(buffer + ofs_st); - for(Array::iterator i = iqmSt.begin(); i != iqmSt.end(); ++i) - { - istream_read_iqmSt(stStream, *i); - } - - PointerInputStream triangleStream(buffer + header.ofs_triangles); - for(unsigned int i = 0; i < header.num_triangles; ++i) - { - iqmTriangle_t triangle; - istream_read_iqmTriangle(triangleStream, triangle); - for (int j = 0; j < 3; j++) - surface.indices().insert(inserter.insert(IQMVertex_construct( - &iqmPos[triangle.indices[j]], - &iqmNorm[triangle.indices[j]], - &iqmSt[triangle.indices[j]]))); + UniqueVertexBuffer inserter(surface.vertices()); + inserter.reserve(header.num_vertexes); + + int ofs_position = -1, ofs_st = -1, ofs_normal = -1; + PointerInputStream vaStream(buffer + header.ofs_vertexarrays); + for (unsigned int i = 0; i < header.num_vertexarrays; i++) { + iqmvertexarray_t va; + istream_read_iqmVertexarray(vaStream, va); + + switch (va.type) { + case IQM_POSITION: + if (va.format == IQM_FLOAT && va.size == 3) { + ofs_position = va.offset; + } + break; + case IQM_TEXCOORD: + if (va.format == IQM_FLOAT && va.size == 2) { + ofs_st = va.offset; + } + break; + case IQM_NORMAL: + if (va.format == IQM_FLOAT && va.size == 3) { + ofs_normal = va.offset; + } + break; + } + } + + surface.indices().reserve(header.num_vertexes); + + PointerInputStream posStream(buffer + ofs_position); + Array iqmPos(header.num_vertexes); + for (Array::iterator i = iqmPos.begin(); i != iqmPos.end(); ++i) { + istream_read_iqmPos(posStream, *i); + } + + PointerInputStream normStream(buffer + ofs_normal); + Array iqmNorm(header.num_vertexes); + for (Array::iterator i = iqmNorm.begin(); i != iqmNorm.end(); ++i) { + istream_read_iqmPos(normStream, *i); + } + + Array iqmSt(header.num_vertexes); + PointerInputStream stStream(buffer + ofs_st); + for (Array::iterator i = iqmSt.begin(); i != iqmSt.end(); ++i) { + istream_read_iqmSt(stStream, *i); + } + + PointerInputStream triangleStream(buffer + header.ofs_triangles); + for (unsigned int i = 0; i < header.num_triangles; ++i) { + iqmTriangle_t triangle; + istream_read_iqmTriangle(triangleStream, triangle); + for (int j = 0; j < 3; j++) { + surface.indices().insert(inserter.insert(IQMVertex_construct( + &iqmPos[triangle.indices[j]], + &iqmNorm[triangle.indices[j]], + &iqmSt[triangle.indices[j]]))); + } + } } - } - - surface.setShader(""); - surface.updateAABB(); + + surface.setShader(""); + surface.updateAABB(); } -void IQMModel_read(Model& model, const byte* buffer, ArchiveFile& file) +void IQMModel_read(Model &model, const byte *buffer, ArchiveFile &file) { - IQMSurface_read(model, buffer, file); - model.updateAABB(); + IQMSurface_read(model, buffer, file); + model.updateAABB(); } -scene::Node& IQMModel_new(const byte* buffer, ArchiveFile& file) +scene::Node &IQMModel_new(const byte *buffer, ArchiveFile &file) { - ModelNode* modelNode = new ModelNode(); - IQMModel_read(modelNode->model(), buffer, file); - return modelNode->node(); + ModelNode *modelNode = new ModelNode(); + IQMModel_read(modelNode->model(), buffer, file); + return modelNode->node(); } -scene::Node& IQMModel_default() +scene::Node &IQMModel_default() { - ModelNode* modelNode = new ModelNode(); - Model_constructNull(modelNode->model()); - return modelNode->node(); + ModelNode *modelNode = new ModelNode(); + Model_constructNull(modelNode->model()); + return modelNode->node(); } -scene::Node& IQMModel_fromBuffer(unsigned char* buffer, ArchiveFile& file) +scene::Node &IQMModel_fromBuffer(unsigned char *buffer, ArchiveFile &file) { - if (memcmp(buffer, "INTERQUAKEMODEL", 16)) - { - globalErrorStream() << "IQM read error: incorrect ident\n"; - return IQMModel_default(); - } - else - { - return IQMModel_new(buffer, file); - } + if (memcmp(buffer, "INTERQUAKEMODEL", 16)) { + globalErrorStream() << "IQM read error: incorrect ident\n"; + return IQMModel_default(); + } else { + return IQMModel_new(buffer, file); + } } -scene::Node& loadIQMModel(ArchiveFile& file) +scene::Node &loadIQMModel(ArchiveFile &file) { - ScopedArchiveBuffer buffer(file); - return IQMModel_fromBuffer(buffer.buffer, file); + ScopedArchiveBuffer buffer(file); + return IQMModel_fromBuffer(buffer.buffer, file); } diff --git a/plugins/iqmmodel/iqm.h b/plugins/iqmmodel/iqm.h index 9362b9cf..f706a998 100644 --- a/plugins/iqmmodel/iqm.h +++ b/plugins/iqmmodel/iqm.h @@ -24,7 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA namespace scene { class Node; } class ArchiveFile; -scene::Node& loadIQMModel(ArchiveFile& file); + +scene::Node &loadIQMModel(ArchiveFile &file); #endif diff --git a/plugins/iqmmodel/plugin.cpp b/plugins/iqmmodel/plugin.cpp index 48ba470c..4c026468 100644 --- a/plugins/iqmmodel/plugin.cpp +++ b/plugins/iqmmodel/plugin.cpp @@ -38,50 +38,49 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "iqm.h" -class IQMModelLoader : public ModelLoader -{ +class IQMModelLoader : public ModelLoader { public: - scene::Node& loadModel(ArchiveFile& file) - { - return loadIQMModel(file); - } + scene::Node &loadModel(ArchiveFile &file) + { + return loadIQMModel(file); + } }; class ModelDependencies : - public GlobalFileSystemModuleRef, - public GlobalOpenGLModuleRef, - public GlobalUndoModuleRef, - public GlobalSceneGraphModuleRef, - public GlobalShaderCacheModuleRef, - public GlobalSelectionModuleRef, - public GlobalFiletypesModuleRef -{ + public GlobalFileSystemModuleRef, + public GlobalOpenGLModuleRef, + public GlobalUndoModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalSelectionModuleRef, + public GlobalFiletypesModuleRef { }; -class ModelIQMAPI : public TypeSystemRef -{ - IQMModelLoader m_modeliqm; +class ModelIQMAPI : public TypeSystemRef { + IQMModelLoader m_modeliqm; public: - typedef ModelLoader Type; - STRING_CONSTANT(Name, "iqm"); - - ModelIQMAPI() - { - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("iqm models", "*.iqm")); - } - ModelLoader* getTable() - { - return &m_modeliqm; - } + typedef ModelLoader Type; + + STRING_CONSTANT(Name, "iqm"); + + ModelIQMAPI() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("iqm models", "*.iqm")); + } + + ModelLoader *getTable() + { + return &m_modeliqm; + } }; typedef SingletonModule ModelIQMModule; ModelIQMModule g_ModelIQMModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server) +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) { - initialiseModule(server); + initialiseModule(server); - g_ModelIQMModule.selfRegister(); + g_ModelIQMModule.selfRegister(); } diff --git a/plugins/mapq3/CMakeLists.txt b/plugins/mapq3/CMakeLists.txt index 880b653d..f60c5f99 100644 --- a/plugins/mapq3/CMakeLists.txt +++ b/plugins/mapq3/CMakeLists.txt @@ -5,5 +5,5 @@ radiant_plugin(mapq3 ) target_include_directories(mapq3 - PRIVATE $ -) + PRIVATE $ + ) diff --git a/plugins/mapq3/parse.cpp b/plugins/mapq3/parse.cpp index 03b1acae..4e768865 100644 --- a/plugins/mapq3/parse.cpp +++ b/plugins/mapq3/parse.cpp @@ -33,106 +33,107 @@ #include "stringio.h" #include "eclasslib.h" -inline MapImporter* Node_getMapImporter( scene::Node& node ){ - return NodeTypeCast::cast( node ); +inline MapImporter *Node_getMapImporter(scene::Node &node) +{ + return NodeTypeCast::cast(node); } -typedef std::list< std::pair > KeyValues; +typedef std::list > KeyValues; -NodeSmartReference g_nullNode( NewNullNode() ); +NodeSmartReference g_nullNode(NewNullNode()); -NodeSmartReference Entity_create( EntityCreator& entityTable, EntityClass* entityClass, const KeyValues& keyValues ){ - scene::Node& entity( entityTable.createEntity( entityClass ) ); - for ( KeyValues::const_iterator i = keyValues.begin(); i != keyValues.end(); ++i ) - { - Node_getEntity( entity )->setKeyValue( ( *i ).first.c_str(), ( *i ).second.c_str() ); - } - return NodeSmartReference( entity ); +NodeSmartReference Entity_create(EntityCreator &entityTable, EntityClass *entityClass, const KeyValues &keyValues) +{ + scene::Node &entity(entityTable.createEntity(entityClass)); + for (KeyValues::const_iterator i = keyValues.begin(); i != keyValues.end(); ++i) { + Node_getEntity(entity)->setKeyValue((*i).first.c_str(), (*i).second.c_str()); + } + return NodeSmartReference(entity); } -NodeSmartReference Entity_parseTokens( Tokeniser& tokeniser, EntityCreator& entityTable, const PrimitiveParser& parser, int index ){ - NodeSmartReference entity( g_nullNode ); - KeyValues keyValues; - const char* classname = ""; - - int count_primitives = 0; - while ( 1 ) - { - tokeniser.nextLine(); - const char* token = tokeniser.getToken(); - if ( token == 0 ) { - Tokeniser_unexpectedError( tokeniser, token, "#entity-token" ); - return g_nullNode; - } - if ( !strcmp( token, "}" ) ) { // end entity - if ( entity == g_nullNode ) { - // entity does not have brushes - entity = Entity_create( entityTable, GlobalEntityClassManager().findOrInsert( classname, false ), keyValues ); - } - return entity; - } - else if ( !strcmp( token, "{" ) ) { // begin primitive - if ( entity == g_nullNode ) { - // entity has brushes - entity = Entity_create( entityTable, GlobalEntityClassManager().findOrInsert( classname, true ), keyValues ); - } - - tokeniser.nextLine(); - - NodeSmartReference primitive( parser.parsePrimitive( tokeniser ) ); - if ( primitive == g_nullNode || !Node_getMapImporter( primitive )->importTokens( tokeniser ) ) { - globalErrorStream() << "brush " << count_primitives << ": parse error\n"; - return g_nullNode; - } - - scene::Traversable* traversable = Node_getTraversable( entity ); - if ( Node_getEntity( entity )->isContainer() && traversable != 0 ) { - traversable->insert( primitive ); - } - else - { - globalErrorStream() << "entity " << index << ": type " << classname << ": discarding brush " << count_primitives << "\n"; - } - ++count_primitives; - } - else // epair - { - CopiedString key( token ); - token = tokeniser.getToken(); - if ( token == 0 ) { - Tokeniser_unexpectedError( tokeniser, token, "#epair-value" ); - return g_nullNode; - } - keyValues.push_back( KeyValues::value_type( key, token ) ); - if ( string_equal( key.c_str(), "classname" ) ) { - classname = keyValues.back().second.c_str(); - } - } - } - // unreachable code - return g_nullNode; +NodeSmartReference +Entity_parseTokens(Tokeniser &tokeniser, EntityCreator &entityTable, const PrimitiveParser &parser, int index) +{ + NodeSmartReference entity(g_nullNode); + KeyValues keyValues; + const char *classname = ""; + + int count_primitives = 0; + while (1) { + tokeniser.nextLine(); + const char *token = tokeniser.getToken(); + if (token == 0) { + Tokeniser_unexpectedError(tokeniser, token, "#entity-token"); + return g_nullNode; + } + if (!strcmp(token, "}")) { // end entity + if (entity == g_nullNode) { + // entity does not have brushes + entity = Entity_create(entityTable, GlobalEntityClassManager().findOrInsert(classname, false), + keyValues); + } + return entity; + } else if (!strcmp(token, "{")) { // begin primitive + if (entity == g_nullNode) { + // entity has brushes + entity = Entity_create(entityTable, GlobalEntityClassManager().findOrInsert(classname, true), + keyValues); + } + + tokeniser.nextLine(); + + NodeSmartReference primitive(parser.parsePrimitive(tokeniser)); + if (primitive == g_nullNode || !Node_getMapImporter(primitive)->importTokens(tokeniser)) { + globalErrorStream() << "brush " << count_primitives << ": parse error\n"; + return g_nullNode; + } + + scene::Traversable *traversable = Node_getTraversable(entity); + if (Node_getEntity(entity)->isContainer() && traversable != 0) { + traversable->insert(primitive); + } else { + globalErrorStream() << "entity " << index << ": type " << classname << ": discarding brush " + << count_primitives << "\n"; + } + ++count_primitives; + } else // epair + { + CopiedString key(token); + token = tokeniser.getToken(); + if (token == 0) { + Tokeniser_unexpectedError(tokeniser, token, "#epair-value"); + return g_nullNode; + } + keyValues.push_back(KeyValues::value_type(key, token)); + if (string_equal(key.c_str(), "classname")) { + classname = keyValues.back().second.c_str(); + } + } + } + // unreachable code + return g_nullNode; } -void Map_Read( scene::Node& root, Tokeniser& tokeniser, EntityCreator& entityTable, const PrimitiveParser& parser ){ - int count_entities = 0; - for (;; ) - { - tokeniser.nextLine(); - if ( !tokeniser.getToken() ) { // { or 0 - break; - } +void Map_Read(scene::Node &root, Tokeniser &tokeniser, EntityCreator &entityTable, const PrimitiveParser &parser) +{ + int count_entities = 0; + for (;;) { + tokeniser.nextLine(); + if (!tokeniser.getToken()) { // { or 0 + break; + } - NodeSmartReference entity( Entity_parseTokens( tokeniser, entityTable, parser, count_entities ) ); + NodeSmartReference entity(Entity_parseTokens(tokeniser, entityTable, parser, count_entities)); - if ( entity == g_nullNode ) { - globalErrorStream() << "entity " << count_entities << ": parse error\n"; - return; - } + if (entity == g_nullNode) { + globalErrorStream() << "entity " << count_entities << ": parse error\n"; + return; + } - Node_getTraversable( root )->insert( entity ); + Node_getTraversable(root)->insert(entity); - ++count_entities; - } + ++count_entities; + } } diff --git a/plugins/mapq3/parse.h b/plugins/mapq3/parse.h index 1523c6ad..50424f2e 100644 --- a/plugins/mapq3/parse.h +++ b/plugins/mapq3/parse.h @@ -25,22 +25,22 @@ #include "imap.h" class BrushCreator; + class PatchCreator; -class PrimitiveParser -{ +class PrimitiveParser { public: -virtual scene::Node& parsePrimitive( Tokeniser& tokeniser ) const = 0; + virtual scene::Node &parsePrimitive(Tokeniser &tokeniser) const = 0; }; -void Map_Read( scene::Node& root, Tokeniser& tokeniser, EntityCreator& entityTable, const PrimitiveParser& parser ); +void Map_Read(scene::Node &root, Tokeniser &tokeniser, EntityCreator &entityTable, const PrimitiveParser &parser); -namespace scene -{ -class Node; +namespace scene { + class Node; } #include "generic/referencecounted.h" + typedef SmartReference > NodeSmartReference; extern NodeSmartReference g_nullNode; diff --git a/plugins/mapq3/plugin.cpp b/plugins/mapq3/plugin.cpp index e0731281..764b1d14 100644 --- a/plugins/mapq3/plugin.cpp +++ b/plugins/mapq3/plugin.cpp @@ -38,258 +38,286 @@ class MapDoom3Dependencies : - public GlobalRadiantModuleRef, - public GlobalFiletypesModuleRef, - public GlobalScripLibModuleRef, - public GlobalEntityClassManagerModuleRef, - public GlobalSceneGraphModuleRef, - public GlobalBrushModuleRef -{ -PatchModuleRef m_patchDef2Doom3Module; -PatchModuleRef m_patchDoom3Module; + public GlobalRadiantModuleRef, + public GlobalFiletypesModuleRef, + public GlobalScripLibModuleRef, + public GlobalEntityClassManagerModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalBrushModuleRef { + PatchModuleRef m_patchDef2Doom3Module; + PatchModuleRef m_patchDoom3Module; public: -MapDoom3Dependencies() : - GlobalEntityClassManagerModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entityclass" ) ), - GlobalBrushModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "brushtypes" ) ), - m_patchDef2Doom3Module( "def2doom3" ), - m_patchDoom3Module( "doom3" ){ -} -BrushCreator& getBrushDoom3(){ - return GlobalBrushModule::getTable(); -} -PatchCreator& getPatchDoom3(){ - return *m_patchDoom3Module.getTable(); -} -PatchCreator& getPatchDef2Doom3(){ - return *m_patchDef2Doom3Module.getTable(); -} + MapDoom3Dependencies() : + GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass")), + GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")), + m_patchDef2Doom3Module("def2doom3"), + m_patchDoom3Module("doom3") + { + } + + BrushCreator &getBrushDoom3() + { + return GlobalBrushModule::getTable(); + } + + PatchCreator &getPatchDoom3() + { + return *m_patchDoom3Module.getTable(); + } + + PatchCreator &getPatchDef2Doom3() + { + return *m_patchDef2Doom3Module.getTable(); + } }; -class MapDoom3API : public TypeSystemRef, public MapFormat, public PrimitiveParser -{ -MapDoom3Dependencies& m_dependencies; +class MapDoom3API : public TypeSystemRef, public MapFormat, public PrimitiveParser { + MapDoom3Dependencies &m_dependencies; public: -typedef MapFormat Type; -STRING_CONSTANT( Name, "mapdoom3" ); -UINT_CONSTANT( MapVersion, 2 ); - -MapDoom3API( MapDoom3Dependencies& dependencies ) : m_dependencies( dependencies ){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "doom3 maps", "*.map" ) ); - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "doom3 region", "*.reg" ) ); -} -MapFormat* getTable(){ - return this; -} - -scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { - const char* primitive = tokeniser.getToken(); - if ( primitive != 0 ) { - if ( string_equal( primitive, "patchDef3" ) ) { - return m_dependencies.getPatchDoom3().createPatch(); - } - else if ( string_equal( primitive, "patchDef2" ) ) { - return m_dependencies.getPatchDef2Doom3().createPatch(); - } - else if ( string_equal( primitive, "brushDef3" ) ) { - return m_dependencies.getBrushDoom3().createBrush(); - } - } - - Tokeniser_unexpectedError( tokeniser, primitive, "#doom3-primitive" ); - return g_nullNode; -} -void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { - Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); - tokeniser.nextLine(); - if ( !Tokeniser_parseToken( tokeniser, "Version" ) ) { - return; - } - std::size_t version; - if ( !Tokeniser_getSize( tokeniser, version ) ) { - return; - } - if ( version != MapVersion() ) { - globalErrorStream() << "Doom 3 map version " << MapVersion() << " supported, version is " << Unsigned( version ) << "\n"; - return; - } - tokeniser.nextLine(); - Map_Read( root, tokeniser, entityTable, *this ); - tokeniser.release(); -} -void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream ) const { - TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); - writer.writeToken( "Version" ); - writer.writeInteger( MapVersion() ); - writer.nextLine(); - Map_Write( root, traverse, writer, false ); - writer.release(); -} + typedef MapFormat Type; + + STRING_CONSTANT(Name, "mapdoom3"); + + UINT_CONSTANT(MapVersion, 2); + + MapDoom3API(MapDoom3Dependencies &dependencies) : m_dependencies(dependencies) + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("doom3 maps", "*.map")); + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("doom3 region", "*.reg")); + } + + MapFormat *getTable() + { + return this; + } + + scene::Node &parsePrimitive(Tokeniser &tokeniser) const + { + const char *primitive = tokeniser.getToken(); + if (primitive != 0) { + if (string_equal(primitive, "patchDef3")) { + return m_dependencies.getPatchDoom3().createPatch(); + } else if (string_equal(primitive, "patchDef2")) { + return m_dependencies.getPatchDef2Doom3().createPatch(); + } else if (string_equal(primitive, "brushDef3")) { + return m_dependencies.getBrushDoom3().createBrush(); + } + } + + Tokeniser_unexpectedError(tokeniser, primitive, "#doom3-primitive"); + return g_nullNode; + } + + void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const + { + Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); + tokeniser.nextLine(); + if (!Tokeniser_parseToken(tokeniser, "Version")) { + return; + } + std::size_t version; + if (!Tokeniser_getSize(tokeniser, version)) { + return; + } + if (version != MapVersion()) { + globalErrorStream() << "Doom 3 map version " << MapVersion() << " supported, version is " + << Unsigned(version) << "\n"; + return; + } + tokeniser.nextLine(); + Map_Read(root, tokeniser, entityTable, *this); + tokeniser.release(); + } + + void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream) const + { + TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); + writer.writeToken("Version"); + writer.writeInteger(MapVersion()); + writer.nextLine(); + Map_Write(root, traverse, writer, false); + writer.release(); + } }; typedef SingletonModule< - MapDoom3API, - MapDoom3Dependencies, - DependenciesAPIConstructor - > -MapDoom3Module; + MapDoom3API, + MapDoom3Dependencies, + DependenciesAPIConstructor +> + MapDoom3Module; MapDoom3Module g_MapDoom3Module; -class MapQuake4API : public TypeSystemRef, public MapFormat, public PrimitiveParser -{ -MapDoom3Dependencies& m_dependencies; +class MapQuake4API : public TypeSystemRef, public MapFormat, public PrimitiveParser { + MapDoom3Dependencies &m_dependencies; public: -typedef MapFormat Type; -STRING_CONSTANT( Name, "mapquake4" ); -UINT_CONSTANT( MapVersion, 3 ); - -MapQuake4API( MapDoom3Dependencies& dependencies ) : m_dependencies( dependencies ){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake4 maps", "*.map" ) ); - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake4 region", "*.reg" ) ); -} -MapFormat* getTable(){ - return this; -} - -scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { - const char* primitive = tokeniser.getToken(); - if ( primitive != 0 ) { - if ( string_equal( primitive, "patchDef3" ) ) { - return m_dependencies.getPatchDoom3().createPatch(); - } - else if ( string_equal( primitive, "patchDef2" ) ) { - return m_dependencies.getPatchDef2Doom3().createPatch(); - } - else if ( string_equal( primitive, "brushDef3" ) ) { - return m_dependencies.getBrushDoom3().createBrush(); - } - } - - Tokeniser_unexpectedError( tokeniser, primitive, "#quake4-primitive" ); - return g_nullNode; -} -void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { - Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); - tokeniser.nextLine(); - if ( !Tokeniser_parseToken( tokeniser, "Version" ) ) { - return; - } - std::size_t version; - if ( !Tokeniser_getSize( tokeniser, version ) ) { - return; - } - if ( version != MapVersion() ) { - globalErrorStream() << "Quake 4 map version " << MapVersion() << " supported, version is " << Unsigned( version ) << "\n"; - return; - } - tokeniser.nextLine(); - Map_Read( root, tokeniser, entityTable, *this ); - tokeniser.release(); -} -void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream ) const { - TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); - writer.writeToken( "Version" ); - writer.writeInteger( MapVersion() ); - writer.nextLine(); - Map_Write( root, traverse, writer, false ); - writer.release(); -} + typedef MapFormat Type; + + STRING_CONSTANT(Name, "mapquake4"); + + UINT_CONSTANT(MapVersion, 3); + + MapQuake4API(MapDoom3Dependencies &dependencies) : m_dependencies(dependencies) + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake4 maps", "*.map")); + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake4 region", "*.reg")); + } + + MapFormat *getTable() + { + return this; + } + + scene::Node &parsePrimitive(Tokeniser &tokeniser) const + { + const char *primitive = tokeniser.getToken(); + if (primitive != 0) { + if (string_equal(primitive, "patchDef3")) { + return m_dependencies.getPatchDoom3().createPatch(); + } else if (string_equal(primitive, "patchDef2")) { + return m_dependencies.getPatchDef2Doom3().createPatch(); + } else if (string_equal(primitive, "brushDef3")) { + return m_dependencies.getBrushDoom3().createBrush(); + } + } + + Tokeniser_unexpectedError(tokeniser, primitive, "#quake4-primitive"); + return g_nullNode; + } + + void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const + { + Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); + tokeniser.nextLine(); + if (!Tokeniser_parseToken(tokeniser, "Version")) { + return; + } + std::size_t version; + if (!Tokeniser_getSize(tokeniser, version)) { + return; + } + if (version != MapVersion()) { + globalErrorStream() << "Quake 4 map version " << MapVersion() << " supported, version is " + << Unsigned(version) << "\n"; + return; + } + tokeniser.nextLine(); + Map_Read(root, tokeniser, entityTable, *this); + tokeniser.release(); + } + + void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream) const + { + TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); + writer.writeToken("Version"); + writer.writeInteger(MapVersion()); + writer.nextLine(); + Map_Write(root, traverse, writer, false); + writer.release(); + } }; typedef SingletonModule< - MapQuake4API, - MapDoom3Dependencies, - DependenciesAPIConstructor - > -MapQuake4Module; + MapQuake4API, + MapDoom3Dependencies, + DependenciesAPIConstructor +> + MapQuake4Module; MapQuake4Module g_MapQuake4Module; class MapDependencies : - public GlobalRadiantModuleRef, - public GlobalBrushModuleRef, - public GlobalPatchModuleRef, - public GlobalFiletypesModuleRef, - public GlobalScripLibModuleRef, - public GlobalEntityClassManagerModuleRef, - public GlobalSceneGraphModuleRef -{ + public GlobalRadiantModuleRef, + public GlobalBrushModuleRef, + public GlobalPatchModuleRef, + public GlobalFiletypesModuleRef, + public GlobalScripLibModuleRef, + public GlobalEntityClassManagerModuleRef, + public GlobalSceneGraphModuleRef { public: -MapDependencies() : - GlobalBrushModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "brushtypes" ) ), - GlobalPatchModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "patchtypes" ) ), - GlobalEntityClassManagerModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entityclass" ) ){ -} + MapDependencies() : + GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")), + GlobalPatchModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("patchtypes")), + GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass")) + { + } }; -class MapQ3API : public TypeSystemRef, public MapFormat, public PrimitiveParser -{ -mutable bool detectedFormat; +class MapQ3API : public TypeSystemRef, public MapFormat, public PrimitiveParser { + mutable bool detectedFormat; public: -typedef MapFormat Type; -STRING_CONSTANT( Name, "mapq3" ); - -MapQ3API(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake3 maps", "*.map", true, true, true ) ); - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake3 region", "*.reg", true, true, true ) ); - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake3 compiled maps", "*.bsp", false, true, false ) ); -} -MapFormat* getTable(){ - return this; -} - -scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { - const char* primitive = tokeniser.getToken(); - if ( primitive != 0 ) { - if ( string_equal( primitive, "patchDef2" ) ) { - return GlobalPatchModule::getTable().createPatch(); - } - if ( GlobalBrushModule::getTable().useAlternativeTextureProjection() ) { - if ( string_equal( primitive, "brushDef" ) ) { - detectedFormat = true; - return GlobalBrushModule::getTable().createBrush(); - } - else if ( !detectedFormat && string_equal( primitive, "(" ) ) { - detectedFormat = true; - wrongFormat = true; - Tokeniser_unexpectedError( tokeniser, primitive, "#quake3-switch-to-texdef" ); - return g_nullNode; - } - } - else - { - if ( string_equal( primitive, "(" ) ) { - detectedFormat = true; - tokeniser.ungetToken(); // ( - return GlobalBrushModule::getTable().createBrush(); - } - else if ( !detectedFormat && string_equal( primitive, "brushDef" ) ) { - detectedFormat = true; - wrongFormat = true; - Tokeniser_unexpectedError( tokeniser, primitive, "#quake3-switch-to-brush-primitives" ); - return g_nullNode; - } - } - } - - Tokeniser_unexpectedError( tokeniser, primitive, "#quake3-primitive" ); - return g_nullNode; -} - -void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { - detectedFormat = false; - wrongFormat = false; - Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); - Map_Read( root, tokeniser, entityTable, *this ); - tokeniser.release(); -} -void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream ) const { - TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); - Map_Write( root, traverse, writer, false ); - writer.release(); -} + typedef MapFormat Type; + + STRING_CONSTANT(Name, "mapq3"); + + MapQ3API() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), + filetype_t("quake3 maps", "*.map", true, true, true)); + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), + filetype_t("quake3 region", "*.reg", true, true, true)); + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), + filetype_t("quake3 compiled maps", "*.bsp", false, true, false)); + } + + MapFormat *getTable() + { + return this; + } + + scene::Node &parsePrimitive(Tokeniser &tokeniser) const + { + const char *primitive = tokeniser.getToken(); + if (primitive != 0) { + if (string_equal(primitive, "patchDef2")) { + return GlobalPatchModule::getTable().createPatch(); + } + if (GlobalBrushModule::getTable().useAlternativeTextureProjection()) { + if (string_equal(primitive, "brushDef")) { + detectedFormat = true; + return GlobalBrushModule::getTable().createBrush(); + } else if (!detectedFormat && string_equal(primitive, "(")) { + detectedFormat = true; + wrongFormat = true; + Tokeniser_unexpectedError(tokeniser, primitive, "#quake3-switch-to-texdef"); + return g_nullNode; + } + } else { + if (string_equal(primitive, "(")) { + detectedFormat = true; + tokeniser.ungetToken(); // ( + return GlobalBrushModule::getTable().createBrush(); + } else if (!detectedFormat && string_equal(primitive, "brushDef")) { + detectedFormat = true; + wrongFormat = true; + Tokeniser_unexpectedError(tokeniser, primitive, "#quake3-switch-to-brush-primitives"); + return g_nullNode; + } + } + } + + Tokeniser_unexpectedError(tokeniser, primitive, "#quake3-primitive"); + return g_nullNode; + } + + void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const + { + detectedFormat = false; + wrongFormat = false; + Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); + Map_Read(root, tokeniser, entityTable, *this); + tokeniser.release(); + } + + void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream) const + { + TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); + Map_Write(root, traverse, writer, false); + writer.release(); + } }; typedef SingletonModule MapQ3Module; @@ -297,42 +325,50 @@ typedef SingletonModule MapQ3Module; MapQ3Module g_MapQ3Module; -class MapQ1API : public TypeSystemRef, public MapFormat, public PrimitiveParser -{ +class MapQ1API : public TypeSystemRef, public MapFormat, public PrimitiveParser { public: -typedef MapFormat Type; -STRING_CONSTANT( Name, "mapq1" ); - -MapQ1API(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake maps", "*.map" ) ); - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake region", "*.reg" ) ); -} -MapFormat* getTable(){ - return this; -} - -scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { - const char* primitive = tokeniser.getToken(); - if ( primitive != 0 ) { - if ( string_equal( primitive, "(" ) ) { - tokeniser.ungetToken(); // ( - return GlobalBrushModule::getTable().createBrush(); - } - } - - Tokeniser_unexpectedError( tokeniser, primitive, "#quake-primitive" ); - return g_nullNode; -} -void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { - Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); - Map_Read( root, tokeniser, entityTable, *this ); - tokeniser.release(); -} -void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream ) const { - TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); - Map_Write( root, traverse, writer, true ); - writer.release(); -} + typedef MapFormat Type; + + STRING_CONSTANT(Name, "mapq1"); + + MapQ1API() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake maps", "*.map")); + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake region", "*.reg")); + } + + MapFormat *getTable() + { + return this; + } + + scene::Node &parsePrimitive(Tokeniser &tokeniser) const + { + const char *primitive = tokeniser.getToken(); + if (primitive != 0) { + if (string_equal(primitive, "(")) { + tokeniser.ungetToken(); // ( + return GlobalBrushModule::getTable().createBrush(); + } + } + + Tokeniser_unexpectedError(tokeniser, primitive, "#quake-primitive"); + return g_nullNode; + } + + void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const + { + Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); + Map_Read(root, tokeniser, entityTable, *this); + tokeniser.release(); + } + + void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream) const + { + TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); + Map_Write(root, traverse, writer, true); + writer.release(); + } }; typedef SingletonModule MapQ1Module; @@ -340,42 +376,50 @@ typedef SingletonModule MapQ1Module; MapQ1Module g_MapQ1Module; -class MapHalfLifeAPI : public TypeSystemRef, public MapFormat, public PrimitiveParser -{ +class MapHalfLifeAPI : public TypeSystemRef, public MapFormat, public PrimitiveParser { public: -typedef MapFormat Type; -STRING_CONSTANT( Name, "maphl" ); - -MapHalfLifeAPI(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "half-life maps", "*.map" ) ); - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "half-life region", "*.reg" ) ); -} -MapFormat* getTable(){ - return this; -} - -scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { - const char* primitive = tokeniser.getToken(); - if ( primitive != 0 ) { - if ( string_equal( primitive, "(" ) ) { - tokeniser.ungetToken(); // ( - return GlobalBrushModule::getTable().createBrush(); - } - } - - Tokeniser_unexpectedError( tokeniser, primitive, "#halflife-primitive" ); - return g_nullNode; -} -void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { - Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); - Map_Read( root, tokeniser, entityTable, *this ); - tokeniser.release(); -} -void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream ) const { - TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); - Map_Write( root, traverse, writer, true ); - writer.release(); -} + typedef MapFormat Type; + + STRING_CONSTANT(Name, "maphl"); + + MapHalfLifeAPI() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("half-life maps", "*.map")); + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("half-life region", "*.reg")); + } + + MapFormat *getTable() + { + return this; + } + + scene::Node &parsePrimitive(Tokeniser &tokeniser) const + { + const char *primitive = tokeniser.getToken(); + if (primitive != 0) { + if (string_equal(primitive, "(")) { + tokeniser.ungetToken(); // ( + return GlobalBrushModule::getTable().createBrush(); + } + } + + Tokeniser_unexpectedError(tokeniser, primitive, "#halflife-primitive"); + return g_nullNode; + } + + void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const + { + Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); + Map_Read(root, tokeniser, entityTable, *this); + tokeniser.release(); + } + + void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream) const + { + TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); + Map_Write(root, traverse, writer, true); + writer.release(); + } }; typedef SingletonModule MapHalfLifeModule; @@ -383,41 +427,50 @@ typedef SingletonModule MapHalfLifeModule; MapHalfLifeModule g_MapHalfLifeModule; -class MapQ2API : public TypeSystemRef, public MapFormat, public PrimitiveParser -{ +class MapQ2API : public TypeSystemRef, public MapFormat, public PrimitiveParser { public: -typedef MapFormat Type; -STRING_CONSTANT( Name, "mapq2" ); - -MapQ2API(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake2 maps", "*.map" ) ); - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake2 region", "*.reg" ) ); -} -MapFormat* getTable(){ - return this; -} -scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { - const char* primitive = tokeniser.getToken(); - if ( primitive != 0 ) { - if ( string_equal( primitive, "(" ) ) { - tokeniser.ungetToken(); // ( - return GlobalBrushModule::getTable().createBrush(); - } - } - - Tokeniser_unexpectedError( tokeniser, primitive, "#quake2-primitive" ); - return g_nullNode; -} -void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { - Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); - Map_Read( root, tokeniser, entityTable, *this ); - tokeniser.release(); -} -void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream ) const { - TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); - Map_Write( root, traverse, writer, true ); - writer.release(); -} + typedef MapFormat Type; + + STRING_CONSTANT(Name, "mapq2"); + + MapQ2API() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake2 maps", "*.map")); + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake2 region", "*.reg")); + } + + MapFormat *getTable() + { + return this; + } + + scene::Node &parsePrimitive(Tokeniser &tokeniser) const + { + const char *primitive = tokeniser.getToken(); + if (primitive != 0) { + if (string_equal(primitive, "(")) { + tokeniser.ungetToken(); // ( + return GlobalBrushModule::getTable().createBrush(); + } + } + + Tokeniser_unexpectedError(tokeniser, primitive, "#quake2-primitive"); + return g_nullNode; + } + + void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const + { + Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); + Map_Read(root, tokeniser, entityTable, *this); + tokeniser.release(); + } + + void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream) const + { + TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); + Map_Write(root, traverse, writer, true); + writer.release(); + } }; typedef SingletonModule MapQ2Module; @@ -425,78 +478,89 @@ typedef SingletonModule MapQ2Module; MapQ2Module g_MapQ2Module; - const char *PARSE_ERROR = "error parsing VMF"; -inline void parseToken( Tokeniser& tokeniser, const char* token ){ - ASSERT_MESSAGE( Tokeniser_parseToken( tokeniser, token ), "error parsing vmf: token not found: " << makeQuoted( token ) ); +inline void parseToken(Tokeniser &tokeniser, const char *token) +{ + ASSERT_MESSAGE(Tokeniser_parseToken(tokeniser, token), "error parsing vmf: token not found: " << makeQuoted(token)); } #include "generic/arrayrange.h" class VMFBlock; + typedef ArrayConstRange VMFBlockArrayRange; -class VMFBlock -{ +class VMFBlock { public: -const char* m_name; -VMFBlockArrayRange m_children; -typedef const VMFBlock Value; - -VMFBlock( const char* name, VMFBlockArrayRange children = VMFBlockArrayRange( 0, 0 ) ) : m_name( name ), m_children( children ){ -} -const char* name() const { - return m_name; -} -typedef Value* const_iterator; -const_iterator begin() const { - return m_children.first; -} -const_iterator end() const { - return m_children.last; -} + const char *m_name; + VMFBlockArrayRange m_children; + typedef const VMFBlock Value; + + VMFBlock(const char *name, VMFBlockArrayRange children = VMFBlockArrayRange(0, 0)) : m_name(name), + m_children(children) + { + } + + const char *name() const + { + return m_name; + } + + typedef Value *const_iterator; + + const_iterator begin() const + { + return m_children.first; + } + + const_iterator end() const + { + return m_children.last; + } }; -const VMFBlock c_vmfNormals( "normals" ); -const VMFBlock c_vmfDistances( "distances" ); -const VMFBlock c_vmfOffsets( "offsets" ); -const VMFBlock c_vmfOffsetNormals( "offset_normals" ); -const VMFBlock c_vmfAlphas( "alphas" ); -const VMFBlock c_vmfTriangleTags( "triangle_tags" ); -const VMFBlock c_vmfAllowedVerts( "allowed_verts" ); -const VMFBlock c_vmfDispInfoChildren[] = { c_vmfNormals, c_vmfDistances, c_vmfOffsets, c_vmfOffsetNormals, c_vmfAlphas, c_vmfTriangleTags, c_vmfAllowedVerts }; -const VMFBlock c_vmfDispInfo( "dispinfo", ARRAY_RANGE( c_vmfDispInfoChildren ) ); -const VMFBlock c_vmfSideChildren[] = { c_vmfDispInfo }; -const VMFBlock c_vmfSide( "side", ARRAY_RANGE( c_vmfSideChildren ) ); -const VMFBlock c_vmfEditor( "editor" ); -const VMFBlock c_vmfVersionInfo( "versioninfo" ); -const VMFBlock c_vmfViewSettings( "viewsettings" ); -const VMFBlock c_vmfCordon( "cordon" ); -const VMFBlock c_vmfGroupChildren[] = { c_vmfEditor }; -const VMFBlock c_vmfGroup( "group", ARRAY_RANGE( c_vmfGroupChildren ) ); -const VMFBlock c_vmfCamera( "camera" ); -const VMFBlock c_vmfCamerasChildren[] = { c_vmfCamera }; -const VMFBlock c_vmfCameras( "cameras", ARRAY_RANGE( c_vmfCamerasChildren ) ); -VMFBlock c_vmfVisGroup( "visgroup" ); -VMFBlock c_vmfVisGroups( "visgroups", VMFBlockArrayRange( &c_vmfVisGroup, &c_vmfVisGroup + 1 ) ); -const VMFBlock c_vmfSolidChildren[] = { c_vmfSide, c_vmfEditor }; -const VMFBlock c_vmfSolid( "solid", ARRAY_RANGE( c_vmfSolidChildren ) ); -const VMFBlock c_vmfConnections( "connections" ); -const VMFBlock c_vmfEntityChildren[] = { c_vmfEditor, c_vmfSolid, c_vmfGroup, c_vmfConnections }; -const VMFBlock c_vmfEntity( "entity", ARRAY_RANGE( c_vmfEntityChildren ) ); -const VMFBlock c_vmfWorldChildren[] = { c_vmfEditor, c_vmfSolid, c_vmfGroup }; -const VMFBlock c_vmfWorld( "world", ARRAY_RANGE( c_vmfWorldChildren ) ); -const VMFBlock c_vmfRootChildren[] = { c_vmfVersionInfo, c_vmfViewSettings, c_vmfVisGroups, c_vmfWorld, c_vmfEntity, c_vmfCameras, c_vmfCordon }; -const VMFBlock c_vmfRoot( "", ARRAY_RANGE( c_vmfRootChildren ) ); - -class VMFInit -{ +const VMFBlock c_vmfNormals("normals"); +const VMFBlock c_vmfDistances("distances"); +const VMFBlock c_vmfOffsets("offsets"); +const VMFBlock c_vmfOffsetNormals("offset_normals"); +const VMFBlock c_vmfAlphas("alphas"); +const VMFBlock c_vmfTriangleTags("triangle_tags"); +const VMFBlock c_vmfAllowedVerts("allowed_verts"); +const VMFBlock c_vmfDispInfoChildren[] = {c_vmfNormals, c_vmfDistances, c_vmfOffsets, c_vmfOffsetNormals, c_vmfAlphas, + c_vmfTriangleTags, c_vmfAllowedVerts}; +const VMFBlock c_vmfDispInfo("dispinfo", ARRAY_RANGE(c_vmfDispInfoChildren)); +const VMFBlock c_vmfSideChildren[] = {c_vmfDispInfo}; +const VMFBlock c_vmfSide("side", ARRAY_RANGE(c_vmfSideChildren)); +const VMFBlock c_vmfEditor("editor"); +const VMFBlock c_vmfVersionInfo("versioninfo"); +const VMFBlock c_vmfViewSettings("viewsettings"); +const VMFBlock c_vmfCordon("cordon"); +const VMFBlock c_vmfGroupChildren[] = {c_vmfEditor}; +const VMFBlock c_vmfGroup("group", ARRAY_RANGE(c_vmfGroupChildren)); +const VMFBlock c_vmfCamera("camera"); +const VMFBlock c_vmfCamerasChildren[] = {c_vmfCamera}; +const VMFBlock c_vmfCameras("cameras", ARRAY_RANGE(c_vmfCamerasChildren)); +VMFBlock c_vmfVisGroup("visgroup"); +VMFBlock c_vmfVisGroups("visgroups", VMFBlockArrayRange(&c_vmfVisGroup, &c_vmfVisGroup + 1)); +const VMFBlock c_vmfSolidChildren[] = {c_vmfSide, c_vmfEditor}; +const VMFBlock c_vmfSolid("solid", ARRAY_RANGE(c_vmfSolidChildren)); +const VMFBlock c_vmfConnections("connections"); +const VMFBlock c_vmfEntityChildren[] = {c_vmfEditor, c_vmfSolid, c_vmfGroup, c_vmfConnections}; +const VMFBlock c_vmfEntity("entity", ARRAY_RANGE(c_vmfEntityChildren)); +const VMFBlock c_vmfWorldChildren[] = {c_vmfEditor, c_vmfSolid, c_vmfGroup}; +const VMFBlock c_vmfWorld("world", ARRAY_RANGE(c_vmfWorldChildren)); +const VMFBlock c_vmfRootChildren[] = {c_vmfVersionInfo, c_vmfViewSettings, c_vmfVisGroups, c_vmfWorld, c_vmfEntity, + c_vmfCameras, c_vmfCordon}; +const VMFBlock c_vmfRoot("", ARRAY_RANGE(c_vmfRootChildren)); + +class VMFInit { public: -VMFInit(){ - c_vmfVisGroup.m_children = VMFBlockArrayRange( &c_vmfVisGroup, &c_vmfVisGroup + 1 ); -} + VMFInit() + { + c_vmfVisGroup.m_children = VMFBlockArrayRange(&c_vmfVisGroup, &c_vmfVisGroup + 1); + } }; VMFInit g_VMFInit; @@ -504,76 +568,82 @@ VMFInit g_VMFInit; int g_vmf_entities; int g_vmf_brushes; -inline VMFBlock::const_iterator VMFBlock_find( const VMFBlock& block, const char* name ){ - for ( VMFBlock::const_iterator i = block.begin(); i != block.end(); ++i ) - { - if ( string_equal( name, ( *i ).name() ) ) { - return i; - } - } - return block.end(); -} - -void VMF_parseBlock( Tokeniser& tokeniser, const VMFBlock& block ){ - for (;; ) - { - const char* key = tokeniser.getToken(); - if ( key == 0 || string_equal( key, "}" ) ) { - tokeniser.ungetToken(); - break; - } - CopiedString tmp( key ); - tokeniser.nextLine(); - const char* value = tokeniser.getToken(); - tokeniser.nextLine(); - if ( string_equal( value, "{" ) ) { - VMFBlock::const_iterator i = VMFBlock_find( block, tmp.c_str() ); - ASSERT_MESSAGE( i != block.end(), "error parsing vmf block " << makeQuoted( block.name() ) << ": unknown block: " << makeQuoted( tmp.c_str() ) ); - if ( string_equal( tmp.c_str(), "solid" ) ) { - ++g_vmf_brushes; - } - else if ( string_equal( tmp.c_str(), "entity" ) || string_equal( tmp.c_str(), "world" ) ) { - ++g_vmf_entities; - } - VMF_parseBlock( tokeniser, *i ); - parseToken( tokeniser, "}" ); - tokeniser.nextLine(); - } - else - { - // was a pair - } - } -} - -void VMF_Read( scene::Node& root, Tokeniser& tokeniser, EntityCreator& entityTable ){ - g_vmf_entities = g_vmf_brushes = 0; - VMF_parseBlock( tokeniser, c_vmfRoot ); - globalOutputStream() << g_vmf_entities << " entities\n"; - globalOutputStream() << g_vmf_brushes << " brushes\n"; +inline VMFBlock::const_iterator VMFBlock_find(const VMFBlock &block, const char *name) +{ + for (VMFBlock::const_iterator i = block.begin(); i != block.end(); ++i) { + if (string_equal(name, (*i).name())) { + return i; + } + } + return block.end(); } -class MapVMFAPI : public TypeSystemRef, public MapFormat +void VMF_parseBlock(Tokeniser &tokeniser, const VMFBlock &block) { -public: -typedef MapFormat Type; -STRING_CONSTANT( Name, "mapvmf" ); - -MapVMFAPI(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "vmf maps", "*.vmf" ) ); - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "vmf region", "*.reg" ) ); -} -MapFormat* getTable(){ - return this; + for (;;) { + const char *key = tokeniser.getToken(); + if (key == 0 || string_equal(key, "}")) { + tokeniser.ungetToken(); + break; + } + CopiedString tmp(key); + tokeniser.nextLine(); + const char *value = tokeniser.getToken(); + tokeniser.nextLine(); + if (string_equal(value, "{")) { + VMFBlock::const_iterator i = VMFBlock_find(block, tmp.c_str()); + ASSERT_MESSAGE(i != block.end(), + "error parsing vmf block " << makeQuoted(block.name()) << ": unknown block: " + << makeQuoted(tmp.c_str())); + if (string_equal(tmp.c_str(), "solid")) { + ++g_vmf_brushes; + } else if (string_equal(tmp.c_str(), "entity") || string_equal(tmp.c_str(), "world")) { + ++g_vmf_entities; + } + VMF_parseBlock(tokeniser, *i); + parseToken(tokeniser, "}"); + tokeniser.nextLine(); + } else { + // was a pair + } + } +} + +void VMF_Read(scene::Node &root, Tokeniser &tokeniser, EntityCreator &entityTable) +{ + g_vmf_entities = g_vmf_brushes = 0; + VMF_parseBlock(tokeniser, c_vmfRoot); + globalOutputStream() << g_vmf_entities << " entities\n"; + globalOutputStream() << g_vmf_brushes << " brushes\n"; } -void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { - Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); - VMF_Read( root, tokeniser, entityTable ); - tokeniser.release(); -} -void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream ) const { -} +class MapVMFAPI : public TypeSystemRef, public MapFormat { +public: + typedef MapFormat Type; + + STRING_CONSTANT(Name, "mapvmf"); + + MapVMFAPI() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("vmf maps", "*.vmf")); + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("vmf region", "*.reg")); + } + + MapFormat *getTable() + { + return this; + } + + void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const + { + Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); + VMF_Read(root, tokeniser, entityTable); + tokeniser.release(); + } + + void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream) const + { + } }; typedef SingletonModule MapVMFModule; @@ -581,15 +651,15 @@ typedef SingletonModule MapVMFModule; MapVMFModule g_MapVMFModule; - -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); - - g_MapDoom3Module.selfRegister(); - g_MapQuake4Module.selfRegister(); - g_MapQ3Module.selfRegister(); - g_MapQ1Module.selfRegister(); - g_MapQ2Module.selfRegister(); - g_MapHalfLifeModule.selfRegister(); - g_MapVMFModule.selfRegister(); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); + + g_MapDoom3Module.selfRegister(); + g_MapQuake4Module.selfRegister(); + g_MapQ3Module.selfRegister(); + g_MapQ1Module.selfRegister(); + g_MapQ2Module.selfRegister(); + g_MapHalfLifeModule.selfRegister(); + g_MapVMFModule.selfRegister(); } diff --git a/plugins/mapq3/write.cpp b/plugins/mapq3/write.cpp index 7a954586..f37b5b03 100644 --- a/plugins/mapq3/write.cpp +++ b/plugins/mapq3/write.cpp @@ -25,8 +25,9 @@ #include "iscriplib.h" #include "scenelib.h" -inline MapExporter* Node_getMapExporter( scene::Node& node ){ - return NodeTypeCast::cast( node ); +inline MapExporter *Node_getMapExporter(scene::Node &node) +{ + return NodeTypeCast::cast(node); } @@ -34,79 +35,84 @@ static std::size_t g_count_entities; static std::size_t g_count_brushes; -void Entity_ExportTokens( const Entity& entity, TokenWriter& writer ){ - g_count_brushes = 0; - - class WriteKeyValue : public Entity::Visitor - { - TokenWriter& m_writer; -public: - WriteKeyValue( TokenWriter& writer ) - : m_writer( writer ){ - } - - void visit( const char* key, const char* value ){ - m_writer.writeString( key ); - m_writer.writeString( value ); - m_writer.nextLine(); - } - - } visitor( writer ); - - entity.forEachKeyValue( visitor ); +void Entity_ExportTokens(const Entity &entity, TokenWriter &writer) +{ + g_count_brushes = 0; + + class WriteKeyValue : public Entity::Visitor { + TokenWriter &m_writer; + public: + WriteKeyValue(TokenWriter &writer) + : m_writer(writer) + { + } + + void visit(const char *key, const char *value) + { + m_writer.writeString(key); + m_writer.writeString(value); + m_writer.nextLine(); + } + + } visitor(writer); + + entity.forEachKeyValue(visitor); } -class WriteTokensWalker : public scene::Traversable::Walker -{ -mutable Stack m_stack; -TokenWriter& m_writer; -bool m_ignorePatches; +class WriteTokensWalker : public scene::Traversable::Walker { + mutable Stack m_stack; + TokenWriter &m_writer; + bool m_ignorePatches; public: -WriteTokensWalker( TokenWriter& writer, bool ignorePatches ) - : m_writer( writer ), m_ignorePatches( ignorePatches ){ -} -bool pre( scene::Node& node ) const { - m_stack.push( false ); - - Entity* entity = Node_getEntity( node ); - if ( entity != 0 ) { - m_writer.writeToken( "//" ); - m_writer.writeToken( "entity" ); - m_writer.writeUnsigned( g_count_entities++ ); - m_writer.nextLine(); - - m_writer.writeToken( "{" ); - m_writer.nextLine(); - m_stack.top() = true; - - Entity_ExportTokens( *entity, m_writer ); - } - else - { - MapExporter* exporter = Node_getMapExporter( node ); - if ( exporter != 0 - && !( m_ignorePatches && Node_isPatch( node ) ) ) { - m_writer.writeToken( "//" ); - m_writer.writeToken( "brush" ); - m_writer.writeUnsigned( g_count_brushes++ ); - m_writer.nextLine(); - - exporter->exportTokens( m_writer ); - } - } - - return true; -} -void post( scene::Node& node ) const { - if ( m_stack.top() ) { - m_writer.writeToken( "}" ); - m_writer.nextLine(); - } - m_stack.pop(); -} + WriteTokensWalker(TokenWriter &writer, bool ignorePatches) + : m_writer(writer), m_ignorePatches(ignorePatches) + { + } + + bool pre(scene::Node &node) const + { + m_stack.push(false); + + Entity *entity = Node_getEntity(node); + if (entity != 0) { + m_writer.writeToken("//"); + m_writer.writeToken("entity"); + m_writer.writeUnsigned(g_count_entities++); + m_writer.nextLine(); + + m_writer.writeToken("{"); + m_writer.nextLine(); + m_stack.top() = true; + + Entity_ExportTokens(*entity, m_writer); + } else { + MapExporter *exporter = Node_getMapExporter(node); + if (exporter != 0 + && !(m_ignorePatches && Node_isPatch(node))) { + m_writer.writeToken("//"); + m_writer.writeToken("brush"); + m_writer.writeUnsigned(g_count_brushes++); + m_writer.nextLine(); + + exporter->exportTokens(m_writer); + } + } + + return true; + } + + void post(scene::Node &node) const + { + if (m_stack.top()) { + m_writer.writeToken("}"); + m_writer.nextLine(); + } + m_stack.pop(); + } }; -void Map_Write( scene::Node& root, GraphTraversalFunc traverse, TokenWriter& writer, bool ignorePatches ){ - g_count_entities = 0; - traverse( root, WriteTokensWalker( writer, ignorePatches ) ); +void Map_Write(scene::Node &root, GraphTraversalFunc traverse, TokenWriter &writer, bool ignorePatches) +{ + g_count_entities = 0; + traverse(root, WriteTokensWalker(writer, ignorePatches)); } diff --git a/plugins/mapq3/write.h b/plugins/mapq3/write.h index e934ef64..0fbfce0a 100644 --- a/plugins/mapq3/write.h +++ b/plugins/mapq3/write.h @@ -24,6 +24,6 @@ #include "imap.h" -void Map_Write( scene::Node& root, GraphTraversalFunc traverse, TokenWriter& writer, bool ignorePatches ); +void Map_Write(scene::Node &root, GraphTraversalFunc traverse, TokenWriter &writer, bool ignorePatches); #endif diff --git a/plugins/mapxml/plugin.cpp b/plugins/mapxml/plugin.cpp index b144a415..fb850543 100644 --- a/plugins/mapxml/plugin.cpp +++ b/plugins/mapxml/plugin.cpp @@ -33,51 +33,63 @@ class MapXMLDependencies : - public GlobalRadiantModuleRef, - public GlobalBrushModuleRef, - public GlobalFiletypesModuleRef, - public GlobalEntityClassManagerModuleRef, - public GlobalSceneGraphModuleRef -{ -PatchModuleRef m_patchDef2Doom3Module; -PatchModuleRef m_patchDoom3Module; + public GlobalRadiantModuleRef, + public GlobalBrushModuleRef, + public GlobalFiletypesModuleRef, + public GlobalEntityClassManagerModuleRef, + public GlobalSceneGraphModuleRef { + PatchModuleRef m_patchDef2Doom3Module; + PatchModuleRef m_patchDoom3Module; public: -MapXMLDependencies() : - GlobalBrushModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "brushtypes" ) ), - GlobalEntityClassManagerModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entityclass" ) ), - m_patchDef2Doom3Module( "def2doom3" ), - m_patchDoom3Module( "doom3" ){ -} -BrushCreator& getBrushDoom3(){ - return GlobalBrushModule::getTable(); -} -PatchCreator& getPatchDoom3(){ - return *m_patchDoom3Module.getTable(); -} -PatchCreator& getPatchDef2Doom3(){ - return *m_patchDef2Doom3Module.getTable(); -} + MapXMLDependencies() : + GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")), + GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass")), + m_patchDef2Doom3Module("def2doom3"), + m_patchDoom3Module("doom3") + { + } + + BrushCreator &getBrushDoom3() + { + return GlobalBrushModule::getTable(); + } + + PatchCreator &getPatchDoom3() + { + return *m_patchDoom3Module.getTable(); + } + + PatchCreator &getPatchDef2Doom3() + { + return *m_patchDef2Doom3Module.getTable(); + } }; -class MapXMLAPI : public TypeSystemRef, public MapFormat -{ +class MapXMLAPI : public TypeSystemRef, public MapFormat { public: -typedef MapFormat Type; -STRING_CONSTANT( Name, "xmldoom3" ); + typedef MapFormat Type; -MapXMLAPI(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "xml doom3 maps", "*.xmap" ) ); -} -MapFormat* getTable(){ - return this; -} + STRING_CONSTANT(Name, "xmldoom3"); -void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { - Map_Read( root, inputStream, entityTable ); -} -void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream ) const { - Map_Write( root, traverse, outputStream ); -} + MapXMLAPI() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("xml doom3 maps", "*.xmap")); + } + + MapFormat *getTable() + { + return this; + } + + void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const + { + Map_Read(root, inputStream, entityTable); + } + + void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream) const + { + Map_Write(root, traverse, outputStream); + } }; typedef SingletonModule MapXMLModule; @@ -85,12 +97,12 @@ typedef SingletonModule MapXMLModule; MapXMLModule g_MapXMLModule; +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + GlobalErrorStream::instance().setOutputStream(server.getErrorStream()); + GlobalOutputStream::instance().setOutputStream(server.getOutputStream()); + GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler()); + GlobalModuleServer::instance().set(server); -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - GlobalErrorStream::instance().setOutputStream( server.getErrorStream() ); - GlobalOutputStream::instance().setOutputStream( server.getOutputStream() ); - GlobalDebugMessageHandler::instance().setHandler( server.getDebugMessageHandler() ); - GlobalModuleServer::instance().set( server ); - - g_MapXMLModule.selfRegister(); + g_MapXMLModule.selfRegister(); } diff --git a/plugins/mapxml/xmlparse.cpp b/plugins/mapxml/xmlparse.cpp index ab2eb1bf..b26c5766 100644 --- a/plugins/mapxml/xmlparse.cpp +++ b/plugins/mapxml/xmlparse.cpp @@ -42,200 +42,245 @@ const char *PARSE_ERROR = "XML PARSE ERROR"; -inline XMLImporter* Node_getXMLImporter( scene::Node& node ){ - return NodeTypeCast::cast( node ); +inline XMLImporter *Node_getXMLImporter(scene::Node &node) +{ + return NodeTypeCast::cast(node); } -scene::Node& createPrimitive( const char* name ){ - if ( string_equal( name, "brush" ) ) { - return GlobalBrushCreator().createBrush(); - } - else if ( string_equal( name, "patch" ) ) { - return GlobalPatchCreator().createPatch(); - } - - ASSERT_MESSAGE( 0, PARSE_ERROR << ": primitive type not supported: \"" << name << "\"\n" ); - scene::Node* node = 0; - return *node; +scene::Node &createPrimitive(const char *name) +{ + if (string_equal(name, "brush")) { + return GlobalBrushCreator().createBrush(); + } else if (string_equal(name, "patch")) { + return GlobalPatchCreator().createPatch(); + } + + ASSERT_MESSAGE(0, PARSE_ERROR << ": primitive type not supported: \"" << name << "\"\n"); + scene::Node *node = 0; + return *node; } -class TreeXMLImporter : public XMLImporter -{ +class TreeXMLImporter : public XMLImporter { public: -virtual TreeXMLImporter& child() = 0; + virtual TreeXMLImporter &child() = 0; }; -class SubPrimitiveImporter : public TreeXMLImporter -{ -XMLImporter* m_importer; +class SubPrimitiveImporter : public TreeXMLImporter { + XMLImporter *m_importer; public: -SubPrimitiveImporter( XMLImporter* importer ) : m_importer( importer ){ -} -void pushElement( const XMLElement& element ){ - m_importer->pushElement( element ); -} -void popElement( const char* name ){ - m_importer->popElement( name ); -} -std::size_t write( const char* buffer, std::size_t length ){ - return m_importer->write( buffer, length ); -} -SubPrimitiveImporter& child(){ - return *this; -} + SubPrimitiveImporter(XMLImporter *importer) : m_importer(importer) + { + } + + void pushElement(const XMLElement &element) + { + m_importer->pushElement(element); + } + + void popElement(const char *name) + { + m_importer->popElement(name); + } + + std::size_t write(const char *buffer, std::size_t length) + { + return m_importer->write(buffer, length); + } + + SubPrimitiveImporter &child() + { + return *this; + } }; -class PrimitiveImporter : public TreeXMLImporter -{ -scene::Node& m_parent; -XMLImporter* m_importer; -char m_child[sizeof( SubPrimitiveImporter )]; +class PrimitiveImporter : public TreeXMLImporter { + scene::Node &m_parent; + XMLImporter *m_importer; + char m_child[sizeof(SubPrimitiveImporter)]; -SubPrimitiveImporter& subprimitive(){ - return *reinterpret_cast( m_child ); -} -public: -PrimitiveImporter( scene::Node& parent ) : m_parent( parent ), m_importer( 0 ){ -} -void pushElement( const XMLElement& element ){ - if ( string_equal( element.name(), "epair" ) ) { - ASSERT_MESSAGE( string_equal( element.name(), "epair" ), PARSE_ERROR ); - Node_getEntity( m_parent )->setKeyValue( element.attribute( "key" ), element.attribute( "value" ) ); - } - else - { - NodeSmartReference node( createPrimitive( element.name() ) ); - - m_importer = Node_getXMLImporter( node ); - - constructor( subprimitive(), m_importer ); - - m_importer->pushElement( element ); - - Node_getTraversable( m_parent )->insert( node ); - } -} -void popElement( const char* name ){ - if ( string_equal( name, "epair" ) ) { - } - else - { - m_importer->popElement( name ); - - destructor( subprimitive() ); - m_importer = 0; - } -} -std::size_t write( const char* buffer, std::size_t length ){ - return m_importer->write( buffer, length ); -} -TreeXMLImporter& child(){ - return subprimitive(); -} -}; - -class EntityImporter : public TreeXMLImporter -{ -scene::Node& m_parent; -char m_node[sizeof( NodeSmartReference )]; -char m_child[sizeof( PrimitiveImporter )]; -EntityCreator& m_entityTable; - -NodeSmartReference& node(){ - return *reinterpret_cast( m_node ); -} -PrimitiveImporter& primitive(){ - return *reinterpret_cast( m_child ); -} + SubPrimitiveImporter &subprimitive() + { + return *reinterpret_cast( m_child ); + } public: -EntityImporter( scene::Node& parent, EntityCreator& entityTable ) : m_parent( parent ), m_entityTable( entityTable ){ -} -void pushElement( const XMLElement& element ){ - ASSERT_MESSAGE( string_equal( element.name(), "entity" ), PARSE_ERROR ); - constructor( node(), NodeSmartReference( m_entityTable.createEntity( GlobalEntityClassManager().findOrInsert( "", true ) ) ) ); - constructor( primitive(), makeReference( node().get() ) ); -} -void popElement( const char* name ){ - ASSERT_MESSAGE( string_equal( name, "entity" ), PARSE_ERROR ); - NodeSmartReference entity( m_entityTable.createEntity( GlobalEntityClassManager().findOrInsert( Node_getEntity( node() )->getKeyValue( "classname" ), node_is_group( node() ) ) ) ); + PrimitiveImporter(scene::Node &parent) : m_parent(parent), m_importer(0) + { + } + + void pushElement(const XMLElement &element) + { + if (string_equal(element.name(), "epair")) { + ASSERT_MESSAGE(string_equal(element.name(), "epair"), PARSE_ERROR); + Node_getEntity(m_parent)->setKeyValue(element.attribute("key"), element.attribute("value")); + } else { + NodeSmartReference node(createPrimitive(element.name())); + + m_importer = Node_getXMLImporter(node); + + constructor(subprimitive(), m_importer); + + m_importer->pushElement(element); + + Node_getTraversable(m_parent)->insert(node); + } + } + + void popElement(const char *name) + { + if (string_equal(name, "epair")) { + } else { + m_importer->popElement(name); + + destructor(subprimitive()); + m_importer = 0; + } + } + + std::size_t write(const char *buffer, std::size_t length) + { + return m_importer->write(buffer, length); + } + + TreeXMLImporter &child() + { + return subprimitive(); + } +}; - { - EntityCopyingVisitor visitor( *Node_getEntity( entity ) ); - Node_getEntity( node() )->forEachKeyValue( visitor ); - } +class EntityImporter : public TreeXMLImporter { + scene::Node &m_parent; + char m_node[sizeof(NodeSmartReference)]; + char m_child[sizeof(PrimitiveImporter)]; + EntityCreator &m_entityTable; - if ( Node_getTraversable( entity ) != 0 && !Node_getEntity( entity )->getEntityClass().fixedsize ) { - parentBrushes( node(), entity ); - } + NodeSmartReference &node() + { + return *reinterpret_cast( m_node ); + } - Node_getTraversable( m_parent )->insert( entity ); + PrimitiveImporter &primitive() + { + return *reinterpret_cast( m_child ); + } - destructor( primitive() ); - destructor( node() ); -} -std::size_t write( const char* buffer, std::size_t length ){ - return length; -} -TreeXMLImporter& child(){ - return primitive(); -} +public: + EntityImporter(scene::Node &parent, EntityCreator &entityTable) : m_parent(parent), m_entityTable(entityTable) + { + } + + void pushElement(const XMLElement &element) + { + ASSERT_MESSAGE(string_equal(element.name(), "entity"), PARSE_ERROR); + constructor(node(), + NodeSmartReference(m_entityTable.createEntity(GlobalEntityClassManager().findOrInsert("", true)))); + constructor(primitive(), makeReference(node().get())); + } + + void popElement(const char *name) + { + ASSERT_MESSAGE(string_equal(name, "entity"), PARSE_ERROR); + NodeSmartReference entity(m_entityTable.createEntity( + GlobalEntityClassManager().findOrInsert(Node_getEntity(node())->getKeyValue("classname"), + node_is_group(node())))); + + { + EntityCopyingVisitor visitor(*Node_getEntity(entity)); + Node_getEntity(node())->forEachKeyValue(visitor); + } + + if (Node_getTraversable(entity) != 0 && !Node_getEntity(entity)->getEntityClass().fixedsize) { + parentBrushes(node(), entity); + } + + Node_getTraversable(m_parent)->insert(entity); + + destructor(primitive()); + destructor(node()); + } + + std::size_t write(const char *buffer, std::size_t length) + { + return length; + } + + TreeXMLImporter &child() + { + return primitive(); + } }; -class MapDoom3Importer : public TreeXMLImporter -{ -scene::Node& m_root; -char m_child[sizeof( EntityImporter )]; -EntityCreator& m_entityTable; +class MapDoom3Importer : public TreeXMLImporter { + scene::Node &m_root; + char m_child[sizeof(EntityImporter)]; + EntityCreator &m_entityTable; + + EntityImporter &getEntity() + { + return *reinterpret_cast( m_child ); + } -EntityImporter& getEntity(){ - return *reinterpret_cast( m_child ); -} public: -MapDoom3Importer( scene::Node& root, EntityCreator& entityTable ) : m_root( root ), m_entityTable( entityTable ){ -} -void pushElement( const XMLElement& element ){ - ASSERT_MESSAGE( string_equal( element.name(), "mapdoom3" ), PARSE_ERROR ); - constructor( getEntity(), makeReference( m_root ), makeReference( m_entityTable ) ); -} -void popElement( const char* name ){ - ASSERT_MESSAGE( string_equal( name, "mapdoom3" ), PARSE_ERROR ); - destructor( getEntity() ); -} -std::size_t write( const char* data, std::size_t length ){ - return length; -} -TreeXMLImporter& child(){ - return getEntity(); -} + MapDoom3Importer(scene::Node &root, EntityCreator &entityTable) : m_root(root), m_entityTable(entityTable) + { + } + + void pushElement(const XMLElement &element) + { + ASSERT_MESSAGE(string_equal(element.name(), "mapdoom3"), PARSE_ERROR); + constructor(getEntity(), makeReference(m_root), makeReference(m_entityTable)); + } + + void popElement(const char *name) + { + ASSERT_MESSAGE(string_equal(name, "mapdoom3"), PARSE_ERROR); + destructor(getEntity()); + } + + std::size_t write(const char *data, std::size_t length) + { + return length; + } + + TreeXMLImporter &child() + { + return getEntity(); + } }; -class TreeXMLImporterStack : public XMLImporter -{ -std::vector< Reference > m_importers; +class TreeXMLImporterStack : public XMLImporter { + std::vector > m_importers; public: -TreeXMLImporterStack( TreeXMLImporter& importer ){ - m_importers.push_back( makeReference( importer ) ); -} -void pushElement( const XMLElement& element ){ - m_importers.back().get().pushElement( element ); - m_importers.push_back( makeReference( m_importers.back().get().child() ) ); -} -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.end() - 2 ) ).get().write( buffer, length ); -} + TreeXMLImporterStack(TreeXMLImporter &importer) + { + m_importers.push_back(makeReference(importer)); + } + + void pushElement(const XMLElement &element) + { + m_importers.back().get().pushElement(element); + m_importers.push_back(makeReference(m_importers.back().get().child())); + } + + 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.end() - 2)).get().write(buffer, length); + } }; -void Map_Read( scene::Node& root, TextInputStream& in, EntityCreator& entityTable ){ - XMLStreamParser parser( in ); +void Map_Read(scene::Node &root, TextInputStream &in, EntityCreator &entityTable) +{ + XMLStreamParser parser(in); - MapDoom3Importer importer( root, entityTable ); - TreeXMLImporterStack stack( importer ); - parser.exportXML( stack ); + MapDoom3Importer importer(root, entityTable); + TreeXMLImporterStack stack(importer); + parser.exportXML(stack); } diff --git a/plugins/mapxml/xmlparse.h b/plugins/mapxml/xmlparse.h index b14b9671..709c90bc 100644 --- a/plugins/mapxml/xmlparse.h +++ b/plugins/mapxml/xmlparse.h @@ -24,6 +24,6 @@ #include "imap.h" -void Map_Read( scene::Node& root, TextInputStream& in, EntityCreator& entityTable ); +void Map_Read(scene::Node &root, TextInputStream &in, EntityCreator &entityTable); #endif diff --git a/plugins/mapxml/xmlwrite.cpp b/plugins/mapxml/xmlwrite.cpp index 590e6431..62e2a3b7 100644 --- a/plugins/mapxml/xmlwrite.cpp +++ b/plugins/mapxml/xmlwrite.cpp @@ -29,55 +29,59 @@ #include "scenelib.h" #include "entityxml.h" -inline XMLExporter* Node_getXMLExporter( scene::Node& node ){ - return NodeTypeCast::cast( node ); +inline XMLExporter *Node_getXMLExporter(scene::Node &node) +{ + return NodeTypeCast::cast(node); } -class write_all : public scene::Traversable::Walker -{ -XMLImporter& m_importer; +class write_all : public scene::Traversable::Walker { + XMLImporter &m_importer; public: -write_all( XMLImporter& importer ) : m_importer( importer ){ -} -bool pre( scene::Node& node ) const { - Entity* entity = Node_getEntity( node ); - if ( entity != 0 ) { - m_importer.write( "\n", 1 ); - StaticElement element( "entity" ); - m_importer.pushElement( element ); - entity_export exporter( *entity ); - exporter.exportXML( m_importer ); - } - else - { - XMLExporter* exporter = Node_getXMLExporter( node ); - if ( exporter != 0 ) { - m_importer.write( "\n", 1 ); - exporter->exportXML( m_importer ); - m_importer.write( "\n", 1 ); - } - } - return true; -} -void post( scene::Node& node ) const { - if ( Node_getEntity( node ) != 0 ) { - m_importer.write( "\n", 1 ); - m_importer.popElement( "entity" ); - } -} + write_all(XMLImporter &importer) : m_importer(importer) + { + } + + bool pre(scene::Node &node) const + { + Entity *entity = Node_getEntity(node); + if (entity != 0) { + m_importer.write("\n", 1); + StaticElement element("entity"); + m_importer.pushElement(element); + entity_export exporter(*entity); + exporter.exportXML(m_importer); + } else { + XMLExporter *exporter = Node_getXMLExporter(node); + if (exporter != 0) { + m_importer.write("\n", 1); + exporter->exportXML(m_importer); + m_importer.write("\n", 1); + } + } + return true; + } + + void post(scene::Node &node) const + { + if (Node_getEntity(node) != 0) { + m_importer.write("\n", 1); + m_importer.popElement("entity"); + } + } }; -void Map_Write( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& out ){ - XMLStreamWriter writer( out ); - writer.write( "\n", 1 ); - { - StaticElement element( "mapdoom3" ); - writer.pushElement( element ); +void Map_Write(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &out) +{ + XMLStreamWriter writer(out); + writer.write("\n", 1); + { + StaticElement element("mapdoom3"); + writer.pushElement(element); - traverse( root, write_all( writer ) ); + traverse(root, write_all(writer)); - writer.write( "\n", 1 ); - writer.popElement( element.name() ); - } + writer.write("\n", 1); + writer.popElement(element.name()); + } } diff --git a/plugins/mapxml/xmlwrite.h b/plugins/mapxml/xmlwrite.h index fb6c91db..a1a3e664 100644 --- a/plugins/mapxml/xmlwrite.h +++ b/plugins/mapxml/xmlwrite.h @@ -24,6 +24,6 @@ #include "imap.h" -void Map_Write( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& out ); +void Map_Write(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &out); #endif diff --git a/plugins/md3model/ident.h b/plugins/md3model/ident.h index d14eabc2..1806984f 100644 --- a/plugins/md3model/ident.h +++ b/plugins/md3model/ident.h @@ -25,8 +25,9 @@ #include // equality comparison for two 4-byte ident strings -inline bool ident_equal( const unsigned char* ident, const unsigned char* other ){ - return ident[0] == other[0] && ident[1] == other[1] && ident[2] == other[2] && ident[3] == other[3]; +inline bool ident_equal(const unsigned char *ident, const unsigned char *other) +{ + return ident[0] == other[0] && ident[1] == other[1] && ident[2] == other[2] && ident[3] == other[3]; } #endif diff --git a/plugins/md3model/md2.cpp b/plugins/md3model/md2.cpp index e18ef2f6..a6d75fef 100644 --- a/plugins/md3model/md2.cpp +++ b/plugins/md3model/md2.cpp @@ -42,74 +42,74 @@ typedef unsigned char byte; */ const int MD2_NUMVERTEXNORMALS = 162; -const unsigned char MD2_IDENT[4] = { 'I', 'D', 'P', '2', }; +const unsigned char MD2_IDENT[4] = {'I', 'D', 'P', '2',}; const int MD2_VERSION = 8; -const int MD2_MAX_TRIANGLES = 4096; -const int MD2_MAX_VERTS = 2048; -const int MD2_MAX_FRAMES = 512; -const int MD2_MAX_MD2SKINS = 32; -const int MD2_MAX_SKINNAME = 64; +const int MD2_MAX_TRIANGLES = 4096; +const int MD2_MAX_VERTS = 2048; +const int MD2_MAX_FRAMES = 512; +const int MD2_MAX_MD2SKINS = 32; +const int MD2_MAX_SKINNAME = 64; -typedef struct -{ - short s; - short t; +typedef struct { + short s; + short t; } md2St_t; -void istream_read_md2St( PointerInputStream& inputStream, md2St_t& st ){ - st.s = istream_read_int16_le( inputStream ); - st.t = istream_read_int16_le( inputStream ); +void istream_read_md2St(PointerInputStream &inputStream, md2St_t &st) +{ + st.s = istream_read_int16_le(inputStream); + st.t = istream_read_int16_le(inputStream); } -typedef struct -{ - short index_xyz[3]; - short index_st[3]; +typedef struct { + short index_xyz[3]; + short index_st[3]; } md2Triangle_t; -void istream_read_md2Triangle( PointerInputStream& inputStream, md2Triangle_t& triangle ){ - triangle.index_xyz[0] = istream_read_int16_le( inputStream ); - triangle.index_xyz[1] = istream_read_int16_le( inputStream ); - triangle.index_xyz[2] = istream_read_int16_le( inputStream ); - triangle.index_st[0] = istream_read_int16_le( inputStream ); - triangle.index_st[1] = istream_read_int16_le( inputStream ); - triangle.index_st[2] = istream_read_int16_le( inputStream ); +void istream_read_md2Triangle(PointerInputStream &inputStream, md2Triangle_t &triangle) +{ + triangle.index_xyz[0] = istream_read_int16_le(inputStream); + triangle.index_xyz[1] = istream_read_int16_le(inputStream); + triangle.index_xyz[2] = istream_read_int16_le(inputStream); + triangle.index_st[0] = istream_read_int16_le(inputStream); + triangle.index_st[1] = istream_read_int16_le(inputStream); + triangle.index_st[2] = istream_read_int16_le(inputStream); } -typedef struct -{ - byte v[3]; // scaled byte to fit in frame mins/maxs - byte lightnormalindex; +typedef struct { + byte v[3]; // scaled byte to fit in frame mins/maxs + byte lightnormalindex; } md2XyzNormal_t; -void istream_read_md2XyzNormal( PointerInputStream& inputStream, md2XyzNormal_t& xyz ){ - inputStream.read( xyz.v, 3 ); - inputStream.read( &xyz.lightnormalindex, 1 ); +void istream_read_md2XyzNormal(PointerInputStream &inputStream, md2XyzNormal_t &xyz) +{ + inputStream.read(xyz.v, 3); + inputStream.read(&xyz.lightnormalindex, 1); } -const int MD2_XYZNORMAL_V0 = 0; -const int MD2_XYZNORMAL_V1 = 1; -const int MD2_XYZNORMAL_V2 = 2; -const int MD2_XYZNORMAL_LNI = 3; +const int MD2_XYZNORMAL_V0 = 0; +const int MD2_XYZNORMAL_V1 = 1; +const int MD2_XYZNORMAL_V2 = 2; +const int MD2_XYZNORMAL_LNI = 3; const int MD2_XYZNORMAL_SIZE = 4; -typedef struct -{ - float scale[3]; // multiply byte verts by this - float translate[3]; // then add this - char name[16]; // frame name from grabbing - md2XyzNormal_t verts[1]; // variable sized +typedef struct { + float scale[3]; // multiply byte verts by this + float translate[3]; // then add this + char name[16]; // frame name from grabbing + md2XyzNormal_t verts[1]; // variable sized } md2Frame_t; -void istream_read_md2Frame( PointerInputStream& inputStream, md2Frame_t& frame ){ - frame.scale[0] = istream_read_float32_le( inputStream ); - frame.scale[1] = istream_read_float32_le( inputStream ); - frame.scale[2] = istream_read_float32_le( inputStream ); - frame.translate[0] = istream_read_float32_le( inputStream ); - frame.translate[1] = istream_read_float32_le( inputStream ); - frame.translate[2] = istream_read_float32_le( inputStream ); - inputStream.read( reinterpret_cast( frame.name ), 16 ); +void istream_read_md2Frame(PointerInputStream &inputStream, md2Frame_t &frame) +{ + frame.scale[0] = istream_read_float32_le(inputStream); + frame.scale[1] = istream_read_float32_le(inputStream); + frame.scale[2] = istream_read_float32_le(inputStream); + frame.translate[0] = istream_read_float32_le(inputStream); + frame.translate[1] = istream_read_float32_le(inputStream); + frame.translate[2] = istream_read_float32_le(inputStream); + inputStream.read(reinterpret_cast( frame.name ), 16); } @@ -122,174 +122,180 @@ void istream_read_md2Frame( PointerInputStream& inputStream, md2Frame_t& frame ) // and an integer vertex index. -typedef struct -{ - unsigned char ident[4]; - int version; - - int skinwidth; - int skinheight; - int framesize; // byte size of each frame - - int num_skins; - int num_xyz; - int num_st; // greater than num_xyz for seams - int num_tris; - int num_glcmds; // dwords in strip/fan command list - int num_frames; - - int ofs_skins; // each skin is a MAX_SKINNAME string - int ofs_st; // byte offset from start for md2St_t - int ofs_tris; // offset for md2triangle_t - int ofs_frames; // offset for first md2Frame_t - int ofs_glcmds; - int ofs_end; // end of file +typedef struct { + unsigned char ident[4]; + int version; + + int skinwidth; + int skinheight; + int framesize; // byte size of each frame + + int num_skins; + int num_xyz; + int num_st; // greater than num_xyz for seams + int num_tris; + int num_glcmds; // dwords in strip/fan command list + int num_frames; + + int ofs_skins; // each skin is a MAX_SKINNAME string + int ofs_st; // byte offset from start for md2St_t + int ofs_tris; // offset for md2triangle_t + int ofs_frames; // offset for first md2Frame_t + int ofs_glcmds; + int ofs_end; // end of file } md2Header_t; -void istream_read_md2Header( PointerInputStream& inputStream, md2Header_t& header ){ - inputStream.read( header.ident, 4 ); - header.version = istream_read_int32_le( inputStream ); - header.skinwidth = istream_read_int32_le( inputStream ); - header.skinheight = istream_read_int32_le( inputStream ); - header.framesize = istream_read_int32_le( inputStream ); - header.num_skins = istream_read_int32_le( inputStream ); - header.num_xyz = istream_read_int32_le( inputStream ); - header.num_st = istream_read_int32_le( inputStream ); - header.num_tris = istream_read_int32_le( inputStream ); - header.num_glcmds = istream_read_int32_le( inputStream ); - header.num_frames = istream_read_int32_le( inputStream ); - header.ofs_skins = istream_read_int32_le( inputStream ); - header.ofs_st = istream_read_int32_le( inputStream ); - header.ofs_tris = istream_read_int32_le( inputStream ); - header.ofs_frames = istream_read_int32_le( inputStream ); - header.ofs_glcmds = istream_read_int32_le( inputStream ); - header.ofs_end = istream_read_int32_le( inputStream ); +void istream_read_md2Header(PointerInputStream &inputStream, md2Header_t &header) +{ + inputStream.read(header.ident, 4); + header.version = istream_read_int32_le(inputStream); + header.skinwidth = istream_read_int32_le(inputStream); + header.skinheight = istream_read_int32_le(inputStream); + header.framesize = istream_read_int32_le(inputStream); + header.num_skins = istream_read_int32_le(inputStream); + header.num_xyz = istream_read_int32_le(inputStream); + header.num_st = istream_read_int32_le(inputStream); + header.num_tris = istream_read_int32_le(inputStream); + header.num_glcmds = istream_read_int32_le(inputStream); + header.num_frames = istream_read_int32_le(inputStream); + header.ofs_skins = istream_read_int32_le(inputStream); + header.ofs_st = istream_read_int32_le(inputStream); + header.ofs_tris = istream_read_int32_le(inputStream); + header.ofs_frames = istream_read_int32_le(inputStream); + header.ofs_glcmds = istream_read_int32_le(inputStream); + header.ofs_end = istream_read_int32_le(inputStream); } -ArbitraryMeshVertex MD2Vertex_construct( const md2Header_t* pHeader, const md2Frame_t* pFrame, const md2XyzNormal_t* xyz, const md2St_t* st ){ - return ArbitraryMeshVertex( - Vertex3f( - xyz->v[0] * pFrame->scale[0] + pFrame->translate[0], - xyz->v[1] * pFrame->scale[1] + pFrame->translate[1], - xyz->v[2] * pFrame->scale[2] + pFrame->translate[2] - ), - Normal3f( - g_mdl_normals[xyz->lightnormalindex][0], - g_mdl_normals[xyz->lightnormalindex][1], - g_mdl_normals[xyz->lightnormalindex][2] - ), - TexCoord2f( - (float)st->s / pHeader->skinwidth, - (float)st->t / pHeader->skinheight - ) - ); +ArbitraryMeshVertex +MD2Vertex_construct(const md2Header_t *pHeader, const md2Frame_t *pFrame, const md2XyzNormal_t *xyz, const md2St_t *st) +{ + return ArbitraryMeshVertex( + Vertex3f( + xyz->v[0] * pFrame->scale[0] + pFrame->translate[0], + xyz->v[1] * pFrame->scale[1] + pFrame->translate[1], + xyz->v[2] * pFrame->scale[2] + pFrame->translate[2] + ), + Normal3f( + g_mdl_normals[xyz->lightnormalindex][0], + g_mdl_normals[xyz->lightnormalindex][1], + g_mdl_normals[xyz->lightnormalindex][2] + ), + TexCoord2f( + (float) st->s / pHeader->skinwidth, + (float) st->t / pHeader->skinheight + ) + ); } -void MD2Surface_read( Model& model, const byte* buffer, ArchiveFile& file ){ - Surface& surface = model.newSurface(); - md2Header_t header; - { - PointerInputStream inputStream( buffer ); - istream_read_md2Header( inputStream, header ); - } - - { - - md2Frame_t frame; - PointerInputStream frameStream( buffer + header.ofs_frames ); - istream_read_md2Frame( frameStream, frame ); - - - surface.indices().reserve( header.num_tris * 3 ); - - Array md2Xyz( header.num_xyz ); - for ( Array::iterator i = md2Xyz.begin(); i != md2Xyz.end(); ++i ) - { - istream_read_md2XyzNormal( frameStream, *i ); - } - - Array md2St( header.num_st ); - PointerInputStream stStream( buffer + header.ofs_st ); - for ( Array::iterator i = md2St.begin(); i != md2St.end(); ++i ) - { - istream_read_md2St( stStream, *i ); - } - - UniqueVertexBuffer inserter( surface.vertices() ); - inserter.reserve( header.num_st ); - - PointerInputStream triangleStream( buffer + header.ofs_tris ); - for ( int i = 0; i < header.num_tris; ++i ) - { - md2Triangle_t triangle; - istream_read_md2Triangle( triangleStream, triangle ); - surface.indices().insert( inserter.insert( MD2Vertex_construct( &header, &frame, &md2Xyz[triangle.index_xyz[0]], &md2St[triangle.index_st[0]] ) ) ); - surface.indices().insert( inserter.insert( MD2Vertex_construct( &header, &frame, &md2Xyz[triangle.index_xyz[1]], &md2St[triangle.index_st[1]] ) ) ); - surface.indices().insert( inserter.insert( MD2Vertex_construct( &header, &frame, &md2Xyz[triangle.index_xyz[2]], &md2St[triangle.index_st[2]] ) ) ); - } - } - - char skinname[MD2_MAX_SKINNAME]; - char skinnameRelative[MD2_MAX_SKINNAME]; - char path[MD2_MAX_SKINNAME]; - int i = MD2_MAX_SKINNAME; - PointerInputStream inputStream( buffer + header.ofs_skins ); - inputStream.read( reinterpret_cast( skinnameRelative ), MD2_MAX_SKINNAME ); - // relative texture path - allows moving of models in game dir structure without changing the skinpath - // e.g. used in ufo:ai - if ( skinnameRelative[0] == '.' ) { - strncpy( path, file.getName(), MD2_MAX_SKINNAME ); - for (; i--; ) - { - // skip filename - if ( path[i] == '/' || path[i] == '\\' ) { - break; - } - path[i] = '\0'; - } +void MD2Surface_read(Model &model, const byte *buffer, ArchiveFile &file) +{ + Surface &surface = model.newSurface(); + md2Header_t header; + { + PointerInputStream inputStream(buffer); + istream_read_md2Header(inputStream, header); + } + + { + + md2Frame_t frame; + PointerInputStream frameStream(buffer + header.ofs_frames); + istream_read_md2Frame(frameStream, frame); + + + surface.indices().reserve(header.num_tris * 3); + + Array md2Xyz(header.num_xyz); + for (Array::iterator i = md2Xyz.begin(); i != md2Xyz.end(); ++i) { + istream_read_md2XyzNormal(frameStream, *i); + } + + Array md2St(header.num_st); + PointerInputStream stStream(buffer + header.ofs_st); + for (Array::iterator i = md2St.begin(); i != md2St.end(); ++i) { + istream_read_md2St(stStream, *i); + } + + UniqueVertexBuffer inserter(surface.vertices()); + inserter.reserve(header.num_st); + + PointerInputStream triangleStream(buffer + header.ofs_tris); + for (int i = 0; i < header.num_tris; ++i) { + md2Triangle_t triangle; + istream_read_md2Triangle(triangleStream, triangle); + surface.indices().insert(inserter.insert( + MD2Vertex_construct(&header, &frame, &md2Xyz[triangle.index_xyz[0]], + &md2St[triangle.index_st[0]]))); + surface.indices().insert(inserter.insert( + MD2Vertex_construct(&header, &frame, &md2Xyz[triangle.index_xyz[1]], + &md2St[triangle.index_st[1]]))); + surface.indices().insert(inserter.insert( + MD2Vertex_construct(&header, &frame, &md2Xyz[triangle.index_xyz[2]], + &md2St[triangle.index_st[2]]))); + } + } + + char skinname[MD2_MAX_SKINNAME]; + char skinnameRelative[MD2_MAX_SKINNAME]; + char path[MD2_MAX_SKINNAME]; + int i = MD2_MAX_SKINNAME; + PointerInputStream inputStream(buffer + header.ofs_skins); + inputStream.read(reinterpret_cast( skinnameRelative ), MD2_MAX_SKINNAME); + // relative texture path - allows moving of models in game dir structure without changing the skinpath + // e.g. used in ufo:ai + if (skinnameRelative[0] == '.') { + strncpy(path, file.getName(), MD2_MAX_SKINNAME); + for (; i--;) { + // skip filename + if (path[i] == '/' || path[i] == '\\') { + break; + } + path[i] = '\0'; + } // globalErrorStream() << "modified skinname: " << path << " (path) and " << skinnameRelative << " (texture)" << "\n"; - snprintf( skinname, MD2_MAX_SKINNAME, "%s%s", path, &skinnameRelative[1] ); + snprintf(skinname, MD2_MAX_SKINNAME, "%s%s", path, &skinnameRelative[1]); // globalErrorStream() << skinname << "\n"; - } - else - { - strcpy( skinname, skinnameRelative ); - } - surface.setShader( skinname ); - surface.updateAABB(); + } else { + strcpy(skinname, skinnameRelative); + } + surface.setShader(skinname); + surface.updateAABB(); } -void MD2Model_read( Model& model, const byte* buffer, ArchiveFile& file ){ - MD2Surface_read( model, buffer, file ); - model.updateAABB(); +void MD2Model_read(Model &model, const byte *buffer, ArchiveFile &file) +{ + MD2Surface_read(model, buffer, file); + model.updateAABB(); } -scene::Node& MD2Model_new( const byte* buffer, ArchiveFile& file ){ - ModelNode* modelNode = new ModelNode(); - MD2Model_read( modelNode->model(), buffer, file ); - return modelNode->node(); +scene::Node &MD2Model_new(const byte *buffer, ArchiveFile &file) +{ + ModelNode *modelNode = new ModelNode(); + MD2Model_read(modelNode->model(), buffer, file); + return modelNode->node(); } -scene::Node& MD2Model_default(){ - ModelNode* modelNode = new ModelNode(); - Model_constructNull( modelNode->model() ); - return modelNode->node(); +scene::Node &MD2Model_default() +{ + ModelNode *modelNode = new ModelNode(); + Model_constructNull(modelNode->model()); + return modelNode->node(); } -scene::Node& MD2Model_fromBuffer( unsigned char* buffer, ArchiveFile& file ){ - if ( !ident_equal( buffer, MD2_IDENT ) ) { - globalErrorStream() << "MD2 read error: incorrect ident\n"; - return MD2Model_default(); - } - else - { - return MD2Model_new( buffer, file ); - } +scene::Node &MD2Model_fromBuffer(unsigned char *buffer, ArchiveFile &file) +{ + if (!ident_equal(buffer, MD2_IDENT)) { + globalErrorStream() << "MD2 read error: incorrect ident\n"; + return MD2Model_default(); + } else { + return MD2Model_new(buffer, file); + } } -scene::Node& loadMD2Model( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return MD2Model_fromBuffer( buffer.buffer, file ); +scene::Node &loadMD2Model(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return MD2Model_fromBuffer(buffer.buffer, file); } diff --git a/plugins/md3model/md2.h b/plugins/md3model/md2.h index 33b34d76..3128b27a 100644 --- a/plugins/md3model/md2.h +++ b/plugins/md3model/md2.h @@ -24,7 +24,8 @@ namespace scene { class Node; } class ArchiveFile; -scene::Node& loadMD2Model( ArchiveFile& file ); + +scene::Node &loadMD2Model(ArchiveFile &file); #endif diff --git a/plugins/md3model/md3.cpp b/plugins/md3model/md3.cpp index 0b459827..3c5c5060 100644 --- a/plugins/md3model/md3.cpp +++ b/plugins/md3model/md3.cpp @@ -42,56 +42,59 @@ const int MAX_QPATH = 64; ======================================================================== */ -const unsigned char MD3_IDENT[4] = { 'I', 'D', 'P', '3', }; +const unsigned char MD3_IDENT[4] = {'I', 'D', 'P', '3',}; const int MD3_VERSION = 15; // limits -const int MD3_MAX_LODS = 4; -const int MD3_MAX_TRIANGLES = 8192; // per surface -const int MD3_MAX_VERTS = 4096; // per surface -const int MD3_MAX_SHADERS = 256; // per surface -const int MD3_MAX_FRAMES = 1024; // per model -const int MD3_MAX_SURFACES = 32; // per model -const int MD3_MAX_TAGS = 16; // per frame +const int MD3_MAX_LODS = 4; +const int MD3_MAX_TRIANGLES = 8192; // per surface +const int MD3_MAX_VERTS = 4096; // per surface +const int MD3_MAX_SHADERS = 256; // per surface +const int MD3_MAX_FRAMES = 1024; // per model +const int MD3_MAX_SURFACES = 32; // per model +const int MD3_MAX_TAGS = 16; // per frame // vertex scales -const float MD3_XYZ_SCALE = ( 1.f / 64 ); +const float MD3_XYZ_SCALE = (1.f / 64); typedef float float3[3]; -void istream_read_float3( PointerInputStream& inputStream, float3 f ){ - f[0] = istream_read_float32_le( inputStream ); - f[1] = istream_read_float32_le( inputStream ); - f[2] = istream_read_float32_le( inputStream ); +void istream_read_float3(PointerInputStream &inputStream, float3 f) +{ + f[0] = istream_read_float32_le(inputStream); + f[1] = istream_read_float32_le(inputStream); + f[2] = istream_read_float32_le(inputStream); } typedef struct md3Frame_s { - float3 bounds[2]; - float3 localOrigin; - float radius; - char name[16]; + float3 bounds[2]; + float3 localOrigin; + float radius; + char name[16]; } md3Frame_t; -void istream_read_md3Frame( PointerInputStream& inputStream, md3Frame_t& frame ){ - istream_read_float3( inputStream, frame.bounds[0] ); - istream_read_float3( inputStream, frame.bounds[1] ); - istream_read_float3( inputStream, frame.localOrigin ); - frame.radius = istream_read_float32_le( inputStream ); - inputStream.read( reinterpret_cast( frame.name ), 16 ); +void istream_read_md3Frame(PointerInputStream &inputStream, md3Frame_t &frame) +{ + istream_read_float3(inputStream, frame.bounds[0]); + istream_read_float3(inputStream, frame.bounds[1]); + istream_read_float3(inputStream, frame.localOrigin); + frame.radius = istream_read_float32_le(inputStream); + inputStream.read(reinterpret_cast( frame.name ), 16); } typedef struct md3Tag_s { - char name[MAX_QPATH]; // tag name - float3 origin; - float3 axis[3]; + char name[MAX_QPATH]; // tag name + float3 origin; + float3 axis[3]; } md3Tag_t; -void istream_read_md3Shader( PointerInputStream& inputStream, md3Tag_t& tag ){ - inputStream.read( reinterpret_cast( tag.name ), MAX_QPATH ); - istream_read_float3( inputStream, tag.origin ); - istream_read_float3( inputStream, tag.axis[0] ); - istream_read_float3( inputStream, tag.axis[1] ); - istream_read_float3( inputStream, tag.axis[2] ); +void istream_read_md3Shader(PointerInputStream &inputStream, md3Tag_t &tag) +{ + inputStream.read(reinterpret_cast( tag.name ), MAX_QPATH); + istream_read_float3(inputStream, tag.origin); + istream_read_float3(inputStream, tag.axis[0]); + istream_read_float3(inputStream, tag.axis[1]); + istream_read_float3(inputStream, tag.axis[2]); } /* @@ -105,219 +108,227 @@ void istream_read_md3Shader( PointerInputStream& inputStream, md3Tag_t& tag ){ ** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames */ typedef struct { - char ident[4]; // + char ident[4]; // - char name[MAX_QPATH]; // polyset name + char name[MAX_QPATH]; // polyset name - int flags; - int numFrames; // all surfaces in a model should have the same + int flags; + int numFrames; // all surfaces in a model should have the same - int numShaders; // all surfaces in a model should have the same - int numVerts; + int numShaders; // all surfaces in a model should have the same + int numVerts; - int numTriangles; - int ofsTriangles; + int numTriangles; + int ofsTriangles; - int ofsShaders; // offset from start of md3Surface_t - int ofsSt; // texture coords are common for all frames - int ofsXyzNormals; // numVerts * numFrames + int ofsShaders; // offset from start of md3Surface_t + int ofsSt; // texture coords are common for all frames + int ofsXyzNormals; // numVerts * numFrames - int ofsEnd; // next surface follows + int ofsEnd; // next surface follows } md3Surface_t; -void istream_read_md3Surface( PointerInputStream& inputStream, md3Surface_t& surface ){ - inputStream.read( reinterpret_cast( surface.ident ), 4 ); - inputStream.read( reinterpret_cast( surface.name ), MAX_QPATH ); - surface.flags = istream_read_int32_le( inputStream ); - surface.numFrames = istream_read_int32_le( inputStream ); - surface.numShaders = istream_read_int32_le( inputStream ); - surface.numVerts = istream_read_int32_le( inputStream ); - surface.numTriangles = istream_read_int32_le( inputStream ); - surface.ofsTriangles = istream_read_int32_le( inputStream ); - surface.ofsShaders = istream_read_int32_le( inputStream ); - surface.ofsSt = istream_read_int32_le( inputStream ); - surface.ofsXyzNormals = istream_read_int32_le( inputStream ); - surface.ofsEnd = istream_read_int32_le( inputStream ); +void istream_read_md3Surface(PointerInputStream &inputStream, md3Surface_t &surface) +{ + inputStream.read(reinterpret_cast( surface.ident ), 4); + inputStream.read(reinterpret_cast( surface.name ), MAX_QPATH); + surface.flags = istream_read_int32_le(inputStream); + surface.numFrames = istream_read_int32_le(inputStream); + surface.numShaders = istream_read_int32_le(inputStream); + surface.numVerts = istream_read_int32_le(inputStream); + surface.numTriangles = istream_read_int32_le(inputStream); + surface.ofsTriangles = istream_read_int32_le(inputStream); + surface.ofsShaders = istream_read_int32_le(inputStream); + surface.ofsSt = istream_read_int32_le(inputStream); + surface.ofsXyzNormals = istream_read_int32_le(inputStream); + surface.ofsEnd = istream_read_int32_le(inputStream); } typedef struct { - char name[MAX_QPATH]; - int shaderIndex; // for in-game use + char name[MAX_QPATH]; + int shaderIndex; // for in-game use } md3Shader_t; -void istream_read_md3Shader( PointerInputStream& inputStream, md3Shader_t& shader ){ - inputStream.read( reinterpret_cast( shader.name ), MAX_QPATH ); - shader.shaderIndex = istream_read_int32_le( inputStream ); +void istream_read_md3Shader(PointerInputStream &inputStream, md3Shader_t &shader) +{ + inputStream.read(reinterpret_cast( shader.name ), MAX_QPATH); + shader.shaderIndex = istream_read_int32_le(inputStream); } typedef struct { - int indexes[3]; + int indexes[3]; } md3Triangle_t; -void istream_read_md3Triangle( PointerInputStream& inputStream, md3Triangle_t& triangle ){ - triangle.indexes[0] = istream_read_int32_le( inputStream ); - triangle.indexes[1] = istream_read_int32_le( inputStream ); - triangle.indexes[2] = istream_read_int32_le( inputStream ); +void istream_read_md3Triangle(PointerInputStream &inputStream, md3Triangle_t &triangle) +{ + triangle.indexes[0] = istream_read_int32_le(inputStream); + triangle.indexes[1] = istream_read_int32_le(inputStream); + triangle.indexes[2] = istream_read_int32_le(inputStream); } typedef struct { - float st[2]; + float st[2]; } md3St_t; -void istream_read_md3St( PointerInputStream& inputStream, md3St_t& st ){ - st.st[0] = istream_read_float32_le( inputStream ); - st.st[1] = istream_read_float32_le( inputStream ); +void istream_read_md3St(PointerInputStream &inputStream, md3St_t &st) +{ + st.st[0] = istream_read_float32_le(inputStream); + st.st[1] = istream_read_float32_le(inputStream); } typedef struct { - short xyz[3]; - short normal; + short xyz[3]; + short normal; } md3XyzNormal_t; -void istream_read_md3XyzNormal( PointerInputStream& inputStream, md3XyzNormal_t& xyz ){ - xyz.xyz[0] = istream_read_int16_le( inputStream ); - xyz.xyz[1] = istream_read_int16_le( inputStream ); - xyz.xyz[2] = istream_read_int16_le( inputStream ); - xyz.normal = istream_read_int16_le( inputStream ); +void istream_read_md3XyzNormal(PointerInputStream &inputStream, md3XyzNormal_t &xyz) +{ + xyz.xyz[0] = istream_read_int16_le(inputStream); + xyz.xyz[1] = istream_read_int16_le(inputStream); + xyz.xyz[2] = istream_read_int16_le(inputStream); + xyz.normal = istream_read_int16_le(inputStream); } typedef struct { - char ident[4]; - int version; + char ident[4]; + int version; - char name[MAX_QPATH]; // model name + char name[MAX_QPATH]; // model name - int flags; + int flags; - int numFrames; - int numTags; - int numSurfaces; + int numFrames; + int numTags; + int numSurfaces; - int numSkins; + int numSkins; - int ofsFrames; // offset for first frame - int ofsTags; // numFrames * numTags - int ofsSurfaces; // first surface, others follow + int ofsFrames; // offset for first frame + int ofsTags; // numFrames * numTags + int ofsSurfaces; // first surface, others follow - int ofsEnd; // end of file + int ofsEnd; // end of file } md3Header_t; -void istream_read_md3Header( PointerInputStream& inputStream, md3Header_t& header ){ - inputStream.read( reinterpret_cast( header.ident ), 4 ); - header.version = istream_read_int32_le( inputStream ); - inputStream.read( reinterpret_cast( header.name ), MAX_QPATH ); - header.flags = istream_read_int32_le( inputStream ); - header.numFrames = istream_read_int32_le( inputStream ); - header.numTags = istream_read_int32_le( inputStream ); - header.numSurfaces = istream_read_int32_le( inputStream ); - header.numSkins = istream_read_int32_le( inputStream ); - header.ofsFrames = istream_read_int32_le( inputStream ); - header.ofsTags = istream_read_int32_le( inputStream ); - header.ofsSurfaces = istream_read_int32_le( inputStream ); - header.ofsEnd = istream_read_int32_le( inputStream ); +void istream_read_md3Header(PointerInputStream &inputStream, md3Header_t &header) +{ + inputStream.read(reinterpret_cast( header.ident ), 4); + header.version = istream_read_int32_le(inputStream); + inputStream.read(reinterpret_cast( header.name ), MAX_QPATH); + header.flags = istream_read_int32_le(inputStream); + header.numFrames = istream_read_int32_le(inputStream); + header.numTags = istream_read_int32_le(inputStream); + header.numSurfaces = istream_read_int32_le(inputStream); + header.numSkins = istream_read_int32_le(inputStream); + header.ofsFrames = istream_read_int32_le(inputStream); + header.ofsTags = istream_read_int32_le(inputStream); + header.ofsSurfaces = istream_read_int32_le(inputStream); + header.ofsEnd = istream_read_int32_le(inputStream); } -int MD3Surface_read( Surface& surface, unsigned char* buffer ){ - md3Surface_t md3Surface; - { - PointerInputStream inputStream( buffer ); - istream_read_md3Surface( inputStream, md3Surface ); - } - - { - surface.vertices().reserve( md3Surface.numVerts ); - - PointerInputStream xyzNormalStream( buffer + md3Surface.ofsXyzNormals ); - PointerInputStream stStream( buffer + md3Surface.ofsSt ); - - // read verts into vertex array - xyz, st, normal - for ( int i = 0; i < md3Surface.numVerts; i++ ) - { - md3XyzNormal_t md3Xyz; - istream_read_md3XyzNormal( xyzNormalStream, md3Xyz ); - - md3St_t md3St; - istream_read_md3St( stStream, md3St ); - - surface.vertices().push_back( - ArbitraryMeshVertex( - Vertex3f( md3Xyz.xyz[0] * MD3_XYZ_SCALE, md3Xyz.xyz[1] * MD3_XYZ_SCALE, md3Xyz.xyz[2] * MD3_XYZ_SCALE ), - DecodeNormal( reinterpret_cast( &md3Xyz.normal ) ), - TexCoord2f( md3St.st[0], md3St.st[1] ) - ) - ); - } - } - - { - surface.indices().reserve( md3Surface.numTriangles * 3 ); - - PointerInputStream inputStream( buffer + md3Surface.ofsTriangles ); - for ( int i = 0; i < md3Surface.numTriangles; i++ ) - { - md3Triangle_t md3Triangle; - istream_read_md3Triangle( inputStream, md3Triangle ); - surface.indices().insert( md3Triangle.indexes[0] ); - surface.indices().insert( md3Triangle.indexes[1] ); - surface.indices().insert( md3Triangle.indexes[2] ); - } - } - - { - md3Shader_t md3Shader; - { - PointerInputStream inputStream( buffer + md3Surface.ofsShaders ); - istream_read_md3Shader( inputStream, md3Shader ); - } - surface.setShader( md3Shader.name ); - } - - surface.updateAABB(); - - return md3Surface.ofsEnd; +int MD3Surface_read(Surface &surface, unsigned char *buffer) +{ + md3Surface_t md3Surface; + { + PointerInputStream inputStream(buffer); + istream_read_md3Surface(inputStream, md3Surface); + } + + { + surface.vertices().reserve(md3Surface.numVerts); + + PointerInputStream xyzNormalStream(buffer + md3Surface.ofsXyzNormals); + PointerInputStream stStream(buffer + md3Surface.ofsSt); + + // read verts into vertex array - xyz, st, normal + for (int i = 0; i < md3Surface.numVerts; i++) { + md3XyzNormal_t md3Xyz; + istream_read_md3XyzNormal(xyzNormalStream, md3Xyz); + + md3St_t md3St; + istream_read_md3St(stStream, md3St); + + surface.vertices().push_back( + ArbitraryMeshVertex( + Vertex3f(md3Xyz.xyz[0] * MD3_XYZ_SCALE, md3Xyz.xyz[1] * MD3_XYZ_SCALE, + md3Xyz.xyz[2] * MD3_XYZ_SCALE), + DecodeNormal(reinterpret_cast( &md3Xyz.normal )), + TexCoord2f(md3St.st[0], md3St.st[1]) + ) + ); + } + } + + { + surface.indices().reserve(md3Surface.numTriangles * 3); + + PointerInputStream inputStream(buffer + md3Surface.ofsTriangles); + for (int i = 0; i < md3Surface.numTriangles; i++) { + md3Triangle_t md3Triangle; + istream_read_md3Triangle(inputStream, md3Triangle); + surface.indices().insert(md3Triangle.indexes[0]); + surface.indices().insert(md3Triangle.indexes[1]); + surface.indices().insert(md3Triangle.indexes[2]); + } + } + + { + md3Shader_t md3Shader; + { + PointerInputStream inputStream(buffer + md3Surface.ofsShaders); + istream_read_md3Shader(inputStream, md3Shader); + } + surface.setShader(md3Shader.name); + } + + surface.updateAABB(); + + return md3Surface.ofsEnd; } -void MD3Model_read( Model& model, unsigned char* buffer ){ - md3Header_t md3Header; - { - PointerInputStream inputStream( buffer ); - istream_read_md3Header( inputStream, md3Header ); - } +void MD3Model_read(Model &model, unsigned char *buffer) +{ + md3Header_t md3Header; + { + PointerInputStream inputStream(buffer); + istream_read_md3Header(inputStream, md3Header); + } - unsigned char* surfacePosition = buffer + md3Header.ofsSurfaces; + unsigned char *surfacePosition = buffer + md3Header.ofsSurfaces; - for ( int i = 0; i != md3Header.numSurfaces; ++i ) - { - surfacePosition += MD3Surface_read( model.newSurface(), surfacePosition ); - } + for (int i = 0; i != md3Header.numSurfaces; ++i) { + surfacePosition += MD3Surface_read(model.newSurface(), surfacePosition); + } - model.updateAABB(); + model.updateAABB(); } -scene::Node& MD3Model_new( unsigned char* buffer ){ - ModelNode* modelNode = new ModelNode(); - MD3Model_read( modelNode->model(), buffer ); - return modelNode->node(); +scene::Node &MD3Model_new(unsigned char *buffer) +{ + ModelNode *modelNode = new ModelNode(); + MD3Model_read(modelNode->model(), buffer); + return modelNode->node(); } -scene::Node& MD3Model_default(){ - ModelNode* modelNode = new ModelNode(); - Model_constructNull( modelNode->model() ); - return modelNode->node(); +scene::Node &MD3Model_default() +{ + ModelNode *modelNode = new ModelNode(); + Model_constructNull(modelNode->model()); + return modelNode->node(); } -scene::Node& MD3Model_fromBuffer( unsigned char* buffer ){ - if ( !ident_equal( buffer, MD3_IDENT ) ) { - globalErrorStream() << "MD3 read error: incorrect ident\n"; - return MD3Model_default(); - } - else - { - return MD3Model_new( buffer ); - } +scene::Node &MD3Model_fromBuffer(unsigned char *buffer) +{ + if (!ident_equal(buffer, MD3_IDENT)) { + globalErrorStream() << "MD3 read error: incorrect ident\n"; + return MD3Model_default(); + } else { + return MD3Model_new(buffer); + } } -scene::Node& loadMD3Model( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return MD3Model_fromBuffer( buffer.buffer ); +scene::Node &loadMD3Model(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return MD3Model_fromBuffer(buffer.buffer); } diff --git a/plugins/md3model/md3.h b/plugins/md3model/md3.h index 6b1e3e31..79e9ac63 100644 --- a/plugins/md3model/md3.h +++ b/plugins/md3model/md3.h @@ -24,6 +24,7 @@ namespace scene { class Node; } class ArchiveFile; -scene::Node& loadMD3Model( ArchiveFile& file ); + +scene::Node &loadMD3Model(ArchiveFile &file); #endif diff --git a/plugins/md3model/md3normals.h b/plugins/md3model/md3normals.h index 3803c370..77529c87 100644 --- a/plugins/md3model/md3normals.h +++ b/plugins/md3model/md3normals.h @@ -27,15 +27,16 @@ typedef unsigned char byte; // latitude-longditude to normal conversion -inline Normal3f DecodeNormal( const byte bytes[2] ){ - double lat = bytes[0] * ( c_pi / 128.0 ); - double lng = bytes[1] * ( c_pi / 128.0 ); - - return Normal3f( - static_cast( cos( lat ) * sin( lng ) ), - static_cast( sin( lat ) * sin( lng ) ), - static_cast( cos( lng ) ) - ); +inline Normal3f DecodeNormal(const byte bytes[2]) +{ + double lat = bytes[0] * (c_pi / 128.0); + double lng = bytes[1] * (c_pi / 128.0); + + return Normal3f( + static_cast( cos(lat) * sin(lng)), + static_cast( sin(lat) * sin(lng)), + static_cast( cos(lng)) + ); } #endif diff --git a/plugins/md3model/md5.cpp b/plugins/md3model/md5.cpp index e1c5de56..0a548f44 100644 --- a/plugins/md3model/md5.cpp +++ b/plugins/md3model/md5.cpp @@ -31,91 +31,94 @@ #define MD5_RETURN_FALSE_IF_FAIL(expression) do { if (!(expression)) { globalErrorStream() << "md5 parse failed: " #expression "\n"; return false; } } while (0) -bool MD5_parseToken( Tokeniser& tokeniser, const char* string ){ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL( token != 0 ); - return string_equal( token, string ); +bool MD5_parseToken(Tokeniser &tokeniser, const char *string) +{ + const char *token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL(token != 0); + return string_equal(token, string); } -bool MD5_parseFloat( Tokeniser& tokeniser, float& f ){ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL( token != 0 ); - return string_parse_float( token, f ); +bool MD5_parseFloat(Tokeniser &tokeniser, float &f) +{ + const char *token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL(token != 0); + return string_parse_float(token, f); } -bool MD5_parseString( Tokeniser& tokeniser, const char*& s ){ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL( token != 0 ); - s = token; - return true; +bool MD5_parseString(Tokeniser &tokeniser, const char *&s) +{ + const char *token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL(token != 0); + s = token; + return true; } -bool MD5_parseInteger( Tokeniser& tokeniser, int& i ){ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL( token != 0 ); - return string_parse_int( token, i ); +bool MD5_parseInteger(Tokeniser &tokeniser, int &i) +{ + const char *token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL(token != 0); + return string_parse_int(token, i); } -bool MD5_parseSize( Tokeniser& tokeniser, std::size_t& i ){ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL( token != 0 ); - return string_parse_size( token, i ); +bool MD5_parseSize(Tokeniser &tokeniser, std::size_t &i) +{ + const char *token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL(token != 0); + return string_parse_size(token, i); } -bool MD5_parseVector3( Tokeniser& tokeniser, Vector3& v ){ - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "(" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, v.x() ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, v.y() ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, v.z() ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, ")" ) ); - return true; +bool MD5_parseVector3(Tokeniser &tokeniser, Vector3 &v) +{ + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "(")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.x())); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.y())); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.z())); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, ")")); + return true; } template -inline Element float_squared( const Element& f ){ - return f * f; +inline Element float_squared(const Element &f) +{ + return f * f; } -class MD5Joint -{ +class MD5Joint { public: -int parent; -Vector3 position; -Vector4 rotation; + int parent; + Vector3 position; + Vector4 rotation; }; typedef Array MD5Joints; -class MD5Vert -{ +class MD5Vert { public: -std::size_t index; -float u; -float v; -std::size_t weight_index; -std::size_t weight_count; + std::size_t index; + float u; + float v; + std::size_t weight_index; + std::size_t weight_count; }; typedef Array MD5Verts; -class MD5Tri -{ +class MD5Tri { public: -std::size_t index; -std::size_t a; -std::size_t b; -std::size_t c; + std::size_t index; + std::size_t a; + std::size_t b; + std::size_t c; }; typedef Array MD5Tris; -class MD5Weight -{ +class MD5Weight { public: -std::size_t index; -std::size_t joint; -float t; -Vector3 v; + std::size_t index; + std::size_t joint; + float t; + Vector3 v; }; typedef Array MD5Weights; @@ -123,317 +126,312 @@ typedef Array MD5Weights; typedef float MD5Component; typedef Array MD5Components; -class MD5Frame -{ +class MD5Frame { public: -MD5Components m_components; + MD5Components m_components; }; typedef Array MD5Weights; -bool MD5_parseVersion( Tokeniser& tokeniser ){ - { - const char* versionKey = tokeniser.getToken(); - if ( versionKey == 0 || !string_equal( versionKey, "MD5Version" ) ) { - globalErrorStream() << "not a valid md5 file\n"; - return false; - } - } - { - const char* versionValue = tokeniser.getToken(); - if ( versionValue == 0 || !string_equal( versionValue, "10" ) ) { - globalErrorStream() << "only md5 version 10 supported\n"; - return false; - } - } - - return true; +bool MD5_parseVersion(Tokeniser &tokeniser) +{ + { + const char *versionKey = tokeniser.getToken(); + if (versionKey == 0 || !string_equal(versionKey, "MD5Version")) { + globalErrorStream() << "not a valid md5 file\n"; + return false; + } + } + { + const char *versionValue = tokeniser.getToken(); + if (versionValue == 0 || !string_equal(versionValue, "10")) { + globalErrorStream() << "only md5 version 10 supported\n"; + return false; + } + } + + return true; } -bool MD5Anim_parse( Tokeniser& tokeniser ){ - MD5_RETURN_FALSE_IF_FAIL( MD5_parseVersion( tokeniser ) ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "commandline" ) ); - const char* commandline; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, commandline ) ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numFrames" ) ); - std::size_t numFrames; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numFrames ) ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numJoints" ) ); - std::size_t numJoints; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numJoints ) ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "frameRate" ) ); - std::size_t frameRate; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, frameRate ) ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numAnimatedComponents" ) ); - std::size_t numAnimatedComponents; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numAnimatedComponents ) ); - tokeniser.nextLine(); - - // parse heirarchy - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "hierarchy" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); - - for ( std::size_t i = 0; i < numJoints; ++i ) - { - const char* name; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, name ) ); - int parent; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseInteger( tokeniser, parent ) ); - std::size_t flags; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, flags ) ); - std::size_t index; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, index ) ); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); - tokeniser.nextLine(); - - // parse bounds - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "bounds" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); - - for ( std::size_t i = 0; i < numFrames; ++i ) - { - Vector3 mins; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, mins ) ); - Vector3 maxs; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, maxs ) ); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); - tokeniser.nextLine(); - - // parse baseframe - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "baseframe" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); - - for ( std::size_t i = 0; i < numJoints; ++i ) - { - Vector3 position; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, position ) ); - Vector3 rotation; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, rotation ) ); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); - tokeniser.nextLine(); - - // parse frames - for ( std::size_t i = 0; i < numFrames; ++i ) - { - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "frame" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); - - for ( std::size_t i = 0; i < numAnimatedComponents; ++i ) - { - float component; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, component ) ); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); - tokeniser.nextLine(); - } - - return true; +bool MD5Anim_parse(Tokeniser &tokeniser) +{ + MD5_RETURN_FALSE_IF_FAIL(MD5_parseVersion(tokeniser)); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "commandline")); + const char *commandline; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, commandline)); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numFrames")); + std::size_t numFrames; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numFrames)); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numJoints")); + std::size_t numJoints; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numJoints)); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "frameRate")); + std::size_t frameRate; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, frameRate)); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numAnimatedComponents")); + std::size_t numAnimatedComponents; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numAnimatedComponents)); + tokeniser.nextLine(); + + // parse heirarchy + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "hierarchy")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); + tokeniser.nextLine(); + + for (std::size_t i = 0; i < numJoints; ++i) { + const char *name; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, name)); + int parent; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, parent)); + std::size_t flags; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, flags)); + std::size_t index; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, index)); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); + tokeniser.nextLine(); + + // parse bounds + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "bounds")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); + tokeniser.nextLine(); + + for (std::size_t i = 0; i < numFrames; ++i) { + Vector3 mins; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, mins)); + Vector3 maxs; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, maxs)); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); + tokeniser.nextLine(); + + // parse baseframe + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "baseframe")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); + tokeniser.nextLine(); + + for (std::size_t i = 0; i < numJoints; ++i) { + Vector3 position; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, position)); + Vector3 rotation; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, rotation)); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); + tokeniser.nextLine(); + + // parse frames + for (std::size_t i = 0; i < numFrames; ++i) { + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "frame")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); + tokeniser.nextLine(); + + for (std::size_t i = 0; i < numAnimatedComponents; ++i) { + float component; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, component)); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); + tokeniser.nextLine(); + } + + return true; } -bool MD5Model_parse( Model& model, Tokeniser& tokeniser ){ - MD5_RETURN_FALSE_IF_FAIL( MD5_parseVersion( tokeniser ) ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "commandline" ) ); - const char* commandline; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, commandline ) ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numJoints" ) ); - std::size_t numJoints; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numJoints ) ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numMeshes" ) ); - std::size_t numMeshes; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numMeshes ) ); - tokeniser.nextLine(); - - MD5Joints joints( numJoints ); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "joints" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); - - for ( MD5Joints::iterator i = joints.begin(); i != joints.end(); ++i ) - { - const char* jointName; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, jointName ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseInteger( tokeniser, ( *i ).parent ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, ( *i ).position ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, vector4_to_vector3( ( *i ).rotation ) ) ); - ( *i ).rotation.w() = -static_cast( sqrt( 1.0f - ( float_squared( ( *i ).rotation.x() ) + float_squared( ( *i ).rotation.y() ) + float_squared( ( *i ).rotation.z() ) ) ) ); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); - tokeniser.nextLine(); - - for ( std::size_t i = 0; i < numMeshes; ++i ) - { - Surface& surface = model.newSurface(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "mesh" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "shader" ) ); - const char* shader; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, shader ) ); - surface.setShader( shader ); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numverts" ) ); - std::size_t numVerts; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numVerts ) ); - tokeniser.nextLine(); - - MD5Verts verts( numVerts ); - - for ( MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j ) - { - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "vert" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).index ) ); - MD5_RETURN_FALSE_IF_FAIL( ( *j ).index == std::size_t( j - verts.begin() ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "(" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, ( *j ).u ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, ( *j ).v ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, ")" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).weight_index ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).weight_count ) ); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numtris" ) ); - std::size_t numTris; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numTris ) ); - tokeniser.nextLine(); - - MD5Tris tris( numTris ); - - for ( MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j ) - { - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "tri" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).index ) ); - MD5_RETURN_FALSE_IF_FAIL( ( *j ).index == std::size_t( j - tris.begin() ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).a ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).b ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).c ) ); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numweights" ) ); - std::size_t numWeights; - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numWeights ) ); - tokeniser.nextLine(); - - MD5Weights weights( numWeights ); - - for ( MD5Weights::iterator j = weights.begin(); j != weights.end(); ++j ) - { - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "weight" ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).index ) ); - MD5_RETURN_FALSE_IF_FAIL( ( *j ).index == std::size_t( j - weights.begin() ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).joint ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, ( *j ).t ) ); - MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, ( *j ).v ) ); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); - tokeniser.nextLine(); - - for ( MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j ) - { - MD5Vert& vert = ( *j ); - - Vector3 skinned( 0, 0, 0 ); - for ( std::size_t k = 0; k != vert.weight_count; ++k ) - { - MD5Weight& weight = weights[vert.weight_index + k]; - MD5Joint& joint = joints[weight.joint]; - - skinned += ( quaternion_transformed_point( joint.rotation, weight.v ) + joint.position ) * weight.t; - } - - surface.vertices().push_back( ArbitraryMeshVertex( vertex3f_for_vector3( skinned ), Normal3f( 0, 0, 0 ), TexCoord2f( vert.u, vert.v ) ) ); - } - - for ( MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j ) - { - MD5Tri& tri = ( *j ); - surface.indices().insert( RenderIndex( tri.a ) ); - surface.indices().insert( RenderIndex( tri.b ) ); - surface.indices().insert( RenderIndex( tri.c ) ); - } - - for ( Surface::indices_t::iterator j = surface.indices().begin(); j != surface.indices().end(); j += 3 ) - { - ArbitraryMeshVertex& a = surface.vertices()[*( j + 0 )]; - ArbitraryMeshVertex& b = surface.vertices()[*( j + 1 )]; - ArbitraryMeshVertex& c = surface.vertices()[*( j + 2 )]; - Vector3 weightedNormal( - vector3_cross( - reinterpret_cast( c.vertex ) - reinterpret_cast( a.vertex ), - reinterpret_cast( b.vertex ) - reinterpret_cast( a.vertex ) - ) - ); - reinterpret_cast( a.normal ) += weightedNormal; - reinterpret_cast( b.normal ) += weightedNormal; - reinterpret_cast( c.normal ) += weightedNormal; - } - - for ( Surface::vertices_t::iterator j = surface.vertices().begin(); j != surface.vertices().end(); ++j ) - { - vector3_normalise( reinterpret_cast( ( *j ).normal ) ); - } - - surface.updateAABB(); - } - - model.updateAABB(); - - return true; +bool MD5Model_parse(Model &model, Tokeniser &tokeniser) +{ + MD5_RETURN_FALSE_IF_FAIL(MD5_parseVersion(tokeniser)); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "commandline")); + const char *commandline; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, commandline)); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numJoints")); + std::size_t numJoints; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numJoints)); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numMeshes")); + std::size_t numMeshes; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numMeshes)); + tokeniser.nextLine(); + + MD5Joints joints(numJoints); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "joints")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); + tokeniser.nextLine(); + + for (MD5Joints::iterator i = joints.begin(); i != joints.end(); ++i) { + const char *jointName; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, jointName)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, (*i).parent)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*i).position)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, vector4_to_vector3((*i).rotation))); + (*i).rotation.w() = -static_cast( sqrt(1.0f - (float_squared((*i).rotation.x()) + + float_squared((*i).rotation.y()) + + float_squared((*i).rotation.z())))); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); + tokeniser.nextLine(); + + for (std::size_t i = 0; i < numMeshes; ++i) { + Surface &surface = model.newSurface(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "mesh")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "shader")); + const char *shader; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, shader)); + surface.setShader(shader); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numverts")); + std::size_t numVerts; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numVerts)); + tokeniser.nextLine(); + + MD5Verts verts(numVerts); + + for (MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j) { + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "vert")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index)); + MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - verts.begin())); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "(")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).u)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).v)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, ")")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_index)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_count)); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numtris")); + std::size_t numTris; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numTris)); + tokeniser.nextLine(); + + MD5Tris tris(numTris); + + for (MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j) { + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "tri")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index)); + MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - tris.begin())); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).a)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).b)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).c)); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numweights")); + std::size_t numWeights; + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numWeights)); + tokeniser.nextLine(); + + MD5Weights weights(numWeights); + + for (MD5Weights::iterator j = weights.begin(); j != weights.end(); ++j) { + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "weight")); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index)); + MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - weights.begin())); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).joint)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).t)); + MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*j).v)); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); + tokeniser.nextLine(); + + for (MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j) { + MD5Vert &vert = (*j); + + Vector3 skinned(0, 0, 0); + for (std::size_t k = 0; k != vert.weight_count; ++k) { + MD5Weight &weight = weights[vert.weight_index + k]; + MD5Joint &joint = joints[weight.joint]; + + skinned += (quaternion_transformed_point(joint.rotation, weight.v) + joint.position) * weight.t; + } + + surface.vertices().push_back( + ArbitraryMeshVertex(vertex3f_for_vector3(skinned), Normal3f(0, 0, 0), TexCoord2f(vert.u, vert.v))); + } + + for (MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j) { + MD5Tri &tri = (*j); + surface.indices().insert(RenderIndex(tri.a)); + surface.indices().insert(RenderIndex(tri.b)); + surface.indices().insert(RenderIndex(tri.c)); + } + + for (Surface::indices_t::iterator j = surface.indices().begin(); j != surface.indices().end(); j += 3) { + ArbitraryMeshVertex &a = surface.vertices()[*(j + 0)]; + ArbitraryMeshVertex &b = surface.vertices()[*(j + 1)]; + ArbitraryMeshVertex &c = surface.vertices()[*(j + 2)]; + Vector3 weightedNormal( + vector3_cross( + reinterpret_cast( c.vertex ) - + reinterpret_cast( a.vertex ), + reinterpret_cast( b.vertex ) - + reinterpret_cast( a.vertex ) + ) + ); + reinterpret_cast( a.normal ) += weightedNormal; + reinterpret_cast( b.normal ) += weightedNormal; + reinterpret_cast( c.normal ) += weightedNormal; + } + + for (Surface::vertices_t::iterator j = surface.vertices().begin(); j != surface.vertices().end(); ++j) { + vector3_normalise(reinterpret_cast((*j).normal )); + } + + surface.updateAABB(); + } + + model.updateAABB(); + + return true; } -void MD5Model_construct( Model& model, TextInputStream& inputStream ){ - Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser( inputStream ); - MD5Model_parse( model, tokeniser ); - tokeniser.release(); +void MD5Model_construct(Model &model, TextInputStream &inputStream) +{ + Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(inputStream); + MD5Model_parse(model, tokeniser); + tokeniser.release(); } -scene::Node& MD5Model_new( TextInputStream& inputStream ){ - ModelNode* modelNode = new ModelNode(); - MD5Model_construct( modelNode->model(), inputStream ); - return modelNode->node(); +scene::Node &MD5Model_new(TextInputStream &inputStream) +{ + ModelNode *modelNode = new ModelNode(); + MD5Model_construct(modelNode->model(), inputStream); + return modelNode->node(); } -scene::Node& loadMD5Model( ArchiveFile& file ){ - BinaryToTextInputStream inputStream( file.getInputStream() ); - return MD5Model_new( inputStream ); +scene::Node &loadMD5Model(ArchiveFile &file) +{ + BinaryToTextInputStream inputStream(file.getInputStream()); + return MD5Model_new(inputStream); } diff --git a/plugins/md3model/md5.h b/plugins/md3model/md5.h index bcddd0d7..21dc0391 100644 --- a/plugins/md3model/md5.h +++ b/plugins/md3model/md5.h @@ -24,6 +24,7 @@ namespace scene { class Node; } class ArchiveFile; -scene::Node& loadMD5Model( ArchiveFile& file ); + +scene::Node &loadMD5Model(ArchiveFile &file); #endif diff --git a/plugins/md3model/mdc.cpp b/plugins/md3model/mdc.cpp index db333189..3d8675b7 100644 --- a/plugins/md3model/mdc.cpp +++ b/plugins/md3model/mdc.cpp @@ -32,247 +32,246 @@ #include "md3normals.h" -const unsigned char MDC_IDENT[4] = { 'I', 'D', 'P', 'C', }; +const unsigned char MDC_IDENT[4] = {'I', 'D', 'P', 'C',}; const float MDC_XYZ_SCALE = 0.015625f; const int MAX_QPATH = 64; // max length of a quake game pathname typedef float float3[3]; -struct mdcTriangle_t -{ - unsigned int indexes[3]; // not my spelling +struct mdcTriangle_t { + unsigned int indexes[3]; // not my spelling }; -void istream_read_mdcTriangle( PointerInputStream& inputStream, mdcTriangle_t& triangle ){ - triangle.indexes[0] = istream_read_uint32_le( inputStream ); - triangle.indexes[1] = istream_read_uint32_le( inputStream ); - triangle.indexes[2] = istream_read_uint32_le( inputStream ); +void istream_read_mdcTriangle(PointerInputStream &inputStream, mdcTriangle_t &triangle) +{ + triangle.indexes[0] = istream_read_uint32_le(inputStream); + triangle.indexes[1] = istream_read_uint32_le(inputStream); + triangle.indexes[2] = istream_read_uint32_le(inputStream); } -struct mdcXyzNormal_t -{ - short xyz[3]; // divide by 64 - short normal; // packed same way as md3 +struct mdcXyzNormal_t { + short xyz[3]; // divide by 64 + short normal; // packed same way as md3 }; -void istream_read_mdcXyzNormal( PointerInputStream& inputStream, mdcXyzNormal_t& xyz ){ - xyz.xyz[0] = istream_read_int16_le( inputStream ); - xyz.xyz[1] = istream_read_int16_le( inputStream ); - xyz.xyz[2] = istream_read_int16_le( inputStream ); - xyz.normal = istream_read_int16_le( inputStream ); +void istream_read_mdcXyzNormal(PointerInputStream &inputStream, mdcXyzNormal_t &xyz) +{ + xyz.xyz[0] = istream_read_int16_le(inputStream); + xyz.xyz[1] = istream_read_int16_le(inputStream); + xyz.xyz[2] = istream_read_int16_le(inputStream); + xyz.normal = istream_read_int16_le(inputStream); } -struct mdcSt_t -{ - float st[2]; // may need to reverse t +struct mdcSt_t { + float st[2]; // may need to reverse t }; -void istream_read_mdcSt( PointerInputStream& inputStream, mdcSt_t& st ){ - st.st[0] = istream_read_float32_le( inputStream ); - st.st[1] = istream_read_float32_le( inputStream ); +void istream_read_mdcSt(PointerInputStream &inputStream, mdcSt_t &st) +{ + st.st[0] = istream_read_float32_le(inputStream); + st.st[1] = istream_read_float32_le(inputStream); } -struct mdcShader_t -{ - char name[MAX_QPATH]; - unsigned int flags; +struct mdcShader_t { + char name[MAX_QPATH]; + unsigned int flags; }; -void istream_read_mdcShader( PointerInputStream& inputStream, mdcShader_t& shader ){ - inputStream.read( reinterpret_cast( shader.name ), MAX_QPATH ); - shader.flags = istream_read_uint32_le( inputStream ); +void istream_read_mdcShader(PointerInputStream &inputStream, mdcShader_t &shader) +{ + inputStream.read(reinterpret_cast( shader.name ), MAX_QPATH); + shader.flags = istream_read_uint32_le(inputStream); } -struct mdcTagName_t -{ - char name[MAX_QPATH]; +struct mdcTagName_t { + char name[MAX_QPATH]; }; -struct mdcTagFrame_t -{ - short xyz[3]; // divide by 64 - short angles[3]; // euler in z x y order... deg = * (360.0 / 32767.0) .. rad = * (PI / 32767.0) +struct mdcTagFrame_t { + short xyz[3]; // divide by 64 + short angles[3]; // euler in z x y order... deg = * (360.0 / 32767.0) .. rad = * (PI / 32767.0) }; -struct mdcFrame_t -{ - float3 bboxMin; - float3 bboxMax; - float3 localOrigin; - float radius; - char name[16]; +struct mdcFrame_t { + float3 bboxMin; + float3 bboxMax; + float3 localOrigin; + float radius; + char name[16]; }; -struct mdcSurface_t -{ - byte ident[4]; - char name[MAX_QPATH]; - unsigned int flags; - unsigned int numCompFrames; - unsigned int numBaseFrames; - unsigned int numShaders; - unsigned int numVerts; - unsigned int numTriangles; - unsigned int ofsTriangles; - unsigned int ofsShaders; - unsigned int ofsSt; - unsigned int ofsXyzNormals; - unsigned int ofsCompVerts; - unsigned int ofsFrameBaseFrames; - unsigned int ofsFrameCompFrames; - unsigned int ofsEnd; +struct mdcSurface_t { + byte ident[4]; + char name[MAX_QPATH]; + unsigned int flags; + unsigned int numCompFrames; + unsigned int numBaseFrames; + unsigned int numShaders; + unsigned int numVerts; + unsigned int numTriangles; + unsigned int ofsTriangles; + unsigned int ofsShaders; + unsigned int ofsSt; + unsigned int ofsXyzNormals; + unsigned int ofsCompVerts; + unsigned int ofsFrameBaseFrames; + unsigned int ofsFrameCompFrames; + unsigned int ofsEnd; }; -void istream_read_mdcSurface( PointerInputStream& inputStream, mdcSurface_t& surface ){ - inputStream.read( surface.ident, 4 ); - inputStream.read( reinterpret_cast( surface.name ), MAX_QPATH ); - surface.flags = istream_read_uint32_le( inputStream ); - surface.numCompFrames = istream_read_uint32_le( inputStream ); - surface.numBaseFrames = istream_read_uint32_le( inputStream ); - surface.numShaders = istream_read_uint32_le( inputStream ); - surface.numVerts = istream_read_uint32_le( inputStream ); - surface.numTriangles = istream_read_uint32_le( inputStream ); - surface.ofsTriangles = istream_read_uint32_le( inputStream ); - surface.ofsShaders = istream_read_uint32_le( inputStream ); - surface.ofsSt = istream_read_uint32_le( inputStream ); - surface.ofsXyzNormals = istream_read_uint32_le( inputStream ); - surface.ofsCompVerts = istream_read_uint32_le( inputStream ); - surface.ofsFrameBaseFrames = istream_read_uint32_le( inputStream ); - surface.ofsFrameCompFrames = istream_read_uint32_le( inputStream ); - surface.ofsEnd = istream_read_uint32_le( inputStream ); +void istream_read_mdcSurface(PointerInputStream &inputStream, mdcSurface_t &surface) +{ + inputStream.read(surface.ident, 4); + inputStream.read(reinterpret_cast( surface.name ), MAX_QPATH); + surface.flags = istream_read_uint32_le(inputStream); + surface.numCompFrames = istream_read_uint32_le(inputStream); + surface.numBaseFrames = istream_read_uint32_le(inputStream); + surface.numShaders = istream_read_uint32_le(inputStream); + surface.numVerts = istream_read_uint32_le(inputStream); + surface.numTriangles = istream_read_uint32_le(inputStream); + surface.ofsTriangles = istream_read_uint32_le(inputStream); + surface.ofsShaders = istream_read_uint32_le(inputStream); + surface.ofsSt = istream_read_uint32_le(inputStream); + surface.ofsXyzNormals = istream_read_uint32_le(inputStream); + surface.ofsCompVerts = istream_read_uint32_le(inputStream); + surface.ofsFrameBaseFrames = istream_read_uint32_le(inputStream); + surface.ofsFrameCompFrames = istream_read_uint32_le(inputStream); + surface.ofsEnd = istream_read_uint32_le(inputStream); } -struct mdcHeader_t -{ - byte ident[4]; - unsigned int version; - char name[MAX_QPATH]; - unsigned int flags; - unsigned int numFrames; - unsigned int numTags; - unsigned int numSurfaces; - unsigned int numSkins; - unsigned int ofsFrames; - unsigned int ofsTagNames; - unsigned int ofsTags; - unsigned int ofsSurfaces; - unsigned int ofsEnd; +struct mdcHeader_t { + byte ident[4]; + unsigned int version; + char name[MAX_QPATH]; + unsigned int flags; + unsigned int numFrames; + unsigned int numTags; + unsigned int numSurfaces; + unsigned int numSkins; + unsigned int ofsFrames; + unsigned int ofsTagNames; + unsigned int ofsTags; + unsigned int ofsSurfaces; + unsigned int ofsEnd; }; -void istream_read_mdcHeader( PointerInputStream& inputStream, mdcHeader_t& header ){ - inputStream.read( header.ident, 4 ); - header.version = istream_read_uint32_le( inputStream ); - inputStream.read( reinterpret_cast( header.name ), MAX_QPATH ); - header.flags = istream_read_uint32_le( inputStream ); - header.numFrames = istream_read_uint32_le( inputStream ); - header.numTags = istream_read_uint32_le( inputStream ); - header.numSurfaces = istream_read_uint32_le( inputStream ); - header.numSkins = istream_read_uint32_le( inputStream ); - header.ofsFrames = istream_read_uint32_le( inputStream ); - header.ofsTagNames = istream_read_uint32_le( inputStream ); - header.ofsTags = istream_read_uint32_le( inputStream ); - header.ofsSurfaces = istream_read_uint32_le( inputStream ); - header.ofsEnd = istream_read_uint32_le( inputStream ); +void istream_read_mdcHeader(PointerInputStream &inputStream, mdcHeader_t &header) +{ + inputStream.read(header.ident, 4); + header.version = istream_read_uint32_le(inputStream); + inputStream.read(reinterpret_cast( header.name ), MAX_QPATH); + header.flags = istream_read_uint32_le(inputStream); + header.numFrames = istream_read_uint32_le(inputStream); + header.numTags = istream_read_uint32_le(inputStream); + header.numSurfaces = istream_read_uint32_le(inputStream); + header.numSkins = istream_read_uint32_le(inputStream); + header.ofsFrames = istream_read_uint32_le(inputStream); + header.ofsTagNames = istream_read_uint32_le(inputStream); + header.ofsTags = istream_read_uint32_le(inputStream); + header.ofsSurfaces = istream_read_uint32_le(inputStream); + header.ofsEnd = istream_read_uint32_le(inputStream); } -unsigned int MDCSurface_read( Surface& surface, const byte* buffer ){ - mdcSurface_t mdcSurface; - { - PointerInputStream inputStream( buffer ); - istream_read_mdcSurface( inputStream, mdcSurface ); - } - - { - surface.vertices().reserve( mdcSurface.numVerts ); - - PointerInputStream xyzStream( buffer + mdcSurface.ofsXyzNormals ); - PointerInputStream stStream( buffer + mdcSurface.ofsSt ); - // read verts into vertex array - xyz, st, normal - for ( std::size_t i = 0; i < mdcSurface.numVerts; i++ ) - { - mdcXyzNormal_t mdcXyzNormal; - istream_read_mdcXyzNormal( xyzStream, mdcXyzNormal ); - mdcSt_t mdcSt; - istream_read_mdcSt( stStream, mdcSt ); - - surface.vertices().push_back( - ArbitraryMeshVertex( - Vertex3f( mdcXyzNormal.xyz[0] * MDC_XYZ_SCALE, mdcXyzNormal.xyz[1] * MDC_XYZ_SCALE, mdcXyzNormal.xyz[2] * MDC_XYZ_SCALE ), - DecodeNormal( reinterpret_cast( &mdcXyzNormal.normal ) ), - TexCoord2f( mdcSt.st[0], mdcSt.st[1] ) - ) - ); - } - } - - { - surface.indices().reserve( mdcSurface.numTriangles * 3 ); - - PointerInputStream triangleStream( buffer + mdcSurface.ofsTriangles ); - - for ( std::size_t i = 0; i < mdcSurface.numTriangles; i++ ) - { - mdcTriangle_t triangle; - istream_read_mdcTriangle( triangleStream, triangle ); - surface.indices().insert( triangle.indexes[0] ); - surface.indices().insert( triangle.indexes[1] ); - surface.indices().insert( triangle.indexes[2] ); - } - } - - { - mdcShader_t shader; - PointerInputStream inputStream( buffer + mdcSurface.ofsShaders ); - istream_read_mdcShader( inputStream, shader ); - surface.setShader( shader.name ); - } - - surface.updateAABB(); - - return mdcSurface.ofsEnd; +unsigned int MDCSurface_read(Surface &surface, const byte *buffer) +{ + mdcSurface_t mdcSurface; + { + PointerInputStream inputStream(buffer); + istream_read_mdcSurface(inputStream, mdcSurface); + } + + { + surface.vertices().reserve(mdcSurface.numVerts); + + PointerInputStream xyzStream(buffer + mdcSurface.ofsXyzNormals); + PointerInputStream stStream(buffer + mdcSurface.ofsSt); + // read verts into vertex array - xyz, st, normal + for (std::size_t i = 0; i < mdcSurface.numVerts; i++) { + mdcXyzNormal_t mdcXyzNormal; + istream_read_mdcXyzNormal(xyzStream, mdcXyzNormal); + mdcSt_t mdcSt; + istream_read_mdcSt(stStream, mdcSt); + + surface.vertices().push_back( + ArbitraryMeshVertex( + Vertex3f(mdcXyzNormal.xyz[0] * MDC_XYZ_SCALE, mdcXyzNormal.xyz[1] * MDC_XYZ_SCALE, + mdcXyzNormal.xyz[2] * MDC_XYZ_SCALE), + DecodeNormal(reinterpret_cast( &mdcXyzNormal.normal )), + TexCoord2f(mdcSt.st[0], mdcSt.st[1]) + ) + ); + } + } + + { + surface.indices().reserve(mdcSurface.numTriangles * 3); + + PointerInputStream triangleStream(buffer + mdcSurface.ofsTriangles); + + for (std::size_t i = 0; i < mdcSurface.numTriangles; i++) { + mdcTriangle_t triangle; + istream_read_mdcTriangle(triangleStream, triangle); + surface.indices().insert(triangle.indexes[0]); + surface.indices().insert(triangle.indexes[1]); + surface.indices().insert(triangle.indexes[2]); + } + } + + { + mdcShader_t shader; + PointerInputStream inputStream(buffer + mdcSurface.ofsShaders); + istream_read_mdcShader(inputStream, shader); + surface.setShader(shader.name); + } + + surface.updateAABB(); + + return mdcSurface.ofsEnd; } -void MDCModel_read( Model& model, const byte* buffer ){ - mdcHeader_t header; - { - PointerInputStream inputStream( buffer ); - istream_read_mdcHeader( inputStream, header ); - } +void MDCModel_read(Model &model, const byte *buffer) +{ + mdcHeader_t header; + { + PointerInputStream inputStream(buffer); + istream_read_mdcHeader(inputStream, header); + } - const byte* surfacePosition = buffer + header.ofsSurfaces; + const byte *surfacePosition = buffer + header.ofsSurfaces; - for ( std::size_t i = 0; i < header.numSurfaces; i++ ) - { - surfacePosition += MDCSurface_read( model.newSurface(), surfacePosition ); - } + for (std::size_t i = 0; i < header.numSurfaces; i++) { + surfacePosition += MDCSurface_read(model.newSurface(), surfacePosition); + } - model.updateAABB(); + model.updateAABB(); } -scene::Node& MDCModel_new( const byte* buffer ){ - ModelNode* modelNode = new ModelNode(); - MDCModel_read( modelNode->model(), buffer ); - return modelNode->node(); +scene::Node &MDCModel_new(const byte *buffer) +{ + ModelNode *modelNode = new ModelNode(); + MDCModel_read(modelNode->model(), buffer); + return modelNode->node(); } -scene::Node& MDCModel_default(){ - ModelNode* modelNode = new ModelNode(); - Model_constructNull( modelNode->model() ); - return modelNode->node(); +scene::Node &MDCModel_default() +{ + ModelNode *modelNode = new ModelNode(); + Model_constructNull(modelNode->model()); + return modelNode->node(); } -scene::Node& MDCModel_fromBuffer( unsigned char* buffer ){ - if ( !ident_equal( buffer, MDC_IDENT ) ) { - globalErrorStream() << "MDC read error: incorrect ident\n"; - return MDCModel_default(); - } - else - { - return MDCModel_new( buffer ); - } +scene::Node &MDCModel_fromBuffer(unsigned char *buffer) +{ + if (!ident_equal(buffer, MDC_IDENT)) { + globalErrorStream() << "MDC read error: incorrect ident\n"; + return MDCModel_default(); + } else { + return MDCModel_new(buffer); + } } -scene::Node& loadMDCModel( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return MDCModel_fromBuffer( buffer.buffer ); +scene::Node &loadMDCModel(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return MDCModel_fromBuffer(buffer.buffer); } diff --git a/plugins/md3model/mdc.h b/plugins/md3model/mdc.h index 1f88439b..82f85a60 100644 --- a/plugins/md3model/mdc.h +++ b/plugins/md3model/mdc.h @@ -24,7 +24,8 @@ namespace scene { class Node; } class ArchiveFile; -scene::Node& loadMDCModel( ArchiveFile& file ); + +scene::Node &loadMDCModel(ArchiveFile &file); #endif diff --git a/plugins/md3model/mdl.cpp b/plugins/md3model/mdl.cpp index 6fe16c41..a52a9085 100644 --- a/plugins/md3model/mdl.cpp +++ b/plugins/md3model/mdl.cpp @@ -32,202 +32,205 @@ #include "mdlnormals.h" #include "mdlformat.h" -void istream_read_mdlHeader( PointerInputStream& inputStream, mdlHeader_t& header ){ - inputStream.read( header.ident, 4 ); - header.version = istream_read_int32_le( inputStream ); - header.scale[0] = istream_read_float32_le( inputStream ); - header.scale[1] = istream_read_float32_le( inputStream ); - header.scale[2] = istream_read_float32_le( inputStream ); - header.scale_origin[0] = istream_read_float32_le( inputStream ); - header.scale_origin[1] = istream_read_float32_le( inputStream ); - header.scale_origin[2] = istream_read_float32_le( inputStream ); - header.boundingradius = istream_read_float32_le( inputStream ); - header.eyeposition[0] = istream_read_float32_le( inputStream ); - header.eyeposition[1] = istream_read_float32_le( inputStream ); - header.eyeposition[2] = istream_read_float32_le( inputStream ); - header.numskins = istream_read_int32_le( inputStream ); - header.skinwidth = istream_read_int32_le( inputStream ); - header.skinheight = istream_read_int32_le( inputStream ); - header.numverts = istream_read_int32_le( inputStream ); - header.numtris = istream_read_int32_le( inputStream ); - header.numframes = istream_read_int32_le( inputStream ); - header.synctype = istream_read_int32_le( inputStream ); - header.flags = istream_read_int32_le( inputStream ); - header.size = istream_read_float32_le( inputStream ); -} - -inline ArbitraryMeshVertex MDLVertex_construct( const mdlHeader_t& header, const mdlXyzNormal_t& xyz, const mdlSt_t& st, bool facesfront ){ - return ArbitraryMeshVertex( - Vertex3f( - xyz.v[0] * header.scale[0] + header.scale_origin[0], - xyz.v[1] * header.scale[1] + header.scale_origin[1], - xyz.v[2] * header.scale[2] + header.scale_origin[2] - ), - Normal3f( - g_mdl_normals[xyz.lightnormalindex][0], - g_mdl_normals[xyz.lightnormalindex][1], - g_mdl_normals[xyz.lightnormalindex][2] - ), - TexCoord2f( - ( (float)st.s / header.skinwidth ) + ( ( st.onseam == MDL_ONSEAM && !facesfront ) ? 0.5f : 0.0f ), - (float)st.t / header.skinheight - ) - ); +void istream_read_mdlHeader(PointerInputStream &inputStream, mdlHeader_t &header) +{ + inputStream.read(header.ident, 4); + header.version = istream_read_int32_le(inputStream); + header.scale[0] = istream_read_float32_le(inputStream); + header.scale[1] = istream_read_float32_le(inputStream); + header.scale[2] = istream_read_float32_le(inputStream); + header.scale_origin[0] = istream_read_float32_le(inputStream); + header.scale_origin[1] = istream_read_float32_le(inputStream); + header.scale_origin[2] = istream_read_float32_le(inputStream); + header.boundingradius = istream_read_float32_le(inputStream); + header.eyeposition[0] = istream_read_float32_le(inputStream); + header.eyeposition[1] = istream_read_float32_le(inputStream); + header.eyeposition[2] = istream_read_float32_le(inputStream); + header.numskins = istream_read_int32_le(inputStream); + header.skinwidth = istream_read_int32_le(inputStream); + header.skinheight = istream_read_int32_le(inputStream); + header.numverts = istream_read_int32_le(inputStream); + header.numtris = istream_read_int32_le(inputStream); + header.numframes = istream_read_int32_le(inputStream); + header.synctype = istream_read_int32_le(inputStream); + header.flags = istream_read_int32_le(inputStream); + header.size = istream_read_float32_le(inputStream); } -class mdlVertex_t +inline ArbitraryMeshVertex +MDLVertex_construct(const mdlHeader_t &header, const mdlXyzNormal_t &xyz, const mdlSt_t &st, bool facesfront) { -public: -inline mdlVertex_t( int vertindex, int facesfront ) - : m_vertindex( vertindex ), m_facesfront( facesfront ) -{} -inline bool operator<( const mdlVertex_t& other ) const { - if ( m_facesfront < other.m_facesfront ) { - return true; - } - if ( other.m_facesfront < m_facesfront ) { - return false; - } - - if ( m_vertindex < other.m_vertindex ) { - return true; - } - if ( other.m_vertindex < m_vertindex ) { - return false; - } - - return false; -} -inline bool operator==( const mdlVertex_t& other ) const { - return m_vertindex == other.m_vertindex - && m_facesfront == other.m_facesfront; + return ArbitraryMeshVertex( + Vertex3f( + xyz.v[0] * header.scale[0] + header.scale_origin[0], + xyz.v[1] * header.scale[1] + header.scale_origin[1], + xyz.v[2] * header.scale[2] + header.scale_origin[2] + ), + Normal3f( + g_mdl_normals[xyz.lightnormalindex][0], + g_mdl_normals[xyz.lightnormalindex][1], + g_mdl_normals[xyz.lightnormalindex][2] + ), + TexCoord2f( + ((float) st.s / header.skinwidth) + ((st.onseam == MDL_ONSEAM && !facesfront) ? 0.5f : 0.0f), + (float) st.t / header.skinheight + ) + ); } -int m_vertindex; -int m_facesfront; +class mdlVertex_t { +public: + inline mdlVertex_t(int vertindex, int facesfront) + : m_vertindex(vertindex), m_facesfront(facesfront) + {} + + inline bool operator<(const mdlVertex_t &other) const + { + if (m_facesfront < other.m_facesfront) { + return true; + } + if (other.m_facesfront < m_facesfront) { + return false; + } + + if (m_vertindex < other.m_vertindex) { + return true; + } + if (other.m_vertindex < m_vertindex) { + return false; + } + + return false; + } + + inline bool operator==(const mdlVertex_t &other) const + { + return m_vertindex == other.m_vertindex + && m_facesfront == other.m_facesfront; + } + + int m_vertindex; + int m_facesfront; }; -typedef const mdlTriangle_t* mdlTriangleIterator; - -void MDLSurface_read( Surface& surface, const byte* buffer, const char* name ){ - mdlHeader_t header; - - PointerInputStream inputStream( buffer ); - istream_read_mdlHeader( inputStream, header ); - - for ( int i = 0; i < header.numskins; ++i ) - { - switch ( istream_read_int32_le( inputStream ) ) - { - case MDL_SKIN_SINGLE: - inputStream.seek( header.skinwidth * header.skinheight ); - break; - case MDL_SKIN_GROUP: - int numskins = istream_read_int32_le( inputStream ); - inputStream.seek( numskins * ( 4 + ( header.skinwidth * header.skinheight ) ) ); - break; - } - } - - Array mdlSts( header.numverts ); - for ( Array::iterator i = mdlSts.begin(); i != mdlSts.end(); ++i ) - { - ( *i ).onseam = istream_read_int32_le( inputStream ); - ( *i ).s = istream_read_int32_le( inputStream ); - ( *i ).t = istream_read_int32_le( inputStream ); - } - - Array mdlTriangles( header.numtris ); - for ( Array::iterator i = mdlTriangles.begin(); i != mdlTriangles.end(); ++i ) - { - ( *i ).facesfront = istream_read_int32_le( inputStream ); - ( *i ).vertindex[0] = istream_read_int32_le( inputStream ); - ( *i ).vertindex[1] = istream_read_int32_le( inputStream ); - ( *i ).vertindex[2] = istream_read_int32_le( inputStream ); - } - - { - bool found = false; - for ( int i = 0; i < header.numframes && found == false; i++ ) - { - switch ( istream_read_int32_le( inputStream ) ) - { - case MDL_FRAME_SINGLE: - inputStream.seek( MDL_FRAME_SIZE ); - found = true; - break; - case MDL_FRAME_GROUP: - int numframes = istream_read_int32_le( inputStream ); - inputStream.seek( ( MDL_XYZNORMAL_SIZE * 2 ) + ( numframes * 4 ) ); - found = true; - break; - } - } - } - - Array mdlXyzNormals( header.numtris ); - for ( Array::iterator i = mdlXyzNormals.begin(); i != mdlXyzNormals.end(); ++i ) - { - inputStream.read( ( *i ).v, 3 ); - inputStream.read( &( *i ).lightnormalindex, 1 ); - } - - { - VertexBuffer mdl_vertices; - - { - UniqueVertexBuffer inserter( mdl_vertices ); - for ( Array::iterator i = mdlTriangles.begin(); i != mdlTriangles.end(); ++i ) - { - surface.indices().insert( inserter.insert( mdlVertex_t( ( *i ).vertindex[0], ( *i ).facesfront ) ) ); - surface.indices().insert( inserter.insert( mdlVertex_t( ( *i ).vertindex[1], ( *i ).facesfront ) ) ); - surface.indices().insert( inserter.insert( mdlVertex_t( ( *i ).vertindex[2], ( *i ).facesfront ) ) ); - } - } - - { - surface.vertices().reserve( mdl_vertices.size() ); - - for ( VertexBuffer::iterator i = mdl_vertices.begin(); i != mdl_vertices.end(); ++i ) - { - surface.vertices().push_back( MDLVertex_construct( header, mdlXyzNormals[( *i ).m_vertindex], mdlSts[( *i ).m_vertindex], ( *i ).m_facesfront == MDL_FACES_FRONT ) ); - } - } - } - - surface.setShader( name ); - surface.updateAABB(); +typedef const mdlTriangle_t *mdlTriangleIterator; + +void MDLSurface_read(Surface &surface, const byte *buffer, const char *name) +{ + mdlHeader_t header; + + PointerInputStream inputStream(buffer); + istream_read_mdlHeader(inputStream, header); + + for (int i = 0; i < header.numskins; ++i) { + switch (istream_read_int32_le(inputStream)) { + case MDL_SKIN_SINGLE: + inputStream.seek(header.skinwidth * header.skinheight); + break; + case MDL_SKIN_GROUP: + int numskins = istream_read_int32_le(inputStream); + inputStream.seek(numskins * (4 + (header.skinwidth * header.skinheight))); + break; + } + } + + Array mdlSts(header.numverts); + for (Array::iterator i = mdlSts.begin(); i != mdlSts.end(); ++i) { + (*i).onseam = istream_read_int32_le(inputStream); + (*i).s = istream_read_int32_le(inputStream); + (*i).t = istream_read_int32_le(inputStream); + } + + Array mdlTriangles(header.numtris); + for (Array::iterator i = mdlTriangles.begin(); i != mdlTriangles.end(); ++i) { + (*i).facesfront = istream_read_int32_le(inputStream); + (*i).vertindex[0] = istream_read_int32_le(inputStream); + (*i).vertindex[1] = istream_read_int32_le(inputStream); + (*i).vertindex[2] = istream_read_int32_le(inputStream); + } + + { + bool found = false; + for (int i = 0; i < header.numframes && found == false; i++) { + switch (istream_read_int32_le(inputStream)) { + case MDL_FRAME_SINGLE: + inputStream.seek(MDL_FRAME_SIZE); + found = true; + break; + case MDL_FRAME_GROUP: + int numframes = istream_read_int32_le(inputStream); + inputStream.seek((MDL_XYZNORMAL_SIZE * 2) + (numframes * 4)); + found = true; + break; + } + } + } + + Array mdlXyzNormals(header.numtris); + for (Array::iterator i = mdlXyzNormals.begin(); i != mdlXyzNormals.end(); ++i) { + inputStream.read((*i).v, 3); + inputStream.read(&(*i).lightnormalindex, 1); + } + + { + VertexBuffer mdl_vertices; + + { + UniqueVertexBuffer inserter(mdl_vertices); + for (Array::iterator i = mdlTriangles.begin(); i != mdlTriangles.end(); ++i) { + surface.indices().insert(inserter.insert(mdlVertex_t((*i).vertindex[0], (*i).facesfront))); + surface.indices().insert(inserter.insert(mdlVertex_t((*i).vertindex[1], (*i).facesfront))); + surface.indices().insert(inserter.insert(mdlVertex_t((*i).vertindex[2], (*i).facesfront))); + } + } + + { + surface.vertices().reserve(mdl_vertices.size()); + + for (VertexBuffer::iterator i = mdl_vertices.begin(); i != mdl_vertices.end(); ++i) { + surface.vertices().push_back( + MDLVertex_construct(header, mdlXyzNormals[(*i).m_vertindex], mdlSts[(*i).m_vertindex], + (*i).m_facesfront == MDL_FACES_FRONT)); + } + } + } + + surface.setShader(name); + surface.updateAABB(); } -void MDLModel_read( Model& model, const byte* buffer, const char* name ){ - MDLSurface_read( model.newSurface(), buffer, name ); - model.updateAABB(); +void MDLModel_read(Model &model, const byte *buffer, const char *name) +{ + MDLSurface_read(model.newSurface(), buffer, name); + model.updateAABB(); } -scene::Node& MDLModel_new( const byte* buffer, const char* name ){ - ModelNode* modelNode = new ModelNode(); - MDLModel_read( modelNode->model(), buffer, name ); - return modelNode->node(); +scene::Node &MDLModel_new(const byte *buffer, const char *name) +{ + ModelNode *modelNode = new ModelNode(); + MDLModel_read(modelNode->model(), buffer, name); + return modelNode->node(); } -scene::Node& MDLModel_default(){ - ModelNode* modelNode = new ModelNode(); - Model_constructNull( modelNode->model() ); - return modelNode->node(); +scene::Node &MDLModel_default() +{ + ModelNode *modelNode = new ModelNode(); + Model_constructNull(modelNode->model()); + return modelNode->node(); } -scene::Node& MDLModel_fromBuffer( unsigned char* buffer, const char* name ){ - if ( !ident_equal( buffer, MDL_IDENT ) ) { - globalErrorStream() << "MDL read error: incorrect ident\n"; - return MDLModel_default(); - } - else - { - return MDLModel_new( buffer, name ); - } +scene::Node &MDLModel_fromBuffer(unsigned char *buffer, const char *name) +{ + if (!ident_equal(buffer, MDL_IDENT)) { + globalErrorStream() << "MDL read error: incorrect ident\n"; + return MDLModel_default(); + } else { + return MDLModel_new(buffer, name); + } } -scene::Node& loadMDLModel( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return MDLModel_fromBuffer( buffer.buffer, file.getName() ); +scene::Node &loadMDLModel(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return MDLModel_fromBuffer(buffer.buffer, file.getName()); } diff --git a/plugins/md3model/mdl.h b/plugins/md3model/mdl.h index dd893b71..22d275b8 100644 --- a/plugins/md3model/mdl.h +++ b/plugins/md3model/mdl.h @@ -24,6 +24,7 @@ namespace scene { class Node; } class ArchiveFile; -scene::Node& loadMDLModel( ArchiveFile& file ); + +scene::Node &loadMDLModel(ArchiveFile &file); #endif diff --git a/plugins/md3model/mdlformat.h b/plugins/md3model/mdlformat.h index 948c5439..2a6964a5 100644 --- a/plugins/md3model/mdlformat.h +++ b/plugins/md3model/mdlformat.h @@ -24,7 +24,7 @@ typedef unsigned char byte; -const unsigned char MDL_IDENT[4] = { 'I', 'D', 'P', 'O', }; +const unsigned char MDL_IDENT[4] = {'I', 'D', 'P', 'O',}; #define MDL_VERSION 6 @@ -37,34 +37,34 @@ typedef enum { MDL_SKIN_SINGLE = 0, MDL_SKIN_GROUP } aliasskintype_t; typedef float float3[3]; typedef struct { - byte ident[4]; - int version; - float3 scale; - float3 scale_origin; - float boundingradius; - float3 eyeposition; - int numskins; - int skinwidth; - int skinheight; - int numverts; - int numtris; - int numframes; - int synctype; - int flags; - float size; + byte ident[4]; + int version; + float3 scale; + float3 scale_origin; + float boundingradius; + float3 eyeposition; + int numskins; + int skinwidth; + int skinheight; + int numverts; + int numtris; + int numframes; + int synctype; + int flags; + float size; } mdlHeader_t; // TODO: could be shorts typedef struct { - int onseam; - int s; - int t; + int onseam; + int s; + int t; } mdlSt_t; typedef struct dtriangle_s { - int facesfront; - int vertindex[3]; + int facesfront; + int vertindex[3]; } mdlTriangle_t; #define MDL_FACES_FRONT 1 @@ -73,46 +73,46 @@ typedef struct dtriangle_s { // load this data typedef struct { - byte v[3]; - byte lightnormalindex; + byte v[3]; + byte lightnormalindex; } mdlXyzNormal_t; const int MDL_XYZNORMAL_SIZE = 4; typedef struct { - mdlXyzNormal_t bboxmin; // lightnormal isn't used - mdlXyzNormal_t bboxmax; // lightnormal isn't used - char name[16]; // frame name from grabbing + mdlXyzNormal_t bboxmin; // lightnormal isn't used + mdlXyzNormal_t bboxmax; // lightnormal isn't used + char name[16]; // frame name from grabbing } mdlFrame_t; -const int MDL_FRAME_SIZE = ( MDL_XYZNORMAL_SIZE * 2 ) + 16; +const int MDL_FRAME_SIZE = (MDL_XYZNORMAL_SIZE * 2) + 16; typedef struct { - int numframes; - mdlXyzNormal_t bboxmin; // lightnormal isn't used - mdlXyzNormal_t bboxmax; // lightnormal isn't used + int numframes; + mdlXyzNormal_t bboxmin; // lightnormal isn't used + mdlXyzNormal_t bboxmax; // lightnormal isn't used } mdlFrameGroup_t; -const int MDL_FRAMEGROUP_SIZE = 4 + ( MDL_XYZNORMAL_SIZE * 2 ); +const int MDL_FRAMEGROUP_SIZE = 4 + (MDL_XYZNORMAL_SIZE * 2); typedef struct { - int numskins; + int numskins; } mdlSkinGroup_t; typedef struct { - float interval; + float interval; } mdlFrameInterval_t; typedef struct { - float interval; + float interval; } mdlSkinInterval_t; typedef struct { - aliasframetype_t type; + aliasframetype_t type; } mdlFrameType_t; typedef struct { - aliasskintype_t type; + aliasskintype_t type; } mdlSkinType_t; #endif diff --git a/plugins/md3model/mdlimage.cpp b/plugins/md3model/mdlimage.cpp index 3ab4e9e0..fe2d66cf 100644 --- a/plugins/md3model/mdlimage.cpp +++ b/plugins/md3model/mdlimage.cpp @@ -35,122 +35,122 @@ unsigned char mdl_palette[768]; + /* ============== Texture_InitPalette ============== */ -void Texture_InitPalette( byte *pal ){ - int r,g,b; - int i; - int inf; - byte gammatable[256]; - double gamma; - - gamma = 1.0; //g_qeglobals.d_savedinfo.fGamma; - - if ( gamma == 1.0 ) { - for ( i = 0 ; i < 256 ; i++ ) - gammatable[i] = i; - } - else - { - for ( i = 0 ; i < 256 ; i++ ) - { - inf = (int)( 255 * pow( ( i + 0.5 ) / 255.5, gamma ) + 0.5 ); - if ( inf < 0 ) { - inf = 0; - } - if ( inf > 255 ) { - inf = 255; - } - gammatable[i] = inf; - } - } - - for ( i = 0 ; i < 256 ; i++ ) - { - r = gammatable[pal[0]]; - g = gammatable[pal[1]]; - b = gammatable[pal[2]]; - pal += 3; - - //v = (r<<24) + (g<<16) + (b<<8) + 255; - //v = BigLong (v); - - //mdl_palette[i] = v; - mdl_palette[i * 3 + 0] = r; - mdl_palette[i * 3 + 1] = g; - mdl_palette[i * 3 + 2] = b; - } +void Texture_InitPalette(byte *pal) +{ + int r, g, b; + int i; + int inf; + byte gammatable[256]; + double gamma; + + gamma = 1.0; //g_qeglobals.d_savedinfo.fGamma; + + if (gamma == 1.0) { + for (i = 0; i < 256; i++) { + gammatable[i] = i; + } + } else { + for (i = 0; i < 256; i++) { + inf = (int) (255 * pow((i + 0.5) / 255.5, gamma) + 0.5); + if (inf < 0) { + inf = 0; + } + if (inf > 255) { + inf = 255; + } + gammatable[i] = inf; + } + } + + for (i = 0; i < 256; i++) { + r = gammatable[pal[0]]; + g = gammatable[pal[1]]; + b = gammatable[pal[2]]; + pal += 3; + + //v = (r<<24) + (g<<16) + (b<<8) + 255; + //v = BigLong (v); + + //mdl_palette[i] = v; + mdl_palette[i * 3 + 0] = r; + mdl_palette[i * 3 + 1] = g; + mdl_palette[i * 3 + 2] = b; + } } -bool LoadPalette(){ - unsigned char* buffer; - //int len = - vfsLoadFile( "gfx/palette.lmp", (void **) &buffer ); - if ( buffer == 0 ) { - return false; - } +bool LoadPalette() +{ + unsigned char *buffer; + //int len = + vfsLoadFile("gfx/palette.lmp", (void **) &buffer); + if (buffer == 0) { + return false; + } - Texture_InitPalette( buffer ); + Texture_InitPalette(buffer); - vfsFreeFile( buffer ); + vfsFreeFile(buffer); - return true; + return true; } -Image* LoadMDLImageBuff( byte* buffer ){ - if ( !LoadPalette() ) { - return 0; - } - - if ( !ident_equal( buffer, MDL_IDENT ) ) { - globalErrorStream() << "LoadMDLImage: data has wrong ident\n"; - return 0; - } - - PointerInputStream inputStream( buffer ); - inputStream.seek( 4 + 4 + 12 + 12 + 4 + 12 ); - //int numskins = - istream_read_int32_le( inputStream ); - int skinwidth = istream_read_int32_le( inputStream ); - int skinheight = istream_read_int32_le( inputStream ); - inputStream.seek( 4 + 4 + 4 + 4 + 4 + 4 ); - - switch ( istream_read_int32_le( inputStream ) ) - { - case MDL_SKIN_SINGLE: - break; - case MDL_SKIN_GROUP: - int numskins = istream_read_int32_le( inputStream ); - inputStream.seek( numskins * 4 ); - break; - } - - RGBAImage* image = new RGBAImage( skinwidth, skinheight ); - unsigned char* pRGBA = image->getRGBAPixels(); - - for ( int i = 0; i < ( skinheight ); i++ ) - { - for ( int j = 0; j < ( skinwidth ); j++ ) - { - byte index = istream_read_byte( inputStream ); - *pRGBA++ = mdl_palette[index * 3 + 0]; - *pRGBA++ = mdl_palette[index * 3 + 1]; - *pRGBA++ = mdl_palette[index * 3 + 2]; - *pRGBA++ = 255; - } - } - - return image; +Image *LoadMDLImageBuff(byte *buffer) +{ + if (!LoadPalette()) { + return 0; + } + + if (!ident_equal(buffer, MDL_IDENT)) { + globalErrorStream() << "LoadMDLImage: data has wrong ident\n"; + return 0; + } + + PointerInputStream inputStream(buffer); + inputStream.seek(4 + 4 + 12 + 12 + 4 + 12); + //int numskins = + istream_read_int32_le(inputStream); + int skinwidth = istream_read_int32_le(inputStream); + int skinheight = istream_read_int32_le(inputStream); + inputStream.seek(4 + 4 + 4 + 4 + 4 + 4); + + switch (istream_read_int32_le(inputStream)) { + case MDL_SKIN_SINGLE: + break; + case MDL_SKIN_GROUP: + int numskins = istream_read_int32_le(inputStream); + inputStream.seek(numskins * 4); + break; + } + + RGBAImage *image = new RGBAImage(skinwidth, skinheight); + unsigned char *pRGBA = image->getRGBAPixels(); + + for (int i = 0; i < (skinheight); i++) { + for (int j = 0; j < (skinwidth); j++) { + byte index = istream_read_byte(inputStream); + *pRGBA++ = mdl_palette[index * 3 + 0]; + *pRGBA++ = mdl_palette[index * 3 + 1]; + *pRGBA++ = mdl_palette[index * 3 + 2]; + *pRGBA++ = 255; + } + } + + return image; } -Image* LoadMDLImage( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - return LoadMDLImageBuff( buffer.buffer ); +Image *LoadMDLImage(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + return LoadMDLImageBuff(buffer.buffer); } -void MDLImage_Destroy( byte* pic ){ - free( pic ); +void MDLImage_Destroy(byte *pic) +{ + free(pic); } diff --git a/plugins/md3model/mdlimage.h b/plugins/md3model/mdlimage.h index 8652a1da..11ca0517 100644 --- a/plugins/md3model/mdlimage.h +++ b/plugins/md3model/mdlimage.h @@ -23,8 +23,9 @@ #define INCLUDED_MDLIMAGE_H class Image; + class ArchiveFile; -Image* LoadMDLImage( ArchiveFile& file ); +Image *LoadMDLImage(ArchiveFile &file); #endif diff --git a/plugins/md3model/mdlnormals.h b/plugins/md3model/mdlnormals.h index d9407ef5..539975ae 100644 --- a/plugins/md3model/mdlnormals.h +++ b/plugins/md3model/mdlnormals.h @@ -24,166 +24,166 @@ typedef const float mdlNormal_t[3]; typedef const mdlNormal_t mdlNormals_t[162]; const mdlNormals_t g_mdl_normals = { - {-0.525731f, 0.000000f, 0.850651f, }, - {-0.442863f, 0.238856f, 0.864188f, }, - {-0.295242f, 0.000000f, 0.955423f, }, - {-0.309017f, 0.500000f, 0.809017f, }, - {-0.162460f, 0.262866f, 0.951056f, }, - { 0.000000f, 0.000000f, 1.000000f, }, - { 0.000000f, 0.850651f, 0.525731f, }, - {-0.147621f, 0.716567f, 0.681718f, }, - { 0.147621f, 0.716567f, 0.681718f, }, - { 0.000000f, 0.525731f, 0.850651f, }, - { 0.309017f, 0.500000f, 0.809017f, }, - { 0.525731f, 0.000000f, 0.850651f, }, - { 0.295242f, 0.000000f, 0.955423f, }, - { 0.442863f, 0.238856f, 0.864188f, }, - { 0.162460f, 0.262866f, 0.951056f, }, - {-0.681718f, 0.147621f, 0.716567f, }, - {-0.809017f, 0.309017f, 0.500000f, }, - {-0.587785f, 0.425325f, 0.688191f, }, - {-0.850651f, 0.525731f, 0.000000f, }, - {-0.864188f, 0.442863f, 0.238856f, }, - {-0.716567f, 0.681718f, 0.147621f, }, - {-0.688191f, 0.587785f, 0.425325f, }, - {-0.500000f, 0.809017f, 0.309017f, }, - {-0.238856f, 0.864188f, 0.442863f, }, - {-0.425325f, 0.688191f, 0.587785f, }, - {-0.716567f, 0.681718f,-0.147621f, }, - {-0.500000f, 0.809017f,-0.309017f, }, - {-0.525731f, 0.850651f, 0.000000f, }, - { 0.000000f, 0.850651f,-0.525731f, }, - {-0.238856f, 0.864188f,-0.442863f, }, - { 0.000000f, 0.955423f,-0.295242f, }, - {-0.262866f, 0.951056f,-0.162460f, }, - { 0.000000f, 1.000000f, 0.000000f, }, - { 0.000000f, 0.955423f, 0.295242f, }, - {-0.262866f, 0.951056f, 0.162460f, }, - { 0.238856f, 0.864188f, 0.442863f, }, - { 0.262866f, 0.951056f, 0.162460f, }, - { 0.500000f, 0.809017f, 0.309017f, }, - { 0.238856f, 0.864188f,-0.442863f, }, - { 0.262866f, 0.951056f,-0.162460f, }, - { 0.500000f, 0.809017f,-0.309017f, }, - { 0.850651f, 0.525731f, 0.000000f, }, - { 0.716567f, 0.681718f, 0.147621f, }, - { 0.716567f, 0.681718f,-0.147621f, }, - { 0.525731f, 0.850651f, 0.000000f, }, - { 0.425325f, 0.688191f, 0.587785f, }, - { 0.864188f, 0.442863f, 0.238856f, }, - { 0.688191f, 0.587785f, 0.425325f, }, - { 0.809017f, 0.309017f, 0.500000f, }, - { 0.681718f, 0.147621f, 0.716567f, }, - { 0.587785f, 0.425325f, 0.688191f, }, - { 0.955423f, 0.295242f, 0.000000f, }, - { 1.000000f, 0.000000f, 0.000000f, }, - { 0.951056f, 0.162460f, 0.262866f, }, - { 0.850651f,-0.525731f, 0.000000f, }, - { 0.955423f,-0.295242f, 0.000000f, }, - { 0.864188f,-0.442863f, 0.238856f, }, - { 0.951056f,-0.162460f, 0.262866f, }, - { 0.809017f,-0.309017f, 0.500000f, }, - { 0.681718f,-0.147621f, 0.716567f, }, - { 0.850651f, 0.000000f, 0.525731f, }, - { 0.864188f, 0.442863f,-0.238856f, }, - { 0.809017f, 0.309017f,-0.500000f, }, - { 0.951056f, 0.162460f,-0.262866f, }, - { 0.525731f, 0.000000f,-0.850651f, }, - { 0.681718f, 0.147621f,-0.716567f, }, - { 0.681718f,-0.147621f,-0.716567f, }, - { 0.850651f, 0.000000f,-0.525731f, }, - { 0.809017f,-0.309017f,-0.500000f, }, - { 0.864188f,-0.442863f,-0.238856f, }, - { 0.951056f,-0.162460f,-0.262866f, }, - { 0.147621f, 0.716567f,-0.681718f, }, - { 0.309017f, 0.500000f,-0.809017f, }, - { 0.425325f, 0.688191f,-0.587785f, }, - { 0.442863f, 0.238856f,-0.864188f, }, - { 0.587785f, 0.425325f,-0.688191f, }, - { 0.688191f, 0.587785f,-0.425325f, }, - {-0.147621f, 0.716567f,-0.681718f, }, - {-0.309017f, 0.500000f,-0.809017f, }, - { 0.000000f, 0.525731f,-0.850651f, }, - {-0.525731f, 0.000000f,-0.850651f, }, - {-0.442863f, 0.238856f,-0.864188f, }, - {-0.295242f, 0.000000f,-0.955423f, }, - {-0.162460f, 0.262866f,-0.951056f, }, - { 0.000000f, 0.000000f,-1.000000f, }, - { 0.295242f, 0.000000f,-0.955423f, }, - { 0.162460f, 0.262866f,-0.951056f, }, - {-0.442863f,-0.238856f,-0.864188f, }, - {-0.309017f,-0.500000f,-0.809017f, }, - {-0.162460f,-0.262866f,-0.951056f, }, - { 0.000000f,-0.850651f,-0.525731f, }, - {-0.147621f,-0.716567f,-0.681718f, }, - { 0.147621f,-0.716567f,-0.681718f, }, - { 0.000000f,-0.525731f,-0.850651f, }, - { 0.309017f,-0.500000f,-0.809017f, }, - { 0.442863f,-0.238856f,-0.864188f, }, - { 0.162460f,-0.262866f,-0.951056f, }, - { 0.238856f,-0.864188f,-0.442863f, }, - { 0.500000f,-0.809017f,-0.309017f, }, - { 0.425325f,-0.688191f,-0.587785f, }, - { 0.716567f,-0.681718f,-0.147621f, }, - { 0.688191f,-0.587785f,-0.425325f, }, - { 0.587785f,-0.425325f,-0.688191f, }, - { 0.000000f,-0.955423f,-0.295242f, }, - { 0.000000f,-1.000000f, 0.000000f, }, - { 0.262866f,-0.951056f,-0.162460f, }, - { 0.000000f,-0.850651f, 0.525731f, }, - { 0.000000f,-0.955423f, 0.295242f, }, - { 0.238856f,-0.864188f, 0.442863f, }, - { 0.262866f,-0.951056f, 0.162460f, }, - { 0.500000f,-0.809017f, 0.309017f, }, - { 0.716567f,-0.681718f, 0.147621f, }, - { 0.525731f,-0.850651f, 0.000000f, }, - {-0.238856f,-0.864188f,-0.442863f, }, - {-0.500000f,-0.809017f,-0.309017f, }, - {-0.262866f,-0.951056f,-0.162460f, }, - {-0.850651f,-0.525731f, 0.000000f, }, - {-0.716567f,-0.681718f,-0.147621f, }, - {-0.716567f,-0.681718f, 0.147621f, }, - {-0.525731f,-0.850651f, 0.000000f, }, - {-0.500000f,-0.809017f, 0.309017f, }, - {-0.238856f,-0.864188f, 0.442863f, }, - {-0.262866f,-0.951056f, 0.162460f, }, - {-0.864188f,-0.442863f, 0.238856f, }, - {-0.809017f,-0.309017f, 0.500000f, }, - {-0.688191f,-0.587785f, 0.425325f, }, - {-0.681718f,-0.147621f, 0.716567f, }, - {-0.442863f,-0.238856f, 0.864188f, }, - {-0.587785f,-0.425325f, 0.688191f, }, - {-0.309017f,-0.500000f, 0.809017f, }, - {-0.147621f,-0.716567f, 0.681718f, }, - {-0.425325f,-0.688191f, 0.587785f, }, - {-0.162460f,-0.262866f, 0.951056f, }, - { 0.442863f,-0.238856f, 0.864188f, }, - { 0.162460f,-0.262866f, 0.951056f, }, - { 0.309017f,-0.500000f, 0.809017f, }, - { 0.147621f,-0.716567f, 0.681718f, }, - { 0.000000f,-0.525731f, 0.850651f, }, - { 0.425325f,-0.688191f, 0.587785f, }, - { 0.587785f,-0.425325f, 0.688191f, }, - { 0.688191f,-0.587785f, 0.425325f, }, - {-0.955423f, 0.295242f, 0.000000f, }, - {-0.951056f, 0.162460f, 0.262866f, }, - {-1.000000f, 0.000000f, 0.000000f, }, - {-0.850651f, 0.000000f, 0.525731f, }, - {-0.955423f,-0.295242f, 0.000000f, }, - {-0.951056f,-0.162460f, 0.262866f, }, - {-0.864188f, 0.442863f,-0.238856f, }, - {-0.951056f, 0.162460f,-0.262866f, }, - {-0.809017f, 0.309017f,-0.500000f, }, - {-0.864188f,-0.442863f,-0.238856f, }, - {-0.951056f,-0.162460f,-0.262866f, }, - {-0.809017f,-0.309017f,-0.500000f, }, - {-0.681718f, 0.147621f,-0.716567f, }, - {-0.681718f,-0.147621f,-0.716567f, }, - {-0.850651f, 0.000000f,-0.525731f, }, - {-0.688191f, 0.587785f,-0.425325f, }, - {-0.587785f, 0.425325f,-0.688191f, }, - {-0.425325f, 0.688191f,-0.587785f, }, - {-0.425325f,-0.688191f,-0.587785f, }, - {-0.587785f,-0.425325f,-0.688191f, }, - {-0.688191f,-0.587785f,-0.425325f, }, + {-0.525731f, 0.000000f, 0.850651f,}, + {-0.442863f, 0.238856f, 0.864188f,}, + {-0.295242f, 0.000000f, 0.955423f,}, + {-0.309017f, 0.500000f, 0.809017f,}, + {-0.162460f, 0.262866f, 0.951056f,}, + {0.000000f, 0.000000f, 1.000000f,}, + {0.000000f, 0.850651f, 0.525731f,}, + {-0.147621f, 0.716567f, 0.681718f,}, + {0.147621f, 0.716567f, 0.681718f,}, + {0.000000f, 0.525731f, 0.850651f,}, + {0.309017f, 0.500000f, 0.809017f,}, + {0.525731f, 0.000000f, 0.850651f,}, + {0.295242f, 0.000000f, 0.955423f,}, + {0.442863f, 0.238856f, 0.864188f,}, + {0.162460f, 0.262866f, 0.951056f,}, + {-0.681718f, 0.147621f, 0.716567f,}, + {-0.809017f, 0.309017f, 0.500000f,}, + {-0.587785f, 0.425325f, 0.688191f,}, + {-0.850651f, 0.525731f, 0.000000f,}, + {-0.864188f, 0.442863f, 0.238856f,}, + {-0.716567f, 0.681718f, 0.147621f,}, + {-0.688191f, 0.587785f, 0.425325f,}, + {-0.500000f, 0.809017f, 0.309017f,}, + {-0.238856f, 0.864188f, 0.442863f,}, + {-0.425325f, 0.688191f, 0.587785f,}, + {-0.716567f, 0.681718f, -0.147621f,}, + {-0.500000f, 0.809017f, -0.309017f,}, + {-0.525731f, 0.850651f, 0.000000f,}, + {0.000000f, 0.850651f, -0.525731f,}, + {-0.238856f, 0.864188f, -0.442863f,}, + {0.000000f, 0.955423f, -0.295242f,}, + {-0.262866f, 0.951056f, -0.162460f,}, + {0.000000f, 1.000000f, 0.000000f,}, + {0.000000f, 0.955423f, 0.295242f,}, + {-0.262866f, 0.951056f, 0.162460f,}, + {0.238856f, 0.864188f, 0.442863f,}, + {0.262866f, 0.951056f, 0.162460f,}, + {0.500000f, 0.809017f, 0.309017f,}, + {0.238856f, 0.864188f, -0.442863f,}, + {0.262866f, 0.951056f, -0.162460f,}, + {0.500000f, 0.809017f, -0.309017f,}, + {0.850651f, 0.525731f, 0.000000f,}, + {0.716567f, 0.681718f, 0.147621f,}, + {0.716567f, 0.681718f, -0.147621f,}, + {0.525731f, 0.850651f, 0.000000f,}, + {0.425325f, 0.688191f, 0.587785f,}, + {0.864188f, 0.442863f, 0.238856f,}, + {0.688191f, 0.587785f, 0.425325f,}, + {0.809017f, 0.309017f, 0.500000f,}, + {0.681718f, 0.147621f, 0.716567f,}, + {0.587785f, 0.425325f, 0.688191f,}, + {0.955423f, 0.295242f, 0.000000f,}, + {1.000000f, 0.000000f, 0.000000f,}, + {0.951056f, 0.162460f, 0.262866f,}, + {0.850651f, -0.525731f, 0.000000f,}, + {0.955423f, -0.295242f, 0.000000f,}, + {0.864188f, -0.442863f, 0.238856f,}, + {0.951056f, -0.162460f, 0.262866f,}, + {0.809017f, -0.309017f, 0.500000f,}, + {0.681718f, -0.147621f, 0.716567f,}, + {0.850651f, 0.000000f, 0.525731f,}, + {0.864188f, 0.442863f, -0.238856f,}, + {0.809017f, 0.309017f, -0.500000f,}, + {0.951056f, 0.162460f, -0.262866f,}, + {0.525731f, 0.000000f, -0.850651f,}, + {0.681718f, 0.147621f, -0.716567f,}, + {0.681718f, -0.147621f, -0.716567f,}, + {0.850651f, 0.000000f, -0.525731f,}, + {0.809017f, -0.309017f, -0.500000f,}, + {0.864188f, -0.442863f, -0.238856f,}, + {0.951056f, -0.162460f, -0.262866f,}, + {0.147621f, 0.716567f, -0.681718f,}, + {0.309017f, 0.500000f, -0.809017f,}, + {0.425325f, 0.688191f, -0.587785f,}, + {0.442863f, 0.238856f, -0.864188f,}, + {0.587785f, 0.425325f, -0.688191f,}, + {0.688191f, 0.587785f, -0.425325f,}, + {-0.147621f, 0.716567f, -0.681718f,}, + {-0.309017f, 0.500000f, -0.809017f,}, + {0.000000f, 0.525731f, -0.850651f,}, + {-0.525731f, 0.000000f, -0.850651f,}, + {-0.442863f, 0.238856f, -0.864188f,}, + {-0.295242f, 0.000000f, -0.955423f,}, + {-0.162460f, 0.262866f, -0.951056f,}, + {0.000000f, 0.000000f, -1.000000f,}, + {0.295242f, 0.000000f, -0.955423f,}, + {0.162460f, 0.262866f, -0.951056f,}, + {-0.442863f, -0.238856f, -0.864188f,}, + {-0.309017f, -0.500000f, -0.809017f,}, + {-0.162460f, -0.262866f, -0.951056f,}, + {0.000000f, -0.850651f, -0.525731f,}, + {-0.147621f, -0.716567f, -0.681718f,}, + {0.147621f, -0.716567f, -0.681718f,}, + {0.000000f, -0.525731f, -0.850651f,}, + {0.309017f, -0.500000f, -0.809017f,}, + {0.442863f, -0.238856f, -0.864188f,}, + {0.162460f, -0.262866f, -0.951056f,}, + {0.238856f, -0.864188f, -0.442863f,}, + {0.500000f, -0.809017f, -0.309017f,}, + {0.425325f, -0.688191f, -0.587785f,}, + {0.716567f, -0.681718f, -0.147621f,}, + {0.688191f, -0.587785f, -0.425325f,}, + {0.587785f, -0.425325f, -0.688191f,}, + {0.000000f, -0.955423f, -0.295242f,}, + {0.000000f, -1.000000f, 0.000000f,}, + {0.262866f, -0.951056f, -0.162460f,}, + {0.000000f, -0.850651f, 0.525731f,}, + {0.000000f, -0.955423f, 0.295242f,}, + {0.238856f, -0.864188f, 0.442863f,}, + {0.262866f, -0.951056f, 0.162460f,}, + {0.500000f, -0.809017f, 0.309017f,}, + {0.716567f, -0.681718f, 0.147621f,}, + {0.525731f, -0.850651f, 0.000000f,}, + {-0.238856f, -0.864188f, -0.442863f,}, + {-0.500000f, -0.809017f, -0.309017f,}, + {-0.262866f, -0.951056f, -0.162460f,}, + {-0.850651f, -0.525731f, 0.000000f,}, + {-0.716567f, -0.681718f, -0.147621f,}, + {-0.716567f, -0.681718f, 0.147621f,}, + {-0.525731f, -0.850651f, 0.000000f,}, + {-0.500000f, -0.809017f, 0.309017f,}, + {-0.238856f, -0.864188f, 0.442863f,}, + {-0.262866f, -0.951056f, 0.162460f,}, + {-0.864188f, -0.442863f, 0.238856f,}, + {-0.809017f, -0.309017f, 0.500000f,}, + {-0.688191f, -0.587785f, 0.425325f,}, + {-0.681718f, -0.147621f, 0.716567f,}, + {-0.442863f, -0.238856f, 0.864188f,}, + {-0.587785f, -0.425325f, 0.688191f,}, + {-0.309017f, -0.500000f, 0.809017f,}, + {-0.147621f, -0.716567f, 0.681718f,}, + {-0.425325f, -0.688191f, 0.587785f,}, + {-0.162460f, -0.262866f, 0.951056f,}, + {0.442863f, -0.238856f, 0.864188f,}, + {0.162460f, -0.262866f, 0.951056f,}, + {0.309017f, -0.500000f, 0.809017f,}, + {0.147621f, -0.716567f, 0.681718f,}, + {0.000000f, -0.525731f, 0.850651f,}, + {0.425325f, -0.688191f, 0.587785f,}, + {0.587785f, -0.425325f, 0.688191f,}, + {0.688191f, -0.587785f, 0.425325f,}, + {-0.955423f, 0.295242f, 0.000000f,}, + {-0.951056f, 0.162460f, 0.262866f,}, + {-1.000000f, 0.000000f, 0.000000f,}, + {-0.850651f, 0.000000f, 0.525731f,}, + {-0.955423f, -0.295242f, 0.000000f,}, + {-0.951056f, -0.162460f, 0.262866f,}, + {-0.864188f, 0.442863f, -0.238856f,}, + {-0.951056f, 0.162460f, -0.262866f,}, + {-0.809017f, 0.309017f, -0.500000f,}, + {-0.864188f, -0.442863f, -0.238856f,}, + {-0.951056f, -0.162460f, -0.262866f,}, + {-0.809017f, -0.309017f, -0.500000f,}, + {-0.681718f, 0.147621f, -0.716567f,}, + {-0.681718f, -0.147621f, -0.716567f,}, + {-0.850651f, 0.000000f, -0.525731f,}, + {-0.688191f, 0.587785f, -0.425325f,}, + {-0.587785f, 0.425325f, -0.688191f,}, + {-0.425325f, 0.688191f, -0.587785f,}, + {-0.425325f, -0.688191f, -0.587785f,}, + {-0.587785f, -0.425325f, -0.688191f,}, + {-0.688191f, -0.587785f, -0.425325f,}, }; diff --git a/plugins/md3model/model.h b/plugins/md3model/model.h index 5f03d734..ea4f0492 100644 --- a/plugins/md3model/model.h +++ b/plugins/md3model/model.h @@ -39,534 +39,607 @@ #include "traverselib.h" #include "render.h" -class VectorLightList : public LightList -{ -typedef std::vector Lights; -Lights m_lights; +class VectorLightList : public LightList { + typedef std::vector Lights; + Lights m_lights; public: -void addLight( const RendererLight& light ){ - m_lights.push_back( &light ); -} -void clear(){ - m_lights.clear(); -} -void evaluateLights() const { -} -void lightsChanged() const { -} -void forEachLight( const RendererLightCallback& callback ) const { - for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i ) - { - callback( *( *i ) ); - } -} + void addLight(const RendererLight &light) + { + m_lights.push_back(&light); + } + + void clear() + { + m_lights.clear(); + } + + void evaluateLights() const + { + } + + void lightsChanged() const + { + } + + void forEachLight(const RendererLightCallback &callback) const + { + for (Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i) { + callback(*(*i)); + } + } }; -inline VertexPointer vertexpointer_arbitrarymeshvertex( const ArbitraryMeshVertex* array ){ - return VertexPointer( VertexPointer::pointer( &array->vertex ), sizeof( ArbitraryMeshVertex ) ); +inline VertexPointer vertexpointer_arbitrarymeshvertex(const ArbitraryMeshVertex *array) +{ + return VertexPointer(VertexPointer::pointer(&array->vertex), sizeof(ArbitraryMeshVertex)); } -inline void parseTextureName( CopiedString& name, const char* token ){ - StringOutputStream cleaned( 256 ); - cleaned << PathCleaned( token ); - name = StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ); // remove extension +inline void parseTextureName(CopiedString &name, const char *token) +{ + StringOutputStream cleaned(256); + cleaned << PathCleaned(token); + name = StringRange(cleaned.c_str(), path_get_filename_base_end(cleaned.c_str())); // remove extension } // generic renderable triangle surface class Surface : - public OpenGLRenderable -{ + public OpenGLRenderable { public: -typedef VertexBuffer vertices_t; -typedef IndexBuffer indices_t; + typedef VertexBuffer vertices_t; + typedef IndexBuffer indices_t; private: -AABB m_aabb_local; -CopiedString m_shader; -Shader* m_state; - -vertices_t m_vertices; -indices_t m_indices; + AABB m_aabb_local; + CopiedString m_shader; + Shader *m_state; -void CaptureShader(){ - m_state = GlobalShaderCache().capture( m_shader.c_str() ); -} -void ReleaseShader(){ - GlobalShaderCache().release( m_shader.c_str() ); -} + vertices_t m_vertices; + indices_t m_indices; -public: + void CaptureShader() + { + m_state = GlobalShaderCache().capture(m_shader.c_str()); + } -Surface() - : m_shader( "" ), m_state( 0 ){ - CaptureShader(); -} -~Surface(){ - ReleaseShader(); -} + void ReleaseShader() + { + GlobalShaderCache().release(m_shader.c_str()); + } -vertices_t& vertices(){ - return m_vertices; -} -indices_t& indices(){ - return m_indices; -} - -void setShader( const char* name ){ - ReleaseShader(); - parseTextureName( m_shader, name ); - CaptureShader(); -} -const char* getShader() const { - return m_shader.c_str(); -} -Shader* getState() const { - return m_state; -} -void updateAABB(){ - m_aabb_local = AABB(); - for ( vertices_t::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i ) - aabb_extend_by_point_safe( m_aabb_local, reinterpret_cast( ( *i ).vertex ) ); - - - - for ( Surface::indices_t::iterator i = m_indices.begin(); i != m_indices.end(); i += 3 ) - { - ArbitraryMeshVertex& a = m_vertices[*( i + 0 )]; - ArbitraryMeshVertex& b = m_vertices[*( i + 1 )]; - ArbitraryMeshVertex& c = m_vertices[*( i + 2 )]; - - ArbitraryMeshTriangle_sumTangents( a, b, c ); - } - - for ( Surface::vertices_t::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i ) - { - vector3_normalise( reinterpret_cast( ( *i ).tangent ) ); - vector3_normalise( reinterpret_cast( ( *i ).bitangent ) ); - } -} +public: -void render( RenderStateFlags state ) const { + Surface() + : m_shader(""), m_state(0) + { + CaptureShader(); + } + + ~Surface() + { + ReleaseShader(); + } + + vertices_t &vertices() + { + return m_vertices; + } + + indices_t &indices() + { + return m_indices; + } + + void setShader(const char *name) + { + ReleaseShader(); + parseTextureName(m_shader, name); + CaptureShader(); + } + + const char *getShader() const + { + return m_shader.c_str(); + } + + Shader *getState() const + { + return m_state; + } + + void updateAABB() + { + m_aabb_local = AABB(); + for (vertices_t::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i) { + aabb_extend_by_point_safe(m_aabb_local, reinterpret_cast((*i).vertex )); + } + + + for (Surface::indices_t::iterator i = m_indices.begin(); i != m_indices.end(); i += 3) { + ArbitraryMeshVertex &a = m_vertices[*(i + 0)]; + ArbitraryMeshVertex &b = m_vertices[*(i + 1)]; + ArbitraryMeshVertex &c = m_vertices[*(i + 2)]; + + ArbitraryMeshTriangle_sumTangents(a, b, c); + } + + for (Surface::vertices_t::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i) { + vector3_normalise(reinterpret_cast((*i).tangent )); + vector3_normalise(reinterpret_cast((*i).bitangent )); + } + } + + void render(RenderStateFlags state) const + { #if 1 - if ( ( state & RENDER_BUMP ) != 0 ) { - if ( GlobalShaderCache().useShaderLanguage() ) { - glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->normal ); - glVertexAttribPointerARB( c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->texcoord ); - glVertexAttribPointerARB( c_attr_Tangent, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->tangent ); - glVertexAttribPointerARB( c_attr_Binormal, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->bitangent ); - } - else - { - glVertexAttribPointerARB( 11, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->normal ); - glVertexAttribPointerARB( 8, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->texcoord ); - glVertexAttribPointerARB( 9, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->tangent ); - glVertexAttribPointerARB( 10, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->bitangent ); - } - } - else - { - glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->normal ); - glTexCoordPointer( 2, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->texcoord ); - } - glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->vertex ); - glDrawElements( GL_TRIANGLES, GLsizei( m_indices.size() ), RenderIndexTypeID, m_indices.data() ); + if ((state & RENDER_BUMP) != 0) { + if (GlobalShaderCache().useShaderLanguage()) { + glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->normal); + glVertexAttribPointerARB(c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_vertices.data()->texcoord); + glVertexAttribPointerARB(c_attr_Tangent, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_vertices.data()->tangent); + glVertexAttribPointerARB(c_attr_Binormal, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_vertices.data()->bitangent); + } else { + glVertexAttribPointerARB(11, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->normal); + glVertexAttribPointerARB(8, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->texcoord); + glVertexAttribPointerARB(9, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->tangent); + glVertexAttribPointerARB(10, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_vertices.data()->bitangent); + } + } else { + glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->normal); + glTexCoordPointer(2, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->texcoord); + } + glVertexPointer(3, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->vertex); + glDrawElements(GL_TRIANGLES, GLsizei(m_indices.size()), RenderIndexTypeID, m_indices.data()); #else - glBegin( GL_TRIANGLES ); - for ( unsigned int i = 0; i < m_indices.size(); ++i ) - { - glTexCoord2fv( &m_vertices[m_indices[i]].texcoord.s ); - glNormal3fv( &m_vertices[m_indices[i]].normal.x ); - glVertex3fv( &m_vertices[m_indices[i]].vertex.x ); - } - glEnd(); + glBegin( GL_TRIANGLES ); + for ( unsigned int i = 0; i < m_indices.size(); ++i ) + { + glTexCoord2fv( &m_vertices[m_indices[i]].texcoord.s ); + glNormal3fv( &m_vertices[m_indices[i]].normal.x ); + glVertex3fv( &m_vertices[m_indices[i]].vertex.x ); + } + glEnd(); #endif #if GDEF_DEBUG - glBegin( GL_LINES ); - - for ( VertexBuffer::const_iterator i = m_vertices.begin(); i != m_vertices.end(); ++i ) - { - Vector3 normal = vector3_added( vertex3f_to_vector3( ( *i ).vertex ), vector3_scaled( normal3f_to_vector3( ( *i ).normal ), 8 ) ); - glVertex3fv( vertex3f_to_array( ( *i ).vertex ) ); - glVertex3fv( vector3_to_array( normal ) ); - } - glEnd(); + glBegin(GL_LINES); + + for (VertexBuffer::const_iterator i = m_vertices.begin(); i != m_vertices.end(); ++i) { + Vector3 normal = vector3_added(vertex3f_to_vector3((*i).vertex), + vector3_scaled(normal3f_to_vector3((*i).normal), 8)); + glVertex3fv(vertex3f_to_array((*i).vertex)); + glVertex3fv(vector3_to_array(normal)); + } + glEnd(); #endif -} - -VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const { - return test.TestAABB( m_aabb_local, localToWorld ); -} - -const AABB& localAABB() const { - return m_aabb_local; -} - -void render( Renderer& renderer, const Matrix4& localToWorld, Shader* state ) const { - renderer.SetState( state, Renderer::eFullMaterials ); - renderer.addRenderable( *this, localToWorld ); -} - -void render( Renderer& renderer, const Matrix4& localToWorld ) const { - render( renderer, localToWorld, m_state ); -} - -void testSelect( Selector& selector, SelectionTest& test, const Matrix4& localToWorld ){ - test.BeginMesh( localToWorld ); - - SelectionIntersection best; - test.TestTriangles( - vertexpointer_arbitrarymeshvertex( m_vertices.data() ), - IndexPointer( m_indices.data(), IndexPointer::index_type( m_indices.size() ) ), - best - ); - if ( best.valid() ) { - selector.addIntersection( best ); - } -} + } + + VolumeIntersectionValue intersectVolume(const VolumeTest &test, const Matrix4 &localToWorld) const + { + return test.TestAABB(m_aabb_local, localToWorld); + } + + const AABB &localAABB() const + { + return m_aabb_local; + } + + void render(Renderer &renderer, const Matrix4 &localToWorld, Shader *state) const + { + renderer.SetState(state, Renderer::eFullMaterials); + renderer.addRenderable(*this, localToWorld); + } + + void render(Renderer &renderer, const Matrix4 &localToWorld) const + { + render(renderer, localToWorld, m_state); + } + + void testSelect(Selector &selector, SelectionTest &test, const Matrix4 &localToWorld) + { + test.BeginMesh(localToWorld); + + SelectionIntersection best; + test.TestTriangles( + vertexpointer_arbitrarymeshvertex(m_vertices.data()), + IndexPointer(m_indices.data(), IndexPointer::index_type(m_indices.size())), + best + ); + if (best.valid()) { + selector.addIntersection(best); + } + } }; // generic model node class Model : - public Cullable, - public Bounded -{ -typedef std::vector surfaces_t; -surfaces_t m_surfaces; + public Cullable, + public Bounded { + typedef std::vector surfaces_t; + surfaces_t m_surfaces; -AABB m_aabb_local; + AABB m_aabb_local; public: -Callback m_lightsChanged; - -~Model(){ - for ( surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i ) - { - delete *i; - } -} - -typedef surfaces_t::const_iterator const_iterator; - -const_iterator begin() const { - return m_surfaces.begin(); -} -const_iterator end() const { - return m_surfaces.end(); -} -std::size_t size() const { - return m_surfaces.size(); -} - -Surface& newSurface(){ - m_surfaces.push_back( new Surface ); - return *m_surfaces.back(); -} -void updateAABB(){ - m_aabb_local = AABB(); - for ( surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i ) - { - aabb_extend_by_aabb_safe( m_aabb_local, ( *i )->localAABB() ); - } -} - -VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const { - return test.TestAABB( m_aabb_local, localToWorld ); -} - -virtual const AABB& localAABB() const { - return m_aabb_local; -} - -void testSelect( Selector& selector, SelectionTest& test, const Matrix4& localToWorld ){ - for ( surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i ) - { - if ( ( *i )->intersectVolume( test.getVolume(), localToWorld ) != c_volumeOutside ) { - ( *i )->testSelect( selector, test, localToWorld ); - } - } -} + Callback m_lightsChanged; + + ~Model() + { + for (surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i) { + delete *i; + } + } + + typedef surfaces_t::const_iterator const_iterator; + + const_iterator begin() const + { + return m_surfaces.begin(); + } + + const_iterator end() const + { + return m_surfaces.end(); + } + + std::size_t size() const + { + return m_surfaces.size(); + } + + Surface &newSurface() + { + m_surfaces.push_back(new Surface); + return *m_surfaces.back(); + } + + void updateAABB() + { + m_aabb_local = AABB(); + for (surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i) { + aabb_extend_by_aabb_safe(m_aabb_local, (*i)->localAABB()); + } + } + + VolumeIntersectionValue intersectVolume(const VolumeTest &test, const Matrix4 &localToWorld) const + { + return test.TestAABB(m_aabb_local, localToWorld); + } + + virtual const AABB &localAABB() const + { + return m_aabb_local; + } + + void testSelect(Selector &selector, SelectionTest &test, const Matrix4 &localToWorld) + { + for (surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i) { + if ((*i)->intersectVolume(test.getVolume(), localToWorld) != c_volumeOutside) { + (*i)->testSelect(selector, test, localToWorld); + } + } + } }; -inline void Surface_addLight( const Surface& surface, VectorLightList& lights, const Matrix4& localToWorld, const RendererLight& light ){ - if ( light.testAABB( aabb_for_oriented_aabb( surface.localAABB(), localToWorld ) ) ) { - lights.addLight( light ); - } -} - -class ModelInstance : - public scene::Instance, - public Renderable, - public SelectionTestable, - public LightCullable, - public SkinnedModel -{ -class TypeCasts +inline void Surface_addLight(const Surface &surface, VectorLightList &lights, const Matrix4 &localToWorld, + const RendererLight &light) { -InstanceTypeCastTable m_casts; -public: -TypeCasts(){ - InstanceContainedCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); + if (light.testAABB(aabb_for_oriented_aabb(surface.localAABB(), localToWorld))) { + lights.addLight(light); + } } -InstanceTypeCastTable& get(){ - return m_casts; -} -}; - -Model& m_model; - -const LightList* m_lightList; -typedef Array SurfaceLightLists; -SurfaceLightLists m_surfaceLightLists; -class Remap -{ -public: -CopiedString first; -Shader* second; -Remap() : second( 0 ){ -} -}; -typedef Array SurfaceRemaps; -SurfaceRemaps m_skins; +class ModelInstance : + public scene::Instance, + public Renderable, + public SelectionTestable, + public LightCullable, + public SkinnedModel { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + InstanceContainedCast::install(m_casts); + InstanceContainedCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + Model &m_model; + + const LightList *m_lightList; + typedef Array SurfaceLightLists; + SurfaceLightLists m_surfaceLightLists; + + class Remap { + public: + CopiedString first; + Shader *second; + + Remap() : second(0) + { + } + }; + + typedef Array SurfaceRemaps; + SurfaceRemaps m_skins; public: -typedef LazyStatic StaticTypeCasts; - -Bounded& get( NullType){ - return m_model; -} -Cullable& get( NullType){ - return m_model; -} - -void lightsChanged(){ - m_lightList->lightsChanged(); -} -typedef MemberCaller LightsChangedCaller; - -void constructRemaps(){ - ModelSkin* skin = NodeTypeCast::cast( path().parent() ); - if ( skin != 0 && skin->realised() ) { - SurfaceRemaps::iterator j = m_skins.begin(); - for ( Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i, ++j ) - { - const char* remap = skin->getRemap( ( *i )->getShader() ); - if ( !string_empty( remap ) ) { - ( *j ).first = remap; - ( *j ).second = GlobalShaderCache().capture( remap ); - } - else - { - ( *j ).second = 0; - } - } - SceneChangeNotify(); - } -} -void destroyRemaps(){ - for ( SurfaceRemaps::iterator i = m_skins.begin(); i != m_skins.end(); ++i ) - { - if ( ( *i ).second != 0 ) { - GlobalShaderCache().release( ( *i ).first.c_str() ); - ( *i ).second = 0; - } - } -} -void skinChanged(){ - ASSERT_MESSAGE( m_skins.size() == m_model.size(), "ERROR" ); - destroyRemaps(); - constructRemaps(); -} - -ModelInstance( const scene::Path& path, scene::Instance* parent, Model& model ) : - Instance( path, parent, this, StaticTypeCasts::instance().get() ), - m_model( model ), - m_surfaceLightLists( m_model.size() ), - m_skins( m_model.size() ){ - m_lightList = &GlobalShaderCache().attach( *this ); - m_model.m_lightsChanged = LightsChangedCaller( *this ); - - Instance::setTransformChangedCallback( LightsChangedCaller( *this ) ); - - constructRemaps(); -} -~ModelInstance(){ - destroyRemaps(); - - Instance::setTransformChangedCallback( Callback() ); - - m_model.m_lightsChanged = Callback(); - GlobalShaderCache().detach( *this ); -} - -void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - SurfaceLightLists::const_iterator j = m_surfaceLightLists.begin(); - SurfaceRemaps::const_iterator k = m_skins.begin(); - for ( Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i, ++j, ++k ) - { - if ( ( *i )->intersectVolume( volume, localToWorld ) != c_volumeOutside ) { - renderer.setLights( *j ); - ( *i )->render( renderer, localToWorld, ( *k ).second != 0 ? ( *k ).second : ( *i )->getState() ); - } - } -} - -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_lightList->evaluateLights(); - - render( renderer, volume, Instance::localToWorld() ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - renderSolid( renderer, volume ); -} - -void testSelect( Selector& selector, SelectionTest& test ){ - m_model.testSelect( selector, test, Instance::localToWorld() ); -} - -bool testLight( const RendererLight& light ) const { - return light.testAABB( worldAABB() ); -} -void insertLight( const RendererLight& light ){ - const Matrix4& localToWorld = Instance::localToWorld(); - SurfaceLightLists::iterator j = m_surfaceLightLists.begin(); - for ( Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i ) - { - Surface_addLight( *( *i ), *j++, localToWorld, light ); - } -} -void clearLights(){ - for ( SurfaceLightLists::iterator i = m_surfaceLightLists.begin(); i != m_surfaceLightLists.end(); ++i ) - { - ( *i ).clear(); - } -} + typedef LazyStatic StaticTypeCasts; + + Bounded &get(NullType) + { + return m_model; + } + + Cullable &get(NullType) + { + return m_model; + } + + void lightsChanged() + { + m_lightList->lightsChanged(); + } + + typedef MemberCaller LightsChangedCaller; + + void constructRemaps() + { + ModelSkin *skin = NodeTypeCast::cast(path().parent()); + if (skin != 0 && skin->realised()) { + SurfaceRemaps::iterator j = m_skins.begin(); + for (Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i, ++j) { + const char *remap = skin->getRemap((*i)->getShader()); + if (!string_empty(remap)) { + (*j).first = remap; + (*j).second = GlobalShaderCache().capture(remap); + } else { + (*j).second = 0; + } + } + SceneChangeNotify(); + } + } + + void destroyRemaps() + { + for (SurfaceRemaps::iterator i = m_skins.begin(); i != m_skins.end(); ++i) { + if ((*i).second != 0) { + GlobalShaderCache().release((*i).first.c_str()); + (*i).second = 0; + } + } + } + + void skinChanged() + { + ASSERT_MESSAGE(m_skins.size() == m_model.size(), "ERROR"); + destroyRemaps(); + constructRemaps(); + } + + ModelInstance(const scene::Path &path, scene::Instance *parent, Model &model) : + Instance(path, parent, this, StaticTypeCasts::instance().get()), + m_model(model), + m_surfaceLightLists(m_model.size()), + m_skins(m_model.size()) + { + m_lightList = &GlobalShaderCache().attach(*this); + m_model.m_lightsChanged = LightsChangedCaller(*this); + + Instance::setTransformChangedCallback(LightsChangedCaller(*this)); + + constructRemaps(); + } + + ~ModelInstance() + { + destroyRemaps(); + + Instance::setTransformChangedCallback(Callback()); + + m_model.m_lightsChanged = Callback(); + GlobalShaderCache().detach(*this); + } + + void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + SurfaceLightLists::const_iterator j = m_surfaceLightLists.begin(); + SurfaceRemaps::const_iterator k = m_skins.begin(); + for (Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i, ++j, ++k) { + if ((*i)->intersectVolume(volume, localToWorld) != c_volumeOutside) { + renderer.setLights(*j); + (*i)->render(renderer, localToWorld, (*k).second != 0 ? (*k).second : (*i)->getState()); + } + } + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_lightList->evaluateLights(); + + render(renderer, volume, Instance::localToWorld()); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + renderSolid(renderer, volume); + } + + void testSelect(Selector &selector, SelectionTest &test) + { + m_model.testSelect(selector, test, Instance::localToWorld()); + } + + bool testLight(const RendererLight &light) const + { + return light.testAABB(worldAABB()); + } + + void insertLight(const RendererLight &light) + { + const Matrix4 &localToWorld = Instance::localToWorld(); + SurfaceLightLists::iterator j = m_surfaceLightLists.begin(); + for (Model::const_iterator i = m_model.begin(); i != m_model.end(); ++i) { + Surface_addLight(*(*i), *j++, localToWorld, light); + } + } + + void clearLights() + { + for (SurfaceLightLists::iterator i = m_surfaceLightLists.begin(); i != m_surfaceLightLists.end(); ++i) { + (*i).clear(); + } + } }; -class ModelNode : public scene::Node::Symbiot, public scene::Instantiable -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; +class ModelNode : public scene::Node::Symbiot, public scene::Instantiable { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + } + + NodeTypeCastTable &get() + { + return m_casts; + } + }; + + + scene::Node m_node; + InstanceSet m_instances; + Model m_model; public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} -}; - - -scene::Node m_node; -InstanceSet m_instances; -Model m_model; -public: - -typedef LazyStatic StaticTypeCasts; -ModelNode() : m_node( this, this, StaticTypeCasts::instance().get() ){ -} - -Model& model(){ - return m_model; -} - -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} - -scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new ModelInstance( path, parent, m_model ); -} -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 ); -} + typedef LazyStatic StaticTypeCasts; + + ModelNode() : m_node(this, this, StaticTypeCasts::instance().get()) + { + } + + Model &model() + { + return m_model; + } + + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } + + scene::Instance *create(const scene::Path &path, scene::Instance *parent) + { + return new ModelInstance(path, parent, m_model); + } + + 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 void Surface_constructQuad( Surface& surface, const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d, const Vector3& normal ){ - surface.vertices().push_back( - ArbitraryMeshVertex( - vertex3f_for_vector3( a ), - normal3f_for_vector3( normal ), - texcoord2f_from_array( aabb_texcoord_topleft ) - ) - ); - surface.vertices().push_back( - ArbitraryMeshVertex( - vertex3f_for_vector3( b ), - normal3f_for_vector3( normal ), - texcoord2f_from_array( aabb_texcoord_topright ) - ) - ); - surface.vertices().push_back( - ArbitraryMeshVertex( - vertex3f_for_vector3( c ), - normal3f_for_vector3( normal ), - texcoord2f_from_array( aabb_texcoord_botright ) - ) - ); - surface.vertices().push_back( - ArbitraryMeshVertex( - vertex3f_for_vector3( d ), - normal3f_for_vector3( normal ), - texcoord2f_from_array( aabb_texcoord_botleft ) - ) - ); -} - -inline void Model_constructNull( Model& model ){ - Surface& surface = model.newSurface(); +inline void +Surface_constructQuad(Surface &surface, const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector3 &d, + const Vector3 &normal) +{ + surface.vertices().push_back( + ArbitraryMeshVertex( + vertex3f_for_vector3(a), + normal3f_for_vector3(normal), + texcoord2f_from_array(aabb_texcoord_topleft) + ) + ); + surface.vertices().push_back( + ArbitraryMeshVertex( + vertex3f_for_vector3(b), + normal3f_for_vector3(normal), + texcoord2f_from_array(aabb_texcoord_topright) + ) + ); + surface.vertices().push_back( + ArbitraryMeshVertex( + vertex3f_for_vector3(c), + normal3f_for_vector3(normal), + texcoord2f_from_array(aabb_texcoord_botright) + ) + ); + surface.vertices().push_back( + ArbitraryMeshVertex( + vertex3f_for_vector3(d), + normal3f_for_vector3(normal), + texcoord2f_from_array(aabb_texcoord_botleft) + ) + ); +} + +inline void Model_constructNull(Model &model) +{ + Surface &surface = model.newSurface(); - AABB aabb( Vector3( 0, 0, 0 ), Vector3( 8, 8, 8 ) ); + AABB aabb(Vector3(0, 0, 0), Vector3(8, 8, 8)); - Vector3 points[8]; - aabb_corners( aabb, points ); + Vector3 points[8]; + aabb_corners(aabb, points); - surface.vertices().reserve( 24 ); + surface.vertices().reserve(24); - Surface_constructQuad( surface, points[2], points[1], points[5], points[6], aabb_normals[0] ); - Surface_constructQuad( surface, points[1], points[0], points[4], points[5], aabb_normals[1] ); - Surface_constructQuad( surface, points[0], points[1], points[2], points[3], aabb_normals[2] ); - Surface_constructQuad( surface, points[0], points[3], points[7], points[4], aabb_normals[3] ); - Surface_constructQuad( surface, points[3], points[2], points[6], points[7], aabb_normals[4] ); - Surface_constructQuad( surface, points[7], points[6], points[5], points[4], aabb_normals[5] ); + Surface_constructQuad(surface, points[2], points[1], points[5], points[6], aabb_normals[0]); + Surface_constructQuad(surface, points[1], points[0], points[4], points[5], aabb_normals[1]); + Surface_constructQuad(surface, points[0], points[1], points[2], points[3], aabb_normals[2]); + Surface_constructQuad(surface, points[0], points[3], points[7], points[4], aabb_normals[3]); + Surface_constructQuad(surface, points[3], points[2], points[6], points[7], aabb_normals[4]); + Surface_constructQuad(surface, points[7], points[6], points[5], points[4], aabb_normals[5]); - surface.indices().reserve( 36 ); + surface.indices().reserve(36); - RenderIndex indices[36] = { - 0, 1, 2, 0, 2, 3, - 4, 5, 6, 4, 6, 7, - 8, 9, 10, 8, 10, 11, - 12, 13, 14, 12, 14, 15, - 16, 17, 18, 16, 18, 19, - 20, 21, 22, 10, 22, 23, - }; + RenderIndex indices[36] = { + 0, 1, 2, 0, 2, 3, + 4, 5, 6, 4, 6, 7, + 8, 9, 10, 8, 10, 11, + 12, 13, 14, 12, 14, 15, + 16, 17, 18, 16, 18, 19, + 20, 21, 22, 10, 22, 23, + }; - for ( RenderIndex* i = indices; i != indices + ( sizeof( indices ) / sizeof( RenderIndex ) ); ++i ) - { - surface.indices().insert( *i ); - } + for (RenderIndex *i = indices; i != indices + (sizeof(indices) / sizeof(RenderIndex)); ++i) { + surface.indices().insert(*i); + } - surface.setShader( "" ); + surface.setShader(""); - surface.updateAABB(); + surface.updateAABB(); - model.updateAABB(); + model.updateAABB(); } #endif diff --git a/plugins/md3model/plugin.cpp b/plugins/md3model/plugin.cpp index 58c97677..5d5be170 100644 --- a/plugins/md3model/plugin.cpp +++ b/plugins/md3model/plugin.cpp @@ -41,38 +41,40 @@ #include "md5.h" -class MD3ModelLoader : public ModelLoader -{ +class MD3ModelLoader : public ModelLoader { public: -scene::Node& loadModel( ArchiveFile& file ){ - return loadMD3Model( file ); -} + scene::Node &loadModel(ArchiveFile &file) + { + return loadMD3Model(file); + } }; class ModelDependencies : - public GlobalFileSystemModuleRef, - public GlobalOpenGLModuleRef, - public GlobalUndoModuleRef, - public GlobalSceneGraphModuleRef, - public GlobalShaderCacheModuleRef, - public GlobalSelectionModuleRef, - public GlobalFiletypesModuleRef -{ + public GlobalFileSystemModuleRef, + public GlobalOpenGLModuleRef, + public GlobalUndoModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalSelectionModuleRef, + public GlobalFiletypesModuleRef { }; -class ModelMD3API : public TypeSystemRef -{ -MD3ModelLoader m_modelmd3; +class ModelMD3API : public TypeSystemRef { + MD3ModelLoader m_modelmd3; public: -typedef ModelLoader Type; -STRING_CONSTANT( Name, "md3" ); + typedef ModelLoader Type; -ModelMD3API(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "md3 models", "*.md3" ) ); -} -ModelLoader* getTable(){ - return &m_modelmd3; -} + STRING_CONSTANT(Name, "md3"); + + ModelMD3API() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("md3 models", "*.md3")); + } + + ModelLoader *getTable() + { + return &m_modelmd3; + } }; typedef SingletonModule ModelMD3Module; @@ -80,82 +82,90 @@ typedef SingletonModule ModelMD3Module; ModelMD3Module g_ModelMD3Module; - -class MD2ModelLoader : public ModelLoader -{ +class MD2ModelLoader : public ModelLoader { public: -scene::Node& loadModel( ArchiveFile& file ){ - return loadMD2Model( file ); -} + scene::Node &loadModel(ArchiveFile &file) + { + return loadMD2Model(file); + } }; -class ModelMD2API : public TypeSystemRef -{ -MD2ModelLoader m_modelmd2; +class ModelMD2API : public TypeSystemRef { + MD2ModelLoader m_modelmd2; public: -typedef ModelLoader Type; -STRING_CONSTANT( Name, "md2" ); + typedef ModelLoader Type; -ModelMD2API(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "md2 models", "*.md2" ) ); -} -ModelLoader* getTable(){ - return &m_modelmd2; -} + STRING_CONSTANT(Name, "md2"); + + ModelMD2API() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("md2 models", "*.md2")); + } + + ModelLoader *getTable() + { + return &m_modelmd2; + } }; typedef SingletonModule ModelMD2Module; ModelMD2Module g_ModelMD2Module; -class MDLModelLoader : public ModelLoader -{ +class MDLModelLoader : public ModelLoader { public: -scene::Node& loadModel( ArchiveFile& file ){ - return loadMDLModel( file ); -} + scene::Node &loadModel(ArchiveFile &file) + { + return loadMDLModel(file); + } }; -class ModelMDLAPI : public TypeSystemRef -{ -MDLModelLoader m_modelmdl; +class ModelMDLAPI : public TypeSystemRef { + MDLModelLoader m_modelmdl; public: -typedef ModelLoader Type; -STRING_CONSTANT( Name, "mdl" ); + typedef ModelLoader Type; -ModelMDLAPI(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "mdl models", "*.mdl" ) ); -} -ModelLoader* getTable(){ - return &m_modelmdl; -} + STRING_CONSTANT(Name, "mdl"); + + ModelMDLAPI() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("mdl models", "*.mdl")); + } + + ModelLoader *getTable() + { + return &m_modelmdl; + } }; typedef SingletonModule ModelMDLModule; ModelMDLModule g_ModelMDLModule; -class MDCModelLoader : public ModelLoader -{ +class MDCModelLoader : public ModelLoader { public: -scene::Node& loadModel( ArchiveFile& file ){ - return loadMDCModel( file ); -} + scene::Node &loadModel(ArchiveFile &file) + { + return loadMDCModel(file); + } }; -class ModelMDCAPI : public TypeSystemRef -{ -MDCModelLoader m_modelmdc; +class ModelMDCAPI : public TypeSystemRef { + MDCModelLoader m_modelmdc; public: -typedef ModelLoader Type; -STRING_CONSTANT( Name, "mdc" ); + typedef ModelLoader Type; -ModelMDCAPI(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "mdc models", "*.mdc" ) ); -} -ModelLoader* getTable(){ - return &m_modelmdc; -} + STRING_CONSTANT(Name, "mdc"); + + ModelMDCAPI() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("mdc models", "*.mdc")); + } + + ModelLoader *getTable() + { + return &m_modelmdc; + } }; typedef SingletonModule ModelMDCModule; @@ -163,19 +173,22 @@ typedef SingletonModule ModelMDCModule; ModelMDCModule g_ModelMDCModule; -class ImageMDLAPI -{ -_QERPlugImageTable m_imagemdl; +class ImageMDLAPI { + _QERPlugImageTable m_imagemdl; public: -typedef _QERPlugImageTable Type; -STRING_CONSTANT( Name, "mdl" ); + typedef _QERPlugImageTable Type; -ImageMDLAPI(){ - m_imagemdl.loadImage = &LoadMDLImage; -} -_QERPlugImageTable* getTable(){ - return &m_imagemdl; -} + STRING_CONSTANT(Name, "mdl"); + + ImageMDLAPI() + { + m_imagemdl.loadImage = &LoadMDLImage; + } + + _QERPlugImageTable *getTable() + { + return &m_imagemdl; + } }; typedef SingletonModule ImageMDLModule; @@ -183,31 +196,33 @@ typedef SingletonModule ImageMDLModule; ImageMDLModule g_ImageMDLModule; -class MD5ModelLoader : public ModelLoader -{ +class MD5ModelLoader : public ModelLoader { public: -scene::Node& loadModel( ArchiveFile& file ){ - return loadMD5Model( file ); -} + scene::Node &loadModel(ArchiveFile &file) + { + return loadMD5Model(file); + } }; -class ModelMD5Dependencies : public ModelDependencies, public GlobalScripLibModuleRef -{ +class ModelMD5Dependencies : public ModelDependencies, public GlobalScripLibModuleRef { }; -class ModelMD5API : public TypeSystemRef -{ -MD5ModelLoader m_modelmd5; +class ModelMD5API : public TypeSystemRef { + MD5ModelLoader m_modelmd5; public: -typedef ModelLoader Type; -STRING_CONSTANT( Name, "md5mesh" ); + typedef ModelLoader Type; -ModelMD5API(){ - GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "md5 meshes", "*.md5mesh" ) ); -} -ModelLoader* getTable(){ - return &m_modelmd5; -} + STRING_CONSTANT(Name, "md5mesh"); + + ModelMD5API() + { + GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("md5 meshes", "*.md5mesh")); + } + + ModelLoader *getTable() + { + return &m_modelmd5; + } }; typedef SingletonModule ModelMD5Module; @@ -215,13 +230,14 @@ typedef SingletonModule ModelMD5Module; ModelMD5Module g_ModelMD5Module; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); - - g_ModelMD3Module.selfRegister(); - g_ModelMD2Module.selfRegister(); - g_ModelMDLModule.selfRegister(); - g_ModelMDCModule.selfRegister(); - g_ImageMDLModule.selfRegister(); - g_ModelMD5Module.selfRegister(); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); + + g_ModelMD3Module.selfRegister(); + g_ModelMD2Module.selfRegister(); + g_ModelMDLModule.selfRegister(); + g_ModelMDCModule.selfRegister(); + g_ImageMDLModule.selfRegister(); + g_ModelMD5Module.selfRegister(); } diff --git a/plugins/model/model.cpp b/plugins/model/model.cpp index 5811af6f..1234c7bd 100644 --- a/plugins/model/model.cpp +++ b/plugins/model/model.cpp @@ -43,271 +43,297 @@ #include "traverselib.h" #include "render.h" -class VectorLightList : public LightList -{ -typedef std::vector Lights; -Lights m_lights; +class VectorLightList : public LightList { + typedef std::vector Lights; + Lights m_lights; public: -void addLight( const RendererLight& light ){ - m_lights.push_back( &light ); -} -void clear(){ - m_lights.clear(); -} -void evaluateLights() const { -} -void lightsChanged() const { -} -void forEachLight( const RendererLightCallback& callback ) const { - for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i ) - { - callback( *( *i ) ); - } -} + void addLight(const RendererLight &light) + { + m_lights.push_back(&light); + } + + void clear() + { + m_lights.clear(); + } + + void evaluateLights() const + { + } + + void lightsChanged() const + { + } + + void forEachLight(const RendererLightCallback &callback) const + { + for (Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i) { + callback(*(*i)); + } + } }; class PicoSurface : - public OpenGLRenderable -{ -AABB m_aabb_local; -CopiedString m_shader; -Shader* m_state; + public OpenGLRenderable { + AABB m_aabb_local; + CopiedString m_shader; + Shader *m_state; -Array m_vertices; -Array m_indices; + Array m_vertices; + Array m_indices; public: -PicoSurface(){ - constructNull(); - CaptureShader(); -} -PicoSurface( picoSurface_t* surface ){ - CopyPicoSurface( surface ); - CaptureShader(); -} -~PicoSurface(){ - ReleaseShader(); -} - -void render( RenderStateFlags state ) const { - if ( ( state & RENDER_BUMP ) != 0 ) { - if ( GlobalShaderCache().useShaderLanguage() ) { - glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->normal ); - glVertexAttribPointerARB( c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->texcoord ); - glVertexAttribPointerARB( c_attr_Tangent, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->tangent ); - glVertexAttribPointerARB( c_attr_Binormal, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->bitangent ); - } - else - { - glVertexAttribPointerARB( 11, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->normal ); - glVertexAttribPointerARB( 8, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->texcoord ); - glVertexAttribPointerARB( 9, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->tangent ); - glVertexAttribPointerARB( 10, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->bitangent ); - } - } - else - { - glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->normal ); - glTexCoordPointer( 2, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->texcoord ); - } - glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_vertices.data()->vertex ); - glDrawElements( GL_TRIANGLES, GLsizei( m_indices.size() ), RenderIndexTypeID, m_indices.data() ); + PicoSurface() + { + constructNull(); + CaptureShader(); + } + + PicoSurface(picoSurface_t *surface) + { + CopyPicoSurface(surface); + CaptureShader(); + } + + ~PicoSurface() + { + ReleaseShader(); + } + + void render(RenderStateFlags state) const + { + if ((state & RENDER_BUMP) != 0) { + if (GlobalShaderCache().useShaderLanguage()) { + glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->normal); + glVertexAttribPointerARB(c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_vertices.data()->texcoord); + glVertexAttribPointerARB(c_attr_Tangent, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_vertices.data()->tangent); + glVertexAttribPointerARB(c_attr_Binormal, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_vertices.data()->bitangent); + } else { + glVertexAttribPointerARB(11, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->normal); + glVertexAttribPointerARB(8, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->texcoord); + glVertexAttribPointerARB(9, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_vertices.data()->tangent); + glVertexAttribPointerARB(10, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_vertices.data()->bitangent); + } + } else { + glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->normal); + glTexCoordPointer(2, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->texcoord); + } + glVertexPointer(3, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_vertices.data()->vertex); + glDrawElements(GL_TRIANGLES, GLsizei(m_indices.size()), RenderIndexTypeID, m_indices.data()); #if GDEF_DEBUG - GLfloat modelview[16]; - glGetFloatv( GL_MODELVIEW_MATRIX, modelview ); // I know this is slow as hell, but hey - we're in _DEBUG - Matrix4 modelview_inv( - modelview[0], modelview[1], modelview[2], modelview[3], - modelview[4], modelview[5], modelview[6], modelview[7], - modelview[8], modelview[9], modelview[10], modelview[11], - modelview[12], modelview[13], modelview[14], modelview[15] ); - matrix4_full_invert( modelview_inv ); - Matrix4 modelview_inv_transposed = matrix4_transposed( modelview_inv ); - - glBegin( GL_LINES ); - - for ( Array::const_iterator i = m_vertices.begin(); i != m_vertices.end(); ++i ) - { - Vector3 normal = normal3f_to_vector3( ( *i ).normal ); - normal = matrix4_transformed_direction( modelview_inv, vector3_normalised( matrix4_transformed_direction( modelview_inv_transposed, normal ) ) ); // do some magic - Vector3 normalTransformed = vector3_added( vertex3f_to_vector3( ( *i ).vertex ), vector3_scaled( normal, 8 ) ); - glVertex3fv( vertex3f_to_array( ( *i ).vertex ) ); - glVertex3fv( vector3_to_array( normalTransformed ) ); - } - glEnd(); + GLfloat modelview[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, modelview); // I know this is slow as hell, but hey - we're in _DEBUG + Matrix4 modelview_inv( + modelview[0], modelview[1], modelview[2], modelview[3], + modelview[4], modelview[5], modelview[6], modelview[7], + modelview[8], modelview[9], modelview[10], modelview[11], + modelview[12], modelview[13], modelview[14], modelview[15]); + matrix4_full_invert(modelview_inv); + Matrix4 modelview_inv_transposed = matrix4_transposed(modelview_inv); + + glBegin(GL_LINES); + + for (Array::const_iterator i = m_vertices.begin(); i != m_vertices.end(); ++i) { + Vector3 normal = normal3f_to_vector3((*i).normal); + normal = matrix4_transformed_direction(modelview_inv, vector3_normalised( + matrix4_transformed_direction(modelview_inv_transposed, normal))); // do some magic + Vector3 normalTransformed = vector3_added(vertex3f_to_vector3((*i).vertex), vector3_scaled(normal, 8)); + glVertex3fv(vertex3f_to_array((*i).vertex)); + glVertex3fv(vector3_to_array(normalTransformed)); + } + glEnd(); #endif -} - -VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const { - return test.TestAABB( m_aabb_local, localToWorld ); -} - -const AABB& localAABB() const { - return m_aabb_local; -} - -void render( Renderer& renderer, const Matrix4& localToWorld, Shader* state ) const { - renderer.SetState( state, Renderer::eFullMaterials ); - renderer.addRenderable( *this, localToWorld ); -} - -void render( Renderer& renderer, const Matrix4& localToWorld ) const { - render( renderer, localToWorld, m_state ); -} - -void testSelect( Selector& selector, SelectionTest& test, const Matrix4& localToWorld ){ - test.BeginMesh( localToWorld ); - - SelectionIntersection best; - testSelect( test, best ); - if ( best.valid() ) { - selector.addIntersection( best ); - } -} - -const char* getShader() const { - return m_shader.c_str(); -} -Shader* getState() const { - return m_state; -} + } + + VolumeIntersectionValue intersectVolume(const VolumeTest &test, const Matrix4 &localToWorld) const + { + return test.TestAABB(m_aabb_local, localToWorld); + } + + const AABB &localAABB() const + { + return m_aabb_local; + } + + void render(Renderer &renderer, const Matrix4 &localToWorld, Shader *state) const + { + renderer.SetState(state, Renderer::eFullMaterials); + renderer.addRenderable(*this, localToWorld); + } + + void render(Renderer &renderer, const Matrix4 &localToWorld) const + { + render(renderer, localToWorld, m_state); + } + + void testSelect(Selector &selector, SelectionTest &test, const Matrix4 &localToWorld) + { + test.BeginMesh(localToWorld); + + SelectionIntersection best; + testSelect(test, best); + if (best.valid()) { + selector.addIntersection(best); + } + } + + const char *getShader() const + { + return m_shader.c_str(); + } + + Shader *getState() const + { + return m_state; + } private: -void CaptureShader(){ - m_state = GlobalShaderCache().capture( m_shader.c_str() ); -} -void ReleaseShader(){ - GlobalShaderCache().release( m_shader.c_str() ); -} - -void UpdateAABB(){ - m_aabb_local = AABB(); - for ( std::size_t i = 0; i < m_vertices.size(); ++i ) - aabb_extend_by_point_safe( m_aabb_local, reinterpret_cast( m_vertices[i].vertex ) ); - - - for ( Array::iterator i = m_indices.begin(); i != m_indices.end(); i += 3 ) - { - ArbitraryMeshVertex& a = m_vertices[*( i + 0 )]; - ArbitraryMeshVertex& b = m_vertices[*( i + 1 )]; - ArbitraryMeshVertex& c = m_vertices[*( i + 2 )]; - - ArbitraryMeshTriangle_sumTangents( a, b, c ); - } - - for ( Array::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i ) - { - vector3_normalise( reinterpret_cast( ( *i ).tangent ) ); - vector3_normalise( reinterpret_cast( ( *i ).bitangent ) ); - } -} - -void testSelect( SelectionTest& test, SelectionIntersection& best ){ - test.TestTriangles( - VertexPointer( VertexPointer::pointer( &m_vertices.data()->vertex ), sizeof( ArbitraryMeshVertex ) ), - IndexPointer( m_indices.data(), IndexPointer::index_type( m_indices.size() ) ), - best - ); -} - -void CopyPicoSurface( picoSurface_t* surface ){ - picoShader_t* shader = PicoGetSurfaceShader( surface ); - if ( shader == 0 ) { - m_shader = ""; - } - else{ - m_shader = PicoGetShaderName( shader ); - } - - m_vertices.resize( PicoGetSurfaceNumVertexes( surface ) ); - m_indices.resize( PicoGetSurfaceNumIndexes( surface ) ); - - for ( std::size_t i = 0; i < m_vertices.size(); ++i ) - { - picoVec_t* xyz = PicoGetSurfaceXYZ( surface, int(i) ); - m_vertices[i].vertex = vertex3f_from_array( xyz ); - - picoVec_t* normal = PicoGetSurfaceNormal( surface, int(i) ); - m_vertices[i].normal = normal3f_from_array( normal ); - - picoVec_t* st = PicoGetSurfaceST( surface, 0, int(i) ); - m_vertices[i].texcoord = TexCoord2f( st[0], st[1] ); + void CaptureShader() + { + m_state = GlobalShaderCache().capture(m_shader.c_str()); + } + + void ReleaseShader() + { + GlobalShaderCache().release(m_shader.c_str()); + } + + void UpdateAABB() + { + m_aabb_local = AABB(); + for (std::size_t i = 0; i < m_vertices.size(); ++i) { + aabb_extend_by_point_safe(m_aabb_local, reinterpret_cast( m_vertices[i].vertex )); + } + + + for (Array::iterator i = m_indices.begin(); i != m_indices.end(); i += 3) { + ArbitraryMeshVertex &a = m_vertices[*(i + 0)]; + ArbitraryMeshVertex &b = m_vertices[*(i + 1)]; + ArbitraryMeshVertex &c = m_vertices[*(i + 2)]; + + ArbitraryMeshTriangle_sumTangents(a, b, c); + } + + for (Array::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i) { + vector3_normalise(reinterpret_cast((*i).tangent )); + vector3_normalise(reinterpret_cast((*i).bitangent )); + } + } + + void testSelect(SelectionTest &test, SelectionIntersection &best) + { + test.TestTriangles( + VertexPointer(VertexPointer::pointer(&m_vertices.data()->vertex), sizeof(ArbitraryMeshVertex)), + IndexPointer(m_indices.data(), IndexPointer::index_type(m_indices.size())), + best + ); + } + + void CopyPicoSurface(picoSurface_t *surface) + { + picoShader_t *shader = PicoGetSurfaceShader(surface); + if (shader == 0) { + m_shader = ""; + } else { + m_shader = PicoGetShaderName(shader); + } + + m_vertices.resize(PicoGetSurfaceNumVertexes(surface)); + m_indices.resize(PicoGetSurfaceNumIndexes(surface)); + + for (std::size_t i = 0; i < m_vertices.size(); ++i) { + picoVec_t *xyz = PicoGetSurfaceXYZ(surface, int(i)); + m_vertices[i].vertex = vertex3f_from_array(xyz); + + picoVec_t *normal = PicoGetSurfaceNormal(surface, int(i)); + m_vertices[i].normal = normal3f_from_array(normal); + + picoVec_t *st = PicoGetSurfaceST(surface, 0, int(i)); + m_vertices[i].texcoord = TexCoord2f(st[0], st[1]); #if 0 - picoVec_t* color = PicoGetSurfaceColor( surface, 0, int(i) ); - m_vertices[i].colour = Colour4b( color[0], color[1], color[2], color[3] ); + picoVec_t* color = PicoGetSurfaceColor( surface, 0, int(i) ); + m_vertices[i].colour = Colour4b( color[0], color[1], color[2], color[3] ); #endif - } - - picoIndex_t* indexes = PicoGetSurfaceIndexes( surface, 0 ); - for ( std::size_t j = 0; j < m_indices.size(); ++j ) - m_indices[ j ] = indexes[ j ]; - - UpdateAABB(); -} - -void constructQuad( std::size_t index, const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d, const Vector3& normal ){ - m_vertices[index * 4 + 0] = ArbitraryMeshVertex( - vertex3f_for_vector3( a ), - normal3f_for_vector3( normal ), - texcoord2f_from_array( aabb_texcoord_topleft ) - ); - m_vertices[index * 4 + 1] = ArbitraryMeshVertex( - vertex3f_for_vector3( b ), - normal3f_for_vector3( normal ), - texcoord2f_from_array( aabb_texcoord_topright ) - ); - m_vertices[index * 4 + 2] = ArbitraryMeshVertex( - vertex3f_for_vector3( c ), - normal3f_for_vector3( normal ), - texcoord2f_from_array( aabb_texcoord_botright ) - ); - m_vertices[index * 4 + 3] = ArbitraryMeshVertex( - vertex3f_for_vector3( d ), - normal3f_for_vector3( normal ), - texcoord2f_from_array( aabb_texcoord_botleft ) - ); -} - -void constructNull(){ - AABB aabb( Vector3( 0, 0, 0 ), Vector3( 8, 8, 8 ) ); - - Vector3 points[8]; - aabb_corners( aabb, points ); - - m_vertices.resize( 24 ); - - constructQuad( 0, points[2], points[1], points[5], points[6], aabb_normals[0] ); - constructQuad( 1, points[1], points[0], points[4], points[5], aabb_normals[1] ); - constructQuad( 2, points[0], points[1], points[2], points[3], aabb_normals[2] ); - constructQuad( 3, points[0], points[3], points[7], points[4], aabb_normals[3] ); - constructQuad( 4, points[3], points[2], points[6], points[7], aabb_normals[4] ); - constructQuad( 5, points[7], points[6], points[5], points[4], aabb_normals[5] ); - - m_indices.resize( 36 ); - - RenderIndex indices[36] = { - 0, 1, 2, 0, 2, 3, - 4, 5, 6, 4, 6, 7, - 8, 9, 10, 8, 10, 11, - 12, 13, 14, 12, 14, 15, - 16, 17, 18, 16, 18, 19, - 20, 21, 22, 10, 22, 23, - }; - - - Array::iterator j = m_indices.begin(); - for ( RenderIndex* i = indices; i != indices + ( sizeof( indices ) / sizeof( RenderIndex ) ); ++i ) - { - *j++ = *i; - } - - m_shader = ""; - - UpdateAABB(); -} + } + + picoIndex_t *indexes = PicoGetSurfaceIndexes(surface, 0); + for (std::size_t j = 0; j < m_indices.size(); ++j) { + m_indices[j] = indexes[j]; + } + + UpdateAABB(); + } + + void constructQuad(std::size_t index, const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector3 &d, + const Vector3 &normal) + { + m_vertices[index * 4 + 0] = ArbitraryMeshVertex( + vertex3f_for_vector3(a), + normal3f_for_vector3(normal), + texcoord2f_from_array(aabb_texcoord_topleft) + ); + m_vertices[index * 4 + 1] = ArbitraryMeshVertex( + vertex3f_for_vector3(b), + normal3f_for_vector3(normal), + texcoord2f_from_array(aabb_texcoord_topright) + ); + m_vertices[index * 4 + 2] = ArbitraryMeshVertex( + vertex3f_for_vector3(c), + normal3f_for_vector3(normal), + texcoord2f_from_array(aabb_texcoord_botright) + ); + m_vertices[index * 4 + 3] = ArbitraryMeshVertex( + vertex3f_for_vector3(d), + normal3f_for_vector3(normal), + texcoord2f_from_array(aabb_texcoord_botleft) + ); + } + + void constructNull() + { + AABB aabb(Vector3(0, 0, 0), Vector3(8, 8, 8)); + + Vector3 points[8]; + aabb_corners(aabb, points); + + m_vertices.resize(24); + + constructQuad(0, points[2], points[1], points[5], points[6], aabb_normals[0]); + constructQuad(1, points[1], points[0], points[4], points[5], aabb_normals[1]); + constructQuad(2, points[0], points[1], points[2], points[3], aabb_normals[2]); + constructQuad(3, points[0], points[3], points[7], points[4], aabb_normals[3]); + constructQuad(4, points[3], points[2], points[6], points[7], aabb_normals[4]); + constructQuad(5, points[7], points[6], points[5], points[4], aabb_normals[5]); + + m_indices.resize(36); + + RenderIndex indices[36] = { + 0, 1, 2, 0, 2, 3, + 4, 5, 6, 4, 6, 7, + 8, 9, 10, 8, 10, 11, + 12, 13, 14, 12, 14, 15, + 16, 17, 18, 16, 18, 19, + 20, 21, 22, 10, 22, 23, + }; + + + Array::iterator j = m_indices.begin(); + for (RenderIndex *i = indices; i != indices + (sizeof(indices) / sizeof(RenderIndex)); ++i) { + *j++ = *i; + } + + m_shader = ""; + + UpdateAABB(); + } }; @@ -315,311 +341,363 @@ typedef std::pair PicoModelKey; class PicoModel : - public Cullable, - public Bounded -{ -typedef std::vector surfaces_t; -surfaces_t m_surfaces; + public Cullable, + public Bounded { + typedef std::vector surfaces_t; + surfaces_t m_surfaces; -AABB m_aabb_local; + AABB m_aabb_local; public: -Callback m_lightsChanged; - -PicoModel(){ - constructNull(); -} -PicoModel( picoModel_t* model ){ - CopyPicoModel( model ); -} -~PicoModel(){ - for ( surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i ) - delete *i; -} - -typedef surfaces_t::const_iterator const_iterator; - -const_iterator begin() const { - return m_surfaces.begin(); -} -const_iterator end() const { - return m_surfaces.end(); -} -std::size_t size() const { - return m_surfaces.size(); -} - -VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const { - return test.TestAABB( m_aabb_local, localToWorld ); -} - -virtual const AABB& localAABB() const { - return m_aabb_local; -} - -void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, std::vector states ) const { - for ( surfaces_t::const_iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i ) - { - if ( ( *i )->intersectVolume( volume, localToWorld ) != c_volumeOutside ) { - ( *i )->render( renderer, localToWorld, states[i - m_surfaces.begin()] ); - } - } -} - -void testSelect( Selector& selector, SelectionTest& test, const Matrix4& localToWorld ){ - for ( surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i ) - { - if ( ( *i )->intersectVolume( test.getVolume(), localToWorld ) != c_volumeOutside ) { - ( *i )->testSelect( selector, test, localToWorld ); - } - } -} + Callback m_lightsChanged; + + PicoModel() + { + constructNull(); + } + + PicoModel(picoModel_t *model) + { + CopyPicoModel(model); + } + + ~PicoModel() + { + for (surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i) { + delete *i; + } + } + + typedef surfaces_t::const_iterator const_iterator; + + const_iterator begin() const + { + return m_surfaces.begin(); + } + + const_iterator end() const + { + return m_surfaces.end(); + } + + std::size_t size() const + { + return m_surfaces.size(); + } + + VolumeIntersectionValue intersectVolume(const VolumeTest &test, const Matrix4 &localToWorld) const + { + return test.TestAABB(m_aabb_local, localToWorld); + } + + virtual const AABB &localAABB() const + { + return m_aabb_local; + } + + void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld, + std::vector states) const + { + for (surfaces_t::const_iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i) { + if ((*i)->intersectVolume(volume, localToWorld) != c_volumeOutside) { + (*i)->render(renderer, localToWorld, states[i - m_surfaces.begin()]); + } + } + } + + void testSelect(Selector &selector, SelectionTest &test, const Matrix4 &localToWorld) + { + for (surfaces_t::iterator i = m_surfaces.begin(); i != m_surfaces.end(); ++i) { + if ((*i)->intersectVolume(test.getVolume(), localToWorld) != c_volumeOutside) { + (*i)->testSelect(selector, test, localToWorld); + } + } + } private: -void CopyPicoModel( picoModel_t* model ){ - m_aabb_local = AABB(); - - /* each surface on the model will become a new map drawsurface */ - int numSurfaces = PicoGetModelNumSurfaces( model ); - //% SYs_FPrintf( SYS_VRB, "Model %s has %d surfaces\n", name, numSurfaces ); - for ( int s = 0; s < numSurfaces; ++s ) - { - /* get surface */ - picoSurface_t* surface = PicoGetModelSurface( model, s ); - if ( surface == 0 ) { - continue; - } - - /* only handle triangle surfaces initially (fixme: support patches) */ - if ( PicoGetSurfaceType( surface ) != PICO_TRIANGLES ) { - continue; - } - - /* fix the surface's normals */ - PicoFixSurfaceNormals( surface ); - - PicoSurface* picosurface = new PicoSurface( surface ); - aabb_extend_by_aabb_safe( m_aabb_local, picosurface->localAABB() ); - m_surfaces.push_back( picosurface ); - } -} -void constructNull(){ - PicoSurface* picosurface = new PicoSurface(); - m_aabb_local = picosurface->localAABB(); - m_surfaces.push_back( picosurface ); -} + void CopyPicoModel(picoModel_t *model) + { + m_aabb_local = AABB(); + + /* each surface on the model will become a new map drawsurface */ + int numSurfaces = PicoGetModelNumSurfaces(model); + //% SYs_FPrintf( SYS_VRB, "Model %s has %d surfaces\n", name, numSurfaces ); + for (int s = 0; s < numSurfaces; ++s) { + /* get surface */ + picoSurface_t *surface = PicoGetModelSurface(model, s); + if (surface == 0) { + continue; + } + + /* only handle triangle surfaces initially (fixme: support patches) */ + if (PicoGetSurfaceType(surface) != PICO_TRIANGLES) { + continue; + } + + /* fix the surface's normals */ + PicoFixSurfaceNormals(surface); + + PicoSurface *picosurface = new PicoSurface(surface); + aabb_extend_by_aabb_safe(m_aabb_local, picosurface->localAABB()); + m_surfaces.push_back(picosurface); + } + } + + void constructNull() + { + PicoSurface *picosurface = new PicoSurface(); + m_aabb_local = picosurface->localAABB(); + m_surfaces.push_back(picosurface); + } }; -inline void Surface_addLight( PicoSurface& surface, VectorLightList& lights, const Matrix4& localToWorld, const RendererLight& light ){ - if ( light.testAABB( aabb_for_oriented_aabb( surface.localAABB(), localToWorld ) ) ) { - lights.addLight( light ); - } -} - -class PicoModelInstance : - public scene::Instance, - public Renderable, - public SelectionTestable, - public LightCullable, - public SkinnedModel -{ -class TypeCasts +inline void +Surface_addLight(PicoSurface &surface, VectorLightList &lights, const Matrix4 &localToWorld, const RendererLight &light) { -InstanceTypeCastTable m_casts; -public: -TypeCasts(){ - InstanceContainedCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; + if (light.testAABB(aabb_for_oriented_aabb(surface.localAABB(), localToWorld))) { + lights.addLight(light); + } } -}; - -PicoModel& m_picomodel; -const LightList* m_lightList; -typedef Array SurfaceLightLists; -SurfaceLightLists m_surfaceLightLists; +class PicoModelInstance : + public scene::Instance, + public Renderable, + public SelectionTestable, + public LightCullable, + public SkinnedModel { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + InstanceContainedCast::install(m_casts); + InstanceContainedCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + PicoModel &m_picomodel; + + const LightList *m_lightList; + typedef Array SurfaceLightLists; + SurfaceLightLists m_surfaceLightLists; + + class Remap { + public: + CopiedString first; + Shader *second; + + Remap() : second(0) + { + } + }; + + typedef Array SurfaceRemaps; + SurfaceRemaps m_skins; + + PicoModelInstance(const PicoModelInstance &); + + PicoModelInstance operator=(const PicoModelInstance &); -class Remap -{ public: -CopiedString first; -Shader* second; -Remap() : second( 0 ){ -} + typedef LazyStatic StaticTypeCasts; + + void *m_test; + + Bounded &get(NullType) + { + return m_picomodel; + } + + Cullable &get(NullType) + { + return m_picomodel; + } + + void lightsChanged() + { + m_lightList->lightsChanged(); + } + + typedef MemberCaller LightsChangedCaller; + + void constructRemaps() + { + ASSERT_MESSAGE(m_skins.size() == m_picomodel.size(), "ERROR"); + ModelSkin *skin = NodeTypeCast::cast(path().parent()); + if (skin != 0 && skin->realised()) { + SurfaceRemaps::iterator j = m_skins.begin(); + for (PicoModel::const_iterator i = m_picomodel.begin(); i != m_picomodel.end(); ++i, ++j) { + const char *remap = skin->getRemap((*i)->getShader()); + if (!string_empty(remap)) { + (*j).first = remap; + (*j).second = GlobalShaderCache().capture(remap); + } else { + (*j).second = 0; + } + } + SceneChangeNotify(); + } + } + + void destroyRemaps() + { + ASSERT_MESSAGE(m_skins.size() == m_picomodel.size(), "ERROR"); + for (SurfaceRemaps::iterator i = m_skins.begin(); i != m_skins.end(); ++i) { + if ((*i).second != 0) { + GlobalShaderCache().release((*i).first.c_str()); + (*i).second = 0; + } + } + } + + void skinChanged() + { + destroyRemaps(); + constructRemaps(); + } + + PicoModelInstance(const scene::Path &path, scene::Instance *parent, PicoModel &picomodel) : + Instance(path, parent, this, StaticTypeCasts::instance().get()), + m_picomodel(picomodel), + m_surfaceLightLists(m_picomodel.size()), + m_skins(m_picomodel.size()) + { + m_lightList = &GlobalShaderCache().attach(*this); + m_picomodel.m_lightsChanged = LightsChangedCaller(*this); + + Instance::setTransformChangedCallback(LightsChangedCaller(*this)); + + constructRemaps(); + } + + ~PicoModelInstance() + { + destroyRemaps(); + + Instance::setTransformChangedCallback(Callback()); + + m_picomodel.m_lightsChanged = Callback(); + GlobalShaderCache().detach(*this); + } + + void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + SurfaceLightLists::const_iterator j = m_surfaceLightLists.begin(); + SurfaceRemaps::const_iterator k = m_skins.begin(); + for (PicoModel::const_iterator i = m_picomodel.begin(); i != m_picomodel.end(); ++i, ++j, ++k) { + if ((*i)->intersectVolume(volume, localToWorld) != c_volumeOutside) { + renderer.setLights(*j); + (*i)->render(renderer, localToWorld, (*k).second != 0 ? (*k).second : (*i)->getState()); + } + } + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_lightList->evaluateLights(); + + render(renderer, volume, Instance::localToWorld()); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + renderSolid(renderer, volume); + } + + void testSelect(Selector &selector, SelectionTest &test) + { + m_picomodel.testSelect(selector, test, Instance::localToWorld()); + } + + bool testLight(const RendererLight &light) const + { + return light.testAABB(worldAABB()); + } + + void insertLight(const RendererLight &light) + { + const Matrix4 &localToWorld = Instance::localToWorld(); + SurfaceLightLists::iterator j = m_surfaceLightLists.begin(); + for (PicoModel::const_iterator i = m_picomodel.begin(); i != m_picomodel.end(); ++i) { + Surface_addLight(*(*i), *j++, localToWorld, light); + } + } + + void clearLights() + { + for (SurfaceLightLists::iterator i = m_surfaceLightLists.begin(); i != m_surfaceLightLists.end(); ++i) { + (*i).clear(); + } + } }; -typedef Array SurfaceRemaps; -SurfaceRemaps m_skins; - -PicoModelInstance( const PicoModelInstance& ); -PicoModelInstance operator=( const PicoModelInstance& ); -public: -typedef LazyStatic StaticTypeCasts; - -void* m_test; - -Bounded& get( NullType){ - return m_picomodel; -} -Cullable& get( NullType){ - return m_picomodel; -} - -void lightsChanged(){ - m_lightList->lightsChanged(); -} -typedef MemberCaller LightsChangedCaller; - -void constructRemaps(){ - ASSERT_MESSAGE( m_skins.size() == m_picomodel.size(), "ERROR" ); - ModelSkin* skin = NodeTypeCast::cast( path().parent() ); - if ( skin != 0 && skin->realised() ) { - SurfaceRemaps::iterator j = m_skins.begin(); - for ( PicoModel::const_iterator i = m_picomodel.begin(); i != m_picomodel.end(); ++i, ++j ) - { - const char* remap = skin->getRemap( ( *i )->getShader() ); - if ( !string_empty( remap ) ) { - ( *j ).first = remap; - ( *j ).second = GlobalShaderCache().capture( remap ); - } - else - { - ( *j ).second = 0; - } - } - SceneChangeNotify(); - } -} -void destroyRemaps(){ - ASSERT_MESSAGE( m_skins.size() == m_picomodel.size(), "ERROR" ); - for ( SurfaceRemaps::iterator i = m_skins.begin(); i != m_skins.end(); ++i ) - { - if ( ( *i ).second != 0 ) { - GlobalShaderCache().release( ( *i ).first.c_str() ); - ( *i ).second = 0; - } - } -} -void skinChanged(){ - destroyRemaps(); - constructRemaps(); -} -PicoModelInstance( const scene::Path& path, scene::Instance* parent, PicoModel& picomodel ) : - Instance( path, parent, this, StaticTypeCasts::instance().get() ), - m_picomodel( picomodel ), - m_surfaceLightLists( m_picomodel.size() ), - m_skins( m_picomodel.size() ){ - m_lightList = &GlobalShaderCache().attach( *this ); - m_picomodel.m_lightsChanged = LightsChangedCaller( *this ); +class PicoModelNode : public scene::Node::Symbiot, public scene::Instantiable { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + } - Instance::setTransformChangedCallback( LightsChangedCaller( *this ) ); + NodeTypeCastTable &get() + { + return m_casts; + } + }; - constructRemaps(); -} -~PicoModelInstance(){ - destroyRemaps(); - - Instance::setTransformChangedCallback( Callback() ); - m_picomodel.m_lightsChanged = Callback(); - GlobalShaderCache().detach( *this ); -} + scene::Node m_node; + InstanceSet m_instances; + PicoModel m_picomodel; -void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - SurfaceLightLists::const_iterator j = m_surfaceLightLists.begin(); - SurfaceRemaps::const_iterator k = m_skins.begin(); - for ( PicoModel::const_iterator i = m_picomodel.begin(); i != m_picomodel.end(); ++i, ++j, ++k ) - { - if ( ( *i )->intersectVolume( volume, localToWorld ) != c_volumeOutside ) { - renderer.setLights( *j ); - ( *i )->render( renderer, localToWorld, ( *k ).second != 0 ? ( *k ).second : ( *i )->getState() ); - } - } -} - -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_lightList->evaluateLights(); - - render( renderer, volume, Instance::localToWorld() ); -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - renderSolid( renderer, volume ); -} - -void testSelect( Selector& selector, SelectionTest& test ){ - m_picomodel.testSelect( selector, test, Instance::localToWorld() ); -} - -bool testLight( const RendererLight& light ) const { - return light.testAABB( worldAABB() ); -} -void insertLight( const RendererLight& light ){ - const Matrix4& localToWorld = Instance::localToWorld(); - SurfaceLightLists::iterator j = m_surfaceLightLists.begin(); - for ( PicoModel::const_iterator i = m_picomodel.begin(); i != m_picomodel.end(); ++i ) - { - Surface_addLight( *( *i ), *j++, localToWorld, light ); - } -} -void clearLights(){ - for ( SurfaceLightLists::iterator i = m_surfaceLightLists.begin(); i != m_surfaceLightLists.end(); ++i ) - { - ( *i ).clear(); - } -} -}; - -class PicoModelNode : public scene::Node::Symbiot, public scene::Instantiable -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} -}; - - -scene::Node m_node; -InstanceSet m_instances; -PicoModel m_picomodel; - -public: -typedef LazyStatic StaticTypeCasts; - -PicoModelNode() : m_node( this, this, StaticTypeCasts::instance().get() ){ -} -PicoModelNode( picoModel_t* model ) : m_node( this, this, StaticTypeCasts::instance().get() ), m_picomodel( model ){ -} - -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} - -scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new PicoModelInstance( path, parent, m_picomodel ); -} -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 ); -} + typedef LazyStatic StaticTypeCasts; + + PicoModelNode() : m_node(this, this, StaticTypeCasts::instance().get()) + { + } + + PicoModelNode(picoModel_t *model) : m_node(this, this, StaticTypeCasts::instance().get()), m_picomodel(model) + { + } + + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } + + scene::Instance *create(const scene::Path &path, scene::Instance *parent) + { + return new PicoModelInstance(path, parent, m_picomodel); + } + + 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); + } }; @@ -630,10 +708,10 @@ class create_new { public: static Type* construct( const Key& key ){ - return new Type( key ); + return new Type( key ); } static void destroy( Type* value ){ - delete value; + delete value; } }; @@ -643,35 +721,35 @@ class cache_element : public creation_policy public: inline cache_element() : m_count( 0 ), m_value( 0 ) {} inline ~cache_element(){ - ASSERT_MESSAGE( m_count == 0, "destroyed a reference before it was released\n" ); - if ( m_count > 0 ) { - destroy(); - } + ASSERT_MESSAGE( m_count == 0, "destroyed a reference before it was released\n" ); + if ( m_count > 0 ) { + destroy(); + } } inline Type* capture( const Key& key ){ - if ( ++m_count == 1 ) { - construct( key ); - } - return m_value; + if ( ++m_count == 1 ) { + construct( key ); + } + return m_value; } inline void release(){ - ASSERT_MESSAGE( !empty(), "failed to release reference - not found in cache\n" ); - if ( --m_count == 0 ) { - destroy(); - } + ASSERT_MESSAGE( !empty(), "failed to release reference - not found in cache\n" ); + if ( --m_count == 0 ) { + destroy(); + } } inline bool empty(){ - return m_count == 0; + return m_count == 0; } inline void refresh( const Key& key ){ - m_value->refresh( key ); + m_value->refresh( key ); } private: inline void construct( const Key& key ){ - m_value = creation_policy::construct( key ); + m_value = creation_policy::construct( key ); } inline void destroy(){ - creation_policy::destroy( m_value ); + creation_policy::destroy( m_value ); } std::size_t m_count; @@ -684,13 +762,13 @@ typedef PicoModelKey key_type; typedef PicoModel value_type; public: static value_type* construct( const key_type& key ){ - picoModel_t* picomodel = PicoLoadModel( const_cast( key.first.c_str() ), key.second ); - value_type* value = new value_type( picomodel ); - PicoFreeModel( picomodel ); - return value; + picoModel_t* picomodel = PicoLoadModel( const_cast( key.first.c_str() ), key.second ); + value_type* value = new value_type( picomodel ); + PicoFreeModel( picomodel ); + return value; } static void destroy( value_type* value ){ - delete value; + delete value; } }; @@ -706,10 +784,10 @@ typedef cache_element elem_type; typedef std::map cache_type; value_type* capture( const key_type& key ){ - return m_cache[key].capture( key ); + return m_cache[key].capture( key ); } void release( const key_type& key ){ - m_cache[key].release(); + m_cache[key].release(); } private: @@ -721,141 +799,141 @@ ModelCache g_model_cache; typedef struct remap_s { - char m_remapbuff[64 + 1024]; - char *original; - char *remap; + char m_remapbuff[64 + 1024]; + char *original; + char *remap; } remap_t; class RemapWrapper : - public Cullable, - public Bounded + public Cullable, + public Bounded { public: RemapWrapper( const char* name ){ - parse_namestr( name ); + parse_namestr( name ); - m_model = g_model_cache.capture( ModelCache::key_type( m_name, m_frame ) ); + m_model = g_model_cache.capture( ModelCache::key_type( m_name, m_frame ) ); - construct_shaders(); + construct_shaders(); } virtual ~RemapWrapper(){ - g_model_cache.release( ModelCache::key_type( m_name, m_frame ) ); + g_model_cache.release( ModelCache::key_type( m_name, m_frame ) ); - for ( shaders_t::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) - { - GlobalShaderCache().release( ( *i ).c_str() ); - } + for ( shaders_t::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) + { + GlobalShaderCache().release( ( *i ).c_str() ); + } - for ( remaps_t::iterator j = m_remaps.begin(); j != m_remaps.end(); ++j ) - { - delete ( *j ); - } + for ( remaps_t::iterator j = m_remaps.begin(); j != m_remaps.end(); ++j ) + { + delete ( *j ); + } } VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const { - return m_model->intersectVolume( test, localToWorld ); + return m_model->intersectVolume( test, localToWorld ); } virtual const AABB& localAABB() const { - return m_model->localAABB(); + return m_model->localAABB(); } void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - m_model->render( renderer, volume, localToWorld, m_states ); + m_model->render( renderer, volume, localToWorld, m_states ); } void testSelect( Selector& selector, SelectionTest& test, const Matrix4& localToWorld ){ - m_model->testSelect( selector, test, localToWorld ); + m_model->testSelect( selector, test, localToWorld ); } private: void add_remap( const char *remap ){ - const char *ch; - remap_t *pRemap; + const char *ch; + remap_t *pRemap; - ch = remap; + ch = remap; - while ( *ch && *ch != ';' ) - ch++; + while ( *ch && *ch != ';' ) + ch++; - if ( *ch == '\0' ) { - // bad remap - globalErrorStream() << "WARNING: Shader _remap key found in a model entity without a ; character\n"; - } - else { - pRemap = new remap_t; + if ( *ch == '\0' ) { + // bad remap + globalErrorStream() << "WARNING: Shader _remap key found in a model entity without a ; character\n"; + } + else { + pRemap = new remap_t; - strncpy( pRemap->m_remapbuff, remap, sizeof( pRemap->m_remapbuff ) ); + strncpy( pRemap->m_remapbuff, remap, sizeof( pRemap->m_remapbuff ) ); - pRemap->m_remapbuff[ch - remap] = '\0'; + pRemap->m_remapbuff[ch - remap] = '\0'; - pRemap->original = pRemap->m_remapbuff; - pRemap->remap = pRemap->m_remapbuff + ( ch - remap ) + 1; + pRemap->original = pRemap->m_remapbuff; + pRemap->remap = pRemap->m_remapbuff + ( ch - remap ) + 1; - m_remaps.push_back( pRemap ); - } + m_remaps.push_back( pRemap ); + } } void parse_namestr( const char *name ){ - const char *ptr, *s; - bool hasName, hasFrame; - - hasName = hasFrame = false; - - m_frame = 0; - - for ( s = ptr = name; ; ++ptr ) - { - if ( !hasName && ( *ptr == ':' || *ptr == '\0' ) ) { - // model name - hasName = true; - m_name = CopiedString( s, ptr ); - s = ptr + 1; - } - else if ( *ptr == '?' || *ptr == '\0' ) { - // model frame - hasFrame = true; - m_frame = atoi( CopiedString( s, ptr ).c_str() ); - s = ptr + 1; - } - else if ( *ptr == '&' || *ptr == '\0' ) { - // a remap - add_remap( CopiedString( s, ptr ).c_str() ); - s = ptr + 1; - } - - if ( *ptr == '\0' ) { - break; - } - } + const char *ptr, *s; + bool hasName, hasFrame; + + hasName = hasFrame = false; + + m_frame = 0; + + for ( s = ptr = name; ; ++ptr ) + { + if ( !hasName && ( *ptr == ':' || *ptr == '\0' ) ) { + // model name + hasName = true; + m_name = CopiedString( s, ptr ); + s = ptr + 1; + } + else if ( *ptr == '?' || *ptr == '\0' ) { + // model frame + hasFrame = true; + m_frame = atoi( CopiedString( s, ptr ).c_str() ); + s = ptr + 1; + } + else if ( *ptr == '&' || *ptr == '\0' ) { + // a remap + add_remap( CopiedString( s, ptr ).c_str() ); + s = ptr + 1; + } + + if ( *ptr == '\0' ) { + break; + } + } } void construct_shaders(){ - const char* global_shader = shader_for_remap( "*" ); - - m_shaders.reserve( m_model->size() ); - m_states.reserve( m_model->size() ); - for ( PicoModel::iterator i = m_model->begin(); i != m_model->end(); ++i ) - { - const char* shader = shader_for_remap( ( *i )->getShader() ); - m_shaders.push_back( - ( shader[0] != '\0' ) - ? shader - : ( global_shader[0] != '\0' ) - ? global_shader - : ( *i )->getShader() ); - m_states.push_back( GlobalShaderCache().capture( m_shaders.back().c_str() ) ); - } + const char* global_shader = shader_for_remap( "*" ); + + m_shaders.reserve( m_model->size() ); + m_states.reserve( m_model->size() ); + for ( PicoModel::iterator i = m_model->begin(); i != m_model->end(); ++i ) + { + const char* shader = shader_for_remap( ( *i )->getShader() ); + m_shaders.push_back( + ( shader[0] != '\0' ) + ? shader + : ( global_shader[0] != '\0' ) + ? global_shader + : ( *i )->getShader() ); + m_states.push_back( GlobalShaderCache().capture( m_shaders.back().c_str() ) ); + } } inline const char* shader_for_remap( const char* remap ){ - for ( remaps_t::iterator i = m_remaps.begin(); i != m_remaps.end(); ++i ) - { - if ( shader_equal( remap, ( *i )->original ) ) { - return ( *i )->remap; - } - } - return ""; + for ( remaps_t::iterator i = m_remaps.begin(); i != m_remaps.end(); ++i ) + { + if ( shader_equal( remap, ( *i )->original ) ) { + return ( *i )->remap; + } + } + return ""; } CopiedString m_name; @@ -875,20 +953,20 @@ class RemapWrapperInstance : public scene::Instance, public Renderable, public S RemapWrapper& m_remapwrapper; public: RemapWrapperInstance( const scene::Path& path, scene::Instance* parent, RemapWrapper& remapwrapper ) : Instance( path, parent ), m_remapwrapper( remapwrapper ){ - scene::Instance::m_cullable = &m_remapwrapper; - scene::Instance::m_render = this; - scene::Instance::m_select = this; + scene::Instance::m_cullable = &m_remapwrapper; + scene::Instance::m_render = this; + scene::Instance::m_select = this; } void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_remapwrapper.render( renderer, volume, Instance::localToWorld() ); + m_remapwrapper.render( renderer, volume, Instance::localToWorld() ); } void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - renderSolid( renderer, volume ); + renderSolid( renderer, volume ); } void testSelect( Selector& selector, SelectionTest& test ){ - m_remapwrapper.testSelect( selector, test, Instance::localToWorld() ); + m_remapwrapper.testSelect( selector, test, Instance::localToWorld() ); } }; @@ -900,44 +978,47 @@ InstanceSet m_instances; RemapWrapper m_remapwrapper; public: RemapWrapperNode( const char* name ) : m_node( this ), m_remapwrapper( name ){ - m_node.m_instance = this; + m_node.m_instance = this; } void release(){ - delete this; + delete this; } scene::Node& node(){ - return m_node; + return m_node; } scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new instance_type( path, parent, m_remapwrapper ); + return new instance_type( path, parent, m_remapwrapper ); } void forEachInstance( const scene::Instantiable::Visitor& visitor ){ - m_instances.forEachInstance( visitor ); + m_instances.forEachInstance( visitor ); } void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){ - m_instances.insert( observer, path, instance ); + m_instances.insert( observer, path, instance ); } scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){ - return m_instances.erase( observer, path ); + return m_instances.erase( observer, path ); } }; scene::Node& LoadRemapModel( const char* name ){ - return ( new RemapWrapperNode( name ) )->node(); + return ( new RemapWrapperNode( name ) )->node(); } #endif -size_t picoInputStreamReam( void* inputStream, unsigned char* buffer, size_t length ){ - return reinterpret_cast( inputStream )->read( buffer, length ); +size_t picoInputStreamReam(void *inputStream, unsigned char *buffer, size_t length) +{ + return reinterpret_cast( inputStream )->read(buffer, length); } -scene::Node& loadPicoModel( const picoModule_t* module, ArchiveFile& file ){ - picoModel_t* model = PicoModuleLoadModelStream( module, &file.getInputStream(), picoInputStreamReam, file.size(), 0, file.getName() ); - PicoModelNode* modelNode = new PicoModelNode( model ); - PicoFreeModel( model ); - return modelNode->node(); +scene::Node &loadPicoModel(const picoModule_t *module, ArchiveFile &file) +{ + picoModel_t *model = PicoModuleLoadModelStream(module, &file.getInputStream(), picoInputStreamReam, file.size(), 0, + file.getName()); + PicoModelNode *modelNode = new PicoModelNode(model); + PicoFreeModel(model); + return modelNode->node(); } diff --git a/plugins/model/model.h b/plugins/model/model.h index 9961fb9f..b0145f54 100644 --- a/plugins/model/model.h +++ b/plugins/model/model.h @@ -24,7 +24,9 @@ namespace scene { class Node; } class ArchiveFile; + typedef struct picoModule_s picoModule_t; -scene::Node& loadPicoModel( const picoModule_t* module, ArchiveFile& file ); + +scene::Node &loadPicoModel(const picoModule_t *module, ArchiveFile &file); #endif diff --git a/plugins/model/plugin.cpp b/plugins/model/plugin.cpp index d23809a6..51aa05b3 100644 --- a/plugins/model/plugin.cpp +++ b/plugins/model/plugin.cpp @@ -21,7 +21,9 @@ #include #include "picomodel.h" + typedef unsigned char byte; + #include #include #include @@ -44,108 +46,121 @@ typedef unsigned char byte; #include "model.h" -void PicoPrintFunc( int level, const char *str ){ - if ( str == 0 ) { - return; - } - switch ( level ) - { - case PICO_NORMAL: - globalOutputStream() << str << "\n"; - break; - - case PICO_VERBOSE: - //globalOutputStream() << "PICO_VERBOSE: " << str << "\n"; - break; - - case PICO_WARNING: - globalErrorStream() << "PICO_WARNING: " << str << "\n"; - break; - - case PICO_ERROR: - globalErrorStream() << "PICO_ERROR: " << str << "\n"; - break; - - case PICO_FATAL: - globalErrorStream() << "PICO_FATAL: " << str << "\n"; - break; - } +void PicoPrintFunc(int level, const char *str) +{ + if (str == 0) { + return; + } + switch (level) { + case PICO_NORMAL: + globalOutputStream() << str << "\n"; + break; + + case PICO_VERBOSE: + //globalOutputStream() << "PICO_VERBOSE: " << str << "\n"; + break; + + case PICO_WARNING: + globalErrorStream() << "PICO_WARNING: " << str << "\n"; + break; + + case PICO_ERROR: + globalErrorStream() << "PICO_ERROR: " << str << "\n"; + break; + + case PICO_FATAL: + globalErrorStream() << "PICO_FATAL: " << str << "\n"; + break; + } } -void PicoLoadFileFunc( const char *name, byte **buffer, int *bufSize ){ - *bufSize = vfsLoadFile( name, (void**) buffer ); +void PicoLoadFileFunc(const char *name, byte **buffer, int *bufSize) +{ + *bufSize = vfsLoadFile(name, (void **) buffer); } -void PicoFreeFileFunc( void* file ){ - vfsFreeFile( file ); +void PicoFreeFileFunc(void *file) +{ + vfsFreeFile(file); } -void pico_initialise(){ - PicoInit(); - PicoSetMallocFunc( malloc ); - PicoSetFreeFunc( free ); - PicoSetPrintFunc( PicoPrintFunc ); - PicoSetLoadFileFunc( PicoLoadFileFunc ); - PicoSetFreeFileFunc( PicoFreeFileFunc ); +void pico_initialise() +{ + PicoInit(); + PicoSetMallocFunc(malloc); + PicoSetFreeFunc(free); + PicoSetPrintFunc(PicoPrintFunc); + PicoSetLoadFileFunc(PicoLoadFileFunc); + PicoSetFreeFileFunc(PicoFreeFileFunc); } -class PicoModelLoader : public ModelLoader -{ -const picoModule_t* m_module; +class PicoModelLoader : public ModelLoader { + const picoModule_t *m_module; public: -PicoModelLoader( const picoModule_t* module ) : m_module( module ){ -} -scene::Node& loadModel( ArchiveFile& file ){ - return loadPicoModel( m_module, file ); -} + PicoModelLoader(const picoModule_t *module) : m_module(module) + { + } + + scene::Node &loadModel(ArchiveFile &file) + { + return loadPicoModel(m_module, file); + } }; class ModelPicoDependencies : - public GlobalFileSystemModuleRef, - public GlobalOpenGLModuleRef, - public GlobalUndoModuleRef, - public GlobalSceneGraphModuleRef, - public GlobalShaderCacheModuleRef, - public GlobalSelectionModuleRef, - public GlobalFiletypesModuleRef -{ + public GlobalFileSystemModuleRef, + public GlobalOpenGLModuleRef, + public GlobalUndoModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalSelectionModuleRef, + public GlobalFiletypesModuleRef { }; -class ModelPicoAPI : public TypeSystemRef -{ -PicoModelLoader m_modelLoader; +class ModelPicoAPI : public TypeSystemRef { + PicoModelLoader m_modelLoader; public: -typedef ModelLoader Type; - -ModelPicoAPI( const char* extension, const picoModule_t* module ) : - m_modelLoader( module ){ - StringOutputStream filter( 128 ); - filter << "*." << extension; - GlobalFiletypesModule::getTable().addType( Type::Name(), extension, filetype_t( module->displayName, filter.c_str() ) ); -} -ModelLoader* getTable(){ - return &m_modelLoader; -} + typedef ModelLoader Type; + + ModelPicoAPI(const char *extension, const picoModule_t *module) : + m_modelLoader(module) + { + StringOutputStream filter(128); + filter << "*." << extension; + GlobalFiletypesModule::getTable().addType(Type::Name(), extension, + filetype_t(module->displayName, filter.c_str())); + } + + ModelLoader *getTable() + { + return &m_modelLoader; + } }; -class PicoModelAPIConstructor -{ -CopiedString m_extension; -const picoModule_t* m_module; +class PicoModelAPIConstructor { + CopiedString m_extension; + const picoModule_t *m_module; public: -PicoModelAPIConstructor( const char* extension, const picoModule_t* module ) : - m_extension( extension ), m_module( module ){ -} -const char* getName(){ - return m_extension.c_str(); -} -ModelPicoAPI* constructAPI( ModelPicoDependencies& dependencies ){ - return new ModelPicoAPI( m_extension.c_str(), m_module ); -} -void destroyAPI( ModelPicoAPI* api ){ - delete api; -} + PicoModelAPIConstructor(const char *extension, const picoModule_t *module) : + m_extension(extension), m_module(module) + { + } + + const char *getName() + { + return m_extension.c_str(); + } + + ModelPicoAPI *constructAPI(ModelPicoDependencies &dependencies) + { + return new ModelPicoAPI(m_extension.c_str(), m_module); + } + + void destroyAPI(ModelPicoAPI *api) + { + delete api; + } }; @@ -154,21 +169,20 @@ typedef std::list PicoModelModules; PicoModelModules g_PicoModelModules; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); - - pico_initialise(); - - const picoModule_t** modules = PicoModuleList( 0 ); - while ( *modules != 0 ) - { - const picoModule_t* module = *modules++; - if ( module->canload && module->load ) { - for ( char*const* ext = module->defaultExts; *ext != 0; ++ext ) - { - g_PicoModelModules.push_back( PicoModelModule( PicoModelAPIConstructor( *ext, module ) ) ); - g_PicoModelModules.back().selfRegister(); - } - } - } +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); + + pico_initialise(); + + const picoModule_t **modules = PicoModuleList(0); + while (*modules != 0) { + const picoModule_t *module = *modules++; + if (module->canload && module->load) { + for (char *const *ext = module->defaultExts; *ext != 0; ++ext) { + g_PicoModelModules.push_back(PicoModelModule(PicoModelAPIConstructor(*ext, module))); + g_PicoModelModules.back().selfRegister(); + } + } + } } diff --git a/plugins/sample/sample.cpp b/plugins/sample/sample.cpp index df3ba904..565a09f4 100644 --- a/plugins/sample/sample.cpp +++ b/plugins/sample/sample.cpp @@ -29,57 +29,73 @@ #include "modulesystem/singletonmodule.h" #include "typesystem.h" -namespace Sample -{ -const char* init( void* hApp, void* pMainWidget ){ - return ""; -} -const char* getName(){ - return "Sample Plugin"; -} -const char* getCommandList(){ - return "About;Do Something"; -} -const char* getCommandTitleList(){ - return ""; -} -void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){ - if ( string_equal( command, "About" ) ) { - globalOutputStream() << "Sample Demo Plugin\n"; - } - if ( string_equal( command, "Do Something" ) ) { - globalOutputStream() << "Sample Command\n"; - } -} +namespace Sample { + const char *init(void *hApp, void *pMainWidget) + { + return ""; + } + + const char *getName() + { + return "Sample Plugin"; + } + + const char *getCommandList() + { + return "About;Do Something"; + } + + const char *getCommandTitleList() + { + return ""; + } + + void dispatch(const char *command, float *vMin, float *vMax, bool bSingleBrush) + { + if (string_equal(command, "About")) { + globalOutputStream() << "Sample Demo Plugin\n"; + } + if (string_equal(command, "Do Something")) { + globalOutputStream() << "Sample Command\n"; + } + } } // namespace -class SamplePluginModule : public TypeSystemRef -{ -_QERPluginTable m_plugin; +class SamplePluginModule : public TypeSystemRef { + _QERPluginTable m_plugin; public: -typedef _QERPluginTable Type; -STRING_CONSTANT( Name, "sample" ); - -SamplePluginModule(){ - m_plugin.m_pfnQERPlug_Init = &Sample::init; - m_plugin.m_pfnQERPlug_GetName = &Sample::getName; - m_plugin.m_pfnQERPlug_GetCommandList = &Sample::getCommandList; - m_plugin.m_pfnQERPlug_GetCommandTitleList = &Sample::getCommandTitleList; - m_plugin.m_pfnQERPlug_Dispatch = &Sample::dispatch; -} -_QERPluginTable* getTable(){ - return &m_plugin; -} + typedef _QERPluginTable Type; + STRING_CONSTANT( Name, + "sample" ); + + SamplePluginModule() + { + m_plugin.m_pfnQERPlug_Init = &Sample::init; + m_plugin.m_pfnQERPlug_GetName = &Sample::getName; + m_plugin.m_pfnQERPlug_GetCommandList = &Sample::getCommandList; + m_plugin.m_pfnQERPlug_GetCommandTitleList = &Sample::getCommandTitleList; + m_plugin.m_pfnQERPlug_Dispatch = &Sample::dispatch; + } + + _QERPluginTable *getTable() + { + return &m_plugin; + } }; -typedef SingletonModule SingletonSamplePluginModule; +typedef SingletonModule SingletonSamplePluginModule; SingletonSamplePluginModule g_SamplePluginModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); +extern "C" void RADIANT_DLLEXPORT +Radiant_RegisterModules( ModuleServer +& server ){ +initialiseModule( server ); + +g_SamplePluginModule. + +selfRegister(); - g_SamplePluginModule.selfRegister(); } diff --git a/plugins/shaders/plugin.cpp b/plugins/shaders/plugin.cpp index 4576a641..93f215d7 100644 --- a/plugins/shaders/plugin.cpp +++ b/plugins/shaders/plugin.cpp @@ -31,41 +31,48 @@ #include "shaders.h" class ShadersDependencies : - public GlobalFileSystemModuleRef, - public GlobalTexturesModuleRef, - public GlobalScripLibModuleRef, - public GlobalRadiantModuleRef -{ -ImageModuleRef m_bitmapModule; + public GlobalFileSystemModuleRef, + public GlobalTexturesModuleRef, + public GlobalScripLibModuleRef, + public GlobalRadiantModuleRef { + ImageModuleRef m_bitmapModule; public: -ShadersDependencies() : - m_bitmapModule( "png" ){ -} -ImageModuleRef& getBitmapModule(){ - return m_bitmapModule; -} + ShadersDependencies() : + m_bitmapModule("png") + { + } + + ImageModuleRef &getBitmapModule() + { + return m_bitmapModule; + } }; -class ShadersQ3API -{ -ShaderSystem* m_shadersq3; +class ShadersQ3API { + ShaderSystem *m_shadersq3; public: -typedef ShaderSystem Type; -STRING_CONSTANT( Name, "quake3" ); - -ShadersQ3API( ShadersDependencies& dependencies ){ - g_shadersExtension = "shader"; - g_shadersDirectory = "scripts/"; - g_bitmapModule = dependencies.getBitmapModule().getTable(); - Shaders_Construct(); - m_shadersq3 = &GetShaderSystem(); -} -~ShadersQ3API(){ - Shaders_Destroy(); -} -ShaderSystem* getTable(){ - return m_shadersq3; -} + typedef ShaderSystem Type; + + STRING_CONSTANT(Name, "quake3"); + + ShadersQ3API(ShadersDependencies &dependencies) + { + g_shadersExtension = "shader"; + g_shadersDirectory = "scripts/"; + g_bitmapModule = dependencies.getBitmapModule().getTable(); + Shaders_Construct(); + m_shadersq3 = &GetShaderSystem(); + } + + ~ShadersQ3API() + { + Shaders_Destroy(); + } + + ShaderSystem *getTable() + { + return m_shadersq3; + } }; typedef SingletonModule > ShadersQ3Module; @@ -73,29 +80,34 @@ typedef SingletonModule > ShadersDoom3Module; @@ -103,29 +115,34 @@ typedef SingletonModule > ShadersQuake4Module; @@ -133,11 +150,11 @@ typedef SingletonModule g_ActiveShadersChangedNotify; void FreeShaders(); -void LoadShaderFile( const char *filename ); -qtexture_t *Texture_ForName( const char *filename ); + +void LoadShaderFile(const char *filename); + +qtexture_t *Texture_ForName(const char *filename); /*! @@ -96,47 +102,49 @@ qtexture_t *Texture_ForName( const char *filename ); this was in the initial design of the shader code since early GtkRadiant alpha, and got sort of foxed in 1.2 and put back in */ -Image* loadBitmap( void* environment, const char* name ){ - DirectoryArchiveFile file( name, name ); - if ( !file.failed() ) { - return g_bitmapModule->loadImage( file ); - } - return 0; +Image *loadBitmap(void *environment, const char *name) +{ + DirectoryArchiveFile file(name, name); + if (!file.failed()) { + return g_bitmapModule->loadImage(file); + } + return 0; } -inline byte* getPixel( byte* pixels, int width, int height, int x, int y ){ - return pixels + ( ( ( ( ( y + height ) % height ) * width ) + ( ( x + width ) % width ) ) * 4 ); +inline byte *getPixel(byte *pixels, int width, int height, int x, int y) +{ + return pixels + (((((y + height) % height) * width) + ((x + width) % width)) * 4); } -class KernelElement -{ +class KernelElement { public: -int x, y; -float w; + int x, y; + float w; }; -Image& convertHeightmapToNormalmap( Image& heightmap, float scale ){ - int w = heightmap.getWidth(); - int h = heightmap.getHeight(); +Image &convertHeightmapToNormalmap(Image &heightmap, float scale) +{ + int w = heightmap.getWidth(); + int h = heightmap.getHeight(); - Image& normalmap = *( new RGBAImage( heightmap.getWidth(), heightmap.getHeight() ) ); + Image &normalmap = *(new RGBAImage(heightmap.getWidth(), heightmap.getHeight())); - byte* in = heightmap.getRGBAPixels(); - byte* out = normalmap.getRGBAPixels(); + byte *in = heightmap.getRGBAPixels(); + byte *out = normalmap.getRGBAPixels(); #if 1 - // no filtering - const int kernelSize = 2; - KernelElement kernel_du[kernelSize] = { - {-1, 0,-0.5f }, - { 1, 0, 0.5f } - }; - KernelElement kernel_dv[kernelSize] = { - { 0, 1, 0.5f }, - { 0,-1,-0.5f } - }; + // no filtering + const int kernelSize = 2; + KernelElement kernel_du[kernelSize] = { + {-1, 0, -0.5f}, + {1, 0, 0.5f} + }; + KernelElement kernel_dv[kernelSize] = { + {0, 1, 0.5f}, + {0, -1, -0.5f} + }; #else - // 3x3 Prewitt + // 3x3 Prewitt const int kernelSize = 6; KernelElement kernel_du[kernelSize] = { {-1, 1,-1.0f }, @@ -156,70 +164,68 @@ Image& convertHeightmapToNormalmap( Image& heightmap, float scale ){ }; #endif - int x, y = 0; - while ( y < h ) - { - x = 0; - while ( x < w ) - { - float du = 0; - for ( KernelElement* i = kernel_du; i != kernel_du + kernelSize; ++i ) - { - du += ( getPixel( in, w, h, x + ( *i ).x, y + ( *i ).y )[0] / 255.0 ) * ( *i ).w; - } - float dv = 0; - for ( KernelElement* i = kernel_dv; i != kernel_dv + kernelSize; ++i ) - { - dv += ( getPixel( in, w, h, x + ( *i ).x, y + ( *i ).y )[0] / 255.0 ) * ( *i ).w; - } - - float nx = -du * scale; - float ny = -dv * scale; - float nz = 1.0; - - // Normalize - float norm = 1.0 / sqrt( nx * nx + ny * ny + nz * nz ); - out[0] = float_to_integer( ( ( nx * norm ) + 1 ) * 127.5 ); - out[1] = float_to_integer( ( ( ny * norm ) + 1 ) * 127.5 ); - out[2] = float_to_integer( ( ( nz * norm ) + 1 ) * 127.5 ); - out[3] = 255; - - x++; - out += 4; - } - - y++; - } - - return normalmap; -} - -Image* loadHeightmap( void* environment, const char* name ){ - Image* heightmap = GlobalTexturesCache().loadImage( name ); - if ( heightmap != 0 ) { - Image& normalmap = convertHeightmapToNormalmap( *heightmap, *reinterpret_cast( environment ) ); - heightmap->release(); - return &normalmap; - } - return 0; + int x, y = 0; + while (y < h) { + x = 0; + while (x < w) { + float du = 0; + for (KernelElement *i = kernel_du; i != kernel_du + kernelSize; ++i) { + du += (getPixel(in, w, h, x + (*i).x, y + (*i).y)[0] / 255.0) * (*i).w; + } + float dv = 0; + for (KernelElement *i = kernel_dv; i != kernel_dv + kernelSize; ++i) { + dv += (getPixel(in, w, h, x + (*i).x, y + (*i).y)[0] / 255.0) * (*i).w; + } + + float nx = -du * scale; + float ny = -dv * scale; + float nz = 1.0; + + // Normalize + float norm = 1.0 / sqrt(nx * nx + ny * ny + nz * nz); + out[0] = float_to_integer(((nx * norm) + 1) * 127.5); + out[1] = float_to_integer(((ny * norm) + 1) * 127.5); + out[2] = float_to_integer(((nz * norm) + 1) * 127.5); + out[3] = 255; + + x++; + out += 4; + } + + y++; + } + + return normalmap; +} + +Image *loadHeightmap(void *environment, const char *name) +{ + Image *heightmap = GlobalTexturesCache().loadImage(name); + if (heightmap != 0) { + Image &normalmap = convertHeightmapToNormalmap(*heightmap, *reinterpret_cast( environment )); + heightmap->release(); + return &normalmap; + } + return 0; } -Image* loadSpecial( void* environment, const char* name ){ - if ( *name == '_' ) { // special image - StringOutputStream bitmapName( 256 ); - bitmapName << GlobalRadiant().getAppPath() << "bitmaps/" << name + 1 << ".png"; - Image* image = loadBitmap( environment, bitmapName.c_str() ); - if ( image != 0 ) { - return image; - } - } - return GlobalTexturesCache().loadImage( name ); -} - -class ShaderPoolContext +Image *loadSpecial(void *environment, const char *name) { + if (*name == '_') { // special image + StringOutputStream bitmapName(256); + bitmapName << GlobalRadiant().getAppPath() << "bitmaps/" << name + 1 << ".png"; + Image *image = loadBitmap(environment, bitmapName.c_str()); + if (image != 0) { + return image; + } + } + return GlobalTexturesCache().loadImage(name); +} + +class ShaderPoolContext { }; + typedef Static ShaderPool; typedef PooledString ShaderString; typedef ShaderString ShaderVariable; @@ -232,448 +238,440 @@ typedef CopiedString TextureExpression; // we compare as case insensitive. That is Radiant is case insensitive, but knows that the engine is case sensitive. //++timo FIXME: we need to put code somewhere to detect when two shaders that are case insensitive equal are present template -void parseTextureName( StringType& name, const char* token ){ - StringOutputStream cleaned( 256 ); - cleaned << PathCleaned( token ); - name = CopiedString( StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ) ).c_str(); // remove extension +void parseTextureName(StringType &name, const char *token) +{ + StringOutputStream cleaned(256); + cleaned << PathCleaned(token); + name = CopiedString( + StringRange(cleaned.c_str(), path_get_filename_base_end(cleaned.c_str()))).c_str(); // remove extension } -bool Tokeniser_parseTextureName( Tokeniser& tokeniser, TextureExpression& name ){ - const char* token = tokeniser.getToken(); - if ( token == 0 ) { - Tokeniser_unexpectedError( tokeniser, token, "#texture-name" ); - return false; - } - parseTextureName( name, token ); - return true; +bool Tokeniser_parseTextureName(Tokeniser &tokeniser, TextureExpression &name) +{ + const char *token = tokeniser.getToken(); + if (token == 0) { + Tokeniser_unexpectedError(tokeniser, token, "#texture-name"); + return false; + } + parseTextureName(name, token); + return true; } -bool Tokeniser_parseShaderName( Tokeniser& tokeniser, CopiedString& name ){ - const char* token = tokeniser.getToken(); - if ( token == 0 ) { - Tokeniser_unexpectedError( tokeniser, token, "#shader-name" ); - return false; - } - parseTextureName( name, token ); - return true; +bool Tokeniser_parseShaderName(Tokeniser &tokeniser, CopiedString &name) +{ + const char *token = tokeniser.getToken(); + if (token == 0) { + Tokeniser_unexpectedError(tokeniser, token, "#shader-name"); + return false; + } + parseTextureName(name, token); + return true; } -bool Tokeniser_parseString( Tokeniser& tokeniser, ShaderString& string ){ - const char* token = tokeniser.getToken(); - if ( token == 0 ) { - Tokeniser_unexpectedError( tokeniser, token, "#string" ); - return false; - } - string = token; - return true; +bool Tokeniser_parseString(Tokeniser &tokeniser, ShaderString &string) +{ + const char *token = tokeniser.getToken(); + if (token == 0) { + Tokeniser_unexpectedError(tokeniser, token, "#string"); + return false; + } + string = token; + return true; } - typedef std::list ShaderParameters; typedef std::list ShaderArguments; typedef std::pair BlendFuncExpression; -class ShaderTemplate -{ -std::size_t m_refcount; -CopiedString m_Name; +class ShaderTemplate { + std::size_t m_refcount; + CopiedString m_Name; public: -ShaderParameters m_params; + ShaderParameters m_params; -TextureExpression m_textureName; -TextureExpression m_diffuse; -TextureExpression m_bump; -ShaderValue m_heightmapScale; -TextureExpression m_specular; -TextureExpression m_lightFalloffImage; + TextureExpression m_textureName; + TextureExpression m_diffuse; + TextureExpression m_bump; + ShaderValue m_heightmapScale; + TextureExpression m_specular; + TextureExpression m_lightFalloffImage; -int m_nFlags; -float m_fTrans; + int m_nFlags; + float m_fTrans; // alphafunc stuff -IShader::EAlphaFunc m_AlphaFunc; -float m_AlphaRef; + IShader::EAlphaFunc m_AlphaFunc; + float m_AlphaRef; // cull stuff -IShader::ECull m_Cull; - -ShaderTemplate() : - m_refcount( 0 ){ - m_nFlags = 0; - m_fTrans = 1.0f; -} - -void IncRef(){ - ++m_refcount; -} -void DecRef(){ - ASSERT_MESSAGE( m_refcount != 0, "shader reference-count going below zero" ); - if ( --m_refcount == 0 ) { - delete this; - } -} - -std::size_t refcount(){ - return m_refcount; -} - -const char* getName() const { - return m_Name.c_str(); -} -void setName( const char* name ){ - m_Name = name; -} + IShader::ECull m_Cull; + + ShaderTemplate() : + m_refcount(0) + { + m_nFlags = 0; + m_fTrans = 1.0f; + } + + void IncRef() + { + ++m_refcount; + } + + void DecRef() + { + ASSERT_MESSAGE(m_refcount != 0, "shader reference-count going below zero"); + if (--m_refcount == 0) { + delete this; + } + } + + std::size_t refcount() + { + return m_refcount; + } + + const char *getName() const + { + return m_Name.c_str(); + } + + void setName(const char *name) + { + m_Name = name; + } // ----------------------------------------- -bool parseDoom3( Tokeniser& tokeniser ); -bool parseQuake3( Tokeniser& tokeniser ); -bool parseTemplate( Tokeniser& tokeniser ); - - -void CreateDefault( const char *name ){ - if ( g_enableDefaultShaders ) { - m_textureName = name; - } - else - { - m_textureName = ""; - } - setName( name ); -} - - -class MapLayerTemplate -{ -TextureExpression m_texture; -BlendFuncExpression m_blendFunc; -bool m_clampToBorder; -ShaderValue m_alphaTest; -public: -MapLayerTemplate( const TextureExpression& texture, const BlendFuncExpression& blendFunc, bool clampToBorder, const ShaderValue& alphaTest ) : - m_texture( texture ), - m_blendFunc( blendFunc ), - m_clampToBorder( false ), - m_alphaTest( alphaTest ){ -} -const TextureExpression& texture() const { - return m_texture; -} -const BlendFuncExpression& blendFunc() const { - return m_blendFunc; -} -bool clampToBorder() const { - return m_clampToBorder; -} -const ShaderValue& alphaTest() const { - return m_alphaTest; -} + bool parseDoom3(Tokeniser &tokeniser); + + bool parseQuake3(Tokeniser &tokeniser); + + bool parseTemplate(Tokeniser &tokeniser); + + + void CreateDefault(const char *name) + { + if (g_enableDefaultShaders) { + m_textureName = name; + } else { + m_textureName = ""; + } + setName(name); + } + + + class MapLayerTemplate { + TextureExpression m_texture; + BlendFuncExpression m_blendFunc; + bool m_clampToBorder; + ShaderValue m_alphaTest; + public: + MapLayerTemplate(const TextureExpression &texture, const BlendFuncExpression &blendFunc, bool clampToBorder, + const ShaderValue &alphaTest) : + m_texture(texture), + m_blendFunc(blendFunc), + m_clampToBorder(false), + m_alphaTest(alphaTest) + { + } + + const TextureExpression &texture() const + { + return m_texture; + } + + const BlendFuncExpression &blendFunc() const + { + return m_blendFunc; + } + + bool clampToBorder() const + { + return m_clampToBorder; + } + + const ShaderValue &alphaTest() const + { + return m_alphaTest; + } + }; + + typedef std::vector MapLayers; + MapLayers m_layers; }; -typedef std::vector MapLayers; -MapLayers m_layers; -}; - - -bool Doom3Shader_parseHeightmap( Tokeniser& tokeniser, TextureExpression& bump, ShaderValue& heightmapScale ){ - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, bump ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "," ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_parseString( tokeniser, heightmapScale ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); - return true; -} -bool Doom3Shader_parseAddnormals( Tokeniser& tokeniser, TextureExpression& bump ){ - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, bump ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "," ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "heightmap" ) ); - TextureExpression heightmapName; - ShaderValue heightmapScale; - RETURN_FALSE_IF_FAIL( Doom3Shader_parseHeightmap( tokeniser, heightmapName, heightmapScale ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); - return true; -} -bool Doom3Shader_parseBumpmap( Tokeniser& tokeniser, TextureExpression& bump, ShaderValue& heightmapScale ){ - const char* token = tokeniser.getToken(); - if ( token == 0 ) { - Tokeniser_unexpectedError( tokeniser, token, "#bumpmap" ); - return false; - } - if ( string_equal( token, "heightmap" ) ) { - RETURN_FALSE_IF_FAIL( Doom3Shader_parseHeightmap( tokeniser, bump, heightmapScale ) ); - } - else if ( string_equal( token, "addnormals" ) ) { - RETURN_FALSE_IF_FAIL( Doom3Shader_parseAddnormals( tokeniser, bump ) ); - } - else - { - parseTextureName( bump, token ); - } - return true; +bool Doom3Shader_parseHeightmap(Tokeniser &tokeniser, TextureExpression &bump, ShaderValue &heightmapScale) +{ + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); + RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, bump)); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ",")); + RETURN_FALSE_IF_FAIL(Tokeniser_parseString(tokeniser, heightmapScale)); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); + return true; } -enum LayerTypeId +bool Doom3Shader_parseAddnormals(Tokeniser &tokeniser, TextureExpression &bump) { - LAYER_NONE, - LAYER_BLEND, - LAYER_DIFFUSEMAP, - LAYER_BUMPMAP, - LAYER_SPECULARMAP + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); + RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, bump)); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ",")); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "heightmap")); + TextureExpression heightmapName; + ShaderValue heightmapScale; + RETURN_FALSE_IF_FAIL(Doom3Shader_parseHeightmap(tokeniser, heightmapName, heightmapScale)); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); + return true; +} + +bool Doom3Shader_parseBumpmap(Tokeniser &tokeniser, TextureExpression &bump, ShaderValue &heightmapScale) +{ + const char *token = tokeniser.getToken(); + if (token == 0) { + Tokeniser_unexpectedError(tokeniser, token, "#bumpmap"); + return false; + } + if (string_equal(token, "heightmap")) { + RETURN_FALSE_IF_FAIL(Doom3Shader_parseHeightmap(tokeniser, bump, heightmapScale)); + } else if (string_equal(token, "addnormals")) { + RETURN_FALSE_IF_FAIL(Doom3Shader_parseAddnormals(tokeniser, bump)); + } else { + parseTextureName(bump, token); + } + return true; +} + +enum LayerTypeId { + LAYER_NONE, + LAYER_BLEND, + LAYER_DIFFUSEMAP, + LAYER_BUMPMAP, + LAYER_SPECULARMAP }; -class LayerTemplate -{ +class LayerTemplate { public: -LayerTypeId m_type; -TextureExpression m_texture; -BlendFuncExpression m_blendFunc; -bool m_clampToBorder; -ShaderValue m_alphaTest; -ShaderValue m_heightmapScale; - -LayerTemplate() : m_type( LAYER_NONE ), m_blendFunc( "GL_ONE", "GL_ZERO" ), m_clampToBorder( false ), m_alphaTest( "-1" ), m_heightmapScale( "0" ){ -} + LayerTypeId m_type; + TextureExpression m_texture; + BlendFuncExpression m_blendFunc; + bool m_clampToBorder; + ShaderValue m_alphaTest; + ShaderValue m_heightmapScale; + + LayerTemplate() : m_type(LAYER_NONE), m_blendFunc("GL_ONE", "GL_ZERO"), m_clampToBorder(false), m_alphaTest("-1"), + m_heightmapScale("0") + { + } }; -bool parseShaderParameters( Tokeniser& tokeniser, ShaderParameters& params ){ - Tokeniser_parseToken( tokeniser, "(" ); - for (;; ) - { - const char* param = tokeniser.getToken(); - if ( string_equal( param, ")" ) ) { - break; - } - params.push_back( param ); - const char* comma = tokeniser.getToken(); - if ( string_equal( comma, ")" ) ) { - break; - } - if ( !string_equal( comma, "," ) ) { - Tokeniser_unexpectedError( tokeniser, comma, "," ); - return false; - } - } - return true; -} - -bool ShaderTemplate::parseTemplate( Tokeniser& tokeniser ){ - m_Name = tokeniser.getToken(); - if ( !parseShaderParameters( tokeniser, m_params ) ) { - globalErrorStream() << "shader template: " << makeQuoted( m_Name.c_str() ) << ": parameter parse failed\n"; - return false; - } +bool parseShaderParameters(Tokeniser &tokeniser, ShaderParameters ¶ms) +{ + Tokeniser_parseToken(tokeniser, "("); + for (;;) { + const char *param = tokeniser.getToken(); + if (string_equal(param, ")")) { + break; + } + params.push_back(param); + const char *comma = tokeniser.getToken(); + if (string_equal(comma, ")")) { + break; + } + if (!string_equal(comma, ",")) { + Tokeniser_unexpectedError(tokeniser, comma, ","); + return false; + } + } + return true; +} + +bool ShaderTemplate::parseTemplate(Tokeniser &tokeniser) +{ + m_Name = tokeniser.getToken(); + if (!parseShaderParameters(tokeniser, m_params)) { + globalErrorStream() << "shader template: " << makeQuoted(m_Name.c_str()) << ": parameter parse failed\n"; + return false; + } - return parseDoom3( tokeniser ); + return parseDoom3(tokeniser); } -bool ShaderTemplate::parseDoom3( Tokeniser& tokeniser ){ - LayerTemplate currentLayer; - bool isFog = false; - - // we need to read until we hit a balanced } - int depth = 0; - for (;; ) - { - tokeniser.nextLine(); - const char* token = tokeniser.getToken(); - - if ( token == 0 ) { - return false; - } - - if ( string_equal( token, "{" ) ) { - ++depth; - continue; - } - else if ( string_equal( token, "}" ) ) { - --depth; - if ( depth < 0 ) { // error - return false; - } - if ( depth == 0 ) { // end of shader - break; - } - if ( depth == 1 ) { // end of layer - if ( currentLayer.m_type == LAYER_DIFFUSEMAP ) { - m_diffuse = currentLayer.m_texture; - } - else if ( currentLayer.m_type == LAYER_BUMPMAP ) { - m_bump = currentLayer.m_texture; - } - else if ( currentLayer.m_type == LAYER_SPECULARMAP ) { - m_specular = currentLayer.m_texture; - } - else if ( !string_empty( currentLayer.m_texture.c_str() ) ) { - m_layers.push_back( MapLayerTemplate( - currentLayer.m_texture.c_str(), - currentLayer.m_blendFunc, - currentLayer.m_clampToBorder, - currentLayer.m_alphaTest - ) ); - } - currentLayer.m_type = LAYER_NONE; - currentLayer.m_texture = ""; - } - continue; - } - - if ( depth == 2 ) { // in layer - if ( string_equal_nocase( token, "blend" ) ) { - const char* blend = tokeniser.getToken(); - - if ( blend == 0 ) { - Tokeniser_unexpectedError( tokeniser, blend, "#blend" ); - return false; - } - - if ( string_equal_nocase( blend, "diffusemap" ) ) { - currentLayer.m_type = LAYER_DIFFUSEMAP; - } - else if ( string_equal_nocase( blend, "bumpmap" ) ) { - currentLayer.m_type = LAYER_BUMPMAP; - } - else if ( string_equal_nocase( blend, "specularmap" ) ) { - currentLayer.m_type = LAYER_SPECULARMAP; - } - else - { - currentLayer.m_blendFunc.first = blend; - - const char* comma = tokeniser.getToken(); - - if ( comma == 0 ) { - Tokeniser_unexpectedError( tokeniser, comma, "#comma" ); - return false; - } - - if ( string_equal( comma, "," ) ) { - RETURN_FALSE_IF_FAIL( Tokeniser_parseString( tokeniser, currentLayer.m_blendFunc.second ) ); - } - else - { - currentLayer.m_blendFunc.second = ""; - tokeniser.ungetToken(); - } - } - } - else if ( string_equal_nocase( token, "map" ) ) { - if ( currentLayer.m_type == LAYER_BUMPMAP ) { - RETURN_FALSE_IF_FAIL( Doom3Shader_parseBumpmap( tokeniser, currentLayer.m_texture, currentLayer.m_heightmapScale ) ); - } - else - { - const char* map = tokeniser.getToken(); - - if ( map == 0 ) { - Tokeniser_unexpectedError( tokeniser, map, "#map" ); - return false; - } - - if ( string_equal( map, "makealpha" ) ) { - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); - const char* texture = tokeniser.getToken(); - if ( texture == 0 ) { - Tokeniser_unexpectedError( tokeniser, texture, "#texture" ); - return false; - } - currentLayer.m_texture = texture; - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); - } - else - { - parseTextureName( currentLayer.m_texture, map ); - } - } - } - else if ( string_equal_nocase( token, "zeroclamp" ) ) { - currentLayer.m_clampToBorder = true; - } +bool ShaderTemplate::parseDoom3(Tokeniser &tokeniser) +{ + LayerTemplate currentLayer; + bool isFog = false; + + // we need to read until we hit a balanced } + int depth = 0; + for (;;) { + tokeniser.nextLine(); + const char *token = tokeniser.getToken(); + + if (token == 0) { + return false; + } + + if (string_equal(token, "{")) { + ++depth; + continue; + } else if (string_equal(token, "}")) { + --depth; + if (depth < 0) { // error + return false; + } + if (depth == 0) { // end of shader + break; + } + if (depth == 1) { // end of layer + if (currentLayer.m_type == LAYER_DIFFUSEMAP) { + m_diffuse = currentLayer.m_texture; + } else if (currentLayer.m_type == LAYER_BUMPMAP) { + m_bump = currentLayer.m_texture; + } else if (currentLayer.m_type == LAYER_SPECULARMAP) { + m_specular = currentLayer.m_texture; + } else if (!string_empty(currentLayer.m_texture.c_str())) { + m_layers.push_back(MapLayerTemplate( + currentLayer.m_texture.c_str(), + currentLayer.m_blendFunc, + currentLayer.m_clampToBorder, + currentLayer.m_alphaTest + )); + } + currentLayer.m_type = LAYER_NONE; + currentLayer.m_texture = ""; + } + continue; + } + + if (depth == 2) { // in layer + if (string_equal_nocase(token, "blend")) { + const char *blend = tokeniser.getToken(); + + if (blend == 0) { + Tokeniser_unexpectedError(tokeniser, blend, "#blend"); + return false; + } + + if (string_equal_nocase(blend, "diffusemap")) { + currentLayer.m_type = LAYER_DIFFUSEMAP; + } else if (string_equal_nocase(blend, "bumpmap")) { + currentLayer.m_type = LAYER_BUMPMAP; + } else if (string_equal_nocase(blend, "specularmap")) { + currentLayer.m_type = LAYER_SPECULARMAP; + } else { + currentLayer.m_blendFunc.first = blend; + + const char *comma = tokeniser.getToken(); + + if (comma == 0) { + Tokeniser_unexpectedError(tokeniser, comma, "#comma"); + return false; + } + + if (string_equal(comma, ",")) { + RETURN_FALSE_IF_FAIL(Tokeniser_parseString(tokeniser, currentLayer.m_blendFunc.second)); + } else { + currentLayer.m_blendFunc.second = ""; + tokeniser.ungetToken(); + } + } + } else if (string_equal_nocase(token, "map")) { + if (currentLayer.m_type == LAYER_BUMPMAP) { + RETURN_FALSE_IF_FAIL( + Doom3Shader_parseBumpmap(tokeniser, currentLayer.m_texture, currentLayer.m_heightmapScale)); + } else { + const char *map = tokeniser.getToken(); + + if (map == 0) { + Tokeniser_unexpectedError(tokeniser, map, "#map"); + return false; + } + + if (string_equal(map, "makealpha")) { + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); + const char *texture = tokeniser.getToken(); + if (texture == 0) { + Tokeniser_unexpectedError(tokeniser, texture, "#texture"); + return false; + } + currentLayer.m_texture = texture; + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); + } else { + parseTextureName(currentLayer.m_texture, map); + } + } + } else if (string_equal_nocase(token, "zeroclamp")) { + currentLayer.m_clampToBorder = true; + } #if 0 - else if ( string_equal_nocase( token, "alphaTest" ) ) { + else if ( string_equal_nocase( token, "alphaTest" ) ) { Tokeniser_getFloat( tokeniser, currentLayer.m_alphaTest ); } #endif - } - else if ( depth == 1 ) { - if ( string_equal_nocase( token, "qer_editorimage" ) ) { - RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, m_textureName ) ); - } - else if ( string_equal_nocase( token, "qer_trans" ) ) { - m_fTrans = string_read_float( tokeniser.getToken() ); - m_nFlags |= QER_TRANS; - } - else if ( string_equal_nocase( token, "translucent" ) ) { - m_fTrans = 1; - m_nFlags |= QER_TRANS; - } - else if ( string_equal( token, "DECAL_MACRO" ) ) { - m_fTrans = 1; - m_nFlags |= QER_TRANS; - } - else if ( string_equal_nocase( token, "bumpmap" ) ) { - RETURN_FALSE_IF_FAIL( Doom3Shader_parseBumpmap( tokeniser, m_bump, m_heightmapScale ) ); - } - else if ( string_equal_nocase( token, "diffusemap" ) ) { - RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, m_diffuse ) ); - } - else if ( string_equal_nocase( token, "specularmap" ) ) { - RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, m_specular ) ); - } - else if ( string_equal_nocase( token, "twosided" ) ) { - m_Cull = IShader::eCullNone; - m_nFlags |= QER_CULL; - } - else if ( string_equal_nocase( token, "nodraw" ) ) { - m_nFlags |= QER_NODRAW; - } - else if ( string_equal_nocase( token, "nonsolid" ) ) { - m_nFlags |= QER_NONSOLID; - } - else if ( string_equal_nocase( token, "liquid" ) ) { - m_nFlags |= QER_WATER; - } - else if ( string_equal_nocase( token, "areaportal" ) ) { - m_nFlags |= QER_AREAPORTAL; - } - else if ( string_equal_nocase( token, "playerclip" ) - || string_equal_nocase( token, "monsterclip" ) - || string_equal_nocase( token, "ikclip" ) - || string_equal_nocase( token, "moveableclip" ) ) { - m_nFlags |= QER_CLIP; - } - if ( string_equal_nocase( token, "fogLight" ) ) { - isFog = true; - } - else if ( !isFog && string_equal_nocase( token, "lightFalloffImage" ) ) { - const char* lightFalloffImage = tokeniser.getToken(); - if ( lightFalloffImage == 0 ) { - Tokeniser_unexpectedError( tokeniser, lightFalloffImage, "#lightFalloffImage" ); - return false; - } - if ( string_equal_nocase( lightFalloffImage, "makeintensity" ) ) { - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); - TextureExpression name; - RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, name ) ); - m_lightFalloffImage = name; - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); - } - else - { - m_lightFalloffImage = lightFalloffImage; - } - } - } - } - - if ( string_empty( m_textureName.c_str() ) ) { - m_textureName = m_diffuse; - } - - return true; + } else if (depth == 1) { + if (string_equal_nocase(token, "qer_editorimage")) { + RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, m_textureName)); + } else if (string_equal_nocase(token, "qer_trans")) { + m_fTrans = string_read_float(tokeniser.getToken()); + m_nFlags |= QER_TRANS; + } else if (string_equal_nocase(token, "translucent")) { + m_fTrans = 1; + m_nFlags |= QER_TRANS; + } else if (string_equal(token, "DECAL_MACRO")) { + m_fTrans = 1; + m_nFlags |= QER_TRANS; + } else if (string_equal_nocase(token, "bumpmap")) { + RETURN_FALSE_IF_FAIL(Doom3Shader_parseBumpmap(tokeniser, m_bump, m_heightmapScale)); + } else if (string_equal_nocase(token, "diffusemap")) { + RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, m_diffuse)); + } else if (string_equal_nocase(token, "specularmap")) { + RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, m_specular)); + } else if (string_equal_nocase(token, "twosided")) { + m_Cull = IShader::eCullNone; + m_nFlags |= QER_CULL; + } else if (string_equal_nocase(token, "nodraw")) { + m_nFlags |= QER_NODRAW; + } else if (string_equal_nocase(token, "nonsolid")) { + m_nFlags |= QER_NONSOLID; + } else if (string_equal_nocase(token, "liquid")) { + m_nFlags |= QER_WATER; + } else if (string_equal_nocase(token, "areaportal")) { + m_nFlags |= QER_AREAPORTAL; + } else if (string_equal_nocase(token, "playerclip") + || string_equal_nocase(token, "monsterclip") + || string_equal_nocase(token, "ikclip") + || string_equal_nocase(token, "moveableclip")) { + m_nFlags |= QER_CLIP; + } + if (string_equal_nocase(token, "fogLight")) { + isFog = true; + } else if (!isFog && string_equal_nocase(token, "lightFalloffImage")) { + const char *lightFalloffImage = tokeniser.getToken(); + if (lightFalloffImage == 0) { + Tokeniser_unexpectedError(tokeniser, lightFalloffImage, "#lightFalloffImage"); + return false; + } + if (string_equal_nocase(lightFalloffImage, "makeintensity")) { + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); + TextureExpression name; + RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, name)); + m_lightFalloffImage = name; + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); + } else { + m_lightFalloffImage = lightFalloffImage; + } + } + } + } + + if (string_empty(m_textureName.c_str())) { + m_textureName = m_diffuse; + } + + return true; } typedef SmartPointer ShaderTemplatePointer; @@ -682,422 +680,478 @@ typedef std::map ShaderTemplateMap; ShaderTemplateMap g_shaders; ShaderTemplateMap g_shaderTemplates; -ShaderTemplate* findTemplate( const char* name ){ - ShaderTemplateMap::iterator i = g_shaderTemplates.find( name ); - if ( i != g_shaderTemplates.end() ) { - return ( *i ).second.get(); - } - return 0; +ShaderTemplate *findTemplate(const char *name) +{ + ShaderTemplateMap::iterator i = g_shaderTemplates.find(name); + if (i != g_shaderTemplates.end()) { + return (*i).second.get(); + } + return 0; } -class ShaderDefinition -{ +class ShaderDefinition { public: -ShaderDefinition( ShaderTemplate* shaderTemplate, const ShaderArguments& args, const char* filename ) - : shaderTemplate( shaderTemplate ), args( args ), filename( filename ){ -} -ShaderTemplate* shaderTemplate; -ShaderArguments args; -const char* filename; + ShaderDefinition(ShaderTemplate *shaderTemplate, const ShaderArguments &args, const char *filename) + : shaderTemplate(shaderTemplate), args(args), filename(filename) + { + } + + ShaderTemplate *shaderTemplate; + ShaderArguments args; + const char *filename; }; typedef std::map ShaderDefinitionMap; ShaderDefinitionMap g_shaderDefinitions; -bool parseTemplateInstance( Tokeniser& tokeniser, const char* filename ){ - CopiedString name; - RETURN_FALSE_IF_FAIL( Tokeniser_parseShaderName( tokeniser, name ) ); - const char* templateName = tokeniser.getToken(); - ShaderTemplate* shaderTemplate = findTemplate( templateName ); - if ( shaderTemplate == 0 ) { - globalErrorStream() << "shader instance: " << makeQuoted( name.c_str() ) << ": shader template not found: " << makeQuoted( templateName ) << "\n"; - } - - ShaderArguments args; - if ( !parseShaderParameters( tokeniser, args ) ) { - globalErrorStream() << "shader instance: " << makeQuoted( name.c_str() ) << ": argument parse failed\n"; - return false; - } - - if ( shaderTemplate != 0 ) { - if ( !g_shaderDefinitions.insert( ShaderDefinitionMap::value_type( name, ShaderDefinition( shaderTemplate, args, filename ) ) ).second ) { - globalErrorStream() << "shader instance: " << makeQuoted( name.c_str() ) << ": already exists, second definition ignored\n"; - } - } - return true; -} - - -const char* evaluateShaderValue( const char* value, const ShaderParameters& params, const ShaderArguments& args ){ - ShaderArguments::const_iterator j = args.begin(); - for ( ShaderParameters::const_iterator i = params.begin(); i != params.end(); ++i, ++j ) - { - const char* other = ( *i ).c_str(); - if ( string_equal( value, other ) ) { - return ( *j ).c_str(); - } - } - return value; +bool parseTemplateInstance(Tokeniser &tokeniser, const char *filename) +{ + CopiedString name; + RETURN_FALSE_IF_FAIL(Tokeniser_parseShaderName(tokeniser, name)); + const char *templateName = tokeniser.getToken(); + ShaderTemplate *shaderTemplate = findTemplate(templateName); + if (shaderTemplate == 0) { + globalErrorStream() << "shader instance: " << makeQuoted(name.c_str()) << ": shader template not found: " + << makeQuoted(templateName) << "\n"; + } + + ShaderArguments args; + if (!parseShaderParameters(tokeniser, args)) { + globalErrorStream() << "shader instance: " << makeQuoted(name.c_str()) << ": argument parse failed\n"; + return false; + } + + if (shaderTemplate != 0) { + if (!g_shaderDefinitions.insert( + ShaderDefinitionMap::value_type(name, ShaderDefinition(shaderTemplate, args, filename))).second) { + globalErrorStream() << "shader instance: " << makeQuoted(name.c_str()) + << ": already exists, second definition ignored\n"; + } + } + return true; +} + + +const char *evaluateShaderValue(const char *value, const ShaderParameters ¶ms, const ShaderArguments &args) +{ + ShaderArguments::const_iterator j = args.begin(); + for (ShaderParameters::const_iterator i = params.begin(); i != params.end(); ++i, ++j) { + const char *other = (*i).c_str(); + if (string_equal(value, other)) { + return (*j).c_str(); + } + } + return value; } ///\todo BlendFunc parsing -BlendFunc evaluateBlendFunc( const BlendFuncExpression& blendFunc, const ShaderParameters& params, const ShaderArguments& args ){ - return BlendFunc( BLEND_ONE, BLEND_ZERO ); -} - -qtexture_t* evaluateTexture( const TextureExpression& texture, const ShaderParameters& params, const ShaderArguments& args, const LoadImageCallback& loader = GlobalTexturesCache().defaultLoader() ){ - StringOutputStream result( 64 ); - const char* expression = texture.c_str(); - const char* end = expression + string_length( expression ); - if ( !string_empty( expression ) ) { - for (;; ) - { - const char* best = end; - const char* bestParam = 0; - const char* bestArg = 0; - ShaderArguments::const_iterator j = args.begin(); - for ( ShaderParameters::const_iterator i = params.begin(); i != params.end(); ++i, ++j ) - { - const char* found = strstr( expression, ( *i ).c_str() ); - if ( found != 0 && found < best ) { - best = found; - bestParam = ( *i ).c_str(); - bestArg = ( *j ).c_str(); - } - } - if ( best != end ) { - result << StringRange( expression, best ); - result << PathCleaned( bestArg ); - expression = best + string_length( bestParam ); - } - else - { - break; - } - } - result << expression; - } - return GlobalTexturesCache().capture( loader, result.c_str() ); -} - -float evaluateFloat( const ShaderValue& value, const ShaderParameters& params, const ShaderArguments& args ){ - const char* result = evaluateShaderValue( value.c_str(), params, args ); - float f; - if ( !string_parse_float( result, f ) ) { - globalErrorStream() << "parsing float value failed: " << makeQuoted( result ) << "\n"; - } - return f; +BlendFunc +evaluateBlendFunc(const BlendFuncExpression &blendFunc, const ShaderParameters ¶ms, const ShaderArguments &args) +{ + return BlendFunc(BLEND_ONE, BLEND_ZERO); } -BlendFactor evaluateBlendFactor( const ShaderValue& value, const ShaderParameters& params, const ShaderArguments& args ){ - const char* result = evaluateShaderValue( value.c_str(), params, args ); - - if ( string_equal_nocase( result, "gl_zero" ) ) { - return BLEND_ZERO; - } - if ( string_equal_nocase( result, "gl_one" ) ) { - return BLEND_ONE; - } - if ( string_equal_nocase( result, "gl_src_color" ) ) { - return BLEND_SRC_COLOUR; - } - if ( string_equal_nocase( result, "gl_one_minus_src_color" ) ) { - return BLEND_ONE_MINUS_SRC_COLOUR; - } - if ( string_equal_nocase( result, "gl_src_alpha" ) ) { - return BLEND_SRC_ALPHA; - } - if ( string_equal_nocase( result, "gl_one_minus_src_alpha" ) ) { - return BLEND_ONE_MINUS_SRC_ALPHA; - } - if ( string_equal_nocase( result, "gl_dst_color" ) ) { - return BLEND_DST_COLOUR; - } - if ( string_equal_nocase( result, "gl_one_minus_dst_color" ) ) { - return BLEND_ONE_MINUS_DST_COLOUR; - } - if ( string_equal_nocase( result, "gl_dst_alpha" ) ) { - return BLEND_DST_ALPHA; - } - if ( string_equal_nocase( result, "gl_one_minus_dst_alpha" ) ) { - return BLEND_ONE_MINUS_DST_ALPHA; - } - if ( string_equal_nocase( result, "gl_src_alpha_saturate" ) ) { - return BLEND_SRC_ALPHA_SATURATE; - } - - globalErrorStream() << "parsing blend-factor value failed: " << makeQuoted( result ) << "\n"; - return BLEND_ZERO; +qtexture_t * +evaluateTexture(const TextureExpression &texture, const ShaderParameters ¶ms, const ShaderArguments &args, + const LoadImageCallback &loader = GlobalTexturesCache().defaultLoader()) +{ + StringOutputStream result(64); + const char *expression = texture.c_str(); + const char *end = expression + string_length(expression); + if (!string_empty(expression)) { + for (;;) { + const char *best = end; + const char *bestParam = 0; + const char *bestArg = 0; + ShaderArguments::const_iterator j = args.begin(); + for (ShaderParameters::const_iterator i = params.begin(); i != params.end(); ++i, ++j) { + const char *found = strstr(expression, (*i).c_str()); + if (found != 0 && found < best) { + best = found; + bestParam = (*i).c_str(); + bestArg = (*j).c_str(); + } + } + if (best != end) { + result << StringRange(expression, best); + result << PathCleaned(bestArg); + expression = best + string_length(bestParam); + } else { + break; + } + } + result << expression; + } + return GlobalTexturesCache().capture(loader, result.c_str()); +} + +float evaluateFloat(const ShaderValue &value, const ShaderParameters ¶ms, const ShaderArguments &args) +{ + const char *result = evaluateShaderValue(value.c_str(), params, args); + float f; + if (!string_parse_float(result, f)) { + globalErrorStream() << "parsing float value failed: " << makeQuoted(result) << "\n"; + } + return f; } -class CShader : public IShader +BlendFactor evaluateBlendFactor(const ShaderValue &value, const ShaderParameters ¶ms, const ShaderArguments &args) { -std::size_t m_refcount; - -const ShaderTemplate& m_template; -const ShaderArguments& m_args; -const char* m_filename; + const char *result = evaluateShaderValue(value.c_str(), params, args); + + if (string_equal_nocase(result, "gl_zero")) { + return BLEND_ZERO; + } + if (string_equal_nocase(result, "gl_one")) { + return BLEND_ONE; + } + if (string_equal_nocase(result, "gl_src_color")) { + return BLEND_SRC_COLOUR; + } + if (string_equal_nocase(result, "gl_one_minus_src_color")) { + return BLEND_ONE_MINUS_SRC_COLOUR; + } + if (string_equal_nocase(result, "gl_src_alpha")) { + return BLEND_SRC_ALPHA; + } + if (string_equal_nocase(result, "gl_one_minus_src_alpha")) { + return BLEND_ONE_MINUS_SRC_ALPHA; + } + if (string_equal_nocase(result, "gl_dst_color")) { + return BLEND_DST_COLOUR; + } + if (string_equal_nocase(result, "gl_one_minus_dst_color")) { + return BLEND_ONE_MINUS_DST_COLOUR; + } + if (string_equal_nocase(result, "gl_dst_alpha")) { + return BLEND_DST_ALPHA; + } + if (string_equal_nocase(result, "gl_one_minus_dst_alpha")) { + return BLEND_ONE_MINUS_DST_ALPHA; + } + if (string_equal_nocase(result, "gl_src_alpha_saturate")) { + return BLEND_SRC_ALPHA_SATURATE; + } + + globalErrorStream() << "parsing blend-factor value failed: " << makeQuoted(result) << "\n"; + return BLEND_ZERO; +} + +class CShader : public IShader { + std::size_t m_refcount; + + const ShaderTemplate &m_template; + const ShaderArguments &m_args; + const char *m_filename; // name is shader-name, otherwise texture-name (if not a real shader) -CopiedString m_Name; + CopiedString m_Name; -qtexture_t* m_pTexture; -qtexture_t* m_notfound; -qtexture_t* m_pDiffuse; -float m_heightmapScale; -qtexture_t* m_pBump; -qtexture_t* m_pSpecular; -qtexture_t* m_pLightFalloffImage; -BlendFunc m_blendFunc; + qtexture_t *m_pTexture; + qtexture_t *m_notfound; + qtexture_t *m_pDiffuse; + float m_heightmapScale; + qtexture_t *m_pBump; + qtexture_t *m_pSpecular; + qtexture_t *m_pLightFalloffImage; + BlendFunc m_blendFunc; -bool m_bInUse; + bool m_bInUse; public: -static bool m_lightingEnabled; - -CShader( const ShaderDefinition& definition ) : - m_refcount( 0 ), - m_template( *definition.shaderTemplate ), - m_args( definition.args ), - m_filename( definition.filename ), - m_blendFunc( BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA ), - m_bInUse( false ){ - m_pTexture = 0; - m_pDiffuse = 0; - m_pBump = 0; - m_pSpecular = 0; - - m_notfound = 0; - - realise(); -} -virtual ~CShader(){ - unrealise(); + static bool m_lightingEnabled; - ASSERT_MESSAGE( m_refcount == 0, "deleting active shader" ); -} + CShader(const ShaderDefinition &definition) : + m_refcount(0), + m_template(*definition.shaderTemplate), + m_args(definition.args), + m_filename(definition.filename), + m_blendFunc(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA), + m_bInUse(false) + { + m_pTexture = 0; + m_pDiffuse = 0; + m_pBump = 0; + m_pSpecular = 0; -// IShaders implementation ----------------- -void IncRef(){ - ++m_refcount; -} -void DecRef(){ - ASSERT_MESSAGE( m_refcount != 0, "shader reference-count going below zero" ); - if ( --m_refcount == 0 ) { - delete this; - } -} + m_notfound = 0; -std::size_t refcount(){ - return m_refcount; -} + realise(); + } -// get/set the qtexture_t* Radiant uses to represent this shader object -qtexture_t* getTexture() const { - return m_pTexture; -} -qtexture_t* getDiffuse() const { - return m_pDiffuse; -} -qtexture_t* getBump() const { - return m_pBump; -} -qtexture_t* getSpecular() const { - return m_pSpecular; -} -// get shader name -const char* getName() const { - return m_Name.c_str(); -} -bool IsInUse() const { - return m_bInUse; -} -void SetInUse( bool bInUse ){ - m_bInUse = bInUse; - g_ActiveShadersChangedNotify(); -} -// get the shader flags -int getFlags() const { - return m_template.m_nFlags; -} -// get the transparency value -float getTrans() const { - return m_template.m_fTrans; -} -// test if it's a true shader, or a default shader created to wrap around a texture -bool IsDefault() const { - return string_empty( m_filename ); -} -// get the alphaFunc -void getAlphaFunc( EAlphaFunc *func, float *ref ) { *func = m_template.m_AlphaFunc; *ref = m_template.m_AlphaRef; }; -BlendFunc getBlendFunc() const { - return m_blendFunc; -} -// get the cull type -ECull getCull(){ - return m_template.m_Cull; -}; -// get shader file name (ie the file where this one is defined) -const char* getShaderFileName() const { - return m_filename; -} -// ----------------------------------------- + virtual ~CShader() + { + unrealise(); -void realise(){ - m_pTexture = evaluateTexture( m_template.m_textureName, m_template.m_params, m_args ); + ASSERT_MESSAGE(m_refcount == 0, "deleting active shader"); + } - if ( m_pTexture->texture_number == 0 ) { - m_notfound = m_pTexture; +// IShaders implementation ----------------- + void IncRef() + { + ++m_refcount; + } + + void DecRef() + { + ASSERT_MESSAGE(m_refcount != 0, "shader reference-count going below zero"); + if (--m_refcount == 0) { + delete this; + } + } + + std::size_t refcount() + { + return m_refcount; + } - { - StringOutputStream name( 256 ); - name << GlobalRadiant().getAppPath() << "bitmaps/" << ( IsDefault() ? "notex.png" : "shadernotex.png" ); - m_pTexture = GlobalTexturesCache().capture( LoadImageCallback( 0, loadBitmap ), name.c_str() ); - } - } +// get/set the qtexture_t* Radiant uses to represent this shader object + qtexture_t *getTexture() const + { + return m_pTexture; + } + + qtexture_t *getDiffuse() const + { + return m_pDiffuse; + } + + qtexture_t *getBump() const + { + return m_pBump; + } + + qtexture_t *getSpecular() const + { + return m_pSpecular; + } - realiseLighting(); -} +// get shader name + const char *getName() const + { + return m_Name.c_str(); + } + + bool IsInUse() const + { + return m_bInUse; + } + + void SetInUse(bool bInUse) + { + m_bInUse = bInUse; + g_ActiveShadersChangedNotify(); + } -void unrealise(){ - GlobalTexturesCache().release( m_pTexture ); +// get the shader flags + int getFlags() const + { + return m_template.m_nFlags; + } - if ( m_notfound != 0 ) { - GlobalTexturesCache().release( m_notfound ); - } +// get the transparency value + float getTrans() const + { + return m_template.m_fTrans; + } - unrealiseLighting(); -} +// test if it's a true shader, or a default shader created to wrap around a texture + bool IsDefault() const + { + return string_empty(m_filename); + } -void realiseLighting(){ - if ( m_lightingEnabled ) { - LoadImageCallback loader = GlobalTexturesCache().defaultLoader(); - if ( !string_empty( m_template.m_heightmapScale.c_str() ) ) { - m_heightmapScale = evaluateFloat( m_template.m_heightmapScale, m_template.m_params, m_args ); - loader = LoadImageCallback( &m_heightmapScale, loadHeightmap ); - } - m_pDiffuse = evaluateTexture( m_template.m_diffuse, m_template.m_params, m_args ); - m_pBump = evaluateTexture( m_template.m_bump, m_template.m_params, m_args, loader ); - m_pSpecular = evaluateTexture( m_template.m_specular, m_template.m_params, m_args ); - m_pLightFalloffImage = evaluateTexture( m_template.m_lightFalloffImage, m_template.m_params, m_args ); - - for ( ShaderTemplate::MapLayers::const_iterator i = m_template.m_layers.begin(); i != m_template.m_layers.end(); ++i ) - { - m_layers.push_back( evaluateLayer( *i, m_template.m_params, m_args ) ); - } - - if ( m_layers.size() == 1 ) { - const BlendFuncExpression& blendFunc = m_template.m_layers.front().blendFunc(); - if ( !string_empty( blendFunc.second.c_str() ) ) { - m_blendFunc = BlendFunc( - evaluateBlendFactor( blendFunc.first.c_str(), m_template.m_params, m_args ), - evaluateBlendFactor( blendFunc.second.c_str(), m_template.m_params, m_args ) - ); - } - else - { - const char* blend = evaluateShaderValue( blendFunc.first.c_str(), m_template.m_params, m_args ); - - if ( string_equal_nocase( blend, "add" ) ) { - m_blendFunc = BlendFunc( BLEND_ONE, BLEND_ONE ); - } - else if ( string_equal_nocase( blend, "filter" ) ) { - m_blendFunc = BlendFunc( BLEND_DST_COLOUR, BLEND_ZERO ); - } - else if ( string_equal_nocase( blend, "blend" ) ) { - m_blendFunc = BlendFunc( BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA ); - } - else - { - globalErrorStream() << "parsing blend value failed: " << makeQuoted( blend ) << "\n"; - } - } - } - } -} +// get the alphaFunc + void getAlphaFunc(EAlphaFunc *func, float *ref) + { + *func = m_template.m_AlphaFunc; + *ref = m_template.m_AlphaRef; + }; -void unrealiseLighting(){ - if ( m_lightingEnabled ) { - GlobalTexturesCache().release( m_pDiffuse ); - GlobalTexturesCache().release( m_pBump ); - GlobalTexturesCache().release( m_pSpecular ); + BlendFunc getBlendFunc() const + { + return m_blendFunc; + } - GlobalTexturesCache().release( m_pLightFalloffImage ); +// get the cull type + ECull getCull() + { + return m_template.m_Cull; + }; - for ( MapLayers::iterator i = m_layers.begin(); i != m_layers.end(); ++i ) - { - GlobalTexturesCache().release( ( *i ).texture() ); - } - m_layers.clear(); +// get shader file name (ie the file where this one is defined) + const char *getShaderFileName() const + { + return m_filename; + } +// ----------------------------------------- - m_blendFunc = BlendFunc( BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA ); - } -} + void realise() + { + m_pTexture = evaluateTexture(m_template.m_textureName, m_template.m_params, m_args); + + if (m_pTexture->texture_number == 0) { + m_notfound = m_pTexture; + + { + StringOutputStream name(256); + name << GlobalRadiant().getAppPath() << "bitmaps/" << (IsDefault() ? "notex.png" : "shadernotex.png"); + m_pTexture = GlobalTexturesCache().capture(LoadImageCallback(0, loadBitmap), name.c_str()); + } + } + + realiseLighting(); + } + + void unrealise() + { + GlobalTexturesCache().release(m_pTexture); + + if (m_notfound != 0) { + GlobalTexturesCache().release(m_notfound); + } + + unrealiseLighting(); + } + + void realiseLighting() + { + if (m_lightingEnabled) { + LoadImageCallback loader = GlobalTexturesCache().defaultLoader(); + if (!string_empty(m_template.m_heightmapScale.c_str())) { + m_heightmapScale = evaluateFloat(m_template.m_heightmapScale, m_template.m_params, m_args); + loader = LoadImageCallback(&m_heightmapScale, loadHeightmap); + } + m_pDiffuse = evaluateTexture(m_template.m_diffuse, m_template.m_params, m_args); + m_pBump = evaluateTexture(m_template.m_bump, m_template.m_params, m_args, loader); + m_pSpecular = evaluateTexture(m_template.m_specular, m_template.m_params, m_args); + m_pLightFalloffImage = evaluateTexture(m_template.m_lightFalloffImage, m_template.m_params, m_args); + + for (ShaderTemplate::MapLayers::const_iterator i = m_template.m_layers.begin(); + i != m_template.m_layers.end(); ++i) { + m_layers.push_back(evaluateLayer(*i, m_template.m_params, m_args)); + } + + if (m_layers.size() == 1) { + const BlendFuncExpression &blendFunc = m_template.m_layers.front().blendFunc(); + if (!string_empty(blendFunc.second.c_str())) { + m_blendFunc = BlendFunc( + evaluateBlendFactor(blendFunc.first.c_str(), m_template.m_params, m_args), + evaluateBlendFactor(blendFunc.second.c_str(), m_template.m_params, m_args) + ); + } else { + const char *blend = evaluateShaderValue(blendFunc.first.c_str(), m_template.m_params, m_args); + + if (string_equal_nocase(blend, "add")) { + m_blendFunc = BlendFunc(BLEND_ONE, BLEND_ONE); + } else if (string_equal_nocase(blend, "filter")) { + m_blendFunc = BlendFunc(BLEND_DST_COLOUR, BLEND_ZERO); + } else if (string_equal_nocase(blend, "blend")) { + m_blendFunc = BlendFunc(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + } else { + globalErrorStream() << "parsing blend value failed: " << makeQuoted(blend) << "\n"; + } + } + } + } + } + + void unrealiseLighting() + { + if (m_lightingEnabled) { + GlobalTexturesCache().release(m_pDiffuse); + GlobalTexturesCache().release(m_pBump); + GlobalTexturesCache().release(m_pSpecular); + + GlobalTexturesCache().release(m_pLightFalloffImage); + + for (MapLayers::iterator i = m_layers.begin(); i != m_layers.end(); ++i) { + GlobalTexturesCache().release((*i).texture()); + } + m_layers.clear(); + + m_blendFunc = BlendFunc(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + } + } // set shader name -void setName( const char* name ){ - m_Name = name; -} - -class MapLayer : public ShaderLayer -{ -qtexture_t* m_texture; -BlendFunc m_blendFunc; -bool m_clampToBorder; -float m_alphaTest; -public: -MapLayer( qtexture_t* texture, BlendFunc blendFunc, bool clampToBorder, float alphaTest ) : - m_texture( texture ), - m_blendFunc( blendFunc ), - m_clampToBorder( false ), - m_alphaTest( alphaTest ){ -} -qtexture_t* texture() const { - return m_texture; -} -BlendFunc blendFunc() const { - return m_blendFunc; -} -bool clampToBorder() const { - return m_clampToBorder; -} -float alphaTest() const { - return m_alphaTest; -} -}; - -static MapLayer evaluateLayer( const ShaderTemplate::MapLayerTemplate& layerTemplate, const ShaderParameters& params, const ShaderArguments& args ){ - return MapLayer( - evaluateTexture( layerTemplate.texture(), params, args ), - evaluateBlendFunc( layerTemplate.blendFunc(), params, args ), - layerTemplate.clampToBorder(), - evaluateFloat( layerTemplate.alphaTest(), params, args ) - ); -} - -typedef std::vector MapLayers; -MapLayers m_layers; - -const ShaderLayer* firstLayer() const { - if ( m_layers.empty() ) { - return 0; - } - return &m_layers.front(); -} -void forEachLayer( const ShaderLayerCallback& callback ) const { - for ( MapLayers::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i ) - { - callback( *i ); - } -} - -qtexture_t* lightFalloffImage() const { - if ( !string_empty( m_template.m_lightFalloffImage.c_str() ) ) { - return m_pLightFalloffImage; - } - return 0; -} + void setName(const char *name) + { + m_Name = name; + } + + class MapLayer : public ShaderLayer { + qtexture_t *m_texture; + BlendFunc m_blendFunc; + bool m_clampToBorder; + float m_alphaTest; + public: + MapLayer(qtexture_t *texture, BlendFunc blendFunc, bool clampToBorder, float alphaTest) : + m_texture(texture), + m_blendFunc(blendFunc), + m_clampToBorder(false), + m_alphaTest(alphaTest) + { + } + + qtexture_t *texture() const + { + return m_texture; + } + + BlendFunc blendFunc() const + { + return m_blendFunc; + } + + bool clampToBorder() const + { + return m_clampToBorder; + } + + float alphaTest() const + { + return m_alphaTest; + } + }; + + static MapLayer evaluateLayer(const ShaderTemplate::MapLayerTemplate &layerTemplate, const ShaderParameters ¶ms, + const ShaderArguments &args) + { + return MapLayer( + evaluateTexture(layerTemplate.texture(), params, args), + evaluateBlendFunc(layerTemplate.blendFunc(), params, args), + layerTemplate.clampToBorder(), + evaluateFloat(layerTemplate.alphaTest(), params, args) + ); + } + + typedef std::vector MapLayers; + MapLayers m_layers; + + const ShaderLayer *firstLayer() const + { + if (m_layers.empty()) { + return 0; + } + return &m_layers.front(); + } + + void forEachLayer(const ShaderLayerCallback &callback) const + { + for (MapLayers::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) { + callback(*i); + } + } + + qtexture_t *lightFalloffImage() const + { + if (!string_empty(m_template.m_lightFalloffImage.c_str())) { + return m_pLightFalloffImage; + } + return 0; + } }; bool CShader::m_lightingEnabled = false; @@ -1109,407 +1163,388 @@ shaders_t g_ActiveShaders; static shaders_t::iterator g_ActiveShadersIterator; -void ActiveShaders_IteratorBegin(){ - g_ActiveShadersIterator = g_ActiveShaders.begin(); +void ActiveShaders_IteratorBegin() +{ + g_ActiveShadersIterator = g_ActiveShaders.begin(); } -bool ActiveShaders_IteratorAtEnd(){ - return g_ActiveShadersIterator == g_ActiveShaders.end(); +bool ActiveShaders_IteratorAtEnd() +{ + return g_ActiveShadersIterator == g_ActiveShaders.end(); } -IShader *ActiveShaders_IteratorCurrent(){ - return static_cast( g_ActiveShadersIterator->second ); +IShader *ActiveShaders_IteratorCurrent() +{ + return static_cast( g_ActiveShadersIterator->second ); } -void ActiveShaders_IteratorIncrement(){ - ++g_ActiveShadersIterator; +void ActiveShaders_IteratorIncrement() +{ + ++g_ActiveShadersIterator; } -void debug_check_shaders( shaders_t& shaders ){ - for ( shaders_t::iterator i = shaders.begin(); i != shaders.end(); ++i ) - { - ASSERT_MESSAGE( i->second->refcount() == 1, "orphan shader still referenced" ); - } +void debug_check_shaders(shaders_t &shaders) +{ + for (shaders_t::iterator i = shaders.begin(); i != shaders.end(); ++i) { + ASSERT_MESSAGE(i->second->refcount() == 1, "orphan shader still referenced"); + } } // will free all GL binded qtextures and shaders // NOTE: doesn't make much sense out of Radiant exit or called during a reload -void FreeShaders(){ - // reload shaders - // empty the actives shaders list - debug_check_shaders( g_ActiveShaders ); - g_ActiveShaders.clear(); - g_shaders.clear(); - g_shaderTemplates.clear(); - g_shaderDefinitions.clear(); - g_ActiveShadersChangedNotify(); -} - -bool ShaderTemplate::parseQuake3( Tokeniser& tokeniser ){ - // name of the qtexture_t we'll use to represent this shader (this one has the "textures\" before) - m_textureName = m_Name.c_str(); - - tokeniser.nextLine(); - - // we need to read until we hit a balanced } - int depth = 0; - for (;; ) - { - tokeniser.nextLine(); - const char* token = tokeniser.getToken(); - - if ( token == 0 ) { - return false; - } - - if ( string_equal( token, "{" ) ) { - ++depth; - continue; - } - else if ( string_equal( token, "}" ) ) { - --depth; - if ( depth < 0 ) { // underflow - return false; - } - if ( depth == 0 ) { // end of shader - break; - } - - continue; - } - - if ( depth == 1 ) { - if ( string_equal_nocase( token, "qer_nocarve" ) ) { - m_nFlags |= QER_NOCARVE; - } - else if ( string_equal_nocase( token, "qer_trans" ) ) { - RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, m_fTrans ) ); - m_nFlags |= QER_TRANS; - } - else if ( string_equal_nocase( token, "qer_editorimage" ) ) { - RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, m_textureName ) ); - } - else if ( string_equal_nocase( token, "qer_alphafunc" ) ) { - const char* alphafunc = tokeniser.getToken(); - - if ( alphafunc == 0 ) { - Tokeniser_unexpectedError( tokeniser, alphafunc, "#alphafunc" ); - return false; - } - - if ( string_equal_nocase( alphafunc, "equal" ) ) { - m_AlphaFunc = IShader::eEqual; - } - else if ( string_equal_nocase( alphafunc, "greater" ) ) { - m_AlphaFunc = IShader::eGreater; - } - else if ( string_equal_nocase( alphafunc, "less" ) ) { - m_AlphaFunc = IShader::eLess; - } - else if ( string_equal_nocase( alphafunc, "gequal" ) ) { - m_AlphaFunc = IShader::eGEqual; - } - else if ( string_equal_nocase( alphafunc, "lequal" ) ) { - m_AlphaFunc = IShader::eLEqual; - } - else - { - m_AlphaFunc = IShader::eAlways; - } - - m_nFlags |= QER_ALPHATEST; - - RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, m_AlphaRef ) ); - } - else if ( string_equal_nocase( token, "cull" ) ) { - const char* cull = tokeniser.getToken(); - - if ( cull == 0 ) { - Tokeniser_unexpectedError( tokeniser, cull, "#cull" ); - return false; - } - - if ( string_equal_nocase( cull, "none" ) - || string_equal_nocase( cull, "twosided" ) - || string_equal_nocase( cull, "disable" ) ) { - m_Cull = IShader::eCullNone; - } - else if ( string_equal_nocase( cull, "back" ) - || string_equal_nocase( cull, "backside" ) - || string_equal_nocase( cull, "backsided" ) ) { - m_Cull = IShader::eCullBack; - } - else - { - m_Cull = IShader::eCullBack; - } - - m_nFlags |= QER_CULL; - } - else if ( string_equal_nocase( token, "surfaceparm" ) ) { - const char* surfaceparm = tokeniser.getToken(); - - if ( surfaceparm == 0 ) { - Tokeniser_unexpectedError( tokeniser, surfaceparm, "#surfaceparm" ); - return false; - } - - if ( string_equal_nocase( surfaceparm, "fog" ) ) { - m_nFlags |= QER_FOG; - if ( m_fTrans == 1.0f ) { // has not been explicitly set by qer_trans - m_fTrans = 0.35f; - } - } - else if ( string_equal_nocase( surfaceparm, "nodraw" ) ) { - m_nFlags |= QER_NODRAW; - } - else if ( string_equal_nocase( surfaceparm, "nonsolid" ) ) { - m_nFlags |= QER_NONSOLID; - } - else if ( string_equal_nocase( surfaceparm, "water" ) ) { - m_nFlags |= QER_WATER; - } - else if ( string_equal_nocase( surfaceparm, "lava" ) ) { - m_nFlags |= QER_LAVA; - } - else if ( string_equal_nocase( surfaceparm, "areaportal" ) ) { - m_nFlags |= QER_AREAPORTAL; - } - else if ( string_equal_nocase( surfaceparm, "playerclip" ) ) { - m_nFlags |= QER_CLIP; - } - else if ( string_equal_nocase( surfaceparm, "botclip" ) ) { - m_nFlags |= QER_BOTCLIP; - } - } - } - } - - return true; +void FreeShaders() +{ + // reload shaders + // empty the actives shaders list + debug_check_shaders(g_ActiveShaders); + g_ActiveShaders.clear(); + g_shaders.clear(); + g_shaderTemplates.clear(); + g_shaderDefinitions.clear(); + g_ActiveShadersChangedNotify(); } -class Layer +bool ShaderTemplate::parseQuake3(Tokeniser &tokeniser) { + // name of the qtexture_t we'll use to represent this shader (this one has the "textures\" before) + m_textureName = m_Name.c_str(); + + tokeniser.nextLine(); + + // we need to read until we hit a balanced } + int depth = 0; + for (;;) { + tokeniser.nextLine(); + const char *token = tokeniser.getToken(); + + if (token == 0) { + return false; + } + + if (string_equal(token, "{")) { + ++depth; + continue; + } else if (string_equal(token, "}")) { + --depth; + if (depth < 0) { // underflow + return false; + } + if (depth == 0) { // end of shader + break; + } + + continue; + } + + if (depth == 1) { + if (string_equal_nocase(token, "qer_nocarve")) { + m_nFlags |= QER_NOCARVE; + } else if (string_equal_nocase(token, "qer_trans")) { + RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, m_fTrans)); + m_nFlags |= QER_TRANS; + } else if (string_equal_nocase(token, "qer_editorimage")) { + RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, m_textureName)); + } else if (string_equal_nocase(token, "qer_alphafunc")) { + const char *alphafunc = tokeniser.getToken(); + + if (alphafunc == 0) { + Tokeniser_unexpectedError(tokeniser, alphafunc, "#alphafunc"); + return false; + } + + if (string_equal_nocase(alphafunc, "equal")) { + m_AlphaFunc = IShader::eEqual; + } else if (string_equal_nocase(alphafunc, "greater")) { + m_AlphaFunc = IShader::eGreater; + } else if (string_equal_nocase(alphafunc, "less")) { + m_AlphaFunc = IShader::eLess; + } else if (string_equal_nocase(alphafunc, "gequal")) { + m_AlphaFunc = IShader::eGEqual; + } else if (string_equal_nocase(alphafunc, "lequal")) { + m_AlphaFunc = IShader::eLEqual; + } else { + m_AlphaFunc = IShader::eAlways; + } + + m_nFlags |= QER_ALPHATEST; + + RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, m_AlphaRef)); + } else if (string_equal_nocase(token, "cull")) { + const char *cull = tokeniser.getToken(); + + if (cull == 0) { + Tokeniser_unexpectedError(tokeniser, cull, "#cull"); + return false; + } + + if (string_equal_nocase(cull, "none") + || string_equal_nocase(cull, "twosided") + || string_equal_nocase(cull, "disable")) { + m_Cull = IShader::eCullNone; + } else if (string_equal_nocase(cull, "back") + || string_equal_nocase(cull, "backside") + || string_equal_nocase(cull, "backsided")) { + m_Cull = IShader::eCullBack; + } else { + m_Cull = IShader::eCullBack; + } + + m_nFlags |= QER_CULL; + } else if (string_equal_nocase(token, "surfaceparm")) { + const char *surfaceparm = tokeniser.getToken(); + + if (surfaceparm == 0) { + Tokeniser_unexpectedError(tokeniser, surfaceparm, "#surfaceparm"); + return false; + } + + if (string_equal_nocase(surfaceparm, "fog")) { + m_nFlags |= QER_FOG; + if (m_fTrans == 1.0f) { // has not been explicitly set by qer_trans + m_fTrans = 0.35f; + } + } else if (string_equal_nocase(surfaceparm, "nodraw")) { + m_nFlags |= QER_NODRAW; + } else if (string_equal_nocase(surfaceparm, "nonsolid")) { + m_nFlags |= QER_NONSOLID; + } else if (string_equal_nocase(surfaceparm, "water")) { + m_nFlags |= QER_WATER; + } else if (string_equal_nocase(surfaceparm, "lava")) { + m_nFlags |= QER_LAVA; + } else if (string_equal_nocase(surfaceparm, "areaportal")) { + m_nFlags |= QER_AREAPORTAL; + } else if (string_equal_nocase(surfaceparm, "playerclip")) { + m_nFlags |= QER_CLIP; + } else if (string_equal_nocase(surfaceparm, "botclip")) { + m_nFlags |= QER_BOTCLIP; + } + } + } + } + + return true; +} + +class Layer { public: -LayerTypeId m_type; -TextureExpression m_texture; -BlendFunc m_blendFunc; -bool m_clampToBorder; -float m_alphaTest; -float m_heightmapScale; - -Layer() : m_type( LAYER_NONE ), m_blendFunc( BLEND_ONE, BLEND_ZERO ), m_clampToBorder( false ), m_alphaTest( -1 ), m_heightmapScale( 0 ){ -} + LayerTypeId m_type; + TextureExpression m_texture; + BlendFunc m_blendFunc; + bool m_clampToBorder; + float m_alphaTest; + float m_heightmapScale; + + Layer() : m_type(LAYER_NONE), m_blendFunc(BLEND_ONE, BLEND_ZERO), m_clampToBorder(false), m_alphaTest(-1), + m_heightmapScale(0) + { + } }; std::list g_shaderFilenames; -void ParseShaderFile( Tokeniser& tokeniser, const char* filename ){ - g_shaderFilenames.push_back( filename ); - filename = g_shaderFilenames.back().c_str(); - tokeniser.nextLine(); - for (;; ) - { - const char* token = tokeniser.getToken(); - - if ( token == 0 ) { - break; - } - - if ( string_equal( token, "table" ) ) { - if ( tokeniser.getToken() == 0 ) { - Tokeniser_unexpectedError( tokeniser, 0, "#table-name" ); - return; - } - if ( !Tokeniser_parseToken( tokeniser, "{" ) ) { - return; - } - for (;; ) - { - const char* option = tokeniser.getToken(); - if ( string_equal( option, "{" ) ) { - for (;; ) - { - const char* value = tokeniser.getToken(); - if ( string_equal( value, "}" ) ) { - break; - } - } - - if ( !Tokeniser_parseToken( tokeniser, "}" ) ) { - return; - } - break; - } - } - } - else - { - if ( string_equal( token, "guide" ) ) { - parseTemplateInstance( tokeniser, filename ); - } - else - { - if ( !string_equal( token, "material" ) - && !string_equal( token, "particle" ) - && !string_equal( token, "skin" ) ) { - tokeniser.ungetToken(); - } - // first token should be the path + name.. (from base) - CopiedString name; - if ( !Tokeniser_parseShaderName( tokeniser, name ) ) { - } - ShaderTemplatePointer shaderTemplate( new ShaderTemplate() ); - shaderTemplate->setName( name.c_str() ); - - g_shaders.insert( ShaderTemplateMap::value_type( shaderTemplate->getName(), shaderTemplate ) ); - - bool result = ( g_shaderLanguage == SHADERLANGUAGE_QUAKE3 ) - ? shaderTemplate->parseQuake3( tokeniser ) - : shaderTemplate->parseDoom3( tokeniser ); - if ( result ) { - // do we already have this shader? - if ( !g_shaderDefinitions.insert( ShaderDefinitionMap::value_type( shaderTemplate->getName(), ShaderDefinition( shaderTemplate.get(), ShaderArguments(), filename ) ) ).second ) { - #if GDEF_DEBUG - globalOutputStream() << "WARNING: shader " << shaderTemplate->getName() << " is already in memory, definition in " << filename << " ignored.\n"; - #endif - } - } - else - { - globalErrorStream() << "Error parsing shader " << shaderTemplate->getName() << "\n"; - return; - } - } - } - } -} - -void parseGuideFile( Tokeniser& tokeniser, const char* filename ){ - tokeniser.nextLine(); - for (;; ) - { - const char* token = tokeniser.getToken(); - - if ( token == 0 ) { - break; - } - - if ( string_equal( token, "guide" ) ) { - // first token should be the path + name.. (from base) - ShaderTemplatePointer shaderTemplate( new ShaderTemplate ); - shaderTemplate->parseTemplate( tokeniser ); - if ( !g_shaderTemplates.insert( ShaderTemplateMap::value_type( shaderTemplate->getName(), shaderTemplate ) ).second ) { - globalErrorStream() << "guide " << makeQuoted( shaderTemplate->getName() ) << ": already defined, second definition ignored\n"; - } - } - else if ( string_equal( token, "inlineGuide" ) ) { - // skip entire inlineGuide definition - std::size_t depth = 0; - for (;; ) - { - tokeniser.nextLine(); - token = tokeniser.getToken(); - if ( string_equal( token, "{" ) ) { - ++depth; - } - else if ( string_equal( token, "}" ) ) { - if ( --depth == 0 ) { - break; - } - } - } - } - } +void ParseShaderFile(Tokeniser &tokeniser, const char *filename) +{ + g_shaderFilenames.push_back(filename); + filename = g_shaderFilenames.back().c_str(); + tokeniser.nextLine(); + for (;;) { + const char *token = tokeniser.getToken(); + + if (token == 0) { + break; + } + + if (string_equal(token, "table")) { + if (tokeniser.getToken() == 0) { + Tokeniser_unexpectedError(tokeniser, 0, "#table-name"); + return; + } + if (!Tokeniser_parseToken(tokeniser, "{")) { + return; + } + for (;;) { + const char *option = tokeniser.getToken(); + if (string_equal(option, "{")) { + for (;;) { + const char *value = tokeniser.getToken(); + if (string_equal(value, "}")) { + break; + } + } + + if (!Tokeniser_parseToken(tokeniser, "}")) { + return; + } + break; + } + } + } else { + if (string_equal(token, "guide")) { + parseTemplateInstance(tokeniser, filename); + } else { + if (!string_equal(token, "material") + && !string_equal(token, "particle") + && !string_equal(token, "skin")) { + tokeniser.ungetToken(); + } + // first token should be the path + name.. (from base) + CopiedString name; + if (!Tokeniser_parseShaderName(tokeniser, name)) { + } + ShaderTemplatePointer shaderTemplate(new ShaderTemplate()); + shaderTemplate->setName(name.c_str()); + + g_shaders.insert(ShaderTemplateMap::value_type(shaderTemplate->getName(), shaderTemplate)); + + bool result = (g_shaderLanguage == SHADERLANGUAGE_QUAKE3) + ? shaderTemplate->parseQuake3(tokeniser) + : shaderTemplate->parseDoom3(tokeniser); + if (result) { + // do we already have this shader? + if (!g_shaderDefinitions.insert(ShaderDefinitionMap::value_type(shaderTemplate->getName(), + ShaderDefinition( + shaderTemplate.get(), + ShaderArguments(), + filename))).second) { +#if GDEF_DEBUG + globalOutputStream() << "WARNING: shader " << shaderTemplate->getName() + << " is already in memory, definition in " << filename << " ignored.\n"; +#endif + } + } else { + globalErrorStream() << "Error parsing shader " << shaderTemplate->getName() << "\n"; + return; + } + } + } + } } -void LoadShaderFile( const char* filename ){ - ArchiveTextFile* file = GlobalFileSystem().openTextFile( filename ); +void parseGuideFile(Tokeniser &tokeniser, const char *filename) +{ + tokeniser.nextLine(); + for (;;) { + const char *token = tokeniser.getToken(); + + if (token == 0) { + break; + } + + if (string_equal(token, "guide")) { + // first token should be the path + name.. (from base) + ShaderTemplatePointer shaderTemplate(new ShaderTemplate); + shaderTemplate->parseTemplate(tokeniser); + if (!g_shaderTemplates.insert( + ShaderTemplateMap::value_type(shaderTemplate->getName(), shaderTemplate)).second) { + globalErrorStream() << "guide " << makeQuoted(shaderTemplate->getName()) + << ": already defined, second definition ignored\n"; + } + } else if (string_equal(token, "inlineGuide")) { + // skip entire inlineGuide definition + std::size_t depth = 0; + for (;;) { + tokeniser.nextLine(); + token = tokeniser.getToken(); + if (string_equal(token, "{")) { + ++depth; + } else if (string_equal(token, "}")) { + if (--depth == 0) { + break; + } + } + } + } + } +} + +void LoadShaderFile(const char *filename) +{ + ArchiveTextFile *file = GlobalFileSystem().openTextFile(filename); - if ( file != 0 ) { - globalOutputStream() << "Parsing shaderfile " << filename << "\n"; + if (file != 0) { + globalOutputStream() << "Parsing shaderfile " << filename << "\n"; - Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser( file->getInputStream() ); + Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser(file->getInputStream()); - ParseShaderFile( tokeniser, filename ); + ParseShaderFile(tokeniser, filename); - tokeniser.release(); - file->release(); - } - else - { - globalOutputStream() << "Unable to read shaderfile " << filename << "\n"; - } + tokeniser.release(); + file->release(); + } else { + globalOutputStream() << "Unable to read shaderfile " << filename << "\n"; + } } -void loadGuideFile( const char* filename ){ - StringOutputStream fullname( 256 ); - fullname << "guides/" << filename; - ArchiveTextFile* file = GlobalFileSystem().openTextFile( fullname.c_str() ); - - if ( file != 0 ) { - globalOutputStream() << "Parsing guide file " << fullname.c_str() << "\n"; +void loadGuideFile(const char *filename) +{ + StringOutputStream fullname(256); + fullname << "guides/" << filename; + ArchiveTextFile *file = GlobalFileSystem().openTextFile(fullname.c_str()); - Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser( file->getInputStream() ); + if (file != 0) { + globalOutputStream() << "Parsing guide file " << fullname.c_str() << "\n"; - parseGuideFile( tokeniser, fullname.c_str() ); + Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser(file->getInputStream()); - tokeniser.release(); - file->release(); - } - else - { - globalOutputStream() << "Unable to read guide file " << fullname.c_str() << "\n"; - } -} + parseGuideFile(tokeniser, fullname.c_str()); -CShader* Try_Shader_ForName( const char* name ){ - { - shaders_t::iterator i = g_ActiveShaders.find( name ); - if ( i != g_ActiveShaders.end() ) { - return ( *i ).second; - } - } - // active shader was not found - - // find matching shader definition - ShaderDefinitionMap::iterator i = g_shaderDefinitions.find( name ); - if ( i == g_shaderDefinitions.end() ) { - // shader definition was not found - - // create new shader definition from default shader template - ShaderTemplatePointer shaderTemplate( new ShaderTemplate() ); - shaderTemplate->CreateDefault( name ); - g_shaderTemplates.insert( ShaderTemplateMap::value_type( shaderTemplate->getName(), shaderTemplate ) ); - - i = g_shaderDefinitions.insert( ShaderDefinitionMap::value_type( name, ShaderDefinition( shaderTemplate.get(), ShaderArguments(), "" ) ) ).first; - } - - // create shader from existing definition - ShaderPointer pShader( new CShader( ( *i ).second ) ); - pShader->setName( name ); - g_ActiveShaders.insert( shaders_t::value_type( name, pShader ) ); - g_ActiveShadersChangedNotify(); - return pShader; + tokeniser.release(); + file->release(); + } else { + globalOutputStream() << "Unable to read guide file " << fullname.c_str() << "\n"; + } } -IShader *Shader_ForName( const char *name ){ - ASSERT_NOTNULL( name ); +CShader *Try_Shader_ForName(const char *name) +{ + { + shaders_t::iterator i = g_ActiveShaders.find(name); + if (i != g_ActiveShaders.end()) { + return (*i).second; + } + } + // active shader was not found + + // find matching shader definition + ShaderDefinitionMap::iterator i = g_shaderDefinitions.find(name); + if (i == g_shaderDefinitions.end()) { + // shader definition was not found + + // create new shader definition from default shader template + ShaderTemplatePointer shaderTemplate(new ShaderTemplate()); + shaderTemplate->CreateDefault(name); + g_shaderTemplates.insert(ShaderTemplateMap::value_type(shaderTemplate->getName(), shaderTemplate)); + + i = g_shaderDefinitions.insert(ShaderDefinitionMap::value_type(name, ShaderDefinition(shaderTemplate.get(), + ShaderArguments(), + ""))).first; + } + + // create shader from existing definition + ShaderPointer pShader(new CShader((*i).second)); + pShader->setName(name); + g_ActiveShaders.insert(shaders_t::value_type(name, pShader)); + g_ActiveShadersChangedNotify(); + return pShader; +} + +IShader *Shader_ForName(const char *name) +{ + ASSERT_NOTNULL(name); - IShader *pShader = Try_Shader_ForName( name ); - pShader->IncRef(); - return pShader; + IShader *pShader = Try_Shader_ForName(name); + pShader->IncRef(); + return pShader; } - - // the list of scripts/*.shader files we need to work with // those are listed in shaderlist file GSList *l_shaderfiles = 0; -GSList* Shaders_getShaderFileList(){ - return l_shaderfiles; +GSList *Shaders_getShaderFileList() +{ + return l_shaderfiles; } /* @@ -1518,47 +1553,49 @@ GSList* Shaders_getShaderFileList(){ usefull function: dumps the list of .shader files that are not referenced to the console ================== */ -void IfFound_dumpUnreferencedShader( bool& bFound, const char* filename ){ - bool listed = false; - - for ( GSList* sh = l_shaderfiles; sh != 0; sh = g_slist_next( sh ) ) - { - if ( !strcmp( (char*)sh->data, filename ) ) { - listed = true; - break; - } - } - - if ( !listed ) { - if ( !bFound ) { - bFound = true; - globalOutputStream() << "Following shader files are not referenced in any shaderlist.txt:\n"; - } - globalOutputStream() << "\t" << filename << "\n"; - } +void IfFound_dumpUnreferencedShader(bool &bFound, const char *filename) +{ + bool listed = false; + + for (GSList *sh = l_shaderfiles; sh != 0; sh = g_slist_next(sh)) { + if (!strcmp((char *) sh->data, filename)) { + listed = true; + break; + } + } + + if (!listed) { + if (!bFound) { + bFound = true; + globalOutputStream() << "Following shader files are not referenced in any shaderlist.txt:\n"; + } + globalOutputStream() << "\t" << filename << "\n"; + } } -typedef ReferenceCaller IfFoundDumpUnreferencedShaderCaller; -void DumpUnreferencedShaders(){ - bool bFound = false; - GlobalFileSystem().forEachFile( g_shadersDirectory, g_shadersExtension, IfFoundDumpUnreferencedShaderCaller( bFound ) ); +typedef ReferenceCaller IfFoundDumpUnreferencedShaderCaller; + +void DumpUnreferencedShaders() +{ + bool bFound = false; + GlobalFileSystem().forEachFile(g_shadersDirectory, g_shadersExtension, IfFoundDumpUnreferencedShaderCaller(bFound)); } -void ShaderList_addShaderFile( const char* dirstring ){ - bool found = false; - - for ( GSList* tmp = l_shaderfiles; tmp != 0; tmp = tmp->next ) - { - if ( string_equal_nocase( dirstring, (char*)tmp->data ) ) { - found = true; - globalOutputStream() << "duplicate entry \"" << (char*)tmp->data << "\" in shaderlist.txt\n"; - break; - } - } - - if ( !found ) { - l_shaderfiles = g_slist_append( l_shaderfiles, strdup( dirstring ) ); - } +void ShaderList_addShaderFile(const char *dirstring) +{ + bool found = false; + + for (GSList *tmp = l_shaderfiles; tmp != 0; tmp = tmp->next) { + if (string_equal_nocase(dirstring, (char *) tmp->data)) { + found = true; + globalOutputStream() << "duplicate entry \"" << (char *) tmp->data << "\" in shaderlist.txt\n"; + break; + } + } + + if (!found) { + l_shaderfiles = g_slist_append(l_shaderfiles, strdup(dirstring)); + } } /* @@ -1567,234 +1604,264 @@ void ShaderList_addShaderFile( const char* dirstring ){ build a CStringList of shader names ================== */ -void BuildShaderList( TextInputStream& shaderlist ){ - Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser( shaderlist ); - tokeniser.nextLine(); - const char* token = tokeniser.getToken(); - StringOutputStream shaderFile( 64 ); - while ( token != 0 ) - { - // each token should be a shader filename - shaderFile << token << "." << g_shadersExtension; - - ShaderList_addShaderFile( shaderFile.c_str() ); - - tokeniser.nextLine(); - token = tokeniser.getToken(); - - shaderFile.clear(); - } - tokeniser.release(); -} - -void FreeShaderList(){ - while ( l_shaderfiles != 0 ) - { - free( l_shaderfiles->data ); - l_shaderfiles = g_slist_remove( l_shaderfiles, l_shaderfiles->data ); - } -} +void BuildShaderList(TextInputStream &shaderlist) +{ + Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(shaderlist); + tokeniser.nextLine(); + const char *token = tokeniser.getToken(); + StringOutputStream shaderFile(64); + while (token != 0) { + // each token should be a shader filename + shaderFile << token << "." << g_shadersExtension; -void ShaderList_addFromArchive( const char *archivename ){ - const char *shaderpath = GlobalRadiant().getGameDescriptionKeyValue( "shaderpath" ); - if ( string_empty( shaderpath ) ) { - return; - } - - StringOutputStream shaderlist( 256 ); - shaderlist << DirectoryCleaned( shaderpath ) << "shaderlist.txt"; - - Archive *archive = GlobalFileSystem().getArchive( archivename, false ); - if ( archive ) { - ArchiveTextFile *file = archive->openTextFile( shaderlist.c_str() ); - if ( file ) { - globalOutputStream() << "Found shaderlist.txt in " << archivename << "\n"; - BuildShaderList( file->getInputStream() ); - file->release(); - } - } -} + ShaderList_addShaderFile(shaderFile.c_str()); -#include "stream/filestream.h" + tokeniser.nextLine(); + token = tokeniser.getToken(); -bool shaderlist_findOrInstall( const char* enginePath, const char* toolsPath, const char* shaderPath, const char* gamename ){ - StringOutputStream absShaderList( 256 ); - absShaderList << enginePath << gamename << '/' << shaderPath << "shaderlist.txt"; - if ( file_exists( absShaderList.c_str() ) ) { - return true; - } - { - StringOutputStream directory( 256 ); - directory << enginePath << gamename << '/' << shaderPath; - if ( !file_exists( directory.c_str() ) && !Q_mkdir( directory.c_str() ) ) { - return false; - } - } - { - StringOutputStream defaultShaderList( 256 ); - defaultShaderList << toolsPath << gamename << '/' << "default_shaderlist.txt"; - if ( file_exists( defaultShaderList.c_str() ) ) { - return file_copy( defaultShaderList.c_str(), absShaderList.c_str() ); - } - } - return false; + shaderFile.clear(); + } + tokeniser.release(); } -void Shaders_Load(){ - if ( g_shaderLanguage == SHADERLANGUAGE_QUAKE4 ) { - GlobalFileSystem().forEachFile("guides/", "guide", makeCallbackF(loadGuideFile), 0); - } - - const char* shaderPath = GlobalRadiant().getGameDescriptionKeyValue( "shaderpath" ); - if ( !string_empty( shaderPath ) ) { - StringOutputStream path( 256 ); - path << DirectoryCleaned( shaderPath ); - - if ( g_useShaderList ) { - // preload shader files that have been listed in shaderlist.txt - const char* basegame = GlobalRadiant().getRequiredGameDescriptionKeyValue( "basegame" ); - const char* gamename = GlobalRadiant().getGameName(); - const char* enginePath = GlobalRadiant().getEnginePath(); - const char* toolsPath = GlobalRadiant().getGameToolsPath(); - - bool isMod = !string_equal( basegame, gamename ); - - if ( !isMod || !shaderlist_findOrInstall( enginePath, toolsPath, path.c_str(), gamename ) ) { - gamename = basegame; - shaderlist_findOrInstall( enginePath, toolsPath, path.c_str(), gamename ); - } - - GlobalFileSystem().forEachArchive(makeCallbackF(ShaderList_addFromArchive), false, true); - DumpUnreferencedShaders(); - } - else - { - GlobalFileSystem().forEachFile(path.c_str(), g_shadersExtension, makeCallbackF(ShaderList_addShaderFile), 0); - } - - GSList *lst = l_shaderfiles; - StringOutputStream shadername( 256 ); - while ( lst ) - { - shadername << path.c_str() << reinterpret_cast( lst->data ); - LoadShaderFile( shadername.c_str() ); - shadername.clear(); - lst = lst->next; - } - } - - //StringPool_analyse(ShaderPool::instance()); +void FreeShaderList() +{ + while (l_shaderfiles != 0) { + free(l_shaderfiles->data); + l_shaderfiles = g_slist_remove(l_shaderfiles, l_shaderfiles->data); + } } -void Shaders_Free(){ - FreeShaders(); - FreeShaderList(); - g_shaderFilenames.clear(); -} +void ShaderList_addFromArchive(const char *archivename) +{ + const char *shaderpath = GlobalRadiant().getGameDescriptionKeyValue("shaderpath"); + if (string_empty(shaderpath)) { + return; + } -ModuleObservers g_observers; + StringOutputStream shaderlist(256); + shaderlist << DirectoryCleaned(shaderpath) << "shaderlist.txt"; -std::size_t g_shaders_unrealised = 1; // wait until filesystem and is realised before loading anything -bool Shaders_realised(){ - return g_shaders_unrealised == 0; -} -void Shaders_Realise(){ - if ( --g_shaders_unrealised == 0 ) { - Shaders_Load(); - g_observers.realise(); - } -} -void Shaders_Unrealise(){ - if ( ++g_shaders_unrealised == 1 ) { - g_observers.unrealise(); - Shaders_Free(); - } + Archive *archive = GlobalFileSystem().getArchive(archivename, false); + if (archive) { + ArchiveTextFile *file = archive->openTextFile(shaderlist.c_str()); + if (file) { + globalOutputStream() << "Found shaderlist.txt in " << archivename << "\n"; + BuildShaderList(file->getInputStream()); + file->release(); + } + } } -void Shaders_Refresh(){ - Shaders_Unrealise(); - Shaders_Realise(); -} +#include "stream/filestream.h" -class Quake3ShaderSystem : public ShaderSystem, public ModuleObserver +bool +shaderlist_findOrInstall(const char *enginePath, const char *toolsPath, const char *shaderPath, const char *gamename) { -public: -void realise(){ - Shaders_Realise(); -} -void unrealise(){ - Shaders_Unrealise(); -} -void refresh(){ - Shaders_Refresh(); + StringOutputStream absShaderList(256); + absShaderList << enginePath << gamename << '/' << shaderPath << "shaderlist.txt"; + if (file_exists(absShaderList.c_str())) { + return true; + } + { + StringOutputStream directory(256); + directory << enginePath << gamename << '/' << shaderPath; + if (!file_exists(directory.c_str()) && !Q_mkdir(directory.c_str())) { + return false; + } + } + { + StringOutputStream defaultShaderList(256); + defaultShaderList << toolsPath << gamename << '/' << "default_shaderlist.txt"; + if (file_exists(defaultShaderList.c_str())) { + return file_copy(defaultShaderList.c_str(), absShaderList.c_str()); + } + } + return false; +} + +void Shaders_Load() +{ + if (g_shaderLanguage == SHADERLANGUAGE_QUAKE4) { + GlobalFileSystem().forEachFile("guides/", "guide", makeCallbackF(loadGuideFile), 0); + } + + const char *shaderPath = GlobalRadiant().getGameDescriptionKeyValue("shaderpath"); + if (!string_empty(shaderPath)) { + StringOutputStream path(256); + path << DirectoryCleaned(shaderPath); + + if (g_useShaderList) { + // preload shader files that have been listed in shaderlist.txt + const char *basegame = GlobalRadiant().getRequiredGameDescriptionKeyValue("basegame"); + const char *gamename = GlobalRadiant().getGameName(); + const char *enginePath = GlobalRadiant().getEnginePath(); + const char *toolsPath = GlobalRadiant().getGameToolsPath(); + + bool isMod = !string_equal(basegame, gamename); + + if (!isMod || !shaderlist_findOrInstall(enginePath, toolsPath, path.c_str(), gamename)) { + gamename = basegame; + shaderlist_findOrInstall(enginePath, toolsPath, path.c_str(), gamename); + } + + GlobalFileSystem().forEachArchive(makeCallbackF(ShaderList_addFromArchive), false, true); + DumpUnreferencedShaders(); + } else { + GlobalFileSystem().forEachFile(path.c_str(), g_shadersExtension, makeCallbackF(ShaderList_addShaderFile), + 0); + } + + GSList *lst = l_shaderfiles; + StringOutputStream shadername(256); + while (lst) { + shadername << path.c_str() << reinterpret_cast( lst->data ); + LoadShaderFile(shadername.c_str()); + shadername.clear(); + lst = lst->next; + } + } + + //StringPool_analyse(ShaderPool::instance()); +} + +void Shaders_Free() +{ + FreeShaders(); + FreeShaderList(); + g_shaderFilenames.clear(); } -IShader* getShaderForName( const char* name ){ - return Shader_ForName( name ); -} +ModuleObservers g_observers; -void foreachShaderName( const ShaderNameCallback& callback ){ - for ( ShaderDefinitionMap::const_iterator i = g_shaderDefinitions.begin(); i != g_shaderDefinitions.end(); ++i ) - { - callback( ( *i ).first.c_str() ); - } +std::size_t g_shaders_unrealised = 1; // wait until filesystem and is realised before loading anything +bool Shaders_realised() +{ + return g_shaders_unrealised == 0; } -void beginActiveShadersIterator(){ - ActiveShaders_IteratorBegin(); -} -bool endActiveShadersIterator(){ - return ActiveShaders_IteratorAtEnd(); -} -IShader* dereferenceActiveShadersIterator(){ - return ActiveShaders_IteratorCurrent(); -} -void incrementActiveShadersIterator(){ - ActiveShaders_IteratorIncrement(); -} -void setActiveShadersChangedNotify( const Callback& notify ){ - g_ActiveShadersChangedNotify = notify; +void Shaders_Realise() +{ + if (--g_shaders_unrealised == 0) { + Shaders_Load(); + g_observers.realise(); + } } -void attach( ModuleObserver& observer ){ - g_observers.attach( observer ); -} -void detach( ModuleObserver& observer ){ - g_observers.detach( observer ); +void Shaders_Unrealise() +{ + if (++g_shaders_unrealised == 1) { + g_observers.unrealise(); + Shaders_Free(); + } } -void setLightingEnabled( bool enabled ){ - if ( CShader::m_lightingEnabled != enabled ) { - for ( shaders_t::const_iterator i = g_ActiveShaders.begin(); i != g_ActiveShaders.end(); ++i ) - { - ( *i ).second->unrealiseLighting(); - } - CShader::m_lightingEnabled = enabled; - for ( shaders_t::const_iterator i = g_ActiveShaders.begin(); i != g_ActiveShaders.end(); ++i ) - { - ( *i ).second->realiseLighting(); - } - } +void Shaders_Refresh() +{ + Shaders_Unrealise(); + Shaders_Realise(); } -const char* getTexturePrefix() const { - return g_texturePrefix; -} +class Quake3ShaderSystem : public ShaderSystem, public ModuleObserver { +public: + void realise() + { + Shaders_Realise(); + } + + void unrealise() + { + Shaders_Unrealise(); + } + + void refresh() + { + Shaders_Refresh(); + } + + IShader *getShaderForName(const char *name) + { + return Shader_ForName(name); + } + + void foreachShaderName(const ShaderNameCallback &callback) + { + for (ShaderDefinitionMap::const_iterator i = g_shaderDefinitions.begin(); i != g_shaderDefinitions.end(); ++i) { + callback((*i).first.c_str()); + } + } + + void beginActiveShadersIterator() + { + ActiveShaders_IteratorBegin(); + } + + bool endActiveShadersIterator() + { + return ActiveShaders_IteratorAtEnd(); + } + + IShader *dereferenceActiveShadersIterator() + { + return ActiveShaders_IteratorCurrent(); + } + + void incrementActiveShadersIterator() + { + ActiveShaders_IteratorIncrement(); + } + + void setActiveShadersChangedNotify(const Callback ¬ify) + { + g_ActiveShadersChangedNotify = notify; + } + + void attach(ModuleObserver &observer) + { + g_observers.attach(observer); + } + + void detach(ModuleObserver &observer) + { + g_observers.detach(observer); + } + + void setLightingEnabled(bool enabled) + { + if (CShader::m_lightingEnabled != enabled) { + for (shaders_t::const_iterator i = g_ActiveShaders.begin(); i != g_ActiveShaders.end(); ++i) { + (*i).second->unrealiseLighting(); + } + CShader::m_lightingEnabled = enabled; + for (shaders_t::const_iterator i = g_ActiveShaders.begin(); i != g_ActiveShaders.end(); ++i) { + (*i).second->realiseLighting(); + } + } + } + + const char *getTexturePrefix() const + { + return g_texturePrefix; + } }; Quake3ShaderSystem g_Quake3ShaderSystem; -ShaderSystem& GetShaderSystem(){ - return g_Quake3ShaderSystem; +ShaderSystem &GetShaderSystem() +{ + return g_Quake3ShaderSystem; } -void Shaders_Construct(){ - GlobalFileSystem().attach( g_Quake3ShaderSystem ); +void Shaders_Construct() +{ + GlobalFileSystem().attach(g_Quake3ShaderSystem); } -void Shaders_Destroy(){ - GlobalFileSystem().detach( g_Quake3ShaderSystem ); - if ( Shaders_realised() ) { - Shaders_Free(); - } +void Shaders_Destroy() +{ + GlobalFileSystem().detach(g_Quake3ShaderSystem); + + if (Shaders_realised()) { + Shaders_Free(); + } } diff --git a/plugins/shaders/shaders.h b/plugins/shaders/shaders.h index 88f193f9..7567cf49 100644 --- a/plugins/shaders/shaders.h +++ b/plugins/shaders/shaders.h @@ -32,24 +32,26 @@ #define INCLUDED_SHADERS_H void Shaders_Construct(); + void Shaders_Destroy(); + class ShaderSystem; -ShaderSystem& GetShaderSystem(); -enum ShaderLanguage -{ - SHADERLANGUAGE_QUAKE3, - SHADERLANGUAGE_DOOM3, - SHADERLANGUAGE_QUAKE4 +ShaderSystem &GetShaderSystem(); + +enum ShaderLanguage { + SHADERLANGUAGE_QUAKE3, + SHADERLANGUAGE_DOOM3, + SHADERLANGUAGE_QUAKE4 }; -extern const char* g_shadersExtension; -extern const char* g_shadersDirectory; +extern const char *g_shadersExtension; +extern const char *g_shadersDirectory; extern ShaderLanguage g_shaderLanguage; extern bool g_enableDefaultShaders; extern bool g_useShaderList; struct _QERPlugImageTable; -extern _QERPlugImageTable* g_bitmapModule; +extern _QERPlugImageTable *g_bitmapModule; #endif diff --git a/plugins/spritemodel/plugin.cpp b/plugins/spritemodel/plugin.cpp index fd881ecf..84daad66 100644 --- a/plugins/spritemodel/plugin.cpp +++ b/plugins/spritemodel/plugin.cpp @@ -116,96 +116,110 @@ _QERShadersTable g_ShadersTable; #include "synapse.h" -char *supportedmodelformats[] = {"spr","bmp","tga","jpg","hlw",NULL}; // NULL is list delimiter - -static void add_model_apis( CSynapseClient& client ){ - char **ext; - for ( ext = supportedmodelformats; *ext != NULL; ext++ ) - { - client.AddAPI( MODEL_MAJOR, *ext, sizeof( _QERPlugModelTable ) ); - } +char *supportedmodelformats[] = {"spr", "bmp", "tga", "jpg", "hlw", NULL}; // NULL is list delimiter + +static void add_model_apis(CSynapseClient &client) +{ + char **ext; + for (ext = supportedmodelformats; *ext != NULL; ext++) { + client.AddAPI(MODEL_MAJOR, *ext, sizeof(_QERPlugModelTable)); + } } -static bool model_is_supported( const char* extension ){ - char **ext; - for ( ext = supportedmodelformats; *ext != NULL; ext++ ) - { - if ( stricmp( extension,*ext ) == 0 ) { - return true; - } - } - return false; +static bool model_is_supported(const char *extension) +{ + char **ext; + for (ext = supportedmodelformats; *ext != NULL; ext++) { + if (stricmp(extension, *ext) == 0) { + return true; + } + } + return false; } -void init_filetypes(){ - char **ext; - for ( ext = supportedmodelformats; *ext != NULL; ext++ ) - { - GetFileTypeRegistry()->addType( MODEL_MAJOR, filetype_t( "sprite", *ext ) ); - } +void init_filetypes() +{ + char **ext; + for (ext = supportedmodelformats; *ext != NULL; ext++) { + GetFileTypeRegistry()->addType(MODEL_MAJOR, filetype_t("sprite", *ext)); + } } -extern CSynapseServer* g_pSynapseServer; +extern CSynapseServer *g_pSynapseServer; -class CSynapseClientModel : public CSynapseClient -{ +class CSynapseClientModel : public CSynapseClient { public: // CSynapseClient API -bool RequestAPI( APIDescriptor_t *pAPI ); -const char* GetInfo(); -const char* GetName(); + bool RequestAPI(APIDescriptor_t *pAPI); -CSynapseClientModel() { } -virtual ~CSynapseClientModel() { } + const char *GetInfo(); -bool OnActivate(){ - init_filetypes(); // see todo list above. - return true; -} -}; + const char *GetName(); -CSynapseServer* g_pSynapseServer = NULL; -CSynapseClientModel g_SynapseClient; + CSynapseClientModel() + {} -extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ){ - if ( strcmp( version, SYNAPSE_VERSION ) ) { - Syn_Printf( "ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version ); - return NULL; - } - g_pSynapseServer = pServer; - g_pSynapseServer->IncRef(); - Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() ); + virtual ~CSynapseClientModel() + {} - add_model_apis( g_SynapseClient ); // see todo list above. + bool OnActivate() + { + init_filetypes(); // see todo list above. + return true; + } +}; + +CSynapseServer *g_pSynapseServer = NULL; +CSynapseClientModel g_SynapseClient; - g_SynapseClient.AddAPI( PLUGIN_MAJOR, "sprite", sizeof( _QERPluginTable ) ); - g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( g_FuncTable ), SYN_REQUIRE, &g_FuncTable ); - g_SynapseClient.AddAPI( QGL_MAJOR, NULL, sizeof( g_QglTable ), SYN_REQUIRE, &g_QglTable ); - g_SynapseClient.AddAPI( SHADERS_MAJOR, "*", sizeof( g_ShadersTable ), SYN_REQUIRE, &g_ShadersTable ); +extern "C" CSynapseClient *SYNAPSE_DLL_EXPORT - return &g_SynapseClient; +Synapse_EnumerateInterfaces(const char *version, CSynapseServer *pServer) +{ + if (strcmp(version, SYNAPSE_VERSION)) { + Syn_Printf("ERROR: synapse API version mismatch: should be '" + SYNAPSE_VERSION + "', got '%s'\n", version ); + return NULL; + } + g_pSynapseServer = pServer; + g_pSynapseServer->IncRef(); + Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf()); + + add_model_apis(g_SynapseClient); // see todo list above. + + g_SynapseClient.AddAPI(PLUGIN_MAJOR, "sprite", sizeof(_QERPluginTable)); + g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable); + g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(g_QglTable), SYN_REQUIRE, &g_QglTable); + g_SynapseClient.AddAPI(SHADERS_MAJOR, "*", sizeof(g_ShadersTable), SYN_REQUIRE, &g_ShadersTable); + + return &g_SynapseClient; } -bool CSynapseClientModel::RequestAPI( APIDescriptor_t *pAPI ){ - if ( !strcmp( pAPI->major_name, MODEL_MAJOR ) ) { - _QERPlugModelTable* pTable = static_cast<_QERPlugModelTable*>( pAPI->mpTable ); +bool CSynapseClientModel::RequestAPI(APIDescriptor_t *pAPI) +{ + if (!strcmp(pAPI->major_name, MODEL_MAJOR)) { + _QERPlugModelTable *pTable = static_cast<_QERPlugModelTable *>( pAPI->mpTable ); - if ( !strcmp( pAPI->minor_name, "sprite" ) ) { - pTable->m_pfnLoadModel = &LoadSpriteModel; - return true; - } - } + if (!strcmp(pAPI->minor_name, "sprite")) { + pTable->m_pfnLoadModel = &LoadSpriteModel; + return true; + } + } - Syn_Printf( "ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo() ); - return false; + Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo()); + return false; } #include "version.h" -const char* CSynapseClientModel::GetInfo(){ - return "Sprite Model module built " __DATE__ " " RADIANT_VERSION; +const char *CSynapseClientModel::GetInfo() +{ + return "Sprite Model module built " __DATE__ " " + RADIANT_VERSION; } -const char* CSynapseClientModel::GetName(){ - return "sprite"; +const char *CSynapseClientModel::GetName() +{ + return "sprite"; } diff --git a/plugins/spritemodel/plugin.h b/plugins/spritemodel/plugin.h index aa459c55..0b3044ac 100644 --- a/plugins/spritemodel/plugin.h +++ b/plugins/spritemodel/plugin.h @@ -35,11 +35,15 @@ #include #define USE_QERTABLE_DEFINE + #include "qerplugin.h" + extern _QERFuncTable_1 __QERTABLENAME; #define USE_QGLTABLE_DEFINE + #include "igl.h" + extern OpenGLBinding __QGLTABLENAME; #include "imodel.h" diff --git a/plugins/spritemodel/spritemodel.cpp b/plugins/spritemodel/spritemodel.cpp index 8308416f..df36e874 100644 --- a/plugins/spritemodel/spritemodel.cpp +++ b/plugins/spritemodel/spritemodel.cpp @@ -28,60 +28,65 @@ #include "spritemodel.h" -void LoadSpriteModel( entity_interfaces_t *interfaces, const char *name ){ - IShader *pShader; - - pShader = QERApp_Shader_ForName( name ); - - if ( !pShader ) { - Sys_Printf( "ERROR: can't find shader (or image) for: %s\n", name ); - return; // NULL; - } - - CSpriteModel *model = new CSpriteModel(); - model->Construct( pShader ); - interfaces->pRender = (IRender*)model; - interfaces->pRender->IncRef(); - //interfaces->pSelect = (ISelect*)model; - //interfaces->pSelect->IncRef(); - interfaces->pSelect = NULL; - interfaces->pEdit = NULL; - model->DecRef(); +void LoadSpriteModel(entity_interfaces_t *interfaces, const char *name) +{ + IShader *pShader; + + pShader = QERApp_Shader_ForName(name); + + if (!pShader) { + Sys_Printf("ERROR: can't find shader (or image) for: %s\n", name); + return; // NULL; + } + + CSpriteModel *model = new CSpriteModel(); + model->Construct(pShader); + interfaces->pRender = (IRender *) model; + interfaces->pRender->IncRef(); + //interfaces->pSelect = (ISelect*)model; + //interfaces->pSelect->IncRef(); + interfaces->pSelect = NULL; + interfaces->pEdit = NULL; + model->DecRef(); } -void CSpriteModel::Construct( IShader *pShader ){ - m_pShader = pShader; - aabb_clear( &m_BBox ); - /* - md3Surface_t *pSurface = (md3Surface_t *)(((unsigned char *)pHeader) + pHeader->ofsSurfaces); - m_nSurfaces = pHeader->numSurfaces; - CMD3Surface* surfaces = new CMD3Surface[m_nSurfaces]; - for (int i = 0; i < m_nSurfaces; i++ ) - { - surfaces[i].Construct(pSurface); - pSurface = (md3Surface_t *) ((( char * ) pSurface) + pSurface->ofsEnd); - } - m_children = surfaces; - AccumulateBBox(); - */ +void CSpriteModel::Construct(IShader *pShader) +{ + m_pShader = pShader; + aabb_clear(&m_BBox); + /* + md3Surface_t *pSurface = (md3Surface_t *)(((unsigned char *)pHeader) + pHeader->ofsSurfaces); + m_nSurfaces = pHeader->numSurfaces; + CMD3Surface* surfaces = new CMD3Surface[m_nSurfaces]; + for (int i = 0; i < m_nSurfaces; i++ ) + { + surfaces[i].Construct(pSurface); + pSurface = (md3Surface_t *) ((( char * ) pSurface) + pSurface->ofsEnd); + } + m_children = surfaces; + AccumulateBBox(); + */ } -CSpriteModel::CSpriteModel(){ - refCount = 1; - //m_nSurfaces = 0; - //m_children = NULL; - m_pShader = NULL; +CSpriteModel::CSpriteModel() +{ + refCount = 1; + //m_nSurfaces = 0; + //m_children = NULL; + m_pShader = NULL; } -CSpriteModel::~CSpriteModel(){ - // if(m_children) delete[] m_children; - if ( m_pShader ) { - m_pShader->DecRef(); - } +CSpriteModel::~CSpriteModel() +{ + // if(m_children) delete[] m_children; + if (m_pShader) { + m_pShader->DecRef(); + } } -void CSpriteModel::Draw( int state, int rflags ) const { +void CSpriteModel::Draw(int state, int rflags) const +{ /* // Draw a point in the middle of the bbox @@ -93,61 +98,61 @@ void CSpriteModel::Draw( int state, int rflags ) const { g_QglTable.m_pfn_qglEnd (); */ - qtexture_t *q = m_pShader->getTexture(); + qtexture_t *q = m_pShader->getTexture(); - // convert pixels to units and divide in half again so we draw in the middle - // of the bbox. - int h = q->height / 8; - int w = q->width / 8; + // convert pixels to units and divide in half again so we draw in the middle + // of the bbox. + int h = q->height / 8; + int w = q->width / 8; - // setup opengl stuff + // setup opengl stuff - g_QglTable.m_pfn_qglPushAttrib( GL_ALL_ATTRIB_BITS ); // GL_ENABLE_BIT - //g_QglTable.m_pfn_qglColor3f (1,1,1); //testing - //g_QglTable.m_pfn_qglColor4f (1,1,1,1); //testing - g_QglTable.m_pfn_qglBindTexture( GL_TEXTURE_2D, q->texture_number ); + g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS); // GL_ENABLE_BIT + //g_QglTable.m_pfn_qglColor3f (1,1,1); //testing + //g_QglTable.m_pfn_qglColor4f (1,1,1,1); //testing + g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, q->texture_number); - //g_QglTable.m_pfn_qglEnable (GL_TEXTURE_2D); // FIXME: ? this forces textures, even in wireframe mode, bad... ? + //g_QglTable.m_pfn_qglEnable (GL_TEXTURE_2D); // FIXME: ? this forces textures, even in wireframe mode, bad... ? - g_QglTable.m_pfn_qglAlphaFunc( GL_LESS, 1 ); - g_QglTable.m_pfn_qglEnable( GL_ALPHA_TEST ); + g_QglTable.m_pfn_qglAlphaFunc(GL_LESS, 1); + g_QglTable.m_pfn_qglEnable(GL_ALPHA_TEST); - // get rid of this when sprite always faces camera - g_QglTable.m_pfn_qglDisable( GL_CULL_FACE ); - g_QglTable.m_pfn_qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + // get rid of this when sprite always faces camera + g_QglTable.m_pfn_qglDisable(GL_CULL_FACE); + g_QglTable.m_pfn_qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - // draw the sprite + // draw the sprite #if 0 - // using x/y axis, it appears FLAT without the proper transform and rotation. - - g_QglTable.m_pfn_qglBegin( GL_QUADS ); - g_QglTable.m_pfn_qglTexCoord2f( 0,0 ); - g_QglTable.m_pfn_qglVertex3f( 0 - w,0 - h, 0 ); - g_QglTable.m_pfn_qglTexCoord2f( 1,0 ); - g_QglTable.m_pfn_qglVertex3f( w,0 - h, 0 ); - g_QglTable.m_pfn_qglTexCoord2f( 1,1 ); - g_QglTable.m_pfn_qglVertex3f( w, h, 0 ); - g_QglTable.m_pfn_qglTexCoord2f( 0,1 ); - g_QglTable.m_pfn_qglVertex3f( 0 - w, h, 0 ); - g_QglTable.m_pfn_qglEnd(); + // using x/y axis, it appears FLAT without the proper transform and rotation. + + g_QglTable.m_pfn_qglBegin( GL_QUADS ); + g_QglTable.m_pfn_qglTexCoord2f( 0,0 ); + g_QglTable.m_pfn_qglVertex3f( 0 - w,0 - h, 0 ); + g_QglTable.m_pfn_qglTexCoord2f( 1,0 ); + g_QglTable.m_pfn_qglVertex3f( w,0 - h, 0 ); + g_QglTable.m_pfn_qglTexCoord2f( 1,1 ); + g_QglTable.m_pfn_qglVertex3f( w, h, 0 ); + g_QglTable.m_pfn_qglTexCoord2f( 0,1 ); + g_QglTable.m_pfn_qglVertex3f( 0 - w, h, 0 ); + g_QglTable.m_pfn_qglEnd(); #else - // so draw it using y/z instead. - g_QglTable.m_pfn_qglBegin( GL_QUADS ); - g_QglTable.m_pfn_qglTexCoord2f( 0.0f, 0.0f ); - g_QglTable.m_pfn_qglVertex3f( 0.0f, static_cast( w ), static_cast( h ) ); - g_QglTable.m_pfn_qglTexCoord2f( 1.0f, 0.0f ); - g_QglTable.m_pfn_qglVertex3f( 0.0f, 0.0f - static_cast( w ), static_cast( h ) ); - g_QglTable.m_pfn_qglTexCoord2f( 1.0f, 1.0f ); - g_QglTable.m_pfn_qglVertex3f( 0.0f, 0.0f - static_cast( w ), 0.0f - static_cast( h ) ); - g_QglTable.m_pfn_qglTexCoord2f( 0.0f, 0.0f ); - g_QglTable.m_pfn_qglVertex3f( 0.0f, static_cast( w ), 0.0f - static_cast( h ) ); - g_QglTable.m_pfn_qglEnd(); + // so draw it using y/z instead. + g_QglTable.m_pfn_qglBegin(GL_QUADS); + g_QglTable.m_pfn_qglTexCoord2f(0.0f, 0.0f); + g_QglTable.m_pfn_qglVertex3f(0.0f, static_cast( w ), static_cast( h )); + g_QglTable.m_pfn_qglTexCoord2f(1.0f, 0.0f); + g_QglTable.m_pfn_qglVertex3f(0.0f, 0.0f - static_cast( w ), static_cast( h )); + g_QglTable.m_pfn_qglTexCoord2f(1.0f, 1.0f); + g_QglTable.m_pfn_qglVertex3f(0.0f, 0.0f - static_cast( w ), 0.0f - static_cast( h )); + g_QglTable.m_pfn_qglTexCoord2f(0.0f, 0.0f); + g_QglTable.m_pfn_qglVertex3f(0.0f, static_cast( w ), 0.0f - static_cast( h )); + g_QglTable.m_pfn_qglEnd(); #endif - g_QglTable.m_pfn_qglBindTexture( GL_TEXTURE_2D, 0 ); - g_QglTable.m_pfn_qglPopAttrib(); + g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, 0); + g_QglTable.m_pfn_qglPopAttrib(); } /* diff --git a/plugins/spritemodel/spritemodel.h b/plugins/spritemodel/spritemodel.h index 698cf449..d6857879 100644 --- a/plugins/spritemodel/spritemodel.h +++ b/plugins/spritemodel/spritemodel.h @@ -32,31 +32,37 @@ class CSpriteModel : public IRender //, public ISelect { public: -CSpriteModel(); -~CSpriteModel(); + CSpriteModel(); -void IncRef() { refCount++; } -void DecRef() { - if ( --refCount == 0 ) { - delete this; - } -} + ~CSpriteModel(); + + void IncRef() + { refCount++; } + + void DecRef() + { + if (--refCount == 0) { + delete this; + } + } //IRender -void Draw( int state, int rflags ) const; -const aabb_t *GetAABB() const { return &m_BBox; } + void Draw(int state, int rflags) const; + + const aabb_t *GetAABB() const + { return &m_BBox; } //ISelect //bool TestRay (const ray_t *ray, vec_t *dist) const; -void Construct( IShader *pShader ); + void Construct(IShader *pShader); protected: -IShader *m_pShader; + IShader *m_pShader; private: -int refCount; -aabb_t m_BBox; + int refCount; + aabb_t m_BBox; }; -void LoadSpriteModel( entity_interfaces_t *interfaces, const char *name ); +void LoadSpriteModel(entity_interfaces_t *interfaces, const char *name); diff --git a/plugins/textool/2DView.cpp b/plugins/textool/2DView.cpp index 2e3ef526..86e3d5d1 100644 --- a/plugins/textool/2DView.cpp +++ b/plugins/textool/2DView.cpp @@ -29,155 +29,170 @@ #include "StdAfx.h" -static void view_ZoomIn( GtkWidget* widget, gpointer data ){ - ( (C2DView*)data )->ZoomIn(); +static void view_ZoomIn(GtkWidget *widget, gpointer data) +{ + ((C2DView *) data)->ZoomIn(); } -static void view_ZoomOut( GtkWidget* widget, gpointer data ){ - ( (C2DView*)data )->ZoomOut(); +static void view_ZoomOut(GtkWidget *widget, gpointer data) +{ + ((C2DView *) data)->ZoomOut(); } -void C2DView::PreparePaint(){ - g_QglTable.m_pfn_qglClearColor( 0, 0, 0, 0 ); - g_QglTable.m_pfn_qglViewport( 0, 0, m_rect.right, m_rect.bottom ); - g_QglTable.m_pfn_qglMatrixMode( GL_PROJECTION ); - g_QglTable.m_pfn_qglLoadIdentity(); - g_QglTable.m_pfn_qglOrtho( m_Mins[0], m_Maxs[0], m_Maxs[1], m_Mins[1], -1, 1 ); +void C2DView::PreparePaint() +{ + g_QglTable.m_pfn_qglClearColor(0, 0, 0, 0); + g_QglTable.m_pfn_qglViewport(0, 0, m_rect.right, m_rect.bottom); + g_QglTable.m_pfn_qglMatrixMode(GL_PROJECTION); + g_QglTable.m_pfn_qglLoadIdentity(); + g_QglTable.m_pfn_qglOrtho(m_Mins[0], m_Maxs[0], m_Maxs[1], m_Mins[1], -1, 1); } -void C2DView::SpaceForWindow( float c[2], int x, int y ){ - c[0] = ( (float)( x ) ) / ( (float)( m_rect.right - m_rect.left ) ) * ( m_Maxs[0] - m_Mins[0] ) + m_Mins[0]; - c[1] = ( (float)( y ) ) / ( (float)( m_rect.bottom - m_rect.top ) ) * ( m_Maxs[1] - m_Mins[1] ) + m_Mins[1]; +void C2DView::SpaceForWindow(float c[2], int x, int y) +{ + c[0] = ((float) (x)) / ((float) (m_rect.right - m_rect.left)) * (m_Maxs[0] - m_Mins[0]) + m_Mins[0]; + c[1] = ((float) (y)) / ((float) (m_rect.bottom - m_rect.top)) * (m_Maxs[1] - m_Mins[1]) + m_Mins[1]; } -void C2DView::GridForWindow( float c[2], int x, int y ){ - SpaceForWindow( c, x, y ); - if ( !m_bDoGrid ) { - return; - } - c[0] /= m_GridStep[0]; - c[1] /= m_GridStep[1]; - c[0] = (float)floor( c[0] + 0.5f ); - c[1] = (float)floor( c[1] + 0.5f ); - c[0] *= m_GridStep[0]; - c[1] *= m_GridStep[1]; +void C2DView::GridForWindow(float c[2], int x, int y) +{ + SpaceForWindow(c, x, y); + if (!m_bDoGrid) { + return; + } + c[0] /= m_GridStep[0]; + c[1] /= m_GridStep[1]; + c[0] = (float) floor(c[0] + 0.5f); + c[1] = (float) floor(c[1] + 0.5f); + c[0] *= m_GridStep[0]; + c[1] *= m_GridStep[1]; } -void C2DView::WindowForSpace( int &x, int &y, const float c[2] ){ - x = m_rect.left + (int)( ( (float)( m_rect.right - m_rect.left ) ) * ( c[0] - m_Mins[0] ) / ( m_Maxs[0] - m_Mins[0] ) ); - y = m_rect.top + (int)( ( (float)( m_rect.bottom - m_rect.top ) ) * ( c[1] - m_Mins[1] ) / ( m_Maxs[1] - m_Mins[1] ) ); +void C2DView::WindowForSpace(int &x, int &y, const float c[2]) +{ + x = m_rect.left + (int) (((float) (m_rect.right - m_rect.left)) * (c[0] - m_Mins[0]) / (m_Maxs[0] - m_Mins[0])); + y = m_rect.top + (int) (((float) (m_rect.bottom - m_rect.top)) * (c[1] - m_Mins[1]) / (m_Maxs[1] - m_Mins[1])); } -qboolean C2DView::DoesSelect( int x, int y, float c[2] ){ - int xc,yc; - WindowForSpace( xc, yc, c ); - if ( abs( xc - x ) <= 3 && abs( yc - y ) <= 3 ) { - return true; - } - return false; +qboolean C2DView::DoesSelect(int x, int y, float c[2]) +{ + int xc, yc; + WindowForSpace(xc, yc, c); + if (abs(xc - x) <= 3 && abs(yc - y) <= 3) { + return true; + } + return false; } -void C2DView::ZoomIn(){ - m_Mins[0] = 0.5f * ( m_Mins[0] - m_Center[0] ) + m_Center[0]; - m_Mins[1] = 0.5f * ( m_Mins[1] - m_Center[1] ) + m_Center[1]; - m_Maxs[0] = 0.5f * ( m_Maxs[0] - m_Center[0] ) + m_Center[0]; - m_Maxs[1] = 0.5f * ( m_Maxs[1] - m_Center[1] ) + m_Center[1]; - g_pToolWnd->Redraw(); +void C2DView::ZoomIn() +{ + m_Mins[0] = 0.5f * (m_Mins[0] - m_Center[0]) + m_Center[0]; + m_Mins[1] = 0.5f * (m_Mins[1] - m_Center[1]) + m_Center[1]; + m_Maxs[0] = 0.5f * (m_Maxs[0] - m_Center[0]) + m_Center[0]; + m_Maxs[1] = 0.5f * (m_Maxs[1] - m_Center[1]) + m_Center[1]; + g_pToolWnd->Redraw(); } -void C2DView::ZoomOut(){ - m_Mins[0] = 2.0f * ( m_Mins[0] - m_Center[0] ) + m_Center[0]; - m_Mins[1] = 2.0f * ( m_Mins[1] - m_Center[1] ) + m_Center[1]; - m_Maxs[0] = 2.0f * ( m_Maxs[0] - m_Center[0] ) + m_Center[0]; - m_Maxs[1] = 2.0f * ( m_Maxs[1] - m_Center[1] ) + m_Center[1]; - g_pToolWnd->Redraw(); +void C2DView::ZoomOut() +{ + m_Mins[0] = 2.0f * (m_Mins[0] - m_Center[0]) + m_Center[0]; + m_Mins[1] = 2.0f * (m_Mins[1] - m_Center[1]) + m_Center[1]; + m_Maxs[0] = 2.0f * (m_Maxs[0] - m_Center[0]) + m_Center[0]; + m_Maxs[1] = 2.0f * (m_Maxs[1] - m_Center[1]) + m_Center[1]; + g_pToolWnd->Redraw(); } -bool C2DView::OnRButtonDown( int x, int y ){ - if ( ViewState == View_Idle ) { - m_xPosMove = x; // horizontal position of cursor - m_yPosMove = y; // vertical position of cursor - // store - m_MinsMove[0] = m_Mins[0]; m_MinsMove[1] = m_Mins[1]; - m_MaxsMove[0] = m_Maxs[0]; m_MaxsMove[1] = m_Maxs[1]; - ViewState = View_Move; - // set popup to true - m_bPopup = true; - return true; - } - return false; +bool C2DView::OnRButtonDown(int x, int y) +{ + if (ViewState == View_Idle) { + m_xPosMove = x; // horizontal position of cursor + m_yPosMove = y; // vertical position of cursor + // store + m_MinsMove[0] = m_Mins[0]; + m_MinsMove[1] = m_Mins[1]; + m_MaxsMove[0] = m_Maxs[0]; + m_MaxsMove[1] = m_Maxs[1]; + ViewState = View_Move; + // set popup to true + m_bPopup = true; + return true; + } + return false; } -bool C2DView::OnRButtonUp( int x, int y ){ - if ( ViewState == View_Move ) { - // maybe it's time for popup menu - if ( m_bPopup ) { - GtkWidget *menu, *item; - - menu = ui::Menu(); - - item = ui::MenuItem( "Validate (RETURN)" ); - item.connect( "activate", G_CALLBACK( Textool_Validate ), NULL ); - item.show(); - gtk_menu_append( GTK_MENU( menu ), item ); - - item = ui::MenuItem( "Zoom in (INSERT)" ); - item.connect( "activate", G_CALLBACK( view_ZoomIn ), this ); - item.show(); - gtk_menu_append( GTK_MENU( menu ), item ); - - item = ui::MenuItem( "Zoom out (DELETE)" ); - item.connect( "activate", G_CALLBACK( view_ZoomOut ), this ); - item.show(); - gtk_menu_append( GTK_MENU( menu ), item ); - - item = ui::MenuItem( "Cancel (ESC)" ); - item.connect( "activate", G_CALLBACK( Textool_Cancel ), NULL ); - item.show(); - gtk_menu_append( GTK_MENU( menu ), item ); - - gtk_menu_popup( GTK_MENU( menu ), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME ); - } - - // back to Idle mode - ViewState = View_Idle; - return true; - } - return false; +bool C2DView::OnRButtonUp(int x, int y) +{ + if (ViewState == View_Move) { + // maybe it's time for popup menu + if (m_bPopup) { + GtkWidget *menu, *item; + + menu = ui::Menu(); + + item = ui::MenuItem("Validate (RETURN)"); + item.connect("activate", G_CALLBACK(Textool_Validate), NULL); + item.show(); + gtk_menu_append(GTK_MENU(menu), item); + + item = ui::MenuItem("Zoom in (INSERT)"); + item.connect("activate", G_CALLBACK(view_ZoomIn), this); + item.show(); + gtk_menu_append(GTK_MENU(menu), item); + + item = ui::MenuItem("Zoom out (DELETE)"); + item.connect("activate", G_CALLBACK(view_ZoomOut), this); + item.show(); + gtk_menu_append(GTK_MENU(menu), item); + + item = ui::MenuItem("Cancel (ESC)"); + item.connect("activate", G_CALLBACK(Textool_Cancel), NULL); + item.show(); + gtk_menu_append(GTK_MENU(menu), item); + + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME); + } + + // back to Idle mode + ViewState = View_Idle; + return true; + } + return false; } -bool C2DView::OnMouseMove( int xPos, int yPos ){ - if ( ViewState == View_Move ) { - float V[2]; - // V is the offset - V[0] = ( (float)( xPos - m_xPosMove ) ) * ( m_MaxsMove[0] - m_MinsMove[0] ) / ( (float)( m_rect.left - m_rect.right ) ); - V[1] = ( (float)( yPos - m_yPosMove ) ) * ( m_MaxsMove[1] - m_MinsMove[1] ) / ( (float)( m_rect.top - m_rect.bottom ) ); - // update m_Mins m_Maxs and m_Center - m_Mins[0] = m_MinsMove[0] + V[0]; - m_Mins[1] = m_MinsMove[1] + V[1]; - m_Maxs[0] = m_MaxsMove[0] + V[0]; - m_Maxs[1] = m_MaxsMove[1] + V[1]; - m_Center[0] = 0.5f * ( m_Mins[0] + m_Maxs[0] ); - m_Center[1] = 0.5f * ( m_Mins[1] + m_Maxs[1] ); - // no popup menu if we moved - m_bPopup = false; - // send a repaint message - g_pToolWnd->Redraw(); - return true; - } - return false; +bool C2DView::OnMouseMove(int xPos, int yPos) +{ + if (ViewState == View_Move) { + float V[2]; + // V is the offset + V[0] = ((float) (xPos - m_xPosMove)) * (m_MaxsMove[0] - m_MinsMove[0]) / ((float) (m_rect.left - m_rect.right)); + V[1] = ((float) (yPos - m_yPosMove)) * (m_MaxsMove[1] - m_MinsMove[1]) / ((float) (m_rect.top - m_rect.bottom)); + // update m_Mins m_Maxs and m_Center + m_Mins[0] = m_MinsMove[0] + V[0]; + m_Mins[1] = m_MinsMove[1] + V[1]; + m_Maxs[0] = m_MaxsMove[0] + V[0]; + m_Maxs[1] = m_MaxsMove[1] + V[1]; + m_Center[0] = 0.5f * (m_Mins[0] + m_Maxs[0]); + m_Center[1] = 0.5f * (m_Mins[1] + m_Maxs[1]); + // no popup menu if we moved + m_bPopup = false; + // send a repaint message + g_pToolWnd->Redraw(); + return true; + } + return false; } -bool C2DView::OnKeyDown( char *s ){ - if ( ViewState == View_Idle ) { - if ( !strcmp( s,"Insert" ) ) { - ZoomOut(); - return true; - } - if ( !strcmp( s,"Delete" ) ) { - ZoomIn(); - return true; - } - } - return false; +bool C2DView::OnKeyDown(char *s) +{ + if (ViewState == View_Idle) { + if (!strcmp(s, "Insert")) { + ZoomOut(); + return true; + } + if (!strcmp(s, "Delete")) { + ZoomIn(); + return true; + } + } + return false; } diff --git a/plugins/textool/2DView.h b/plugins/textool/2DView.h index c2773abf..439a3030 100644 --- a/plugins/textool/2DView.h +++ b/plugins/textool/2DView.h @@ -30,40 +30,56 @@ #ifndef _2DVIEW_H_ #define _2DVIEW_H_ -class C2DView -{ -enum E2DViewState { View_Idle, View_Move } ViewState; -int m_xPosMove, m_yPosMove; -float m_MinsMove[2], m_MaxsMove[2]; -qboolean m_bDoGrid; -float m_GridStep[2]; -qboolean m_bPopup; +class C2DView { + enum E2DViewState { View_Idle, View_Move } ViewState; + int m_xPosMove, m_yPosMove; + float m_MinsMove[2], m_MaxsMove[2]; + qboolean m_bDoGrid; + float m_GridStep[2]; + qboolean m_bPopup; public: -RECT m_rect; -float m_Mins[2],m_Maxs[2],m_Center[2]; -C2DView(){ - ViewState = View_Idle; - m_bDoGrid = false; - m_bPopup = false; -} -~C2DView() { } -void SetGrid( float xGridStep, float yGridStep ) -{ m_bDoGrid = true; m_GridStep[0] = xGridStep; m_GridStep[1] = yGridStep; } + RECT m_rect; + float m_Mins[2], m_Maxs[2], m_Center[2]; + + C2DView() + { + ViewState = View_Idle; + m_bDoGrid = false; + m_bPopup = false; + } + + ~C2DView() + {} + + void SetGrid(float xGridStep, float yGridStep) + { + m_bDoGrid = true; + m_GridStep[0] = xGridStep; + m_GridStep[1] = yGridStep; + } // get window coordinates for space coordinates -void WindowForSpace( int &x, int &y, const float c[2] ); -void SpaceForWindow( float c[2], int x, int y ); -void GridForWindow( float c[2], int x, int y ); -qboolean DoesSelect( int x, int y, float c[2] ); -void PreparePaint(); - -bool OnRButtonDown( int x, int y ); -bool OnMouseMove( int x, int y ); -bool OnRButtonUp( int x, int y ); -bool OnKeyDown( char *s ); - -void ZoomIn(); -void ZoomOut(); + void WindowForSpace(int &x, int &y, const float c[2]); + + void SpaceForWindow(float c[2], int x, int y); + + void GridForWindow(float c[2], int x, int y); + + qboolean DoesSelect(int x, int y, float c[2]); + + void PreparePaint(); + + bool OnRButtonDown(int x, int y); + + bool OnMouseMove(int x, int y); + + bool OnRButtonUp(int x, int y); + + bool OnKeyDown(char *s); + + void ZoomIn(); + + void ZoomOut(); }; #endif diff --git a/plugins/textool/ControlPointsManager.cpp b/plugins/textool/ControlPointsManager.cpp index 796cf9a5..8ddc77f0 100644 --- a/plugins/textool/ControlPointsManager.cpp +++ b/plugins/textool/ControlPointsManager.cpp @@ -28,198 +28,213 @@ #include "StdAfx.h" -void CControlPointsManagerBFace::Init( int iPts, CtrlPts_t *Pts, C2DView *p2DView, int TexSize[2], - _QERFaceData* pFaceData, OpenGLBinding *pQglTable ){ - ManagerState = Idle; - m_NumPoints = iPts; - m_pPts = Pts; - // store the initial config - memcpy( &m_RefPts, Pts, sizeof( CtrlPts_t ) ); - // init TM - memset( m_TM, 0, sizeof( float[2][3] ) ); - m_TM[0][0] = 1.0f; m_TM[1][1] = 1.0f; - m_bGotAnchor = false; - m_TransOffset[0] = 0.0f; m_TransOffset[1] = 0.0f; - m_TexSize[0] = TexSize[0]; - m_TexSize[1] = TexSize[1]; - m_pFaceData = pFaceData; +void CControlPointsManagerBFace::Init(int iPts, CtrlPts_t *Pts, C2DView *p2DView, int TexSize[2], + _QERFaceData *pFaceData, OpenGLBinding *pQglTable) +{ + ManagerState = Idle; + m_NumPoints = iPts; + m_pPts = Pts; + // store the initial config + memcpy(&m_RefPts, Pts, sizeof(CtrlPts_t)); + // init TM + memset(m_TM, 0, sizeof(float[2][3])); + m_TM[0][0] = 1.0f; + m_TM[1][1] = 1.0f; + m_bGotAnchor = false; + m_TransOffset[0] = 0.0f; + m_TransOffset[1] = 0.0f; + m_TexSize[0] = TexSize[0]; + m_TexSize[1] = TexSize[1]; + m_pFaceData = pFaceData; - CControlPointsManager::Init( p2DView, pQglTable ); + CControlPointsManager::Init(p2DView, pQglTable); } -bool CControlPointsManagerBFace::OnLButtonDown( int xPos, int yPos ){ - if ( ManagerState == Idle ) { - int i; +bool CControlPointsManagerBFace::OnLButtonDown(int xPos, int yPos) +{ + if (ManagerState == Idle) { + int i; - // scan the point list to see if we selected something - for ( i = 0; i < m_NumPoints; i++ ) - if ( m_p2DView->DoesSelect( xPos, yPos, m_pPts->data[i] ) ) { - m_iDragPoint = i; - ManagerState = Drag; - if ( m_bGotAnchor && i == m_iAnchorPoint ) { - // this means we selected the Anchor, so we'll translate - m_bGotAnchor = false; - } - // perhaps we won't use translation, but we can compute it anyway - ComputeTransOffset( i ); - if ( m_bGotAnchor ) { - // we have an Anchor and selected another point - m_Anchor[0] = m_pPts->data[m_iAnchorPoint][0]; - m_Anchor[1] = m_pPts->data[m_iAnchorPoint][1]; - } - } - // send a repaint message - g_pToolWnd->Redraw(); - return true; - } - return false; + // scan the point list to see if we selected something + for (i = 0; i < m_NumPoints; i++) { + if (m_p2DView->DoesSelect(xPos, yPos, m_pPts->data[i])) { + m_iDragPoint = i; + ManagerState = Drag; + if (m_bGotAnchor && i == m_iAnchorPoint) { + // this means we selected the Anchor, so we'll translate + m_bGotAnchor = false; + } + // perhaps we won't use translation, but we can compute it anyway + ComputeTransOffset(i); + if (m_bGotAnchor) { + // we have an Anchor and selected another point + m_Anchor[0] = m_pPts->data[m_iAnchorPoint][0]; + m_Anchor[1] = m_pPts->data[m_iAnchorPoint][1]; + } + } + } + // send a repaint message + g_pToolWnd->Redraw(); + return true; + } + return false; } -bool CControlPointsManagerBFace::OnMouseMove( int xPos, int yPos ){ - if ( ManagerState == Drag ) { - if ( m_bGotAnchor ) { - // there's an anchor, we are rotating the shape - // we need to work in XY space for orthonormality - float Pt[2]; - vec3_t V1,V2; - vec3_t cross; - float c,s; - // used in XY space - float XYTM[2][3]; - float XYRefAnchor[2]; - float XYAnchor[2]; - m_p2DView->GridForWindow( Pt, xPos, yPos ); - V2[0] = Pt[0] - m_Anchor[0]; - V2[1] = Pt[1] - m_Anchor[1]; - V2[2] = 0.0f; - V1[0] = m_RefPts.data[m_iDragPoint][0] - m_RefPts.data[m_iAnchorPoint][0]; - V1[1] = m_RefPts.data[m_iDragPoint][1] - m_RefPts.data[m_iAnchorPoint][1]; - V1[2] = 0.0f; - // compute transformation from V1 to V2 - // we need to work in XY orthonormal space - XYSpaceForSTSpace( V1, V1 ); - XYSpaceForSTSpace( V2, V2 ); - VectorNormalize( V2, V2 ); - VectorNormalize( V1, V1 ); - c = DotProduct( V1, V2 ); - CrossProduct( V1, V2, cross ); - s = VectorLength( cross ); - // we compute the transformation matrix in XY space - // reference position of the Anchor in XY space - XYSpaceForSTSpace( XYRefAnchor, m_RefPts.data[m_iAnchorPoint] ); - // current position of the Anchor in XY space - XYSpaceForSTSpace( XYAnchor, m_Anchor ); - // compute transformation matrix - XYTM[0][0] = c; XYTM[1][1] = c; - if ( cross[2] > 0 ) { - s *= -1.0f; - } - XYTM[0][1] = s; XYTM[1][0] = -s; - XYTM[0][2] = -c * XYRefAnchor[0] - s * XYRefAnchor[1] + XYAnchor[0]; - XYTM[1][2] = s * XYRefAnchor[0] - c * XYRefAnchor[1] + XYAnchor[1]; - // express this transformation matrix in ST space - m_TM[0][0] = XYTM[0][0]; - m_TM[1][0] = XYTM[1][0] * (float)m_TexSize[0] / (float)m_TexSize[1]; - m_TM[0][1] = XYTM[0][1] * (float)m_TexSize[1] / (float)m_TexSize[0]; - m_TM[1][1] = XYTM[1][1]; - m_TM[0][2] = XYTM[0][2] / (float)m_TexSize[0]; - m_TM[1][2] = XYTM[1][2] / (float)m_TexSize[1]; - // update all points - UpdateCtrlPts(); - } - else - { - // no Anchor point is defined, we translate all points - m_p2DView->GridForWindow( m_pPts->data[m_iDragPoint], xPos, yPos ); - m_TM[0][2] = m_pPts->data[m_iDragPoint][0] + m_TransOffset[0]; - m_TM[1][2] = m_pPts->data[m_iDragPoint][1] + m_TransOffset[1]; - // update all points - UpdateCtrlPts(); - } - // send a repaint message - g_pToolWnd->Redraw(); - return true; - } +bool CControlPointsManagerBFace::OnMouseMove(int xPos, int yPos) +{ + if (ManagerState == Drag) { + if (m_bGotAnchor) { + // there's an anchor, we are rotating the shape + // we need to work in XY space for orthonormality + float Pt[2]; + vec3_t V1, V2; + vec3_t cross; + float c, s; + // used in XY space + float XYTM[2][3]; + float XYRefAnchor[2]; + float XYAnchor[2]; + m_p2DView->GridForWindow(Pt, xPos, yPos); + V2[0] = Pt[0] - m_Anchor[0]; + V2[1] = Pt[1] - m_Anchor[1]; + V2[2] = 0.0f; + V1[0] = m_RefPts.data[m_iDragPoint][0] - m_RefPts.data[m_iAnchorPoint][0]; + V1[1] = m_RefPts.data[m_iDragPoint][1] - m_RefPts.data[m_iAnchorPoint][1]; + V1[2] = 0.0f; + // compute transformation from V1 to V2 + // we need to work in XY orthonormal space + XYSpaceForSTSpace(V1, V1); + XYSpaceForSTSpace(V2, V2); + VectorNormalize(V2, V2); + VectorNormalize(V1, V1); + c = DotProduct(V1, V2); + CrossProduct(V1, V2, cross); + s = VectorLength(cross); + // we compute the transformation matrix in XY space + // reference position of the Anchor in XY space + XYSpaceForSTSpace(XYRefAnchor, m_RefPts.data[m_iAnchorPoint]); + // current position of the Anchor in XY space + XYSpaceForSTSpace(XYAnchor, m_Anchor); + // compute transformation matrix + XYTM[0][0] = c; + XYTM[1][1] = c; + if (cross[2] > 0) { + s *= -1.0f; + } + XYTM[0][1] = s; + XYTM[1][0] = -s; + XYTM[0][2] = -c * XYRefAnchor[0] - s * XYRefAnchor[1] + XYAnchor[0]; + XYTM[1][2] = s * XYRefAnchor[0] - c * XYRefAnchor[1] + XYAnchor[1]; + // express this transformation matrix in ST space + m_TM[0][0] = XYTM[0][0]; + m_TM[1][0] = XYTM[1][0] * (float) m_TexSize[0] / (float) m_TexSize[1]; + m_TM[0][1] = XYTM[0][1] * (float) m_TexSize[1] / (float) m_TexSize[0]; + m_TM[1][1] = XYTM[1][1]; + m_TM[0][2] = XYTM[0][2] / (float) m_TexSize[0]; + m_TM[1][2] = XYTM[1][2] / (float) m_TexSize[1]; + // update all points + UpdateCtrlPts(); + } else { + // no Anchor point is defined, we translate all points + m_p2DView->GridForWindow(m_pPts->data[m_iDragPoint], xPos, yPos); + m_TM[0][2] = m_pPts->data[m_iDragPoint][0] + m_TransOffset[0]; + m_TM[1][2] = m_pPts->data[m_iDragPoint][1] + m_TransOffset[1]; + // update all points + UpdateCtrlPts(); + } + // send a repaint message + g_pToolWnd->Redraw(); + return true; + } - return false; + return false; } -bool CControlPointsManagerBFace::OnLButtonUp( int x, int y ){ - if ( ManagerState == Drag ) { - // this button is gonna become our Anchor - m_bGotAnchor = true; - m_iAnchorPoint = m_iDragPoint; - // let's get out of Drag mode - ManagerState = Idle; - // send a repaint message - g_pToolWnd->Redraw(); - return true; - } - return false; +bool CControlPointsManagerBFace::OnLButtonUp(int x, int y) +{ + if (ManagerState == Drag) { + // this button is gonna become our Anchor + m_bGotAnchor = true; + m_iAnchorPoint = m_iDragPoint; + // let's get out of Drag mode + ManagerState = Idle; + // send a repaint message + g_pToolWnd->Redraw(); + return true; + } + return false; } -void CControlPointsManagerBFace::render(){ - int i; +void CControlPointsManagerBFace::render() +{ + int i; - m_pQglTable->m_pfn_qglColor3f( 0, 1, 0 ); - m_pQglTable->m_pfn_qglPointSize( 6 ); - m_pQglTable->m_pfn_qglBegin( GL_POINTS ); - for ( i = 0; i < m_NumPoints; i++ ) - { - if ( ManagerState == Drag && i == m_iDragPoint ) { - m_pQglTable->m_pfn_qglColor3f( 1, 0, 0 ); - } - else if ( m_bGotAnchor && i == m_iAnchorPoint ) { - m_pQglTable->m_pfn_qglColor3f( 0, 0, 1 ); - } - m_pQglTable->m_pfn_qglVertex2f( m_pPts->data[i][0], m_pPts->data[i][1] ); - m_pQglTable->m_pfn_qglColor3f( 0, 1, 0 ); - } - m_pQglTable->m_pfn_qglEnd(); + m_pQglTable->m_pfn_qglColor3f(0, 1, 0); + m_pQglTable->m_pfn_qglPointSize(6); + m_pQglTable->m_pfn_qglBegin(GL_POINTS); + for (i = 0; i < m_NumPoints; i++) { + if (ManagerState == Drag && i == m_iDragPoint) { + m_pQglTable->m_pfn_qglColor3f(1, 0, 0); + } else if (m_bGotAnchor && i == m_iAnchorPoint) { + m_pQglTable->m_pfn_qglColor3f(0, 0, 1); + } + m_pQglTable->m_pfn_qglVertex2f(m_pPts->data[i][0], m_pPts->data[i][1]); + m_pQglTable->m_pfn_qglColor3f(0, 1, 0); + } + m_pQglTable->m_pfn_qglEnd(); } -void CControlPointsManagerBFace::UpdateCtrlPts(){ - int i; +void CControlPointsManagerBFace::UpdateCtrlPts() +{ + int i; - // update all points - for ( i = 0; i < m_NumPoints; i++ ) - { - m_pPts->data[i][0] = m_RefPts.data[i][0] * m_TM[0][0] + m_RefPts.data[i][1] * m_TM[0][1] + m_TM[0][2]; - m_pPts->data[i][1] = m_RefPts.data[i][0] * m_TM[1][0] + m_RefPts.data[i][1] * m_TM[1][1] + m_TM[1][2]; - } + // update all points + for (i = 0; i < m_NumPoints; i++) { + m_pPts->data[i][0] = m_RefPts.data[i][0] * m_TM[0][0] + m_RefPts.data[i][1] * m_TM[0][1] + m_TM[0][2]; + m_pPts->data[i][1] = m_RefPts.data[i][0] * m_TM[1][0] + m_RefPts.data[i][1] * m_TM[1][1] + m_TM[1][2]; + } - if ( g_bPrefsUpdateCameraView ) { - Commit(); - // tell Radiant to update - // NOTE: little speed optimisation, disable window updates, and only update camera view - g_FuncTable.m_pfnSetScreenUpdate( false ); - g_SelectedFaceTable.m_pfnSetFaceInfo( 0, m_pFaceData ); - g_FuncTable.m_pfnSetScreenUpdate( true ); - g_FuncTable.m_pfnSysUpdateWindows( W_CAMERA ); - } + if (g_bPrefsUpdateCameraView) { + Commit(); + // tell Radiant to update + // NOTE: little speed optimisation, disable window updates, and only update camera view + g_FuncTable.m_pfnSetScreenUpdate(false); + g_SelectedFaceTable.m_pfnSetFaceInfo(0, m_pFaceData); + g_FuncTable.m_pfnSetScreenUpdate(true); + g_FuncTable.m_pfnSysUpdateWindows(W_CAMERA); + } } //++timo FIXME: we are using a global for the reference data, use a m_pCancelFaceData instead -void CControlPointsManagerBFace::Commit(){ - brushprimit_texdef_t aux; - aux.coords[0][0] = m_TM[0][0] * g_CancelFaceData.brushprimit_texdef.coords[0][0] + m_TM[0][1] * g_CancelFaceData.brushprimit_texdef.coords[1][0]; - aux.coords[0][1] = m_TM[0][0] * g_CancelFaceData.brushprimit_texdef.coords[0][1] + m_TM[0][1] * g_CancelFaceData.brushprimit_texdef.coords[1][1]; - aux.coords[0][2] = m_TM[0][0] * g_CancelFaceData.brushprimit_texdef.coords[0][2] + m_TM[0][1] * g_CancelFaceData.brushprimit_texdef.coords[1][2] + m_TM[0][2]; - aux.coords[1][0] = m_TM[1][0] * g_CancelFaceData.brushprimit_texdef.coords[0][0] + m_TM[1][1] * g_CancelFaceData.brushprimit_texdef.coords[1][0]; - aux.coords[1][1] = m_TM[1][0] * g_CancelFaceData.brushprimit_texdef.coords[0][1] + m_TM[1][1] * g_CancelFaceData.brushprimit_texdef.coords[1][1]; - aux.coords[1][2] = m_TM[1][0] * g_CancelFaceData.brushprimit_texdef.coords[0][2] + m_TM[1][1] * g_CancelFaceData.brushprimit_texdef.coords[1][2] + m_TM[1][2]; - memcpy( &m_pFaceData->brushprimit_texdef, &aux, sizeof( brushprimit_texdef_t ) ); +void CControlPointsManagerBFace::Commit() +{ + brushprimit_texdef_t aux; + aux.coords[0][0] = m_TM[0][0] * g_CancelFaceData.brushprimit_texdef.coords[0][0] + + m_TM[0][1] * g_CancelFaceData.brushprimit_texdef.coords[1][0]; + aux.coords[0][1] = m_TM[0][0] * g_CancelFaceData.brushprimit_texdef.coords[0][1] + + m_TM[0][1] * g_CancelFaceData.brushprimit_texdef.coords[1][1]; + aux.coords[0][2] = m_TM[0][0] * g_CancelFaceData.brushprimit_texdef.coords[0][2] + + m_TM[0][1] * g_CancelFaceData.brushprimit_texdef.coords[1][2] + m_TM[0][2]; + aux.coords[1][0] = m_TM[1][0] * g_CancelFaceData.brushprimit_texdef.coords[0][0] + + m_TM[1][1] * g_CancelFaceData.brushprimit_texdef.coords[1][0]; + aux.coords[1][1] = m_TM[1][0] * g_CancelFaceData.brushprimit_texdef.coords[0][1] + + m_TM[1][1] * g_CancelFaceData.brushprimit_texdef.coords[1][1]; + aux.coords[1][2] = m_TM[1][0] * g_CancelFaceData.brushprimit_texdef.coords[0][2] + + m_TM[1][1] * g_CancelFaceData.brushprimit_texdef.coords[1][2] + m_TM[1][2]; + memcpy(&m_pFaceData->brushprimit_texdef, &aux, sizeof(brushprimit_texdef_t)); } -void CControlPointsManagerBFace::ComputeTransOffset( int i ){ - // compute the translation offset used to counteract rotation - m_TransOffset[0] = -m_TM[0][0] * m_RefPts.data[i][0] - m_TM[0][1] * m_RefPts.data[i][1]; - m_TransOffset[1] = -m_TM[1][0] * m_RefPts.data[i][0] - m_TM[1][1] * m_RefPts.data[i][1]; +void CControlPointsManagerBFace::ComputeTransOffset(int i) +{ + // compute the translation offset used to counteract rotation + m_TransOffset[0] = -m_TM[0][0] * m_RefPts.data[i][0] - m_TM[0][1] * m_RefPts.data[i][1]; + m_TransOffset[1] = -m_TM[1][0] * m_RefPts.data[i][0] - m_TM[1][1] * m_RefPts.data[i][1]; } -void CControlPointsManagerBFace::XYSpaceForSTSpace( float xy[2], const float st[2] ){ - xy[0] = st[0] * (float)m_TexSize[0]; - xy[1] = st[1] * (float)m_TexSize[1]; +void CControlPointsManagerBFace::XYSpaceForSTSpace(float xy[2], const float st[2]) +{ + xy[0] = st[0] * (float) m_TexSize[0]; + xy[1] = st[1] * (float) m_TexSize[1]; } /* @@ -228,81 +243,90 @@ void CControlPointsManagerBFace::XYSpaceForSTSpace( float xy[2], const float st[ ====================================================================== */ -void CControlPointsManagerPatch::Init( patchMesh_t* pWorkPatch, C2DView *p2DView, OpenGLBinding *pQglTable, patchMesh_t* pPatch ){ - CControlPointsManager::Init( p2DView, pQglTable ); - m_pPatch = pPatch; - m_pWorkPatch = pWorkPatch; +void CControlPointsManagerPatch::Init(patchMesh_t *pWorkPatch, C2DView *p2DView, OpenGLBinding *pQglTable, + patchMesh_t *pPatch) +{ + CControlPointsManager::Init(p2DView, pQglTable); + m_pPatch = pPatch; + m_pWorkPatch = pWorkPatch; } -bool CControlPointsManagerPatch::OnLButtonDown( int xPos, int yPos ){ - if ( ManagerState == Idle ) { - int i,j; +bool CControlPointsManagerPatch::OnLButtonDown(int xPos, int yPos) +{ + if (ManagerState == Idle) { + int i, j; - // scan the point list to see if we selected something - for ( i = 0; i < m_pPatch->width; i++ ) - for ( j = 0; j < m_pPatch->height; j++ ) - if ( m_p2DView->DoesSelect( xPos, yPos, m_pWorkPatch->ctrl[i][j].st ) ) { - m_iDragPoint[0] = i; - m_iDragPoint[1] = j; - ManagerState = Drag; - } - // send a repaint message - g_pToolWnd->Redraw(); - return true; - } - return false; + // scan the point list to see if we selected something + for (i = 0; i < m_pPatch->width; i++) { + for (j = 0; j < m_pPatch->height; j++) { + if (m_p2DView->DoesSelect(xPos, yPos, m_pWorkPatch->ctrl[i][j].st)) { + m_iDragPoint[0] = i; + m_iDragPoint[1] = j; + ManagerState = Drag; + } + } + } + // send a repaint message + g_pToolWnd->Redraw(); + return true; + } + return false; } -bool CControlPointsManagerPatch::OnMouseMove( int xPos, int yPos ){ - if ( ManagerState == Drag ) { - m_p2DView->GridForWindow( m_pWorkPatch->ctrl[ m_iDragPoint[0] ][ m_iDragPoint[1] ].st, xPos, yPos ); - if ( g_bPrefsUpdateCameraView ) { - Commit(); - // ask to rebuild the patch display data - m_pPatch->bDirty = true; - // send a repaint to the camera window as well - g_FuncTable.m_pfnSysUpdateWindows( W_CAMERA ); - } - // send a repaint message - g_pToolWnd->Redraw(); - return true; - } - return false; +bool CControlPointsManagerPatch::OnMouseMove(int xPos, int yPos) +{ + if (ManagerState == Drag) { + m_p2DView->GridForWindow(m_pWorkPatch->ctrl[m_iDragPoint[0]][m_iDragPoint[1]].st, xPos, yPos); + if (g_bPrefsUpdateCameraView) { + Commit(); + // ask to rebuild the patch display data + m_pPatch->bDirty = true; + // send a repaint to the camera window as well + g_FuncTable.m_pfnSysUpdateWindows(W_CAMERA); + } + // send a repaint message + g_pToolWnd->Redraw(); + return true; + } + return false; } -bool CControlPointsManagerPatch::OnLButtonUp( int x, int y ){ - if ( ManagerState == Drag ) { - ManagerState = Idle; - // send a repaint message - g_pToolWnd->Redraw(); - } - return false; +bool CControlPointsManagerPatch::OnLButtonUp(int x, int y) +{ + if (ManagerState == Drag) { + ManagerState = Idle; + // send a repaint message + g_pToolWnd->Redraw(); + } + return false; } -void CControlPointsManagerPatch::render(){ - int i,j; +void CControlPointsManagerPatch::render() +{ + int i, j; - m_pQglTable->m_pfn_qglColor3f( 0, 1, 0 ); - m_pQglTable->m_pfn_qglPointSize( 6 ); - m_pQglTable->m_pfn_qglBegin( GL_POINTS ); - for ( i = 0; i < m_pPatch->width; i++ ) - for ( j = 0; j < m_pPatch->height; j++ ) - { - if ( ManagerState == Drag && i == m_iDragPoint[0] && j == m_iDragPoint[1] ) { - m_pQglTable->m_pfn_qglColor3f( 1, 0, 0 ); - } - m_pQglTable->m_pfn_qglVertex2f( m_pWorkPatch->ctrl[i][j].st[0], m_pWorkPatch->ctrl[i][j].st[1] ); - m_pQglTable->m_pfn_qglColor3f( 0, 1, 0 ); - } - m_pQglTable->m_pfn_qglEnd(); + m_pQglTable->m_pfn_qglColor3f(0, 1, 0); + m_pQglTable->m_pfn_qglPointSize(6); + m_pQglTable->m_pfn_qglBegin(GL_POINTS); + for (i = 0; i < m_pPatch->width; i++) { + for (j = 0; j < m_pPatch->height; j++) { + if (ManagerState == Drag && i == m_iDragPoint[0] && j == m_iDragPoint[1]) { + m_pQglTable->m_pfn_qglColor3f(1, 0, 0); + } + m_pQglTable->m_pfn_qglVertex2f(m_pWorkPatch->ctrl[i][j].st[0], m_pWorkPatch->ctrl[i][j].st[1]); + m_pQglTable->m_pfn_qglColor3f(0, 1, 0); + } + } + m_pQglTable->m_pfn_qglEnd(); } -void CControlPointsManagerPatch::Commit(){ - int i,j; - for ( i = 0; i < m_pPatch->width; i++ ) - for ( j = 0; j < m_pPatch->height; j++ ) - { - m_pPatch->ctrl[i][j].st[0] = m_pWorkPatch->ctrl[i][j].st[0]; - m_pPatch->ctrl[i][j].st[1] = m_pWorkPatch->ctrl[i][j].st[1]; - } +void CControlPointsManagerPatch::Commit() +{ + int i, j; + for (i = 0; i < m_pPatch->width; i++) { + for (j = 0; j < m_pPatch->height; j++) { + m_pPatch->ctrl[i][j].st[0] = m_pWorkPatch->ctrl[i][j].st[0]; + m_pPatch->ctrl[i][j].st[1] = m_pWorkPatch->ctrl[i][j].st[1]; + } + } } diff --git a/plugins/textool/ControlPointsManager.h b/plugins/textool/ControlPointsManager.h index 7ade7c41..b4f1cbd7 100644 --- a/plugins/textool/ControlPointsManager.h +++ b/plugins/textool/ControlPointsManager.h @@ -37,97 +37,125 @@ #ifndef _CONTROLPOINTSMANAGER_H_ #define _CONTROLPOINTSMANAGER_H_ -class CControlPointsManager -{ +class CControlPointsManager { protected: // used by Render -OpenGLBinding *m_pQglTable; -C2DView *m_p2DView; + OpenGLBinding *m_pQglTable; + C2DView *m_p2DView; public: -CControlPointsManager() { m_pQglTable = NULL; m_p2DView = NULL; } -virtual ~CControlPointsManager() { } -void Init( C2DView *p2DView, OpenGLBinding *pQglTable ) { m_pQglTable = pQglTable; m_p2DView = p2DView; } + CControlPointsManager() + { + m_pQglTable = NULL; + m_p2DView = NULL; + } -virtual bool OnLButtonDown( int x, int y ) = 0; -virtual bool OnMouseMove( int x, int y ) = 0; -virtual bool OnLButtonUp( int x, int y ) = 0; + virtual ~CControlPointsManager() + {} -virtual void render() = 0; -virtual void Commit() = 0; + void Init(C2DView *p2DView, OpenGLBinding *pQglTable) + { + m_pQglTable = pQglTable; + m_p2DView = p2DView; + } + + virtual bool OnLButtonDown(int x, int y) = 0; + + virtual bool OnMouseMove(int x, int y) = 0; + + virtual bool OnLButtonUp(int x, int y) = 0; + + virtual void render() = 0; + + virtual void Commit() = 0; }; // brush face manager -class CControlPointsManagerBFace : public CControlPointsManager -{ -enum EManagerState { Idle, Drag } ManagerState; -int m_NumPoints; +class CControlPointsManagerBFace : public CControlPointsManager { + enum EManagerState { Idle, Drag } ManagerState; + int m_NumPoints; // initial geometry -CtrlPts_t m_RefPts; + CtrlPts_t m_RefPts; // current geometry -CtrlPts_t *m_pPts; + CtrlPts_t *m_pPts; // transform matrix ( 2DView is Window <-> ST ) -float m_TM[2][3]; + float m_TM[2][3]; // texture size for ST <-> XY -int m_TexSize[2]; + int m_TexSize[2]; // used when translating -float m_TransOffset[2]; + float m_TransOffset[2]; // dragged point index -int m_iDragPoint; + int m_iDragPoint; // do we have an anchor ? -bool m_bGotAnchor; + bool m_bGotAnchor; // anchor point index -int m_iAnchorPoint; + int m_iAnchorPoint; // coordinates of Anchor -float m_Anchor[2]; + float m_Anchor[2]; // used for commit -_QERFaceData *m_pFaceData; + _QERFaceData *m_pFaceData; public: // construction / init ------------------------------------------------- -CControlPointsManagerBFace() { ManagerState = Idle; } -virtual ~CControlPointsManagerBFace() { } + CControlPointsManagerBFace() + { ManagerState = Idle; } + + virtual ~CControlPointsManagerBFace() + {} + // NOTE: pQglTable is sent to CControlPointsManager::Init -void Init( int iPts, CtrlPts_t * Pts, C2DView * p2DView, int TexSize[2], _QERFaceData * pFaceData, OpenGLBinding * pQglTable ); + void + Init(int iPts, CtrlPts_t *Pts, C2DView *p2DView, int TexSize[2], _QERFaceData *pFaceData, OpenGLBinding *pQglTable); // CControlPointsManager interface ------------------------------------- -virtual bool OnLButtonDown( int x, int y ); -virtual bool OnMouseMove( int x, int y ); -virtual bool OnLButtonUp( int x, int y ); + virtual bool OnLButtonDown(int x, int y); + + virtual bool OnMouseMove(int x, int y); + + virtual bool OnLButtonUp(int x, int y); -virtual void render(); -virtual void Commit(); + virtual void render(); + + virtual void Commit(); private: // internal members -void UpdateCtrlPts(); -void ComputeTransOffset( int i ); -void XYSpaceForSTSpace( float xy[2], const float st[2] ); + void UpdateCtrlPts(); + + void ComputeTransOffset(int i); + + void XYSpaceForSTSpace(float xy[2], const float st[2]); }; // patch manager -class CControlPointsManagerPatch : public CControlPointsManager -{ -enum EManagerState { Idle, Drag } ManagerState; +class CControlPointsManagerPatch : public CControlPointsManager { + enum EManagerState { Idle, Drag } ManagerState; // reference data, used for commits -patchMesh_t* m_pPatch; + patchMesh_t *m_pPatch; // work patch, holds current data -patchMesh_t* m_pWorkPatch; -int m_iDragPoint[2]; + patchMesh_t *m_pWorkPatch; + int m_iDragPoint[2]; public: // construction / init ------------------------------------------------- -CControlPointsManagerPatch() { ManagerState = Idle; } -virtual ~CControlPointsManagerPatch() { } + CControlPointsManagerPatch() + { ManagerState = Idle; } + + virtual ~CControlPointsManagerPatch() + {} + // NOTE: pQglTable is sent to CControlPointsManager::Init -void Init( patchMesh_t* pWorkPatch, C2DView *p2DView, OpenGLBinding *pQglTable, patchMesh_t* pPatch ); + void Init(patchMesh_t *pWorkPatch, C2DView *p2DView, OpenGLBinding *pQglTable, patchMesh_t *pPatch); // CControlPointsManager interface ------------------------------------- -virtual bool OnLButtonDown( int x, int y ); -virtual bool OnMouseMove( int x, int y ); -virtual bool OnLButtonUp( int x, int y ); + virtual bool OnLButtonDown(int x, int y); + + virtual bool OnMouseMove(int x, int y); + + virtual bool OnLButtonUp(int x, int y); + + virtual void render(); -virtual void render(); -virtual void Commit(); + virtual void Commit(); }; #endif diff --git a/plugins/textool/Doc/TexTool.html b/plugins/textool/Doc/TexTool.html index 7e619092..62395235 100644 --- a/plugins/textool/Doc/TexTool.html +++ b/plugins/textool/Doc/TexTool.html @@ -1,121 +1,124 @@ - - - TexTool plugin for Q3Radiant - documentation + + + + + TexTool plugin for Q3Radiant - documentation +
-TexTool plugin for Q3Radiant
-
Introduction + TexTool plugin for Q3Radiant +
+Introduction

TexTool is a set of texture tools for Q3Radiant. It was designed to help fine-tuning texture placement -on brushes and patches.

+ on brushes and patches.

Warning:

The plugin needs brush primitives texture coordinates to operate. If this feature is not enabled in your project -settings you'll only be able to edit patches.

-
Basic use -

It's a "drag-n-drop control points" interface. Select a single face on a brush ( with shift+ctrl+left mouse clic), -or a patch, and do Plugins > Q3 Texture Tools > Go.... You can select points and move them... if you are editing -a brush face, you can rotate the shape by clicking on an anchor point first, then dragging another point.

+ settings you'll only be able to edit patches.

+
+Basic use +

It's a "drag-n-drop control points" interface. Select a single face on a brush ( with shift+ctrl+left + mouse clic), + or a patch, and do Plugins > Q3 Texture Tools > Go.... You can select points and move them... if you + are editing + a brush face, you can rotate the shape by clicking on an anchor point first, then dragging another point.

- - - -TexTool screenshot + TexTool screenshot

There are also a few misc keys to help you. You can -right clic + move the mouse to change the point of view -and use + right clic + move the mouse to change the point of view + and use -Inser and + Inser and -Suppr to zoom in/out. + Suppr to zoom in/out. - + - + -
+
-


+ +
Appendix: keyboard shortcuts

You can use the following keyboard shortcuts:

- - - - + - - + + usage
+ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - -
+ - KEY
-
+ KEY
+
- usage
-
ESC
-
cancel the changes and hide TexTool window
-
ESC
+
cancel the changes and hide TexTool window
+
RETURN
-
validate changes into the editor (also resets the view)
-
RETURN
+
validate changes into the editor (also resets the view)
+
INSERT
-
zoom in
-
INSERT
+
zoom in
+
SUPPR
-
zoom out
-
SUPPR
+
zoom out
+
RIGHT CLIC+MOVE
-
move the view
-
RIGHT CLIC+MOVE
+
move the view
+
LEFT CLIC+MOVE
-
grab a control point and move it
-
LEFT CLIC+MOVE
+
grab a control point and move it
+
RIGHT CLIC
-
drop down menu
-
RIGHT CLIC
+
drop down menu
+

+ + +

Feedback, enhancements bugs etc. to timo@qeradiant.com

diff --git a/plugins/textool/StdAfx.h b/plugins/textool/StdAfx.h index 2ebd1b01..f6c982f9 100644 --- a/plugins/textool/StdAfx.h +++ b/plugins/textool/StdAfx.h @@ -33,9 +33,9 @@ // Necessary for proper boolean type declaration #include "qertypes.h" -typedef void* HMODULE; -typedef void* LPVOID; -typedef char* LPCSTR; +typedef void *HMODULE; +typedef void *LPVOID; +typedef char *LPCSTR; #define MB_OK 0x00000000L #define MB_OKCANCEL 0x00000001L @@ -70,19 +70,18 @@ typedef char* LPCSTR; #define IDYES 6 #define IDNO 7 -typedef struct tagRECT -{ - long left; - long top; - long right; - long bottom; +typedef struct tagRECT { + long left; + long top; + long right; + long bottom; } RECT, *PRECT, *LPRECT; #endif // __linux__ // plugin // FIXME TTimo: drop this -extern "C" void Sys_Printf( char *text, ... ); +extern "C" void Sys_Printf(char *text, ...); #include "synapse.h" #include "iplugin.h" @@ -97,36 +96,51 @@ extern "C" void Sys_Printf( char *text, ... ); // the implementation of a IWindowListener interface to use with the native UI // TODO: move in it's own set of files? // NOTE: I'm not too sure about the bool flags being any use.. they are supposed to tell if we handle the event or not -class CWindowListener : public IWindowListener -{ -int refCount; +class CWindowListener : public IWindowListener { + int refCount; public: // Increment the number of references to this object -void IncRef() { refCount++; } + void IncRef() + { refCount++; } + // Decrement the reference count -void DecRef() { - if ( --refCount <= 0 ) { - delete this; - } -} + void DecRef() + { + if (--refCount <= 0) { + delete this; + } + } + // IWindowListener --------------------------------------- -bool OnLButtonDown( guint32 nFlags, double x, double y ); -bool OnMButtonDown( guint32 nFlags, double x, double y ) { return false; } -bool OnRButtonDown( guint32 nFlags, double x, double y ); -bool OnLButtonUp( guint32 nFlags, double x, double y ); -bool OnMButtonUp( guint32 nFlags, double x, double y ) { return false; } -bool OnRButtonUp( guint32 nFlags, double x, double y ); -bool OnMouseMove( guint32 nFlags, double x, double y ); -bool OnKeyPressed( char *s ); -bool Paint(); -void Close(); + bool OnLButtonDown(guint32 nFlags, double x, double y); + + bool OnMButtonDown(guint32 nFlags, double x, double y) + { return false; } + + bool OnRButtonDown(guint32 nFlags, double x, double y); + + bool OnLButtonUp(guint32 nFlags, double x, double y); + + bool OnMButtonUp(guint32 nFlags, double x, double y) + { return false; } + + bool OnRButtonUp(guint32 nFlags, double x, double y); + + bool OnMouseMove(guint32 nFlags, double x, double y); + + bool OnKeyPressed(char *s); + + bool Paint(); + + void Close(); }; #include "2DView.h" -typedef struct -{ - float data[MAX_POINTS_ON_WINDING][2]; + +typedef struct { + float data[MAX_POINTS_ON_WINDING][2]; } CtrlPts_t; + #include "ControlPointsManager.h" extern OpenGLBinding g_QglTable; @@ -142,17 +156,21 @@ extern _QERFaceData g_CancelFaceData; // call to validate the current changes into the editor extern void Textool_Validate(); + extern void Textool_Cancel(); -class CSynapseClientTexTool : public CSynapseClient -{ +class CSynapseClientTexTool : public CSynapseClient { public: // CSynapseClient API -bool RequestAPI( APIDescriptor_t *pAPI ); -const char* GetInfo(); + bool RequestAPI(APIDescriptor_t *pAPI); + + const char *GetInfo(); + + CSynapseClientTexTool() + {} -CSynapseClientTexTool() { } -virtual ~CSynapseClientTexTool() { } + virtual ~CSynapseClientTexTool() + {} }; extern IWindow *g_pToolWnd; diff --git a/plugins/textool/TexTool.cpp b/plugins/textool/TexTool.cpp index 7d5eba90..a346b074 100644 --- a/plugins/textool/TexTool.cpp +++ b/plugins/textool/TexTool.cpp @@ -28,135 +28,136 @@ #include "StdAfx.h" -static void dialog_button_callback( GtkWidget *widget, gpointer data ){ - int *loop, *ret; - - auto parent = widget.window(); - loop = (int*)g_object_get_data( G_OBJECT( parent ), "loop" ); - ret = (int*)g_object_get_data( G_OBJECT( parent ), "ret" ); - - *loop = 0; - *ret = gpointer_to_int( data ); -} - -static gint dialog_delete_callback( GtkWidget *widget, GdkEvent* event, gpointer data ){ - int *loop; - - gtk_widget_hide( widget ); - loop = (int*)g_object_get_data( G_OBJECT( widget ), "loop" ); - *loop = 0; - - return TRUE; -} - -int DoMessageBox( const char* lpText, const char* lpCaption, guint32 uType ){ - GtkWidget *w, *vbox, *hbox; - int mode = ( uType & MB_TYPEMASK ), ret, loop = 1; - - auto window = ui::Window( ui::window_type::TOP ); - window.connect( "delete_event", - G_CALLBACK( dialog_delete_callback ), NULL ); - window.connect( "destroy", - G_CALLBACK( gtk_widget_destroy ), NULL ); - gtk_window_set_title( window, lpCaption ); - gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); - g_object_set_data( G_OBJECT( window ), "loop", &loop ); - g_object_set_data( G_OBJECT( window ), "ret", &ret ); - gtk_widget_realize( window ); - - vbox = ui::VBox( FALSE, 10 ); - window.add(vbox); - vbox.show(); - - w = ui::Label( lpText ); - vbox.pack_start( w, FALSE, FALSE, 2 ); - gtk_label_set_justify( GTK_LABEL( w ), GTK_JUSTIFY_LEFT ); - w.show(); - - w = gtk_hseparator_new(); - vbox.pack_start( w, FALSE, FALSE, 2 ); - w.show(); - - hbox = ui::HBox( FALSE, 10 ); - vbox.pack_start( hbox, FALSE, FALSE, 2 ); - hbox.show(); - - if ( mode == MB_OK ) { - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDOK ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - ret = IDOK; - } - else if ( mode == MB_OKCANCEL ) { - w = ui::Button( "Ok" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDOK ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) ); - w.show(); - ret = IDCANCEL; - } - else if ( mode == MB_YESNOCANCEL ) { - w = ui::Button( "Yes" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDYES ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "No" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDNO ) ); - w.show(); - - w = ui::Button( "Cancel" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) ); - w.show(); - ret = IDCANCEL; - } - else /* if (mode == MB_YESNO) */ - { - w = ui::Button( "Yes" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDYES ) ); - gtk_widget_set_can_default( w, true ); - gtk_widget_grab_default( w ); - w.show(); - - w = ui::Button( "No" ); - hbox.pack_start( w, TRUE, TRUE, 0 ); - w.connect( "clicked", - G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( IDNO ) ); - w.show(); - ret = IDNO; - } - - window.show(); - gtk_grab_add( window ); - - while ( loop ) - gtk_main_iteration(); - - gtk_grab_remove( window ); - gtk_widget_destroy( window ); - - return ret; +static void dialog_button_callback(GtkWidget *widget, gpointer data) +{ + int *loop, *ret; + + auto parent = widget.window(); + loop = (int *) g_object_get_data(G_OBJECT(parent), "loop"); + ret = (int *) g_object_get_data(G_OBJECT(parent), "ret"); + + *loop = 0; + *ret = gpointer_to_int(data); +} + +static gint dialog_delete_callback(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + int *loop; + + gtk_widget_hide(widget); + loop = (int *) g_object_get_data(G_OBJECT(widget), "loop"); + *loop = 0; + + return TRUE; +} + +int DoMessageBox(const char *lpText, const char *lpCaption, guint32 uType) +{ + GtkWidget *w, *vbox, *hbox; + int mode = (uType & MB_TYPEMASK), ret, loop = 1; + + auto window = ui::Window(ui::window_type::TOP); + window.connect("delete_event", + G_CALLBACK(dialog_delete_callback), NULL); + window.connect("destroy", + G_CALLBACK(gtk_widget_destroy), NULL); + gtk_window_set_title(window, lpCaption); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); + g_object_set_data(G_OBJECT(window), "loop", &loop); + g_object_set_data(G_OBJECT(window), "ret", &ret); + gtk_widget_realize(window); + + vbox = ui::VBox(FALSE, 10); + window.add(vbox); + vbox.show(); + + w = ui::Label(lpText); + vbox.pack_start(w, FALSE, FALSE, 2); + gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT); + w.show(); + + w = gtk_hseparator_new(); + vbox.pack_start(w, FALSE, FALSE, 2); + w.show(); + + hbox = ui::HBox(FALSE, 10); + vbox.pack_start(hbox, FALSE, FALSE, 2); + hbox.show(); + + if (mode == MB_OK) { + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + ret = IDOK; + } else if (mode == MB_OKCANCEL) { + w = ui::Button("Ok"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDCANCEL)); + w.show(); + ret = IDCANCEL; + } else if (mode == MB_YESNOCANCEL) { + w = ui::Button("Yes"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDYES)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("No"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDNO)); + w.show(); + + w = ui::Button("Cancel"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDCANCEL)); + w.show(); + ret = IDCANCEL; + } else /* if (mode == MB_YESNO) */ + { + w = ui::Button("Yes"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDYES)); + gtk_widget_set_can_default(w, true); + gtk_widget_grab_default(w); + w.show(); + + w = ui::Button("No"); + hbox.pack_start(w, TRUE, TRUE, 0); + w.connect("clicked", + G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDNO)); + w.show(); + ret = IDNO; + } + + window.show(); + gtk_grab_add(window); + + while (loop) { + gtk_main_iteration(); + } + + gtk_grab_remove(window); + gtk_widget_destroy(window); + + return ret; } // Radiant function table @@ -185,7 +186,7 @@ _QERUITable g_UITable; // we use this one to commit / read with Radiant _QERFaceData g_SelectedFaceData; // g_pSelectedFaceWindings gets allocated with MAX_POINTS_ON_WINDING at plugin startup ( QERPlug_Init ) -winding_t *g_pSelectedFaceWinding = NULL; +winding_t *g_pSelectedFaceWinding = NULL; const float g_ViewportRatio = 1.2f; // usefull class to manage the 2D view C2DView g_2DView; @@ -207,7 +208,7 @@ bool g_bSurfaceTableInitDone = false; _QERAppSurfaceTable g_SurfaceTable; CControlPointsManagerPatch g_ControlPointsPatch; // data for texture work -patchMesh_t* g_pPatch; +patchMesh_t *g_pPatch; // we only use ctrl[][].st in this one patchMesh_t g_WorkPatch; // copy of initial g_pPatch for Cancel situation @@ -215,7 +216,7 @@ patchMesh_t g_CancelPatch; // --------------------------------------------- // holds the manager we are currently using -CControlPointsManager *g_pManager = NULL; +CControlPointsManager *g_pManager = NULL; // --------------------------------------------- // globals flags for user preferences @@ -230,670 +231,679 @@ bool g_bHelp = false; bool g_bClosing = false; const char *PLUGIN_ABOUT = "Texture Tools for Radiant\n\n" - "Gtk port by Leonardo Zide (leo@lokigames.com)\n" - "Original version by Timothee \"TTimo\" Besset (timo@qeradiant.com)"; + "Gtk port by Leonardo Zide (leo@lokigames.com)\n" + "Original version by Timothee \"TTimo\" Besset (timo@qeradiant.com)"; -extern "C" void* WINAPI QERPlug_GetFuncTable(){ - return &g_FuncTable; +extern "C" void *WINAPI + +QERPlug_GetFuncTable() +{ + return &g_FuncTable; } -const char* QERPlug_Init( void* hApp, void *pWidget ){ - int size; - GtkWidget* pMainWidget = static_cast( pWidget ); +const char *QERPlug_Init(void *hApp, void *pWidget) +{ + int size; + GtkWidget *pMainWidget = static_cast( pWidget ); - g_pMainWnd = pMainWidget; - memset( &g_FuncTable, 0, sizeof( _QERFuncTable_1 ) ); - g_FuncTable.m_nSize = sizeof( _QERFuncTable_1 ); - size = (int)( (winding_t *)0 )->points[MAX_POINTS_ON_WINDING]; - g_pSelectedFaceWinding = (winding_t *)malloc( size ); - memset( g_pSelectedFaceWinding, 0, size ); - return "Texture tools for Radiant"; + g_pMainWnd = pMainWidget; + memset(&g_FuncTable, 0, sizeof(_QERFuncTable_1)); + g_FuncTable.m_nSize = sizeof(_QERFuncTable_1); + size = (int) ((winding_t *) 0)->points[MAX_POINTS_ON_WINDING]; + g_pSelectedFaceWinding = (winding_t *) malloc(size); + memset(g_pSelectedFaceWinding, 0, size); + return "Texture tools for Radiant"; } -const char* QERPlug_GetName(){ - return (char*)PLUGIN_NAME; +const char *QERPlug_GetName() +{ + return (char *) PLUGIN_NAME; } -const char* QERPlug_GetCommandList(){ - return PLUGIN_COMMANDS; +const char *QERPlug_GetCommandList() +{ + return PLUGIN_COMMANDS; } -char *TranslateString( char *buf ){ - static char buf2[32768]; - int i, l; - char *out; +char *TranslateString(char *buf) +{ + static char buf2[32768]; + int i, l; + char *out; - l = strlen( buf ); - out = buf2; - for ( i = 0 ; i < l ; i++ ) - { - if ( buf[i] == '\n' ) { - *out++ = '\r'; - *out++ = '\n'; - } - else{ - *out++ = buf[i]; - } - } - *out++ = 0; + l = strlen(buf); + out = buf2; + for (i = 0; i < l; i++) { + if (buf[i] == '\n') { + *out++ = '\r'; + *out++ = '\n'; + } else { + *out++ = buf[i]; + } + } + *out++ = 0; - return buf2; + return buf2; } // called by InitTexView to fit the view against the bounding box of control points -void FitView( IWindow* hwndDlg, int TexSize[2] ){ - // apply a ratio to get the area we'll draw - g_2DView.m_Center[0] = 0.5f * ( g_2DView.m_Mins[0] + g_2DView.m_Maxs[0] ); - g_2DView.m_Center[1] = 0.5f * ( g_2DView.m_Mins[1] + g_2DView.m_Maxs[1] ); - g_2DView.m_Mins[0] = g_2DView.m_Center[0] + g_ViewportRatio * ( g_2DView.m_Mins[0] - g_2DView.m_Center[0] ); - g_2DView.m_Mins[1] = g_2DView.m_Center[1] + g_ViewportRatio * ( g_2DView.m_Mins[1] - g_2DView.m_Center[1] ); - g_2DView.m_Maxs[0] = g_2DView.m_Center[0] + g_ViewportRatio * ( g_2DView.m_Maxs[0] - g_2DView.m_Center[0] ); - g_2DView.m_Maxs[1] = g_2DView.m_Center[1] + g_ViewportRatio * ( g_2DView.m_Maxs[1] - g_2DView.m_Center[1] ); - - g_2DView.m_rect.left = 0; - g_2DView.m_rect.top = 0; - g_2DView.m_rect.bottom = hwndDlg->getHeight(); - g_2DView.m_rect.right = hwndDlg->getWidth(); - - // we need to draw this area, now compute a bigger area so the texture scale is the same along X and Y - // compute box shape in XY space, let's say X <-> S we'll get a ratio for Y: - if ( !g_bPatch ) { - g_SelectedFaceTable.m_pfnGetTextureSize( 0, TexSize ); - } - else - { - TexSize[0] = g_pPatch->d_texture->width; - TexSize[1] = g_pPatch->d_texture->height; - } - // we want a texture with the same X / Y ratio - // compute XY space / window size ratio - float SSize = (float)fabs( g_2DView.m_Maxs[0] - g_2DView.m_Mins[0] ); - float TSize = (float)fabs( g_2DView.m_Maxs[1] - g_2DView.m_Mins[1] ); - float XSize = TexSize[0] * SSize; - float YSize = TexSize[1] * TSize; - float RatioX = XSize / (float)abs( g_2DView.m_rect.left - g_2DView.m_rect.right ); - float RatioY = YSize / (float)abs( g_2DView.m_rect.top - g_2DView.m_rect.bottom ); - if ( RatioX > RatioY ) { - YSize = (float)abs( g_2DView.m_rect.top - g_2DView.m_rect.bottom ) * RatioX; - TSize = YSize / (float)TexSize[1]; - } - else - { - XSize = (float)abs( g_2DView.m_rect.left - g_2DView.m_rect.right ) * RatioY; - SSize = XSize / (float)TexSize[0]; - } - g_2DView.m_Mins[0] = g_2DView.m_Center[0] - 0.5f * SSize; - g_2DView.m_Maxs[0] = g_2DView.m_Center[0] + 0.5f * SSize; - g_2DView.m_Mins[1] = g_2DView.m_Center[1] - 0.5f * TSize; - g_2DView.m_Maxs[1] = g_2DView.m_Center[1] + 0.5f * TSize; +void FitView(IWindow *hwndDlg, int TexSize[2]) +{ + // apply a ratio to get the area we'll draw + g_2DView.m_Center[0] = 0.5f * (g_2DView.m_Mins[0] + g_2DView.m_Maxs[0]); + g_2DView.m_Center[1] = 0.5f * (g_2DView.m_Mins[1] + g_2DView.m_Maxs[1]); + g_2DView.m_Mins[0] = g_2DView.m_Center[0] + g_ViewportRatio * (g_2DView.m_Mins[0] - g_2DView.m_Center[0]); + g_2DView.m_Mins[1] = g_2DView.m_Center[1] + g_ViewportRatio * (g_2DView.m_Mins[1] - g_2DView.m_Center[1]); + g_2DView.m_Maxs[0] = g_2DView.m_Center[0] + g_ViewportRatio * (g_2DView.m_Maxs[0] - g_2DView.m_Center[0]); + g_2DView.m_Maxs[1] = g_2DView.m_Center[1] + g_ViewportRatio * (g_2DView.m_Maxs[1] - g_2DView.m_Center[1]); + + g_2DView.m_rect.left = 0; + g_2DView.m_rect.top = 0; + g_2DView.m_rect.bottom = hwndDlg->getHeight(); + g_2DView.m_rect.right = hwndDlg->getWidth(); + + // we need to draw this area, now compute a bigger area so the texture scale is the same along X and Y + // compute box shape in XY space, let's say X <-> S we'll get a ratio for Y: + if (!g_bPatch) { + g_SelectedFaceTable.m_pfnGetTextureSize(0, TexSize); + } else { + TexSize[0] = g_pPatch->d_texture->width; + TexSize[1] = g_pPatch->d_texture->height; + } + // we want a texture with the same X / Y ratio + // compute XY space / window size ratio + float SSize = (float) fabs(g_2DView.m_Maxs[0] - g_2DView.m_Mins[0]); + float TSize = (float) fabs(g_2DView.m_Maxs[1] - g_2DView.m_Mins[1]); + float XSize = TexSize[0] * SSize; + float YSize = TexSize[1] * TSize; + float RatioX = XSize / (float) abs(g_2DView.m_rect.left - g_2DView.m_rect.right); + float RatioY = YSize / (float) abs(g_2DView.m_rect.top - g_2DView.m_rect.bottom); + if (RatioX > RatioY) { + YSize = (float) abs(g_2DView.m_rect.top - g_2DView.m_rect.bottom) * RatioX; + TSize = YSize / (float) TexSize[1]; + } else { + XSize = (float) abs(g_2DView.m_rect.left - g_2DView.m_rect.right) * RatioY; + SSize = XSize / (float) TexSize[0]; + } + g_2DView.m_Mins[0] = g_2DView.m_Center[0] - 0.5f * SSize; + g_2DView.m_Maxs[0] = g_2DView.m_Center[0] + 0.5f * SSize; + g_2DView.m_Mins[1] = g_2DView.m_Center[1] - 0.5f * TSize; + g_2DView.m_Maxs[1] = g_2DView.m_Center[1] + 0.5f * TSize; } // call this one each time we need to re-init //++timo TODO: re-init objects state, g_2DView and g_ControlPointsManager -void InitTexView( IWindow* hwndDlg ){ - // size of the texture we are working on - int TexSize[2]; - g_bTexViewReady = false; - if ( g_SelectedFaceTable.m_pfnGetSelectedFaceCount() != 0 ) { - g_SelectedFaceTable.m_pfnGetFaceInfo( 0, &g_SelectedFaceData, g_pSelectedFaceWinding ); - g_bPatch = false; - int i; - // we have something selected - // setup: compute BBox for the winding ( in ST space ) - //++timo FIXME: move this in a C2DView member ? used as well for patches - g_2DView.m_Mins[0] = +9999.0f; g_2DView.m_Mins[1] = +9999.0f; - g_2DView.m_Maxs[0] = -9999.0f; g_2DView.m_Maxs[1] = -9999.0f; - for ( i = 0; i < g_pSelectedFaceWinding->numpoints; i++ ) - { - if ( g_pSelectedFaceWinding->points[i][3] < g_2DView.m_Mins[0] ) { - g_2DView.m_Mins[0] = g_pSelectedFaceWinding->points[i][3]; - } - if ( g_pSelectedFaceWinding->points[i][3] > g_2DView.m_Maxs[0] ) { - g_2DView.m_Maxs[0] = g_pSelectedFaceWinding->points[i][3]; - } - if ( g_pSelectedFaceWinding->points[i][4] < g_2DView.m_Mins[1] ) { - g_2DView.m_Mins[1] = g_pSelectedFaceWinding->points[i][4]; - } - if ( g_pSelectedFaceWinding->points[i][4] > g_2DView.m_Maxs[1] ) { - g_2DView.m_Maxs[1] = g_pSelectedFaceWinding->points[i][4]; - } - } - // NOTE: FitView will read and init TexSize - FitView( hwndDlg, TexSize ); - // now init the work tables - g_NumPoints = g_pSelectedFaceWinding->numpoints; - for ( i = 0; i < g_NumPoints; i++ ) - { - g_WorkWinding.data[i][0] = g_pSelectedFaceWinding->points[i][3]; - g_WorkWinding.data[i][1] = g_pSelectedFaceWinding->points[i][4]; - } - g_ControlPointsBFace.Init( g_NumPoints, &g_WorkWinding, &g_2DView, TexSize, &g_SelectedFaceData, &g_QglTable ); - // init snap-to-grid - float fTexStep[2]; - fTexStep[0] = 1.0f / float(TexSize[0]); - fTexStep[1] = 1.0f / float(TexSize[1]); - g_2DView.SetGrid( fTexStep[0], fTexStep[1] ); - g_pManager = &g_ControlPointsBFace; - // prepare the "Cancel" data - memcpy( &g_CancelFaceData, &g_SelectedFaceData, sizeof( _QERFaceData ) ); - // we are done - g_bTexViewReady = true; - } - else if ( g_SurfaceTable.m_pfnAnyPatchesSelected() ) { - g_pPatch = g_SurfaceTable.m_pfnGetSelectedPatch(); - g_bPatch = true; - int i,j; - // compute BBox for all patch points - g_2DView.m_Mins[0] = +9999.0f; g_2DView.m_Mins[1] = +9999.0f; - g_2DView.m_Maxs[0] = -9999.0f; g_2DView.m_Maxs[1] = -9999.0f; - for ( i = 0; i < g_pPatch->width; i++ ) - { - for ( j = 0; j < g_pPatch->height; j++ ) - { - if ( g_pPatch->ctrl[i][j].st[0] < g_2DView.m_Mins[0] ) { - g_2DView.m_Mins[0] = g_pPatch->ctrl[i][j].st[0]; - } - if ( g_pPatch->ctrl[i][j].st[0] > g_2DView.m_Maxs[0] ) { - g_2DView.m_Maxs[0] = g_pPatch->ctrl[i][j].st[0]; - } - if ( g_pPatch->ctrl[i][j].st[1] < g_2DView.m_Mins[1] ) { - g_2DView.m_Mins[1] = g_pPatch->ctrl[i][j].st[1]; - } - if ( g_pPatch->ctrl[i][j].st[1] > g_2DView.m_Maxs[1] ) { - g_2DView.m_Maxs[1] = g_pPatch->ctrl[i][j].st[1]; - } - } - } - FitView( hwndDlg, TexSize ); - // init the work tables - g_WorkPatch = *g_pPatch; - g_ControlPointsPatch.Init( &g_WorkPatch, &g_2DView, &g_QglTable, g_pPatch ); - // init snap-to-grid - float fTexStep[2]; - fTexStep[0] = 1.0f / float(TexSize[0]); - fTexStep[1] = 1.0f / float(TexSize[1]); - g_2DView.SetGrid( fTexStep[0], fTexStep[1] ); - g_pManager = &g_ControlPointsPatch; - // prepare the "cancel" data - g_CancelPatch = *g_pPatch; - // we are done - g_bTexViewReady = true; - } -} - -void Textool_Validate(){ - // validate current situation into the main view - g_pManager->Commit(); - // for a brush face we have an aditionnal step - if ( !g_bPatch ) { - // tell Radiant to update (will also send update windows messages ) - g_SelectedFaceTable.m_pfnSetFaceInfo( 0, &g_SelectedFaceData ); - } - else - { - // ask to rebuild the patch display data - g_pPatch->bDirty = true; - // send a repaint to the camera window as well - g_FuncTable.m_pfnSysUpdateWindows( W_CAMERA ); - } - // we'll need to update after that as well: - g_bTexViewReady = false; - // send a repaint message - g_pToolWnd->Redraw(); -} - -void Textool_Cancel(){ - if ( !g_bPatch ) { - // tell Radiant to update (will also send update windows messages ) - g_SelectedFaceTable.m_pfnSetFaceInfo( 0, &g_CancelFaceData ); - } - else - { - *g_pPatch = g_CancelPatch; - g_pPatch->bDirty = true; - g_FuncTable.m_pfnSysUpdateWindows( W_CAMERA ); - } - // do not call destroy, decref it - g_pToolWnd->DecRef(); - g_pToolWnd = NULL; -} - -static void DoExpose(){ - int i,j; - - g_2DView.PreparePaint(); - g_QglTable.m_pfn_qglColor3f( 1, 1, 1 ); - // draw the texture background - g_QglTable.m_pfn_qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - if ( !g_bPatch ) { - g_QglTable.m_pfn_qglBindTexture( GL_TEXTURE_2D, g_SelectedFaceTable.m_pfnGetTextureNumber( 0 ) ); - } - else - { - g_QglTable.m_pfn_qglBindTexture( GL_TEXTURE_2D, g_pPatch->d_texture->texture_number ); - } - - g_QglTable.m_pfn_qglEnable( GL_TEXTURE_2D ); - g_QglTable.m_pfn_qglBegin( GL_QUADS ); - g_QglTable.m_pfn_qglTexCoord2f( g_2DView.m_Mins[0], g_2DView.m_Mins[1] ); - g_QglTable.m_pfn_qglVertex2f( g_2DView.m_Mins[0], g_2DView.m_Mins[1] ); - g_QglTable.m_pfn_qglTexCoord2f( g_2DView.m_Maxs[0], g_2DView.m_Mins[1] ); - g_QglTable.m_pfn_qglVertex2f( g_2DView.m_Maxs[0], g_2DView.m_Mins[1] ); - g_QglTable.m_pfn_qglTexCoord2f( g_2DView.m_Maxs[0], g_2DView.m_Maxs[1] ); - g_QglTable.m_pfn_qglVertex2f( g_2DView.m_Maxs[0], g_2DView.m_Maxs[1] ); - g_QglTable.m_pfn_qglTexCoord2f( g_2DView.m_Mins[0], g_2DView.m_Maxs[1] ); - g_QglTable.m_pfn_qglVertex2f( g_2DView.m_Mins[0], g_2DView.m_Maxs[1] ); - g_QglTable.m_pfn_qglEnd(); - g_QglTable.m_pfn_qglDisable( GL_TEXTURE_2D ); - - if ( !g_bPatch ) { - g_QglTable.m_pfn_qglBegin( GL_LINE_LOOP ); - for ( i = 0; i < g_NumPoints; i++ ) - { - g_QglTable.m_pfn_qglVertex2f( g_WorkWinding.data[i][0], g_WorkWinding.data[i][1] ); - } - g_QglTable.m_pfn_qglEnd(); - } - else - { - g_QglTable.m_pfn_qglBegin( GL_LINES ); - for ( i = 0; i < g_pPatch->width; i++ ) - for ( j = 0; j < g_pPatch->height; j++ ) - { - if ( i < g_pPatch->width - 1 ) { - g_QglTable.m_pfn_qglVertex2f( g_WorkPatch.ctrl[i][j].st[0], g_WorkPatch.ctrl[i][j].st[1] ); - g_QglTable.m_pfn_qglVertex2f( g_WorkPatch.ctrl[i + 1][j].st[0], g_WorkPatch.ctrl[i + 1][j].st[1] ); - } - - if ( j < g_pPatch->height - 1 ) { - g_QglTable.m_pfn_qglVertex2f( g_WorkPatch.ctrl[i][j].st[0], g_WorkPatch.ctrl[i][j].st[1] ); - g_QglTable.m_pfn_qglVertex2f( g_WorkPatch.ctrl[i][j + 1].st[0], g_WorkPatch.ctrl[i][j + 1].st[1] ); - } - } - g_QglTable.m_pfn_qglEnd(); - } - - // let the control points manager render - g_pManager->render(); -} - -static bool CanProcess(){ - if ( !g_bTexViewReady && !g_bClosing ) { - InitTexView( g_pToolWnd ); - - if ( !g_bTexViewReady ) { - g_bClosing = true; - DoMessageBox( "You must have brush primitives activated in your project settings and\n" - "have a patch or a single face selected to use the TexTool plugin.\n" - "See plugins/TexToolHelp for documentation.", "TexTool plugin", MB_ICONERROR | MB_OK ); - // decref, this will destroy - g_pToolWnd->DecRef(); - g_pToolWnd = NULL; - return 0; - } - else{ - g_bClosing = false; - } - } - else if ( !g_bTexViewReady && g_bClosing ) { - return 0; - } - - return 1; +void InitTexView(IWindow *hwndDlg) +{ + // size of the texture we are working on + int TexSize[2]; + g_bTexViewReady = false; + if (g_SelectedFaceTable.m_pfnGetSelectedFaceCount() != 0) { + g_SelectedFaceTable.m_pfnGetFaceInfo(0, &g_SelectedFaceData, g_pSelectedFaceWinding); + g_bPatch = false; + int i; + // we have something selected + // setup: compute BBox for the winding ( in ST space ) + //++timo FIXME: move this in a C2DView member ? used as well for patches + g_2DView.m_Mins[0] = +9999.0f; + g_2DView.m_Mins[1] = +9999.0f; + g_2DView.m_Maxs[0] = -9999.0f; + g_2DView.m_Maxs[1] = -9999.0f; + for (i = 0; i < g_pSelectedFaceWinding->numpoints; i++) { + if (g_pSelectedFaceWinding->points[i][3] < g_2DView.m_Mins[0]) { + g_2DView.m_Mins[0] = g_pSelectedFaceWinding->points[i][3]; + } + if (g_pSelectedFaceWinding->points[i][3] > g_2DView.m_Maxs[0]) { + g_2DView.m_Maxs[0] = g_pSelectedFaceWinding->points[i][3]; + } + if (g_pSelectedFaceWinding->points[i][4] < g_2DView.m_Mins[1]) { + g_2DView.m_Mins[1] = g_pSelectedFaceWinding->points[i][4]; + } + if (g_pSelectedFaceWinding->points[i][4] > g_2DView.m_Maxs[1]) { + g_2DView.m_Maxs[1] = g_pSelectedFaceWinding->points[i][4]; + } + } + // NOTE: FitView will read and init TexSize + FitView(hwndDlg, TexSize); + // now init the work tables + g_NumPoints = g_pSelectedFaceWinding->numpoints; + for (i = 0; i < g_NumPoints; i++) { + g_WorkWinding.data[i][0] = g_pSelectedFaceWinding->points[i][3]; + g_WorkWinding.data[i][1] = g_pSelectedFaceWinding->points[i][4]; + } + g_ControlPointsBFace.Init(g_NumPoints, &g_WorkWinding, &g_2DView, TexSize, &g_SelectedFaceData, &g_QglTable); + // init snap-to-grid + float fTexStep[2]; + fTexStep[0] = 1.0f / float(TexSize[0]); + fTexStep[1] = 1.0f / float(TexSize[1]); + g_2DView.SetGrid(fTexStep[0], fTexStep[1]); + g_pManager = &g_ControlPointsBFace; + // prepare the "Cancel" data + memcpy(&g_CancelFaceData, &g_SelectedFaceData, sizeof(_QERFaceData)); + // we are done + g_bTexViewReady = true; + } else if (g_SurfaceTable.m_pfnAnyPatchesSelected()) { + g_pPatch = g_SurfaceTable.m_pfnGetSelectedPatch(); + g_bPatch = true; + int i, j; + // compute BBox for all patch points + g_2DView.m_Mins[0] = +9999.0f; + g_2DView.m_Mins[1] = +9999.0f; + g_2DView.m_Maxs[0] = -9999.0f; + g_2DView.m_Maxs[1] = -9999.0f; + for (i = 0; i < g_pPatch->width; i++) { + for (j = 0; j < g_pPatch->height; j++) { + if (g_pPatch->ctrl[i][j].st[0] < g_2DView.m_Mins[0]) { + g_2DView.m_Mins[0] = g_pPatch->ctrl[i][j].st[0]; + } + if (g_pPatch->ctrl[i][j].st[0] > g_2DView.m_Maxs[0]) { + g_2DView.m_Maxs[0] = g_pPatch->ctrl[i][j].st[0]; + } + if (g_pPatch->ctrl[i][j].st[1] < g_2DView.m_Mins[1]) { + g_2DView.m_Mins[1] = g_pPatch->ctrl[i][j].st[1]; + } + if (g_pPatch->ctrl[i][j].st[1] > g_2DView.m_Maxs[1]) { + g_2DView.m_Maxs[1] = g_pPatch->ctrl[i][j].st[1]; + } + } + } + FitView(hwndDlg, TexSize); + // init the work tables + g_WorkPatch = *g_pPatch; + g_ControlPointsPatch.Init(&g_WorkPatch, &g_2DView, &g_QglTable, g_pPatch); + // init snap-to-grid + float fTexStep[2]; + fTexStep[0] = 1.0f / float(TexSize[0]); + fTexStep[1] = 1.0f / float(TexSize[1]); + g_2DView.SetGrid(fTexStep[0], fTexStep[1]); + g_pManager = &g_ControlPointsPatch; + // prepare the "cancel" data + g_CancelPatch = *g_pPatch; + // we are done + g_bTexViewReady = true; + } +} + +void Textool_Validate() +{ + // validate current situation into the main view + g_pManager->Commit(); + // for a brush face we have an aditionnal step + if (!g_bPatch) { + // tell Radiant to update (will also send update windows messages ) + g_SelectedFaceTable.m_pfnSetFaceInfo(0, &g_SelectedFaceData); + } else { + // ask to rebuild the patch display data + g_pPatch->bDirty = true; + // send a repaint to the camera window as well + g_FuncTable.m_pfnSysUpdateWindows(W_CAMERA); + } + // we'll need to update after that as well: + g_bTexViewReady = false; + // send a repaint message + g_pToolWnd->Redraw(); +} + +void Textool_Cancel() +{ + if (!g_bPatch) { + // tell Radiant to update (will also send update windows messages ) + g_SelectedFaceTable.m_pfnSetFaceInfo(0, &g_CancelFaceData); + } else { + *g_pPatch = g_CancelPatch; + g_pPatch->bDirty = true; + g_FuncTable.m_pfnSysUpdateWindows(W_CAMERA); + } + // do not call destroy, decref it + g_pToolWnd->DecRef(); + g_pToolWnd = NULL; +} + +static void DoExpose() +{ + int i, j; + + g_2DView.PreparePaint(); + g_QglTable.m_pfn_qglColor3f(1, 1, 1); + // draw the texture background + g_QglTable.m_pfn_qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + if (!g_bPatch) { + g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, g_SelectedFaceTable.m_pfnGetTextureNumber(0)); + } else { + g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, g_pPatch->d_texture->texture_number); + } + + g_QglTable.m_pfn_qglEnable(GL_TEXTURE_2D); + g_QglTable.m_pfn_qglBegin(GL_QUADS); + g_QglTable.m_pfn_qglTexCoord2f(g_2DView.m_Mins[0], g_2DView.m_Mins[1]); + g_QglTable.m_pfn_qglVertex2f(g_2DView.m_Mins[0], g_2DView.m_Mins[1]); + g_QglTable.m_pfn_qglTexCoord2f(g_2DView.m_Maxs[0], g_2DView.m_Mins[1]); + g_QglTable.m_pfn_qglVertex2f(g_2DView.m_Maxs[0], g_2DView.m_Mins[1]); + g_QglTable.m_pfn_qglTexCoord2f(g_2DView.m_Maxs[0], g_2DView.m_Maxs[1]); + g_QglTable.m_pfn_qglVertex2f(g_2DView.m_Maxs[0], g_2DView.m_Maxs[1]); + g_QglTable.m_pfn_qglTexCoord2f(g_2DView.m_Mins[0], g_2DView.m_Maxs[1]); + g_QglTable.m_pfn_qglVertex2f(g_2DView.m_Mins[0], g_2DView.m_Maxs[1]); + g_QglTable.m_pfn_qglEnd(); + g_QglTable.m_pfn_qglDisable(GL_TEXTURE_2D); + + if (!g_bPatch) { + g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP); + for (i = 0; i < g_NumPoints; i++) { + g_QglTable.m_pfn_qglVertex2f(g_WorkWinding.data[i][0], g_WorkWinding.data[i][1]); + } + g_QglTable.m_pfn_qglEnd(); + } else { + g_QglTable.m_pfn_qglBegin(GL_LINES); + for (i = 0; i < g_pPatch->width; i++) { + for (j = 0; j < g_pPatch->height; j++) { + if (i < g_pPatch->width - 1) { + g_QglTable.m_pfn_qglVertex2f(g_WorkPatch.ctrl[i][j].st[0], g_WorkPatch.ctrl[i][j].st[1]); + g_QglTable.m_pfn_qglVertex2f(g_WorkPatch.ctrl[i + 1][j].st[0], g_WorkPatch.ctrl[i + 1][j].st[1]); + } + + if (j < g_pPatch->height - 1) { + g_QglTable.m_pfn_qglVertex2f(g_WorkPatch.ctrl[i][j].st[0], g_WorkPatch.ctrl[i][j].st[1]); + g_QglTable.m_pfn_qglVertex2f(g_WorkPatch.ctrl[i][j + 1].st[0], g_WorkPatch.ctrl[i][j + 1].st[1]); + } + } + } + g_QglTable.m_pfn_qglEnd(); + } + + // let the control points manager render + g_pManager->render(); +} + +static bool CanProcess() +{ + if (!g_bTexViewReady && !g_bClosing) { + InitTexView(g_pToolWnd); + + if (!g_bTexViewReady) { + g_bClosing = true; + DoMessageBox("You must have brush primitives activated in your project settings and\n" + "have a patch or a single face selected to use the TexTool plugin.\n" + "See plugins/TexToolHelp for documentation.", "TexTool plugin", MB_ICONERROR | MB_OK); + // decref, this will destroy + g_pToolWnd->DecRef(); + g_pToolWnd = NULL; + return 0; + } else { + g_bClosing = false; + } + } else if (!g_bTexViewReady && g_bClosing) { + return 0; + } + + return 1; } #if 0 static void button_press( GtkWidget *widget, GdkEventButton *event, gpointer data ){ - if ( CanProcess() ) { - switch ( event->button ) - { - case 1: - g_pManager->OnLButtonDown( event->x, event->y ); break; - case 3: - g_2DView.OnRButtonDown( event->x, event->y ); break; - } - } + if ( CanProcess() ) { + switch ( event->button ) + { + case 1: + g_pManager->OnLButtonDown( event->x, event->y ); break; + case 3: + g_2DView.OnRButtonDown( event->x, event->y ); break; + } + } } static void button_release( GtkWidget *widget, GdkEventButton *event, gpointer data ){ - if ( CanProcess() ) { - switch ( event->button ) - { - case 1: - g_pManager->OnLButtonUp( event->x, event->y ); break; - case 3: - g_2DView.OnRButtonUp( event->x, event->y ); break; - } - } + if ( CanProcess() ) { + switch ( event->button ) + { + case 1: + g_pManager->OnLButtonUp( event->x, event->y ); break; + case 3: + g_2DView.OnRButtonUp( event->x, event->y ); break; + } + } } static void motion( GtkWidget *widget, GdkEventMotion *event, gpointer data ){ - if ( CanProcess() ) { - if ( g_2DView.OnMouseMove( event->x, event->y ) ) { - return; - } + if ( CanProcess() ) { + if ( g_2DView.OnMouseMove( event->x, event->y ) ) { + return; + } - if ( g_pManager->OnMouseMove( event->x, event->y ) ) { - return; - } - } + if ( g_pManager->OnMouseMove( event->x, event->y ) ) { + return; + } + } } static gint expose( GtkWidget *widget, GdkEventExpose *event, gpointer data ){ - if ( event->count > 0 ) { - return TRUE; - } + if ( event->count > 0 ) { + return TRUE; + } - if ( !CanProcess() ) { - return TRUE; - } + if ( !CanProcess() ) { + return TRUE; + } - if ( g_bTexViewReady ) { - g_2DView.m_rect.bottom = widget->allocation.height; - g_2DView.m_rect.right = widget->allocation.width; + if ( g_bTexViewReady ) { + g_2DView.m_rect.bottom = widget->allocation.height; + g_2DView.m_rect.right = widget->allocation.width; - if ( !g_QglTable.m_pfn_glwidget_make_current( g_pToolWidget ) ) { - Sys_Printf( "TexTool: glMakeCurrent failed\n" ); - return TRUE; - } + if ( !g_QglTable.m_pfn_glwidget_make_current( g_pToolWidget ) ) { + Sys_Printf( "TexTool: glMakeCurrent failed\n" ); + return TRUE; + } - DoExpose(); + DoExpose(); - g_QglTable.m_pfn_glwidget_swap_buffers( g_pToolWidget ); - } + g_QglTable.m_pfn_glwidget_swap_buffers( g_pToolWidget ); + } - return TRUE; + return TRUE; } static gint keypress( GtkWidget* widget, GdkEventKey* event, gpointer data ){ - unsigned int code = gdk_keyval_to_upper( event->keyval ); + unsigned int code = gdk_keyval_to_upper( event->keyval ); - if ( code == GDK_Escape ) { - gtk_widget_destroy( g_pToolWnd ); - g_pToolWnd = NULL; - return TRUE; - } + if ( code == GDK_Escape ) { + gtk_widget_destroy( g_pToolWnd ); + g_pToolWnd = NULL; + return TRUE; + } - if ( CanProcess() ) { - if ( g_2DView.OnKeyDown( code ) ) { - return FALSE; - } + if ( CanProcess() ) { + if ( g_2DView.OnKeyDown( code ) ) { + return FALSE; + } - if ( code == GDK_Return ) { - Textool_Validate(); - return FALSE; - } - } + if ( code == GDK_Return ) { + Textool_Validate(); + return FALSE; + } + } - return TRUE; + return TRUE; } static gint close( GtkWidget *widget, GdkEvent* event, gpointer data ){ - gtk_widget_destroy( widget ); - g_pToolWnd = NULL; + gtk_widget_destroy( widget ); + g_pToolWnd = NULL; - return TRUE; + return TRUE; } static GtkWidget* CreateOpenGLWidget(){ - g_pToolWidget = g_QglTable.m_pfn_glwidget_new( FALSE, g_QglTable.m_pfn_GetQeglobalsGLWidget() ); + g_pToolWidget = g_QglTable.m_pfn_glwidget_new( FALSE, g_QglTable.m_pfn_GetQeglobalsGLWidget() ); - gtk_widget_set_events( g_pToolWidget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK | - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ); + gtk_widget_set_events( g_pToolWidget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ); - // Connect signal handlers - g_pToolWidget.connect( "expose_event", G_CALLBACK( expose ), NULL ); - g_pToolWidget.connect( "motion_notify_event", - G_CALLBACK( motion ), NULL ); - g_pToolWidget.connect( "button_press_event", - G_CALLBACK( button_press ), NULL ); - g_pToolWidget.connect( "button_release_event", - G_CALLBACK( button_release ), NULL ); + // Connect signal handlers + g_pToolWidget.connect( "expose_event", G_CALLBACK( expose ), NULL ); + g_pToolWidget.connect( "motion_notify_event", + G_CALLBACK( motion ), NULL ); + g_pToolWidget.connect( "button_press_event", + G_CALLBACK( button_press ), NULL ); + g_pToolWidget.connect( "button_release_event", + G_CALLBACK( button_release ), NULL ); - g_pToolWnd.connect( "delete_event", G_CALLBACK( close ), NULL ); - g_pToolWnd.connect( "key_press_event", - G_CALLBACK( keypress ), NULL ); + g_pToolWnd.connect( "delete_event", G_CALLBACK( close ), NULL ); + g_pToolWnd.connect( "key_press_event", + G_CALLBACK( keypress ), NULL ); - return g_pToolWidget; + return g_pToolWidget; } #endif #if 0 static void DoPaint(){ - if ( !CanProcess() ) { - return; - } - - if ( g_bTexViewReady ) { - g_2DView.m_rect.bottom = g_pToolWnd->getHeight(); - g_2DView.m_rect.right = g_pToolWnd->getWidth(); - - // set GL_PROJECTION - g_2DView.PreparePaint(); - // render the objects - // the master is not rendered the same way, draw over a unified texture background - g_2DView.TextureBackground( g_DrawObjects[0].pObject->getTextureNumber() ); - if ( g_nDrawObjects >= 1 ) { - int i; - for ( i = 1; i < g_nDrawObjects; i++ ) - { - // we use a first step to the GL_MODELVIEW for the master object - // GL_MODELVIEW will be altered in RenderAuxiliary too - g_DrawObjects[0].pObject->PrepareModelView( g_DrawObjects[i].pTopo ); - g_DrawObjects[i].pObject->RenderAuxiliary(); - } - } - // draw the polygon outline and control points - g_DrawObjects[0].pObject->PrepareModelView( NULL ); - g_DrawObjects[0].pObject->RenderUI(); - } + if ( !CanProcess() ) { + return; + } + + if ( g_bTexViewReady ) { + g_2DView.m_rect.bottom = g_pToolWnd->getHeight(); + g_2DView.m_rect.right = g_pToolWnd->getWidth(); + + // set GL_PROJECTION + g_2DView.PreparePaint(); + // render the objects + // the master is not rendered the same way, draw over a unified texture background + g_2DView.TextureBackground( g_DrawObjects[0].pObject->getTextureNumber() ); + if ( g_nDrawObjects >= 1 ) { + int i; + for ( i = 1; i < g_nDrawObjects; i++ ) + { + // we use a first step to the GL_MODELVIEW for the master object + // GL_MODELVIEW will be altered in RenderAuxiliary too + g_DrawObjects[0].pObject->PrepareModelView( g_DrawObjects[i].pTopo ); + g_DrawObjects[i].pObject->RenderAuxiliary(); + } + } + // draw the polygon outline and control points + g_DrawObjects[0].pObject->PrepareModelView( NULL ); + g_DrawObjects[0].pObject->RenderUI(); + } } #endif -bool CWindowListener::OnLButtonDown( guint32 nFlags, double x, double y ){ - if ( CanProcess() ) { - g_pManager->OnLButtonDown( (int)x, (int)y ); - return true; - } - return false; +bool CWindowListener::OnLButtonDown(guint32 nFlags, double x, double y) +{ + if (CanProcess()) { + g_pManager->OnLButtonDown((int) x, (int) y); + return true; + } + return false; } -bool CWindowListener::OnRButtonDown( guint32 nFlags, double x, double y ){ - if ( CanProcess() ) { - g_2DView.OnRButtonDown( (int)x, (int)y ); - return true; - } - return false; +bool CWindowListener::OnRButtonDown(guint32 nFlags, double x, double y) +{ + if (CanProcess()) { + g_2DView.OnRButtonDown((int) x, (int) y); + return true; + } + return false; } -bool CWindowListener::OnLButtonUp( guint32 nFlags, double x, double y ){ - if ( CanProcess() ) { - g_pManager->OnLButtonUp( (int)x, (int)y ); - return true; - } - return false; +bool CWindowListener::OnLButtonUp(guint32 nFlags, double x, double y) +{ + if (CanProcess()) { + g_pManager->OnLButtonUp((int) x, (int) y); + return true; + } + return false; } -bool CWindowListener::OnRButtonUp( guint32 nFlags, double x, double y ){ - if ( CanProcess() ) { - g_2DView.OnRButtonUp( (int)x, (int)y ); - return true; - } - return false; +bool CWindowListener::OnRButtonUp(guint32 nFlags, double x, double y) +{ + if (CanProcess()) { + g_2DView.OnRButtonUp((int) x, (int) y); + return true; + } + return false; } -bool CWindowListener::OnMouseMove( guint32 nFlags, double x, double y ){ - if ( CanProcess() ) { - if ( g_2DView.OnMouseMove( (int)x, (int)y ) ) { - return true; - } +bool CWindowListener::OnMouseMove(guint32 nFlags, double x, double y) +{ + if (CanProcess()) { + if (g_2DView.OnMouseMove((int) x, (int) y)) { + return true; + } - g_pManager->OnMouseMove( (int)x, (int)y ); - return true; - } - return false; + g_pManager->OnMouseMove((int) x, (int) y); + return true; + } + return false; } // the widget is closing -void CWindowListener::Close(){ - g_pToolWnd = NULL; -} - -bool CWindowListener::Paint(){ - if ( !CanProcess() ) { - return false; - } - - if ( g_bTexViewReady ) { - DoExpose(); - } - - return true; -} - -bool CWindowListener::OnKeyPressed( char *s ){ - if ( !strcmp( s,"Escape" ) ) { - Textool_Cancel(); - return TRUE; - } - if ( CanProcess() ) { - if ( g_2DView.OnKeyDown( s ) ) { - return TRUE; - } - - if ( !strcmp( s,"Return" ) ) { - Textool_Validate(); - return TRUE; - } - } - return FALSE; -} - -extern "C" void QERPlug_Dispatch( const char* p, vec3_t vMin, vec3_t vMax, bool bSingleBrush ){ - #if 0 - // if it's the first call, perhaps we need some additional init steps - if ( !g_bQglInitDone ) { - g_QglTable.m_nSize = sizeof( OpenGLBinding ); - if ( g_FuncTable.m_pfnRequestInterface( QERQglTable_GUID, static_cast( &g_QglTable ) ) ) { - g_bQglInitDone = true; - } - else - { - Sys_Printf( "TexTool plugin: OpenGLBinding interface request failed\n" ); - return; - } - } - - if ( !g_bSelectedFaceInitDone ) { - g_SelectedFaceTable.m_nSize = sizeof( _QERSelectedFaceTable ); - if ( g_FuncTable.m_pfnRequestInterface( QERSelectedFaceTable_GUID, - static_cast( &g_SelectedFaceTable ) ) ) { - g_bSelectedFaceInitDone = true; - } - else - { - Sys_Printf( "TexTool plugin: _QERSelectedFaceTable interface request failed\n" ); - return; - } - } - - if ( !g_bSurfaceTableInitDone ) { - g_SurfaceTable.m_nSize = sizeof( _QERAppSurfaceTable ); - if ( g_FuncTable.m_pfnRequestInterface( QERAppSurfaceTable_GUID, static_cast( &g_SurfaceTable ) ) ) { - g_bSurfaceTableInitDone = true; - } - else - { - Sys_Printf( "TexTool plugin: _QERAppSurfaceTable interface request failed\n" ); - return; - } - } - - if ( !g_bUITable ) { - g_UITable.m_nSize = sizeof( _QERUITable ); - if ( g_FuncTable.m_pfnRequestInterface( QERUI_GUID, static_cast( &g_UITable ) ) ) { - g_bUITable = true; - } - else - { - Sys_Printf( "TexTool plugin: _QERUITable interface request failed\n" ); - return; - } - } - #endif - - if ( !strcmp( p, "About..." ) ) { - DoMessageBox( PLUGIN_ABOUT, "About ...", MB_OK ); - } - else if ( !strcmp( p, "Go..." ) ) { - if ( !g_pToolWnd ) { - g_pToolWnd = g_UITable.m_pfnCreateGLWindow(); - g_pToolWnd->setSizeParm( 300,300 ); - g_pToolWnd->setName( "TexTool" ); - // g_Listener is a static class, we need to bump the refCount to avoid premature release problems - g_Listen.IncRef(); - // setListener will incRef on the listener too - g_pToolWnd->setListener( &g_Listen ); - if ( !g_pToolWnd->Show() ) { - DoMessageBox( "Error creating texture tools window!", "TexTool plugin", MB_ICONERROR | MB_OK ); - return; - } - } - - g_bTexViewReady = false; - g_bClosing = false; - } - else if ( !strcmp( p, "Help..." ) ) { - if ( !g_bHelp ) { - DoMessageBox( "Select a brush face (ctrl+shift+left mouse) or a patch, and hit Go...\n" - "See tutorials for more", "TexTool plugin", MB_OK ); - } - else{ - DoMessageBox( "Are you kidding me ?", "TexTool plugin", MB_OK ); - } - g_bHelp = true; - } +void CWindowListener::Close() +{ + g_pToolWnd = NULL; +} + +bool CWindowListener::Paint() +{ + if (!CanProcess()) { + return false; + } + + if (g_bTexViewReady) { + DoExpose(); + } + + return true; +} + +bool CWindowListener::OnKeyPressed(char *s) +{ + if (!strcmp(s, "Escape")) { + Textool_Cancel(); + return TRUE; + } + if (CanProcess()) { + if (g_2DView.OnKeyDown(s)) { + return TRUE; + } + + if (!strcmp(s, "Return")) { + Textool_Validate(); + return TRUE; + } + } + return FALSE; +} + +extern "C" void QERPlug_Dispatch(const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush) +{ +#if 0 + // if it's the first call, perhaps we need some additional init steps + if ( !g_bQglInitDone ) { + g_QglTable.m_nSize = sizeof( OpenGLBinding ); + if ( g_FuncTable.m_pfnRequestInterface( QERQglTable_GUID, static_cast( &g_QglTable ) ) ) { + g_bQglInitDone = true; + } + else + { + Sys_Printf( "TexTool plugin: OpenGLBinding interface request failed\n" ); + return; + } + } + + if ( !g_bSelectedFaceInitDone ) { + g_SelectedFaceTable.m_nSize = sizeof( _QERSelectedFaceTable ); + if ( g_FuncTable.m_pfnRequestInterface( QERSelectedFaceTable_GUID, + static_cast( &g_SelectedFaceTable ) ) ) { + g_bSelectedFaceInitDone = true; + } + else + { + Sys_Printf( "TexTool plugin: _QERSelectedFaceTable interface request failed\n" ); + return; + } + } + + if ( !g_bSurfaceTableInitDone ) { + g_SurfaceTable.m_nSize = sizeof( _QERAppSurfaceTable ); + if ( g_FuncTable.m_pfnRequestInterface( QERAppSurfaceTable_GUID, static_cast( &g_SurfaceTable ) ) ) { + g_bSurfaceTableInitDone = true; + } + else + { + Sys_Printf( "TexTool plugin: _QERAppSurfaceTable interface request failed\n" ); + return; + } + } + + if ( !g_bUITable ) { + g_UITable.m_nSize = sizeof( _QERUITable ); + if ( g_FuncTable.m_pfnRequestInterface( QERUI_GUID, static_cast( &g_UITable ) ) ) { + g_bUITable = true; + } + else + { + Sys_Printf( "TexTool plugin: _QERUITable interface request failed\n" ); + return; + } + } +#endif + + if (!strcmp(p, "About...")) { + DoMessageBox(PLUGIN_ABOUT, "About ...", MB_OK); + } else if (!strcmp(p, "Go...")) { + if (!g_pToolWnd) { + g_pToolWnd = g_UITable.m_pfnCreateGLWindow(); + g_pToolWnd->setSizeParm(300, 300); + g_pToolWnd->setName("TexTool"); + // g_Listener is a static class, we need to bump the refCount to avoid premature release problems + g_Listen.IncRef(); + // setListener will incRef on the listener too + g_pToolWnd->setListener(&g_Listen); + if (!g_pToolWnd->Show()) { + DoMessageBox("Error creating texture tools window!", "TexTool plugin", MB_ICONERROR | MB_OK); + return; + } + } + + g_bTexViewReady = false; + g_bClosing = false; + } else if (!strcmp(p, "Help...")) { + if (!g_bHelp) { + DoMessageBox("Select a brush face (ctrl+shift+left mouse) or a patch, and hit Go...\n" + "See tutorials for more", "TexTool plugin", MB_OK); + } else { + DoMessageBox("Are you kidding me ?", "TexTool plugin", MB_OK); + } + g_bHelp = true; + } } // ============================================================================= // SYNAPSE -CSynapseServer* g_pSynapseServer = NULL; +CSynapseServer *g_pSynapseServer = NULL; CSynapseClientTexTool g_SynapseClient; -extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ){ - if ( strcmp( version, SYNAPSE_VERSION ) ) { - Syn_Printf( "ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version ); - return NULL; - } - g_pSynapseServer = pServer; - g_pSynapseServer->IncRef(); - Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() ); +extern "C" CSynapseClient *SYNAPSE_DLL_EXPORT + +Synapse_EnumerateInterfaces(const char *version, CSynapseServer *pServer) +{ + if (strcmp(version, SYNAPSE_VERSION)) { + Syn_Printf("ERROR: synapse API version mismatch: should be '" + SYNAPSE_VERSION + "', got '%s'\n", version ); + return NULL; + } + g_pSynapseServer = pServer; + g_pSynapseServer->IncRef(); + Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf()); - g_SynapseClient.AddAPI( PLUGIN_MAJOR, "textool", sizeof( _QERPluginTable ) ); - g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( g_FuncTable ), SYN_REQUIRE, &g_FuncTable ); - g_SynapseClient.AddAPI( QGL_MAJOR, NULL, sizeof( g_QglTable ), SYN_REQUIRE, &g_QglTable ); - g_SynapseClient.AddAPI( SELECTEDFACE_MAJOR, NULL, sizeof( g_SelectedFaceTable ), SYN_REQUIRE, &g_SelectedFaceTable ); + g_SynapseClient.AddAPI(PLUGIN_MAJOR, "textool", sizeof(_QERPluginTable)); + g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable); + g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(g_QglTable), SYN_REQUIRE, &g_QglTable); + g_SynapseClient.AddAPI(SELECTEDFACE_MAJOR, NULL, sizeof(g_SelectedFaceTable), SYN_REQUIRE, &g_SelectedFaceTable); - return &g_SynapseClient; + return &g_SynapseClient; } -bool CSynapseClientTexTool::RequestAPI( APIDescriptor_t *pAPI ){ - if ( !strcmp( pAPI->major_name, PLUGIN_MAJOR ) ) { - _QERPluginTable *pTable = static_cast<_QERPluginTable*>( pAPI->mpTable ); - pTable->m_pfnQERPlug_Init = QERPlug_Init; - pTable->m_pfnQERPlug_GetName = QERPlug_GetName; - pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; - pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; - return true; - } +bool CSynapseClientTexTool::RequestAPI(APIDescriptor_t *pAPI) +{ + if (!strcmp(pAPI->major_name, PLUGIN_MAJOR)) { + _QERPluginTable *pTable = static_cast<_QERPluginTable *>( pAPI->mpTable ); + pTable->m_pfnQERPlug_Init = QERPlug_Init; + pTable->m_pfnQERPlug_GetName = QERPlug_GetName; + pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList; + pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch; + return true; + } - Syn_Printf( "ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo() ); - return false; + Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo()); + return false; } #include "version.h" -const char* CSynapseClientTexTool::GetInfo(){ - return "Texture Tools plugin built " __DATE__ " " RADIANT_VERSION; +const char *CSynapseClientTexTool::GetInfo() +{ + return "Texture Tools plugin built " __DATE__ " " + RADIANT_VERSION; } diff --git a/plugins/textool/TexTool.rc b/plugins/textool/TexTool.rc index 69d0eaf5..c2093a5a 100644 --- a/plugins/textool/TexTool.rc +++ b/plugins/textool/TexTool.rc @@ -27,11 +27,15 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL // IDD_DIALOG2 DIALOGEX 0, 0, 290, 206 -STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME -EXSTYLE WS_EX_TOOLWINDOW -FONT 8, "MS Sans Serif" +STYLE WS_POPUP +| WS_CAPTION | WS_SYSMENU | +WS_THICKFRAME + EXSTYLE +WS_EX_TOOLWINDOW + FONT +8, "MS Sans Serif" BEGIN -END + END ///////////////////////////////////////////////////////////////////////////// @@ -40,7 +44,7 @@ END // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE +GUIDELINES DESIGNINFO DISCARDABLE BEGIN IDD_DIALOG2, DIALOG BEGIN @@ -70,16 +74,19 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // Menu // -IDR_DROP_MENU MENU DISCARDABLE +IDR_DROP_MENU +MENU DISCARDABLE BEGIN - POPUP "Drop" - BEGIN - MENUITEM "Validate (RETURN)", ID_DROP_VALIDATE - MENUITEM "Zoom in (INSERT)", ID_DROP_ZOOMIN - MENUITEM "Zoom out (SUPPR)", ID_DROP_ZOOMOUT - MENUITEM "Cancel (ESC)", ID_DROP_CANCEL - END + POPUP +"Drop" +BEGIN + MENUITEM +"Validate (RETURN)", ID_DROP_VALIDATE +MENUITEM "Zoom in (INSERT)", ID_DROP_ZOOMIN +MENUITEM "Zoom out (SUPPR)", ID_DROP_ZOOMOUT +MENUITEM "Cancel (ESC)", ID_DROP_CANCEL END + END #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/plugins/vfspk3/archive.cpp b/plugins/vfspk3/archive.cpp index cf2bdeee..f4fc25b4 100644 --- a/plugins/vfspk3/archive.cpp +++ b/plugins/vfspk3/archive.cpp @@ -38,84 +38,91 @@ #include "fs_path.h" -class DirectoryArchive : public Archive -{ -CopiedString m_root; +class DirectoryArchive : public Archive { + CopiedString m_root; public: -DirectoryArchive( const char* root ) : m_root( root ){ -} - -void release(){ - delete this; -} -virtual ArchiveFile* openFile( const char* name ){ - UnixPath path( m_root.c_str() ); - path.push_filename( name ); - DirectoryArchiveFile* file = new DirectoryArchiveFile( name, path.c_str() ); - if ( !file->failed() ) { - return file; - } - file->release(); - return 0; -} -virtual ArchiveTextFile* openTextFile( const char* name ){ - UnixPath path( m_root.c_str() ); - path.push_filename( name ); - DirectoryArchiveTextFile* file = new DirectoryArchiveTextFile( name, path.c_str() ); - if ( !file->failed() ) { - return file; - } - file->release(); - return 0; -} -virtual bool containsFile( const char* name ){ - UnixPath path( m_root.c_str() ); - path.push_filename( name ); - return file_readable( path.c_str() ); -} -virtual void forEachFile( VisitorFunc visitor, const char* root ){ - std::vector dirs; - UnixPath path( m_root.c_str() ); - path.push( root ); - dirs.push_back( directory_open( path.c_str() ) ); - - while ( !dirs.empty() && directory_good( dirs.back() ) ) - { - const char* name = directory_read_and_increment( dirs.back() ); - - if ( name == 0 ) { - directory_close( dirs.back() ); - dirs.pop_back(); - path.pop(); - } - else if ( !string_equal( name, "." ) && !string_equal( name, ".." ) ) { - path.push_filename( name ); - - bool is_directory = file_is_directory( path.c_str() ); - - if ( !is_directory ) { - visitor.file( path_make_relative( path.c_str(), m_root.c_str() ) ); - } - - path.pop(); - - if ( is_directory ) { - path.push( name ); - - if ( !visitor.directory( path_make_relative( path.c_str(), m_root.c_str() ), dirs.size() ) ) { - dirs.push_back( directory_open( path.c_str() ) ); - } - else{ - path.pop(); - } - } - } - } -} + DirectoryArchive(const char *root) : m_root(root) + { + } + + void release() + { + delete this; + } + + virtual ArchiveFile *openFile(const char *name) + { + UnixPath path(m_root.c_str()); + path.push_filename(name); + DirectoryArchiveFile *file = new DirectoryArchiveFile(name, path.c_str()); + if (!file->failed()) { + return file; + } + file->release(); + return 0; + } + + virtual ArchiveTextFile *openTextFile(const char *name) + { + UnixPath path(m_root.c_str()); + path.push_filename(name); + DirectoryArchiveTextFile *file = new DirectoryArchiveTextFile(name, path.c_str()); + if (!file->failed()) { + return file; + } + file->release(); + return 0; + } + + virtual bool containsFile(const char *name) + { + UnixPath path(m_root.c_str()); + path.push_filename(name); + return file_readable(path.c_str()); + } + + virtual void forEachFile(VisitorFunc visitor, const char *root) + { + std::vector dirs; + UnixPath path(m_root.c_str()); + path.push(root); + dirs.push_back(directory_open(path.c_str())); + + while (!dirs.empty() && directory_good(dirs.back())) { + const char *name = directory_read_and_increment(dirs.back()); + + if (name == 0) { + directory_close(dirs.back()); + dirs.pop_back(); + path.pop(); + } else if (!string_equal(name, ".") && !string_equal(name, "..")) { + path.push_filename(name); + + bool is_directory = file_is_directory(path.c_str()); + + if (!is_directory) { + visitor.file(path_make_relative(path.c_str(), m_root.c_str())); + } + + path.pop(); + + if (is_directory) { + path.push(name); + + if (!visitor.directory(path_make_relative(path.c_str(), m_root.c_str()), dirs.size())) { + dirs.push_back(directory_open(path.c_str())); + } else { + path.pop(); + } + } + } + } + } }; -Archive* OpenArchive( const char* name ){ - return new DirectoryArchive( name ); +Archive *OpenArchive(const char *name) +{ + return new DirectoryArchive(name); } #if 0 @@ -126,34 +133,34 @@ class TestVisitor : public Archive::IVisitor { public: virtual void visit( const char* name ){ - int bleh = 0; + int bleh = 0; } }; public: void test1(){ - Archive* archive = OpenArchive( "d:/quake/id1/" ); - ArchiveFile* file = archive->openFile( "quake101.wad" ); - if ( file != 0 ) { - char buffer[1024]; - file->getInputStream().read( buffer, 1024 ); - file->release(); - } - TestVisitor visitor; - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" ); - archive->release(); + Archive* archive = OpenArchive( "d:/quake/id1/" ); + ArchiveFile* file = archive->openFile( "quake101.wad" ); + if ( file != 0 ) { + char buffer[1024]; + file->getInputStream().read( buffer, 1024 ); + file->release(); + } + TestVisitor visitor; + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" ); + archive->release(); } void test2(){ - Archive* archive = OpenArchive( "d:/gtkradiant_root/baseq3/" ); - TestVisitor visitor; - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "textures" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "textures" ); - archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures" ); - archive->release(); + Archive* archive = OpenArchive( "d:/gtkradiant_root/baseq3/" ); + TestVisitor visitor; + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "textures" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "textures" ); + archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures" ); + archive->release(); } TestArchive(){ - test1(); - test2(); + test1(); + test2(); } }; diff --git a/plugins/vfspk3/archive.h b/plugins/vfspk3/archive.h index 3530b48f..2704d258 100644 --- a/plugins/vfspk3/archive.h +++ b/plugins/vfspk3/archive.h @@ -24,6 +24,6 @@ #include "iarchive.h" -const _QERArchiveTable* GetArchiveTable( ArchiveModules& archiveModules, const char* type ); +const _QERArchiveTable *GetArchiveTable(ArchiveModules &archiveModules, const char *type); #endif diff --git a/plugins/vfspk3/vfs.cpp b/plugins/vfspk3/vfs.cpp index 1cd50a31..0829073f 100644 --- a/plugins/vfspk3/vfs.cpp +++ b/plugins/vfspk3/vfs.cpp @@ -51,7 +51,9 @@ #include "qerplugin.h" #include "idatastream.h" #include "iarchive.h" -ArchiveModules& FileSystemQ3API_getArchiveModules(); + +ArchiveModules &FileSystemQ3API_getArchiveModules(); + #include "ifilesystem.h" #include "generic/callback.h" @@ -76,13 +78,12 @@ const int VFS_MAXDIRS = 64; // ============================================================================= // Global variables -Archive* OpenArchive( const char* name ); +Archive *OpenArchive(const char *name); -struct archive_entry_t -{ - CopiedString name; - Archive* archive; - bool is_pakfile; +struct archive_entry_t { + CopiedString name; + Archive *archive; + bool is_pakfile; }; #include @@ -102,143 +103,145 @@ ModuleObservers g_observers; // ============================================================================= // Static functions -static void AddSlash( char *str ){ - std::size_t n = strlen( str ); - if ( n > 0 ) { - if ( str[n - 1] != '\\' && str[n - 1] != '/' ) { - globalErrorStream() << "WARNING: directory path does not end with separator: " << str << "\n"; - strcat( str, "/" ); - } - } +static void AddSlash(char *str) +{ + std::size_t n = strlen(str); + if (n > 0) { + if (str[n - 1] != '\\' && str[n - 1] != '/') { + globalErrorStream() << "WARNING: directory path does not end with separator: " << str << "\n"; + strcat(str, "/"); + } + } } -static void FixDOSName( char *src ){ - if ( src == 0 || strchr( src, '\\' ) == 0 ) { - return; - } +static void FixDOSName(char *src) +{ + if (src == 0 || strchr(src, '\\') == 0) { + return; + } - globalErrorStream() << "WARNING: invalid path separator '\\': " << src << "\n"; + globalErrorStream() << "WARNING: invalid path separator '\\': " << src << "\n"; - while ( *src ) - { - if ( *src == '\\' ) { - *src = '/'; - } - src++; - } + while (*src) { + if (*src == '\\') { + *src = '/'; + } + src++; + } } -const _QERArchiveTable* GetArchiveTable( ArchiveModules& archiveModules, const char* ext ){ - StringOutputStream tmp( 16 ); - tmp << LowerCase( ext ); - return archiveModules.findModule( tmp.c_str() ); +const _QERArchiveTable *GetArchiveTable(ArchiveModules &archiveModules, const char *ext) +{ + StringOutputStream tmp(16); + tmp << LowerCase(ext); + return archiveModules.findModule(tmp.c_str()); } -static Archive* InitPakFile( ArchiveModules& archiveModules, const char *filename ){ - const _QERArchiveTable* table = GetArchiveTable( archiveModules, path_get_extension( filename ) ); +static Archive *InitPakFile(ArchiveModules &archiveModules, const char *filename) +{ + const _QERArchiveTable *table = GetArchiveTable(archiveModules, path_get_extension(filename)); - if ( table != 0 ) { - archive_entry_t entry; - entry.name = filename; + if (table != 0) { + archive_entry_t entry; + entry.name = filename; - entry.archive = table->m_pfnOpenArchive( filename ); - entry.is_pakfile = true; - g_archives.push_back( entry ); - globalOutputStream() << " pak file: " << filename << "\n"; + entry.archive = table->m_pfnOpenArchive(filename); + entry.is_pakfile = true; + g_archives.push_back(entry); + globalOutputStream() << " pak file: " << filename << "\n"; - return entry.archive; - } + return entry.archive; + } - return 0; + return 0; } -inline void pathlist_prepend_unique( GSList*& pathlist, char* path ){ - if ( g_slist_find_custom( pathlist, path, (GCompareFunc)path_compare ) == 0 ) { - pathlist = g_slist_prepend( pathlist, path ); - } - else - { - g_free( path ); - } +inline void pathlist_prepend_unique(GSList *&pathlist, char *path) +{ + if (g_slist_find_custom(pathlist, path, (GCompareFunc) path_compare) == 0) { + pathlist = g_slist_prepend(pathlist, path); + } else { + g_free(path); + } } -class DirectoryListVisitor : public Archive::Visitor -{ -GSList*& m_matches; -const char* m_directory; +class DirectoryListVisitor : public Archive::Visitor { + GSList *&m_matches; + const char *m_directory; public: -DirectoryListVisitor( GSList*& matches, const char* directory ) - : m_matches( matches ), m_directory( directory ) -{} -void visit( const char* name ){ - const char* subname = path_make_relative( name, m_directory ); - if ( subname != name ) { - if ( subname[0] == '/' ) { - ++subname; - } - char* dir = g_strdup( subname ); - char* last_char = dir + strlen( dir ); - if ( last_char != dir && *( --last_char ) == '/' ) { - *last_char = '\0'; - } - pathlist_prepend_unique( m_matches, dir ); - } -} + DirectoryListVisitor(GSList *&matches, const char *directory) + : m_matches(matches), m_directory(directory) + {} + + void visit(const char *name) + { + const char *subname = path_make_relative(name, m_directory); + if (subname != name) { + if (subname[0] == '/') { + ++subname; + } + char *dir = g_strdup(subname); + char *last_char = dir + strlen(dir); + if (last_char != dir && *(--last_char) == '/') { + *last_char = '\0'; + } + pathlist_prepend_unique(m_matches, dir); + } + } }; -class FileListVisitor : public Archive::Visitor -{ -GSList*& m_matches; -const char* m_directory; -const char* m_extension; +class FileListVisitor : public Archive::Visitor { + GSList *&m_matches; + const char *m_directory; + const char *m_extension; public: -FileListVisitor( GSList*& matches, const char* directory, const char* extension ) - : m_matches( matches ), m_directory( directory ), m_extension( extension ) -{} -void visit( const char* name ){ - const char* subname = path_make_relative( name, m_directory ); - if ( subname != name ) { - if ( subname[0] == '/' ) { - ++subname; - } - if ( m_extension[0] == '*' || extension_equal( path_get_extension( subname ), m_extension ) ) { - pathlist_prepend_unique( m_matches, g_strdup( subname ) ); - } - } -} + FileListVisitor(GSList *&matches, const char *directory, const char *extension) + : m_matches(matches), m_directory(directory), m_extension(extension) + {} + + void visit(const char *name) + { + const char *subname = path_make_relative(name, m_directory); + if (subname != name) { + if (subname[0] == '/') { + ++subname; + } + if (m_extension[0] == '*' || extension_equal(path_get_extension(subname), m_extension)) { + pathlist_prepend_unique(m_matches, g_strdup(subname)); + } + } + } }; -static GSList* GetListInternal( const char *refdir, const char *ext, bool directories, std::size_t depth ){ - GSList* files = 0; - - ASSERT_MESSAGE( refdir[strlen( refdir ) - 1] == '/', "search path does not end in '/'" ); - - if ( directories ) { - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - DirectoryListVisitor visitor( files, refdir ); - ( *i ).archive->forEachFile( Archive::VisitorFunc( visitor, Archive::eDirectories, depth ), refdir ); - } - } - else - { - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - FileListVisitor visitor( files, refdir, ext ); - ( *i ).archive->forEachFile( Archive::VisitorFunc( visitor, Archive::eFiles, depth ), refdir ); - } - } - - files = g_slist_reverse( files ); - - return files; +static GSList *GetListInternal(const char *refdir, const char *ext, bool directories, std::size_t depth) +{ + GSList *files = 0; + + ASSERT_MESSAGE(refdir[strlen(refdir) - 1] == '/', "search path does not end in '/'"); + + if (directories) { + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + DirectoryListVisitor visitor(files, refdir); + (*i).archive->forEachFile(Archive::VisitorFunc(visitor, Archive::eDirectories, depth), refdir); + } + } else { + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + FileListVisitor visitor(files, refdir, ext); + (*i).archive->forEachFile(Archive::VisitorFunc(visitor, Archive::eFiles, depth), refdir); + } + } + + files = g_slist_reverse(files); + + return files; } -inline int ascii_to_upper( int c ){ - if ( c >= 'a' && c <= 'z' ) { - return c - ( 'a' - 'A' ); - } - return c; +inline int ascii_to_upper(int c) +{ + if (c >= 'a' && c <= 'z') { + return c - ('a' - 'A'); + } + return c; } /*! @@ -247,22 +250,22 @@ inline int ascii_to_upper( int c ){ it converts all alphabet chars to uppercase before comparison, while stricmp converts them to lowercase. */ -static int string_compare_nocase_upper( const char* a, const char* b ){ - for (;; ) - { - int c1 = ascii_to_upper( *a++ ); - int c2 = ascii_to_upper( *b++ ); - - if ( c1 < c2 ) { - return -1; // a < b - } - if ( c1 > c2 ) { - return 1; // a > b - } - if ( c1 == 0 ) { - return 0; // a == b - } - } +static int string_compare_nocase_upper(const char *a, const char *b) +{ + for (;;) { + int c1 = ascii_to_upper(*a++); + int c2 = ascii_to_upper(*b++); + + if (c1 < c2) { + return -1; // a < b + } + if (c1 > c2) { + return 1; // a > b + } + if (c1 == 0) { + return 0; // a == b + } + } } // Arnout: note - sort pakfiles in reverse order. This ensures that @@ -272,44 +275,45 @@ static int string_compare_nocase_upper( const char* a, const char* b ){ // last one in the list that is). //!\todo Analyse the code in rtcw/q3 to see which order it sorts pak files. -class PakLess -{ +class PakLess { public: -bool operator()( const CopiedString& self, const CopiedString& other ) const { - return string_compare_nocase_upper( self.c_str(), other.c_str() ) > 0; -} + bool operator()(const CopiedString &self, const CopiedString &other) const + { + return string_compare_nocase_upper(self.c_str(), other.c_str()) > 0; + } }; typedef std::set Archives; -Archive* AddPk3Dir( const char* fullpath ){ - if ( g_numDirs == VFS_MAXDIRS ) return 0; +Archive *AddPk3Dir(const char *fullpath) +{ + if (g_numDirs == VFS_MAXDIRS) { return 0; } - strncpy( g_strDirs[g_numDirs], fullpath, PATH_MAX ); - g_strDirs[g_numDirs][PATH_MAX] = '\0'; - g_numDirs++; + strncpy(g_strDirs[g_numDirs], fullpath, PATH_MAX); + g_strDirs[g_numDirs][PATH_MAX] = '\0'; + g_numDirs++; - { - archive_entry_t entry; - entry.name = fullpath; - entry.archive = OpenArchive( fullpath ); - entry.is_pakfile = false; - g_archives.push_back( entry ); + { + archive_entry_t entry; + entry.name = fullpath; + entry.archive = OpenArchive(fullpath); + entry.is_pakfile = false; + g_archives.push_back(entry); - return entry.archive; - } + return entry.archive; + } } // for Daemon DPK vfs -Archive* AddDpkDir( const char* fullpath ){ - return AddPk3Dir( fullpath ); +Archive *AddDpkDir(const char *fullpath) +{ + return AddPk3Dir(fullpath); } -struct pakfile_path_t -{ - CopiedString fullpath; // full pak dir or pk3dir name - bool is_pakfile; // defines is it .pk3dir or .pk3 file +struct pakfile_path_t { + CopiedString fullpath; // full pak dir or pk3dir name + bool is_pakfile; // defines is it .pk3dir or .pk3 file }; typedef std::pair PakfilePathsKV; @@ -317,58 +321,60 @@ typedef std::map PakfilePaths; // key must have n static PakfilePaths g_pakfile_paths; -void AddDpkPak( const char* name, const char* fullpath, bool is_pakfile ){ - pakfile_path_t pakfile_path; - pakfile_path.fullpath = fullpath; - pakfile_path.is_pakfile = is_pakfile; - g_pakfile_paths.insert( PakfilePathsKV( name, pakfile_path ) ); +void AddDpkPak(const char *name, const char *fullpath, bool is_pakfile) +{ + pakfile_path_t pakfile_path; + pakfile_path.fullpath = fullpath; + pakfile_path.is_pakfile = is_pakfile; + g_pakfile_paths.insert(PakfilePathsKV(name, pakfile_path)); } // takes name without ext, returns without ext -static const char* GetLatestDpkPakVersion( const char* name ){ - const char* maxversion = 0; - const char* result = 0; - const char* pakname; - const char* pakversion; - int namelen = string_length( name ); - - for ( PakfilePaths::iterator i = g_pakfile_paths.begin(); i != g_pakfile_paths.end(); ++i ) - { - pakname = i->first.c_str(); - if ( strncmp( pakname, name, namelen ) != 0 || pakname[namelen] != '_' ) continue; - pakversion = pakname + (namelen + 1); - if ( maxversion == 0 || DpkPakVersionCmp( pakversion, maxversion ) > 0 ){ - maxversion = pakversion; - result = pakname; - } - } - return result; +static const char *GetLatestDpkPakVersion(const char *name) +{ + const char *maxversion = 0; + const char *result = 0; + const char *pakname; + const char *pakversion; + int namelen = string_length(name); + + for (PakfilePaths::iterator i = g_pakfile_paths.begin(); i != g_pakfile_paths.end(); ++i) { + pakname = i->first.c_str(); + if (strncmp(pakname, name, namelen) != 0 || pakname[namelen] != '_') { continue; } + pakversion = pakname + (namelen + 1); + if (maxversion == 0 || DpkPakVersionCmp(pakversion, maxversion) > 0) { + maxversion = pakversion; + result = pakname; + } + } + return result; } // release string after using -static char* GetCurrentMapDpkPakName(){ - char* mapdir; - char* mapname; - int mapnamelen; - char* result = 0; - - mapname = string_clone( GlobalRadiant().getMapName() ); - mapnamelen = string_length( mapname ); - - mapdir = strrchr( mapname, '/' ); - if ( mapdir ) { - mapdir -= 12; - if ( strncmp( mapdir, ".dpkdir/maps/", 13 ) == 0 ) { - *mapdir = '\0'; - mapdir = strrchr( mapname, '/' ); - if ( mapdir ) mapdir++; - else mapdir = mapname; - result = string_clone( mapdir ); - } - } - - string_release( mapname, mapnamelen ); - return result; +static char *GetCurrentMapDpkPakName() +{ + char *mapdir; + char *mapname; + int mapnamelen; + char *result = 0; + + mapname = string_clone(GlobalRadiant().getMapName()); + mapnamelen = string_length(mapname); + + mapdir = strrchr(mapname, '/'); + if (mapdir) { + mapdir -= 12; + if (strncmp(mapdir, ".dpkdir/maps/", 13) == 0) { + *mapdir = '\0'; + mapdir = strrchr(mapname, '/'); + if (mapdir) { mapdir++; } + else { mapdir = mapname; } + result = string_clone(mapdir); + } + } + + string_release(mapname, mapnamelen); + return result; } @@ -377,69 +383,70 @@ static Archives g_loaded_dpk_paks; // actual pak adding on initialise, deferred from InitDirectory // Daemon DPK filesystem doesn't need load all paks it finds -static void LoadDpkPakWithDeps( const char* pakname ){ - Archive* arc; - ArchiveTextFile* depsFile; - - if (pakname == NULL) { - // load DEPS from game pack - StringOutputStream baseDirectory( 256 ); - const char* basegame = GlobalRadiant().getRequiredGameDescriptionKeyValue( "basegame" ); - baseDirectory << GlobalRadiant().getGameToolsPath() << basegame << '/'; - arc = AddDpkDir( baseDirectory.c_str() ); - depsFile = arc->openTextFile( "DEPS" ); - } else { - const char* und = strrchr( pakname, '_' ); - if ( !und ) { - pakname = GetLatestDpkPakVersion( pakname ); - } - if ( !pakname || g_loaded_dpk_paks.find( pakname ) != g_loaded_dpk_paks.end() ) { - return; - } - - PakfilePaths::iterator i = g_pakfile_paths.find( pakname ); - if ( i == g_pakfile_paths.end() ) { - return; - } - - if ( i->second.is_pakfile ){ - arc = InitPakFile( FileSystemQ3API_getArchiveModules(), i->second.fullpath.c_str() ); - } else { - arc = AddDpkDir( i->second.fullpath.c_str() ); - } - g_loaded_dpk_paks.insert( pakname ); - - depsFile = arc->openTextFile( "DEPS" ); - } - - if ( !depsFile ) { - return; - } - - { - TextLinesInputStream istream = depsFile->getInputStream(); - - CopiedString line; - char *p_name; - char *p_version; - while ( line = istream.readLine(), string_length( line.c_str() ) ) { - if ( !DpkReadDepsLine( line.c_str(), &p_name, &p_version ) ) continue; - if ( !p_version ) { - const char* p_latest = GetLatestDpkPakVersion( p_name ); - if ( p_latest ) LoadDpkPakWithDeps( p_latest ); - } else { - int len = string_length( p_name ) + string_length( p_version ) + 1; - char* p_pakname = string_new( len ); - sprintf( p_pakname, "%s_%s", p_name, p_version ); - LoadDpkPakWithDeps( p_pakname ); - string_release( p_pakname, len ); - } - string_release( p_name, string_length( p_name ) ); - if ( p_version ) string_release( p_version, string_length( p_version ) ); - } - } - - depsFile->release(); +static void LoadDpkPakWithDeps(const char *pakname) +{ + Archive *arc; + ArchiveTextFile *depsFile; + + if (pakname == NULL) { + // load DEPS from game pack + StringOutputStream baseDirectory(256); + const char *basegame = GlobalRadiant().getRequiredGameDescriptionKeyValue("basegame"); + baseDirectory << GlobalRadiant().getGameToolsPath() << basegame << '/'; + arc = AddDpkDir(baseDirectory.c_str()); + depsFile = arc->openTextFile("DEPS"); + } else { + const char *und = strrchr(pakname, '_'); + if (!und) { + pakname = GetLatestDpkPakVersion(pakname); + } + if (!pakname || g_loaded_dpk_paks.find(pakname) != g_loaded_dpk_paks.end()) { + return; + } + + PakfilePaths::iterator i = g_pakfile_paths.find(pakname); + if (i == g_pakfile_paths.end()) { + return; + } + + if (i->second.is_pakfile) { + arc = InitPakFile(FileSystemQ3API_getArchiveModules(), i->second.fullpath.c_str()); + } else { + arc = AddDpkDir(i->second.fullpath.c_str()); + } + g_loaded_dpk_paks.insert(pakname); + + depsFile = arc->openTextFile("DEPS"); + } + + if (!depsFile) { + return; + } + + { + TextLinesInputStream istream = depsFile->getInputStream(); + + CopiedString line; + char *p_name; + char *p_version; + while (line = istream.readLine(), string_length(line.c_str())) { + if (!DpkReadDepsLine(line.c_str(), &p_name, &p_version)) { continue; } + if (!p_version) { + const char *p_latest = GetLatestDpkPakVersion(p_name); + if (p_latest) { LoadDpkPakWithDeps(p_latest); } + } else { + int len = string_length(p_name) + string_length(p_version) + 1; + char *p_pakname = string_new(len); + sprintf(p_pakname, "%s_%s", p_name, p_version); + LoadDpkPakWithDeps(p_pakname); + string_release(p_pakname, len); + } + string_release(p_name, string_length(p_name)); + if (p_version) { string_release(p_version, string_length(p_version)); } + } + } + + depsFile->release(); } // end for Daemon DPK vfs @@ -448,509 +455,536 @@ static void LoadDpkPakWithDeps( const char* pakname ){ // Global functions // reads all pak files from a dir -void InitDirectory( const char* directory, ArchiveModules& archiveModules ){ - int j; - - g_numForbiddenDirs = 0; - StringTokeniser st( GlobalRadiant().getGameDescriptionKeyValue( "forbidden_paths" ), " " ); - for ( j = 0; j < VFS_MAXDIRS; ++j ) - { - const char *t = st.getToken(); - if ( string_empty( t ) ) { - break; - } - strncpy( g_strForbiddenDirs[g_numForbiddenDirs], t, PATH_MAX ); - g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = '\0'; - ++g_numForbiddenDirs; - } - - for ( j = 0; j < g_numForbiddenDirs; ++j ) - { - char* dbuf = g_strdup( directory ); - if ( *dbuf && dbuf[strlen( dbuf ) - 1] == '/' ) { - dbuf[strlen( dbuf ) - 1] = 0; - } - const char *p = strrchr( dbuf, '/' ); - p = ( p ? ( p + 1 ) : dbuf ); - if ( matchpattern( p, g_strForbiddenDirs[j], TRUE ) ) { - g_free( dbuf ); - break; - } - g_free( dbuf ); - } - if ( j < g_numForbiddenDirs ) { - printf( "Directory %s matched by forbidden dirs, removed\n", directory ); - return; - } - - if ( g_numDirs == VFS_MAXDIRS ) { - return; - } - - strncpy( g_strDirs[g_numDirs], directory, PATH_MAX ); - g_strDirs[g_numDirs][PATH_MAX] = '\0'; - FixDOSName( g_strDirs[g_numDirs] ); - AddSlash( g_strDirs[g_numDirs] ); - - const char* path = g_strDirs[g_numDirs]; - - g_numDirs++; - - { - archive_entry_t entry; - entry.name = path; - entry.archive = OpenArchive( path ); - entry.is_pakfile = false; - g_archives.push_back( entry ); - } - - if ( g_bUsePak ) { - - GDir* dir = g_dir_open( path, 0, 0 ); - - if ( dir != 0 ) { - globalOutputStream() << "vfs directory: " << path << "\n"; - - Archives archives; - Archives archivesOverride; - const char* ignore_prefix = ""; - const char* override_prefix = ""; - bool is_pk3_vfs, is_pk4_vfs, is_dpk_vfs; - - is_pk3_vfs = GetArchiveTable( archiveModules, "pk3" ); - is_pk4_vfs = GetArchiveTable( archiveModules, "pk4" ); - is_dpk_vfs = GetArchiveTable( archiveModules, "dpk" ); - - if ( !is_dpk_vfs ) { - // See if we are in "sp" or "mp" mapping mode - const char* gamemode = gamemode_get(); - - if ( strcmp( gamemode, "sp" ) == 0 ) { - ignore_prefix = "mp_"; - override_prefix = "sp_"; - } - else if ( strcmp( gamemode, "mp" ) == 0 ) { - ignore_prefix = "sp_"; - override_prefix = "mp_"; - } - } - - for (;; ) - { - const char* name = g_dir_read_name( dir ); - if ( name == 0 ) { - break; - } - - for ( j = 0; j < g_numForbiddenDirs; ++j ) - { - const char *p = strrchr( name, '/' ); - p = ( p ? ( p + 1 ) : name ); - if ( matchpattern( p, g_strForbiddenDirs[j], TRUE ) ) { - break; - } - } - if ( j < g_numForbiddenDirs ) { - continue; - } - - const char *ext = strrchr( name, '.' ); - char tmppath[PATH_MAX]; - - if ( is_dpk_vfs ) { - if ( !!ext && !string_compare_nocase_upper( ext, ".dpkdir" ) ) { - snprintf( tmppath, PATH_MAX, "%s%s/", path, name ); - tmppath[PATH_MAX] = '\0'; - FixDOSName( tmppath ); - AddSlash( tmppath ); - AddDpkPak( CopiedString( StringRange( name, ext ) ).c_str(), tmppath, false ); - } - } - - if ( is_pk3_vfs || is_pk4_vfs ) { - if ( !!ext && ( !string_compare_nocase_upper( ext, ".pk3dir" ) - || !string_compare_nocase_upper( ext, ".pk4dir" ) ) ) { - snprintf( tmppath, PATH_MAX, "%s%s/", path, name ); - tmppath[PATH_MAX] = '\0'; - FixDOSName( tmppath ); - AddSlash( tmppath ); - AddPk3Dir( tmppath ); - } - } - - // GetArchiveTable() needs "pk3" if ext is ".pk3" - if ( ( ext == 0 ) || *( ext + 1 ) == '\0' || GetArchiveTable( archiveModules, ext + 1 ) == 0 ) { - continue; - } - - // using the same kludge as in engine to ensure consistency - if ( !string_empty( ignore_prefix ) && strncmp( name, ignore_prefix, strlen( ignore_prefix ) ) == 0 ) { - continue; - } - if ( !string_empty( override_prefix ) && strncmp( name, override_prefix, strlen( override_prefix ) ) == 0 ) { - if ( !string_compare_nocase_upper( ext, ".dpk" ) ) { - if ( is_dpk_vfs ) { - archives.insert( name ); - } - } - else { - archivesOverride.insert( name ); - } - continue; - } - - archives.insert( name ); - } - - g_dir_close( dir ); - - // add the entries to the vfs - char* fullpath; - if ( is_dpk_vfs ) { - for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i ) { - const char* name = i->c_str(); - const char* ext = strrchr( name, '.' ); - if ( !string_compare_nocase_upper( ext, ".dpk" ) ) { - CopiedString name_final = CopiedString( StringRange( name, ext ) ); - fullpath = string_new_concat( path, name ); - AddDpkPak( name_final.c_str(), fullpath, true ); - string_release( fullpath, string_length( fullpath ) ); - } - } - } - if ( is_pk3_vfs || is_pk4_vfs ) { - for ( Archives::iterator i = archivesOverride.begin(); i != archivesOverride.end(); ++i ) - { - const char* name = i->c_str(); - const char* ext = strrchr( name, '.' ); - if ( !string_compare_nocase_upper( ext, ".pk3" ) - || !string_compare_nocase_upper( ext, ".pk4" ) ) { - fullpath = string_new_concat( path, i->c_str() ); - InitPakFile( archiveModules, fullpath ); - string_release( fullpath, string_length( fullpath ) ); - } - } - for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i ) - { - const char* name = i->c_str(); - const char* ext = strrchr( name, '.' ); - if ( !string_compare_nocase_upper( ext, ".pk3" ) - || !string_compare_nocase_upper( ext, ".pk4" ) ) { - fullpath = string_new_concat( path, i->c_str() ); - InitPakFile( archiveModules, fullpath ); - string_release( fullpath, string_length( fullpath ) ); - } - } - } - } - else - { - globalErrorStream() << "vfs directory not found: " << path << "\n"; - } - } +void InitDirectory(const char *directory, ArchiveModules &archiveModules) +{ + int j; + + g_numForbiddenDirs = 0; + StringTokeniser st(GlobalRadiant().getGameDescriptionKeyValue("forbidden_paths"), " "); + for (j = 0; j < VFS_MAXDIRS; ++j) { + const char *t = st.getToken(); + if (string_empty(t)) { + break; + } + strncpy(g_strForbiddenDirs[g_numForbiddenDirs], t, PATH_MAX); + g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = '\0'; + ++g_numForbiddenDirs; + } + + for (j = 0; j < g_numForbiddenDirs; ++j) { + char *dbuf = g_strdup(directory); + if (*dbuf && dbuf[strlen(dbuf) - 1] == '/') { + dbuf[strlen(dbuf) - 1] = 0; + } + const char *p = strrchr(dbuf, '/'); + p = (p ? (p + 1) : dbuf); + if (matchpattern(p, g_strForbiddenDirs[j], TRUE)) { + g_free(dbuf); + break; + } + g_free(dbuf); + } + if (j < g_numForbiddenDirs) { + printf("Directory %s matched by forbidden dirs, removed\n", directory); + return; + } + + if (g_numDirs == VFS_MAXDIRS) { + return; + } + + strncpy(g_strDirs[g_numDirs], directory, PATH_MAX); + g_strDirs[g_numDirs][PATH_MAX] = '\0'; + FixDOSName(g_strDirs[g_numDirs]); + AddSlash(g_strDirs[g_numDirs]); + + const char *path = g_strDirs[g_numDirs]; + + g_numDirs++; + + { + archive_entry_t entry; + entry.name = path; + entry.archive = OpenArchive(path); + entry.is_pakfile = false; + g_archives.push_back(entry); + } + + if (g_bUsePak) { + + GDir *dir = g_dir_open(path, 0, 0); + + if (dir != 0) { + globalOutputStream() << "vfs directory: " << path << "\n"; + + Archives archives; + Archives archivesOverride; + const char *ignore_prefix = ""; + const char *override_prefix = ""; + bool is_pk3_vfs, is_pk4_vfs, is_dpk_vfs; + + is_pk3_vfs = GetArchiveTable(archiveModules, "pk3"); + is_pk4_vfs = GetArchiveTable(archiveModules, "pk4"); + is_dpk_vfs = GetArchiveTable(archiveModules, "dpk"); + + if (!is_dpk_vfs) { + // See if we are in "sp" or "mp" mapping mode + const char *gamemode = gamemode_get(); + + if (strcmp(gamemode, "sp") == 0) { + ignore_prefix = "mp_"; + override_prefix = "sp_"; + } else if (strcmp(gamemode, "mp") == 0) { + ignore_prefix = "sp_"; + override_prefix = "mp_"; + } + } + + for (;;) { + const char *name = g_dir_read_name(dir); + if (name == 0) { + break; + } + + for (j = 0; j < g_numForbiddenDirs; ++j) { + const char *p = strrchr(name, '/'); + p = (p ? (p + 1) : name); + if (matchpattern(p, g_strForbiddenDirs[j], TRUE)) { + break; + } + } + if (j < g_numForbiddenDirs) { + continue; + } + + const char *ext = strrchr(name, '.'); + char tmppath[PATH_MAX]; + + if (is_dpk_vfs) { + if (!!ext && !string_compare_nocase_upper(ext, ".dpkdir")) { + snprintf(tmppath, PATH_MAX, "%s%s/", path, name); + tmppath[PATH_MAX] = '\0'; + FixDOSName(tmppath); + AddSlash(tmppath); + AddDpkPak(CopiedString(StringRange(name, ext)).c_str(), tmppath, false); + } + } + + if (is_pk3_vfs || is_pk4_vfs) { + if (!!ext && (!string_compare_nocase_upper(ext, ".pk3dir") + || !string_compare_nocase_upper(ext, ".pk4dir"))) { + snprintf(tmppath, PATH_MAX, "%s%s/", path, name); + tmppath[PATH_MAX] = '\0'; + FixDOSName(tmppath); + AddSlash(tmppath); + AddPk3Dir(tmppath); + } + } + + // GetArchiveTable() needs "pk3" if ext is ".pk3" + if ((ext == 0) || *(ext + 1) == '\0' || GetArchiveTable(archiveModules, ext + 1) == 0) { + continue; + } + + // using the same kludge as in engine to ensure consistency + if (!string_empty(ignore_prefix) && strncmp(name, ignore_prefix, strlen(ignore_prefix)) == 0) { + continue; + } + if (!string_empty(override_prefix) && strncmp(name, override_prefix, strlen(override_prefix)) == 0) { + if (!string_compare_nocase_upper(ext, ".dpk")) { + if (is_dpk_vfs) { + archives.insert(name); + } + } else { + archivesOverride.insert(name); + } + continue; + } + + archives.insert(name); + } + + g_dir_close(dir); + + // add the entries to the vfs + char *fullpath; + if (is_dpk_vfs) { + for (Archives::iterator i = archives.begin(); i != archives.end(); ++i) { + const char *name = i->c_str(); + const char *ext = strrchr(name, '.'); + if (!string_compare_nocase_upper(ext, ".dpk")) { + CopiedString name_final = CopiedString(StringRange(name, ext)); + fullpath = string_new_concat(path, name); + AddDpkPak(name_final.c_str(), fullpath, true); + string_release(fullpath, string_length(fullpath)); + } + } + } + if (is_pk3_vfs || is_pk4_vfs) { + for (Archives::iterator i = archivesOverride.begin(); i != archivesOverride.end(); ++i) { + const char *name = i->c_str(); + const char *ext = strrchr(name, '.'); + if (!string_compare_nocase_upper(ext, ".pk3") + || !string_compare_nocase_upper(ext, ".pk4")) { + fullpath = string_new_concat(path, i->c_str()); + InitPakFile(archiveModules, fullpath); + string_release(fullpath, string_length(fullpath)); + } + } + for (Archives::iterator i = archives.begin(); i != archives.end(); ++i) { + const char *name = i->c_str(); + const char *ext = strrchr(name, '.'); + if (!string_compare_nocase_upper(ext, ".pk3") + || !string_compare_nocase_upper(ext, ".pk4")) { + fullpath = string_new_concat(path, i->c_str()); + InitPakFile(archiveModules, fullpath); + string_release(fullpath, string_length(fullpath)); + } + } + } + } else { + globalErrorStream() << "vfs directory not found: " << path << "\n"; + } + } } // frees all memory that we allocated // FIXME TTimo this should be improved so that we can shutdown and restart the VFS without exiting Radiant? // (for instance when modifying the project settings) -void Shutdown(){ - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - ( *i ).archive->release(); - } - g_archives.clear(); - - g_numDirs = 0; - g_numForbiddenDirs = 0; - - g_pakfile_paths.clear(); - g_loaded_dpk_paks.clear(); -} - -const int VFS_SEARCH_PAK = 0x1; -const int VFS_SEARCH_DIR = 0x2; +void Shutdown() +{ + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + (*i).archive->release(); + } + g_archives.clear(); -int GetFileCount( const char *filename, int flag ){ - int count = 0; - char fixed[PATH_MAX + 1]; - - strncpy( fixed, filename, PATH_MAX ); - fixed[PATH_MAX] = '\0'; - FixDOSName( fixed ); - - if ( !flag ) { - flag = VFS_SEARCH_PAK | VFS_SEARCH_DIR; - } - - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - if ( (( *i ).is_pakfile && ( flag & VFS_SEARCH_PAK ) != 0) - || (!( *i ).is_pakfile && ( flag & VFS_SEARCH_DIR ) != 0) ) { - if ( ( *i ).archive->containsFile( fixed ) ) { - ++count; - } - } - } - - return count; -} + g_numDirs = 0; + g_numForbiddenDirs = 0; -ArchiveFile* OpenFile( const char* filename ){ - ASSERT_MESSAGE( strchr( filename, '\\' ) == 0, "path contains invalid separator '\\': \"" << filename << "\"" ); - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - ArchiveFile* file = ( *i ).archive->openFile( filename ); - if ( file != 0 ) { - return file; - } - } - - return 0; + g_pakfile_paths.clear(); + g_loaded_dpk_paks.clear(); } -ArchiveTextFile* OpenTextFile( const char* filename ){ - ASSERT_MESSAGE( strchr( filename, '\\' ) == 0, "path contains invalid separator '\\': \"" << filename << "\"" ); - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - ArchiveTextFile* file = ( *i ).archive->openTextFile( filename ); - if ( file != 0 ) { - return file; - } - } - - return 0; -} - -// NOTE: when loading a file, you have to allocate one extra byte and set it to \0 -std::size_t LoadFile( const char *filename, void **bufferptr, int index ){ - char fixed[PATH_MAX + 1]; +const int VFS_SEARCH_PAK = 0x1; +const int VFS_SEARCH_DIR = 0x2; - strncpy( fixed, filename, PATH_MAX ); - fixed[PATH_MAX] = '\0'; - FixDOSName( fixed ); +int GetFileCount(const char *filename, int flag) +{ + int count = 0; + char fixed[PATH_MAX + 1]; - ArchiveFile* file = OpenFile( fixed ); + strncpy(fixed, filename, PATH_MAX); + fixed[PATH_MAX] = '\0'; + FixDOSName(fixed); - if ( file != 0 ) { - *bufferptr = malloc( file->size() + 1 ); - // we need to end the buffer with a 0 - ( (char*) ( *bufferptr ) )[file->size()] = 0; + if (!flag) { + flag = VFS_SEARCH_PAK | VFS_SEARCH_DIR; + } - std::size_t length = file->getInputStream().read( (InputStream::byte_type*)*bufferptr, file->size() ); - file->release(); - return length; - } + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + if (((*i).is_pakfile && (flag & VFS_SEARCH_PAK) != 0) + || (!(*i).is_pakfile && (flag & VFS_SEARCH_DIR) != 0)) { + if ((*i).archive->containsFile(fixed)) { + ++count; + } + } + } - *bufferptr = 0; - return 0; + return count; } -void FreeFile( void *p ){ - free( p ); -} +ArchiveFile *OpenFile(const char *filename) +{ + ASSERT_MESSAGE(strchr(filename, '\\') == 0, "path contains invalid separator '\\': \"" << filename << "\""); + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + ArchiveFile *file = (*i).archive->openFile(filename); + if (file != 0) { + return file; + } + } -GSList* GetFileList( const char *dir, const char *ext, std::size_t depth ){ - return GetListInternal( dir, ext, false, depth ); + return 0; } -GSList* GetDirList( const char *dir, std::size_t depth ){ - return GetListInternal( dir, 0, true, depth ); -} +ArchiveTextFile *OpenTextFile(const char *filename) +{ + ASSERT_MESSAGE(strchr(filename, '\\') == 0, "path contains invalid separator '\\': \"" << filename << "\""); + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + ArchiveTextFile *file = (*i).archive->openTextFile(filename); + if (file != 0) { + return file; + } + } -void ClearFileDirList( GSList **lst ){ - while ( *lst ) - { - g_free( ( *lst )->data ); - *lst = g_slist_remove( *lst, ( *lst )->data ); - } + return 0; } -const char* FindFile( const char* relative ){ - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - if ( ( *i ).archive->containsFile( relative ) ) { - return ( *i ).name.c_str(); - } - } +// NOTE: when loading a file, you have to allocate one extra byte and set it to \0 +std::size_t LoadFile(const char *filename, void **bufferptr, int index) +{ + char fixed[PATH_MAX + 1]; - return ""; -} + strncpy(fixed, filename, PATH_MAX); + fixed[PATH_MAX] = '\0'; + FixDOSName(fixed); -const char* FindPath( const char* absolute ){ - const char *best = ""; - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - if ( string_length( ( *i ).name.c_str() ) > string_length( best ) ) { - if ( path_equal_n( absolute, ( *i ).name.c_str(), string_length( ( *i ).name.c_str() ) ) ) { - best = ( *i ).name.c_str(); - } - } - } - - return best; -} + ArchiveFile *file = OpenFile(fixed); + if (file != 0) { + *bufferptr = malloc(file->size() + 1); + // we need to end the buffer with a 0 + ((char *) (*bufferptr))[file->size()] = 0; -class Quake3FileSystem : public VirtualFileSystem -{ -public: -void initDirectory( const char *path ){ - InitDirectory( path, FileSystemQ3API_getArchiveModules() ); -} -void initialise(){ - load(); - globalOutputStream() << "filesystem initialised\n"; - g_observers.realise(); -} + std::size_t length = file->getInputStream().read((InputStream::byte_type *) *bufferptr, file->size()); + file->release(); + return length; + } -void load(){ - ArchiveModules& archiveModules = FileSystemQ3API_getArchiveModules(); - bool is_dpk_vfs = GetArchiveTable( archiveModules, "dpk" ); - - if ( is_dpk_vfs ) { - const char* pakname; - g_loaded_dpk_paks.clear(); - - // Load DEPS from game pack - LoadDpkPakWithDeps( NULL ); - - // prevent VFS double start, for MapName="" and MapName="unnamed.map" - if ( string_length( GlobalRadiant().getMapName() ) ){ - // load map's paks from DEPS - char* mappakname = GetCurrentMapDpkPakName(); - if ( mappakname != NULL ) { - LoadDpkPakWithDeps( mappakname ); - string_release( mappakname, string_length( mappakname ) ); - } - } - - g_pakfile_paths.clear(); - g_loaded_dpk_paks.clear(); - } + *bufferptr = 0; + return 0; } -void clear() { - // like shutdown() but does not unrealise (keep map etc.) - Shutdown(); +void FreeFile(void *p) +{ + free(p); } -void refresh(){ - // like initialise() but does not realise (keep map etc.) - load(); - globalOutputStream() << "filesystem refreshed\n"; +GSList *GetFileList(const char *dir, const char *ext, std::size_t depth) +{ + return GetListInternal(dir, ext, false, depth); } -void shutdown(){ - g_observers.unrealise(); - globalOutputStream() << "filesystem shutdown\n"; - Shutdown(); +GSList *GetDirList(const char *dir, std::size_t depth) +{ + return GetListInternal(dir, 0, true, depth); } -int getFileCount( const char *filename, int flags ){ - return GetFileCount( filename, flags ); -} -ArchiveFile* openFile( const char* filename ){ - return OpenFile( filename ); -} -ArchiveTextFile* openTextFile( const char* filename ){ - return OpenTextFile( filename ); -} -std::size_t loadFile( const char *filename, void **buffer ){ - return LoadFile( filename, buffer, 0 ); -} -void freeFile( void *p ){ - FreeFile( p ); +void ClearFileDirList(GSList **lst) +{ + while (*lst) { + g_free((*lst)->data); + *lst = g_slist_remove(*lst, (*lst)->data); + } } -void forEachDirectory( const char* basedir, const FileNameCallback& callback, std::size_t depth ){ - GSList* list = GetDirList( basedir, depth ); - - for ( GSList* i = list; i != 0; i = g_slist_next( i ) ) - { - callback( reinterpret_cast( ( *i ).data ) ); - } +const char *FindFile(const char *relative) +{ + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + if ((*i).archive->containsFile(relative)) { + return (*i).name.c_str(); + } + } - ClearFileDirList( &list ); -} -void forEachFile( const char* basedir, const char* extension, const FileNameCallback& callback, std::size_t depth ){ - GSList* list = GetFileList( basedir, extension, depth ); - - for ( GSList* i = list; i != 0; i = g_slist_next( i ) ) - { - const char* name = reinterpret_cast( ( *i ).data ); - if ( extension_equal( path_get_extension( name ), extension ) ) { - callback( name ); - } - } - - ClearFileDirList( &list ); -} -GSList* getDirList( const char *basedir ){ - return GetDirList( basedir, 1 ); -} -GSList* getFileList( const char *basedir, const char *extension ){ - return GetFileList( basedir, extension, 1 ); -} -void clearFileDirList( GSList **lst ){ - ClearFileDirList( lst ); + return ""; } -const char* findFile( const char *name ){ - return FindFile( name ); -} -const char* findRoot( const char *name ){ - return FindPath( name ); -} +const char *FindPath(const char *absolute) +{ + const char *best = ""; + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + if (string_length((*i).name.c_str()) > string_length(best)) { + if (path_equal_n(absolute, (*i).name.c_str(), string_length((*i).name.c_str()))) { + best = (*i).name.c_str(); + } + } + } -void attach( ModuleObserver& observer ){ - g_observers.attach( observer ); -} -void detach( ModuleObserver& observer ){ - g_observers.detach( observer ); + return best; } -Archive* getArchive( const char* archiveName, bool pakonly ){ - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - if ( pakonly && !( *i ).is_pakfile ) { - continue; - } - - if ( path_equal( ( *i ).name.c_str(), archiveName ) ) { - return ( *i ).archive; - } - } - return 0; -} -void forEachArchive( const ArchiveNameCallback& callback, bool pakonly, bool reverse ){ - if ( reverse ) { - g_archives.reverse(); - } - - for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i ) - { - if ( pakonly && !( *i ).is_pakfile ) { - continue; - } - - callback( ( *i ).name.c_str() ); - } - - if ( reverse ) { - g_archives.reverse(); - } -} + +class Quake3FileSystem : public VirtualFileSystem { +public: + void initDirectory(const char *path) + { + InitDirectory(path, FileSystemQ3API_getArchiveModules()); + } + + void initialise() + { + load(); + globalOutputStream() << "filesystem initialised\n"; + g_observers.realise(); + } + + void load() + { + ArchiveModules &archiveModules = FileSystemQ3API_getArchiveModules(); + bool is_dpk_vfs = GetArchiveTable(archiveModules, "dpk"); + + if (is_dpk_vfs) { + const char *pakname; + g_loaded_dpk_paks.clear(); + + // Load DEPS from game pack + LoadDpkPakWithDeps(NULL); + + // prevent VFS double start, for MapName="" and MapName="unnamed.map" + if (string_length(GlobalRadiant().getMapName())) { + // load map's paks from DEPS + char *mappakname = GetCurrentMapDpkPakName(); + if (mappakname != NULL) { + LoadDpkPakWithDeps(mappakname); + string_release(mappakname, string_length(mappakname)); + } + } + + g_pakfile_paths.clear(); + g_loaded_dpk_paks.clear(); + } + } + + void clear() + { + // like shutdown() but does not unrealise (keep map etc.) + Shutdown(); + } + + void refresh() + { + // like initialise() but does not realise (keep map etc.) + load(); + globalOutputStream() << "filesystem refreshed\n"; + } + + void shutdown() + { + g_observers.unrealise(); + globalOutputStream() << "filesystem shutdown\n"; + Shutdown(); + } + + int getFileCount(const char *filename, int flags) + { + return GetFileCount(filename, flags); + } + + ArchiveFile *openFile(const char *filename) + { + return OpenFile(filename); + } + + ArchiveTextFile *openTextFile(const char *filename) + { + return OpenTextFile(filename); + } + + std::size_t loadFile(const char *filename, void **buffer) + { + return LoadFile(filename, buffer, 0); + } + + void freeFile(void *p) + { + FreeFile(p); + } + + void forEachDirectory(const char *basedir, const FileNameCallback &callback, std::size_t depth) + { + GSList *list = GetDirList(basedir, depth); + + for (GSList *i = list; i != 0; i = g_slist_next(i)) { + callback(reinterpret_cast((*i).data )); + } + + ClearFileDirList(&list); + } + + void forEachFile(const char *basedir, const char *extension, const FileNameCallback &callback, std::size_t depth) + { + GSList *list = GetFileList(basedir, extension, depth); + + for (GSList *i = list; i != 0; i = g_slist_next(i)) { + const char *name = reinterpret_cast((*i).data ); + if (extension_equal(path_get_extension(name), extension)) { + callback(name); + } + } + + ClearFileDirList(&list); + } + + GSList *getDirList(const char *basedir) + { + return GetDirList(basedir, 1); + } + + GSList *getFileList(const char *basedir, const char *extension) + { + return GetFileList(basedir, extension, 1); + } + + void clearFileDirList(GSList **lst) + { + ClearFileDirList(lst); + } + + const char *findFile(const char *name) + { + return FindFile(name); + } + + const char *findRoot(const char *name) + { + return FindPath(name); + } + + void attach(ModuleObserver &observer) + { + g_observers.attach(observer); + } + + void detach(ModuleObserver &observer) + { + g_observers.detach(observer); + } + + Archive *getArchive(const char *archiveName, bool pakonly) + { + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + if (pakonly && !(*i).is_pakfile) { + continue; + } + + if (path_equal((*i).name.c_str(), archiveName)) { + return (*i).archive; + } + } + return 0; + } + + void forEachArchive(const ArchiveNameCallback &callback, bool pakonly, bool reverse) + { + if (reverse) { + g_archives.reverse(); + } + + for (archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i) { + if (pakonly && !(*i).is_pakfile) { + continue; + } + + callback((*i).name.c_str()); + } + + if (reverse) { + g_archives.reverse(); + } + } }; Quake3FileSystem g_Quake3FileSystem; -VirtualFileSystem& GetFileSystem(){ - return g_Quake3FileSystem; +VirtualFileSystem &GetFileSystem() +{ + return g_Quake3FileSystem; } -void FileSystem_Init(){ +void FileSystem_Init() +{ } -void FileSystem_Shutdown(){ +void FileSystem_Shutdown() +{ } diff --git a/plugins/vfspk3/vfs.h b/plugins/vfspk3/vfs.h index 5d7762ab..277c7b39 100644 --- a/plugins/vfspk3/vfs.h +++ b/plugins/vfspk3/vfs.h @@ -32,8 +32,11 @@ #define INCLUDED_VFS_H void FileSystem_Init(); + void FileSystem_Shutdown(); + class VirtualFileSystem; -VirtualFileSystem& GetFileSystem(); + +VirtualFileSystem &GetFileSystem(); #endif diff --git a/plugins/vfspk3/vfspk3.cpp b/plugins/vfspk3/vfspk3.cpp index 55b273ec..4f16f732 100644 --- a/plugins/vfspk3/vfspk3.cpp +++ b/plugins/vfspk3/vfspk3.cpp @@ -28,49 +28,57 @@ #include "vfs.h" -class FileSystemDependencies : public GlobalRadiantModuleRef -{ -ArchiveModulesRef m_archive_modules; +class FileSystemDependencies : public GlobalRadiantModuleRef { + ArchiveModulesRef m_archive_modules; public: -FileSystemDependencies() : - m_archive_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "archivetypes" ) ){ -} -ArchiveModules& getArchiveModules(){ - return m_archive_modules.get(); -} + FileSystemDependencies() : + m_archive_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("archivetypes")) + { + } + + ArchiveModules &getArchiveModules() + { + return m_archive_modules.get(); + } }; -class FileSystemQ3API -{ -VirtualFileSystem* m_filesystemq3; +class FileSystemQ3API { + VirtualFileSystem *m_filesystemq3; public: -typedef VirtualFileSystem Type; -STRING_CONSTANT( Name, "*" ); + typedef VirtualFileSystem Type; -FileSystemQ3API(){ - FileSystem_Init(); - m_filesystemq3 = &GetFileSystem(); -} -~FileSystemQ3API(){ - FileSystem_Shutdown(); -} -VirtualFileSystem* getTable(){ - return m_filesystemq3; -} + STRING_CONSTANT(Name, "*"); + + FileSystemQ3API() + { + FileSystem_Init(); + m_filesystemq3 = &GetFileSystem(); + } + + ~FileSystemQ3API() + { + FileSystem_Shutdown(); + } + + VirtualFileSystem *getTable() + { + return m_filesystemq3; + } }; typedef SingletonModule FileSystemQ3Module; FileSystemQ3Module g_FileSystemQ3Module; -ArchiveModules& FileSystemQ3API_getArchiveModules(){ - return g_FileSystemQ3Module.getDependencies().getArchiveModules(); +ArchiveModules &FileSystemQ3API_getArchiveModules() +{ + return g_FileSystemQ3Module.getDependencies().getArchiveModules(); } +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) +{ + initialiseModule(server); -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ - initialiseModule( server ); - - g_FileSystemQ3Module.selfRegister(); + g_FileSystemQ3Module.selfRegister(); } diff --git a/radiant/CMakeLists.txt b/radiant/CMakeLists.txt index 05d79830..c8672d49 100644 --- a/radiant/CMakeLists.txt +++ b/radiant/CMakeLists.txt @@ -7,125 +7,125 @@ add_definitions(-DCMAKE_SHARED_MODULE_SUFFIX="${_clibext}") unset(_clibext) set(RADIANTLIST - autosave.cpp autosave.h - brush.cpp brush.h - brush_primit.cpp brush_primit.h - brushmanip.cpp brushmanip.h - brushmodule.cpp brushmodule.h - brushnode.cpp brushnode.h - brushtokens.cpp brushtokens.h - brushxml.cpp brushxml.h - build.cpp build.h - camwindow.cpp camwindow.h - clippertool.cpp clippertool.h - commands.cpp commands.h - console.cpp console.h - csg.cpp csg.h - dialog.cpp dialog.h - eclass.cpp eclass.h - eclass_def.cpp eclass_def.h - eclass_doom3.cpp eclass_doom3.h - eclass_fgd.cpp eclass_fgd.h - eclass_xml.cpp eclass_xml.h - entity.cpp entity.h - entityinspector.cpp entityinspector.h - entitylist.cpp entitylist.h - environment.cpp environment.h - error.cpp error.h - feedback.cpp feedback.h - filetypes.cpp filetypes.h - filters.cpp filters.h - findtexturedialog.cpp findtexturedialog.h - glwidget.cpp glwidget.h - grid.cpp grid.h - groupdialog.cpp groupdialog.h - gtkdlgs.cpp gtkdlgs.h - gtkmisc.cpp gtkmisc.h - help.cpp help.h - image.cpp image.h - main.cpp main.h - mainframe.cpp mainframe.h - map.cpp map.h - mru.cpp mru.h - nullmodel.cpp nullmodel.h - parse.cpp parse.h - patch.cpp patch.h - patchdialog.cpp patchdialog.h - patchmanip.cpp patchmanip.h - patchmodule.cpp patchmodule.h - plugin.cpp plugin.h - pluginapi.cpp pluginapi.h - pluginmanager.cpp pluginmanager.h - pluginmenu.cpp pluginmenu.h - plugintoolbar.cpp plugintoolbar.h - points.cpp points.h - preferencedictionary.cpp preferencedictionary.h - preferences.cpp preferences.h - qe3.cpp qe3.h - qgl.cpp qgl.h - referencecache.cpp referencecache.h - renderer.cpp renderer.h - renderstate.cpp renderstate.h - resource.h - scenegraph.cpp scenegraph.h - select.cpp select.h - selection.cpp selection.h - server.cpp server.h - shaders.cpp shaders.h - sockets.cpp sockets.h - stacktrace.cpp stacktrace.h - surfacedialog.cpp surfacedialog.h - texmanip.cpp texmanip.h - textureentry.cpp textureentry.h - textures.cpp textures.h - texwindow.cpp texwindow.h - timer.cpp timer.h - treemodel.cpp treemodel.h - undo.cpp undo.h - url.cpp url.h - view.cpp view.h - watchbsp.cpp watchbsp.h - winding.cpp winding.h - windowobservers.cpp windowobservers.h - xmlstuff.cpp xmlstuff.h - xywindow.cpp xywindow.h -) + autosave.cpp autosave.h + brush.cpp brush.h + brush_primit.cpp brush_primit.h + brushmanip.cpp brushmanip.h + brushmodule.cpp brushmodule.h + brushnode.cpp brushnode.h + brushtokens.cpp brushtokens.h + brushxml.cpp brushxml.h + build.cpp build.h + camwindow.cpp camwindow.h + clippertool.cpp clippertool.h + commands.cpp commands.h + console.cpp console.h + csg.cpp csg.h + dialog.cpp dialog.h + eclass.cpp eclass.h + eclass_def.cpp eclass_def.h + eclass_doom3.cpp eclass_doom3.h + eclass_fgd.cpp eclass_fgd.h + eclass_xml.cpp eclass_xml.h + entity.cpp entity.h + entityinspector.cpp entityinspector.h + entitylist.cpp entitylist.h + environment.cpp environment.h + error.cpp error.h + feedback.cpp feedback.h + filetypes.cpp filetypes.h + filters.cpp filters.h + findtexturedialog.cpp findtexturedialog.h + glwidget.cpp glwidget.h + grid.cpp grid.h + groupdialog.cpp groupdialog.h + gtkdlgs.cpp gtkdlgs.h + gtkmisc.cpp gtkmisc.h + help.cpp help.h + image.cpp image.h + main.cpp main.h + mainframe.cpp mainframe.h + map.cpp map.h + mru.cpp mru.h + nullmodel.cpp nullmodel.h + parse.cpp parse.h + patch.cpp patch.h + patchdialog.cpp patchdialog.h + patchmanip.cpp patchmanip.h + patchmodule.cpp patchmodule.h + plugin.cpp plugin.h + pluginapi.cpp pluginapi.h + pluginmanager.cpp pluginmanager.h + pluginmenu.cpp pluginmenu.h + plugintoolbar.cpp plugintoolbar.h + points.cpp points.h + preferencedictionary.cpp preferencedictionary.h + preferences.cpp preferences.h + qe3.cpp qe3.h + qgl.cpp qgl.h + referencecache.cpp referencecache.h + renderer.cpp renderer.h + renderstate.cpp renderstate.h + resource.h + scenegraph.cpp scenegraph.h + select.cpp select.h + selection.cpp selection.h + server.cpp server.h + shaders.cpp shaders.h + sockets.cpp sockets.h + stacktrace.cpp stacktrace.h + surfacedialog.cpp surfacedialog.h + texmanip.cpp texmanip.h + textureentry.cpp textureentry.h + textures.cpp textures.h + texwindow.cpp texwindow.h + timer.cpp timer.h + treemodel.cpp treemodel.h + undo.cpp undo.h + url.cpp url.h + view.cpp view.h + watchbsp.cpp watchbsp.h + winding.cpp winding.h + windowobservers.cpp windowobservers.h + xmlstuff.cpp xmlstuff.h + xywindow.cpp xywindow.h + ) if (WIN32) list(APPEND RADIANTLIST multimon.cpp multimon.h) -endif() +endif () radiant_tool(radiant WIN32 radiant.rc ${RADIANTLIST}) add_dependencies(radiant modules) target_link_libraries(radiant - ${CMAKE_DL_LIBS} - ${LIBXML2_LIBRARIES} - ${OPENGL_gl_LIBRARY} - ${GTK${GTK_TARGET}_LIBRARIES} - ${GTKGL_LIBRARIES} - includes - cmdlib - container - ddslib - debugging - etclib - filematch - generic - l_net - math - mathlib - memory - modulesystem - os - picomodel - profile - script - signal - splines - stream - string - uilib - xmllib -) + ${CMAKE_DL_LIBS} + ${LIBXML2_LIBRARIES} + ${OPENGL_gl_LIBRARY} + ${GTK${GTK_TARGET}_LIBRARIES} + ${GTKGL_LIBRARIES} + includes + cmdlib + container + ddslib + debugging + etclib + filematch + generic + l_net + math + mathlib + memory + modulesystem + os + picomodel + profile + script + signal + splines + stream + string + uilib + xmllib + ) if (X11_LIBRARIES) target_link_libraries(radiant ${X11_LIBRARIES}) endif () diff --git a/radiant/autosave.cpp b/radiant/autosave.cpp index 9921d4be..75281563 100644 --- a/radiant/autosave.cpp +++ b/radiant/autosave.cpp @@ -42,60 +42,61 @@ #endif -bool DoesFileExist( const char* name, std::size_t& size ){ - if ( file_exists( name ) ) { - size += file_size( name ); - return true; - } - return false; +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 "/." - // The snapshot's filename will be "/snapshots/.." - 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(); - ui::alert( MainFrame_getWindow(), strMsg.c_str() ); - } +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 "/." + // The snapshot's filename will be "/snapshots/.." + 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(); + ui::alert(MainFrame_getWindow(), strMsg.c_str()); + } } + /* =============== QE_CheckAutoSave @@ -109,97 +110,101 @@ 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; +namespace { + time_t s_start = 0; + std::size_t s_changes = 0; } -void AutoSave_clear(){ - s_changes = 0; +void AutoSave_clear() +{ + s_changes = 0; } -scene::Node& Map_Node(){ - return GlobalSceneGraph().root(); +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 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 ){ - ui::CheckButton autosave_enabled = page.appendCheckBox( "Autosave", "Enable Autosave", g_AutoSave_Enabled ); - ui::SpinButton 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_constructPreferences(PreferencesPage &page) +{ + ui::CheckButton autosave_enabled = page.appendCheckBox("Autosave", "Enable Autosave", g_AutoSave_Enabled); + ui::SpinButton 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_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Autosave", "Autosave Preferences")); + Autosave_constructPreferences(page); } -void Autosave_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage(makeCallbackF(Autosave_constructPage)); + +void Autosave_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(Autosave_constructPage)); } #include "preferencesystem.h" #include "stringio.h" -void Autosave_Construct(){ - GlobalPreferenceSystem().registerPreference( "Autosave", make_property_string( g_AutoSave_Enabled ) ); - GlobalPreferenceSystem().registerPreference( "AutosaveMinutes", make_property_string( m_AutoSave_Frequency ) ); - GlobalPreferenceSystem().registerPreference( "Snapshots", make_property_string( g_SnapShots_Enabled ) ); +void Autosave_Construct() +{ + GlobalPreferenceSystem().registerPreference("Autosave", make_property_string(g_AutoSave_Enabled)); + GlobalPreferenceSystem().registerPreference("AutosaveMinutes", make_property_string(m_AutoSave_Frequency)); + GlobalPreferenceSystem().registerPreference("Snapshots", make_property_string(g_SnapShots_Enabled)); - Autosave_registerPreferencesPage(); + Autosave_registerPreferencesPage(); } -void Autosave_Destroy(){ +void Autosave_Destroy() +{ } diff --git a/radiant/autosave.h b/radiant/autosave.h index 40422331..e7dc00e2 100644 --- a/radiant/autosave.h +++ b/radiant/autosave.h @@ -25,10 +25,13 @@ extern bool g_SnapShots_Enabled; void AutoSave_clear(); -void QE_CheckAutoSave( void ); + +void QE_CheckAutoSave(void); + void Map_Snapshot(); void Autosave_Construct(); + void Autosave_Destroy(); diff --git a/radiant/brush.cpp b/radiant/brush.cpp index 5e38cc1d..57eb7af2 100644 --- a/radiant/brush.cpp +++ b/radiant/brush.cpp @@ -24,12 +24,14 @@ Signal0 g_brushTextureChangedCallbacks; -void Brush_addTextureChangedCallback( const SignalHandler& handler ){ - g_brushTextureChangedCallbacks.connectLast( handler ); +void Brush_addTextureChangedCallback(const SignalHandler &handler) +{ + g_brushTextureChangedCallbacks.connectLast(handler); } -void Brush_textureChanged(){ - g_brushTextureChangedCallbacks(); +void Brush_textureChanged() +{ + g_brushTextureChangedCallbacks(); } QuantiseFunc Face::m_quantise; @@ -39,350 +41,354 @@ bool g_brush_texturelock_enabled = true; 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; +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; +struct SListNode { + SListNode *m_next; }; -class ProximalVertex -{ +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; -} + 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 ProximalVertexArray; -std::size_t ProximalVertexArray_index( const ProximalVertexArray& array, const ProximalVertex& vertex ){ - return vertex.m_vertices - array.data(); -} +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; +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 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 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 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 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 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 ); - } - } - } - - if ( ( uniqueVertices.size() + faces_size ) - uniqueEdges.size() != 2 ) { - globalErrorStream() << "Final B-Rep: inconsistent vertex count\n"; - } +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 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 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 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 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 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); + } + } + } + + if ((uniqueVertices.size() + faces_size) - uniqueEdges.size() != 2) { + globalErrorStream() << "Final B-Rep: inconsistent vertex count\n"; + } #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() ); - } - } + 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 ); - } - } - } + // 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; +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 ); -} + 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 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 ); +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; +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; +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 ); -} + 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 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 ); +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; +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; } diff --git a/radiant/brush.h b/radiant/brush.h index c338e5f6..6114d59a 100644 --- a/radiant/brush.h +++ b/radiant/brush.h @@ -66,17 +66,16 @@ #include "brush_primit.h" const unsigned int BRUSH_DETAIL_FLAG = 27; -const unsigned int BRUSH_DETAIL_MASK = ( 1 << BRUSH_DETAIL_FLAG ); - -enum EBrushType -{ - eBrushTypeQuake, - eBrushTypeQuake2, - eBrushTypeQuake3, - eBrushTypeQuake3BP, - eBrushTypeDoom3, - eBrushTypeQuake4, - eBrushTypeHalfLife, +const unsigned int BRUSH_DETAIL_MASK = (1 << BRUSH_DETAIL_FLAG); + +enum EBrushType { + eBrushTypeQuake, + eBrushTypeQuake2, + eBrushTypeQuake3, + eBrushTypeQuake3BP, + eBrushTypeDoom3, + eBrushTypeQuake4, + eBrushTypeHalfLife, }; @@ -84,77 +83,79 @@ enum EBrushType #define BRUSH_DEGENERATE_DEBUG 0 template -inline TextOuputStreamType& ostream_write( TextOuputStreamType& ostream, const Matrix4& m ){ - return ostream << "(" << m[0] << " " << m[1] << " " << m[2] << " " << m[3] << ", " - << m[4] << " " << m[5] << " " << m[6] << " " << m[7] << ", " - << m[8] << " " << m[9] << " " << m[10] << " " << m[11] << ", " - << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << ")"; +inline TextOuputStreamType &ostream_write(TextOuputStreamType &ostream, const Matrix4 &m) +{ + return ostream << "(" << m[0] << " " << m[1] << " " << m[2] << " " << m[3] << ", " + << m[4] << " " << m[5] << " " << m[6] << " " << m[7] << ", " + << m[8] << " " << m[9] << " " << m[10] << " " << m[11] << ", " + << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << ")"; } -inline void print_vector3( const Vector3& v ){ - globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )\n"; +inline void print_vector3(const Vector3 &v) +{ + globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )\n"; } -inline void print_3x3( const Matrix4& m ){ - globalOutputStream() << "( " << m.xx() << " " << m.xy() << " " << m.xz() << " ) " - << "( " << m.yx() << " " << m.yy() << " " << m.yz() << " ) " - << "( " << m.zx() << " " << m.zy() << " " << m.zz() << " )\n"; +inline void print_3x3(const Matrix4 &m) +{ + globalOutputStream() << "( " << m.xx() << " " << m.xy() << " " << m.xz() << " ) " + << "( " << m.yx() << " " << m.yy() << " " << m.yz() << " ) " + << "( " << m.zx() << " " << m.zy() << " " << m.zz() << " )\n"; } - -inline bool texdef_sane( const texdef_t& texdef ){ - return fabs( texdef.shift[0] ) < ( 1 << 16 ) - && fabs( texdef.shift[1] ) < ( 1 << 16 ); +inline bool texdef_sane(const texdef_t &texdef) +{ + return fabs(texdef.shift[0]) < (1 << 16) + && fabs(texdef.shift[1]) < (1 << 16); } -inline void Winding_DrawWireframe( const Winding& winding ){ - glVertexPointer( 3, GL_FLOAT, sizeof( WindingVertex ), &winding.points.data()->vertex ); - glDrawArrays( GL_LINE_LOOP, 0, GLsizei( winding.numpoints ) ); +inline void Winding_DrawWireframe(const Winding &winding) +{ + glVertexPointer(3, GL_FLOAT, sizeof(WindingVertex), &winding.points.data()->vertex); + glDrawArrays(GL_LINE_LOOP, 0, GLsizei(winding.numpoints)); } -inline void Winding_Draw( const Winding& winding, const Vector3& normal, RenderStateFlags state ){ - glVertexPointer( 3, GL_FLOAT, sizeof( WindingVertex ), &winding.points.data()->vertex ); - - if ( ( state & RENDER_BUMP ) != 0 ) { - Vector3 normals[c_brush_maxFaces]; - typedef Vector3* Vector3Iter; - for ( Vector3Iter i = normals, end = normals + winding.numpoints; i != end; ++i ) - { - *i = normal; - } - if ( GlobalShaderCache().useShaderLanguage() ) { - glNormalPointer( GL_FLOAT, sizeof( Vector3 ), normals ); - glVertexAttribPointerARB( c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->texcoord ); - glVertexAttribPointerARB( c_attr_Tangent, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->tangent ); - glVertexAttribPointerARB( c_attr_Binormal, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->bitangent ); - } - else - { - glVertexAttribPointerARB( 11, 3, GL_FLOAT, 0, sizeof( Vector3 ), normals ); - glVertexAttribPointerARB( 8, 2, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->texcoord ); - glVertexAttribPointerARB( 9, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->tangent ); - glVertexAttribPointerARB( 10, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->bitangent ); - } - } - else - { - if ( state & RENDER_LIGHTING ) { - Vector3 normals[c_brush_maxFaces]; - typedef Vector3* Vector3Iter; - for ( Vector3Iter i = normals, last = normals + winding.numpoints; i != last; ++i ) - { - *i = normal; - } - glNormalPointer( GL_FLOAT, sizeof( Vector3 ), normals ); - } - - if ( state & RENDER_TEXTURE ) { - glTexCoordPointer( 2, GL_FLOAT, sizeof( WindingVertex ), &winding.points.data()->texcoord ); - } - } +inline void Winding_Draw(const Winding &winding, const Vector3 &normal, RenderStateFlags state) +{ + glVertexPointer(3, GL_FLOAT, sizeof(WindingVertex), &winding.points.data()->vertex); + + if ((state & RENDER_BUMP) != 0) { + Vector3 normals[c_brush_maxFaces]; + typedef Vector3 *Vector3Iter; + for (Vector3Iter i = normals, end = normals + winding.numpoints; i != end; ++i) { + *i = normal; + } + if (GlobalShaderCache().useShaderLanguage()) { + glNormalPointer(GL_FLOAT, sizeof(Vector3), normals); + glVertexAttribPointerARB(c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof(WindingVertex), + &winding.points.data()->texcoord); + glVertexAttribPointerARB(c_attr_Tangent, 3, GL_FLOAT, 0, sizeof(WindingVertex), + &winding.points.data()->tangent); + glVertexAttribPointerARB(c_attr_Binormal, 3, GL_FLOAT, 0, sizeof(WindingVertex), + &winding.points.data()->bitangent); + } else { + glVertexAttribPointerARB(11, 3, GL_FLOAT, 0, sizeof(Vector3), normals); + glVertexAttribPointerARB(8, 2, GL_FLOAT, 0, sizeof(WindingVertex), &winding.points.data()->texcoord); + glVertexAttribPointerARB(9, 3, GL_FLOAT, 0, sizeof(WindingVertex), &winding.points.data()->tangent); + glVertexAttribPointerARB(10, 3, GL_FLOAT, 0, sizeof(WindingVertex), &winding.points.data()->bitangent); + } + } else { + if (state & RENDER_LIGHTING) { + Vector3 normals[c_brush_maxFaces]; + typedef Vector3 *Vector3Iter; + for (Vector3Iter i = normals, last = normals + winding.numpoints; i != last; ++i) { + *i = normal; + } + glNormalPointer(GL_FLOAT, sizeof(Vector3), normals); + } + + if (state & RENDER_TEXTURE) { + glTexCoordPointer(2, GL_FLOAT, sizeof(WindingVertex), &winding.points.data()->texcoord); + } + } #if 0 - if ( state & RENDER_FILL ) { + if ( state & RENDER_FILL ) { glDrawArrays( GL_TRIANGLE_FAN, 0, GLsizei( winding.numpoints ) ); } else @@ -162,11 +163,11 @@ inline void Winding_Draw( const Winding& winding, const Vector3& normal, RenderS glDrawArrays( GL_LINE_LOOP, 0, GLsizei( winding.numpoints ) ); } #else - glDrawArrays( GL_POLYGON, 0, GLsizei( winding.numpoints ) ); + glDrawArrays(GL_POLYGON, 0, GLsizei(winding.numpoints)); #endif #if 0 - const Winding& winding = winding; + const Winding& winding = winding; if ( state & RENDER_FILL ) { glBegin( GL_POLYGON ); @@ -196,1125 +197,1285 @@ inline void Winding_Draw( const Winding& winding, const Vector3& normal, RenderS typedef DoubleVector3 PlanePoints[3]; -inline bool planepts_equal( const PlanePoints planepts, const PlanePoints other ){ - return planepts[0] == other[0] && planepts[1] == other[1] && planepts[2] == other[2]; -} - -inline void planepts_assign( PlanePoints planepts, const PlanePoints other ){ - planepts[0] = other[0]; - planepts[1] = other[1]; - planepts[2] = other[2]; -} - -inline void planepts_quantise( PlanePoints planepts, double snap ){ - vector3_snap( planepts[0], snap ); - vector3_snap( planepts[1], snap ); - vector3_snap( planepts[2], snap ); +inline bool planepts_equal(const PlanePoints planepts, const PlanePoints other) +{ + return planepts[0] == other[0] && planepts[1] == other[1] && planepts[2] == other[2]; } -inline float vector3_max_component( const Vector3& vec3 ){ - return std::max( fabsf( vec3[0] ), std::max( fabsf( vec3[1] ), fabsf( vec3[2] ) ) ); +inline void planepts_assign(PlanePoints planepts, const PlanePoints other) +{ + planepts[0] = other[0]; + planepts[1] = other[1]; + planepts[2] = other[2]; } -inline void edge_snap( Vector3& edge, double snap ){ - float scale = static_cast( ceil( fabs( snap / vector3_max_component( edge ) ) ) ); - if ( scale > 0.0f ) { - vector3_scale( edge, scale ); - } - vector3_snap( edge, snap ); +inline void planepts_quantise(PlanePoints planepts, double snap) +{ + vector3_snap(planepts[0], snap); + vector3_snap(planepts[1], snap); + vector3_snap(planepts[2], snap); } -inline void planepts_snap( PlanePoints planepts, double snap ){ - Vector3 edge01( vector3_subtracted( planepts[1], planepts[0] ) ); - Vector3 edge12( vector3_subtracted( planepts[2], planepts[1] ) ); - Vector3 edge20( vector3_subtracted( planepts[0], planepts[2] ) ); - - double length_squared_01 = vector3_dot( edge01, edge01 ); - double length_squared_12 = vector3_dot( edge12, edge12 ); - double length_squared_20 = vector3_dot( edge20, edge20 ); - - vector3_snap( planepts[0], snap ); - - if ( length_squared_01 < length_squared_12 ) { - if ( length_squared_12 < length_squared_20 ) { - edge_snap( edge01, snap ); - edge_snap( edge12, snap ); - planepts[1] = vector3_added( planepts[0], edge01 ); - planepts[2] = vector3_added( planepts[1], edge12 ); - } - else - { - edge_snap( edge20, snap ); - edge_snap( edge01, snap ); - planepts[1] = vector3_added( planepts[0], edge20 ); - planepts[2] = vector3_added( planepts[1], edge01 ); - } - } - else - { - if ( length_squared_01 < length_squared_20 ) { - edge_snap( edge01, snap ); - edge_snap( edge12, snap ); - planepts[1] = vector3_added( planepts[0], edge01 ); - planepts[2] = vector3_added( planepts[1], edge12 ); - } - else - { - edge_snap( edge12, snap ); - edge_snap( edge20, snap ); - planepts[1] = vector3_added( planepts[0], edge12 ); - planepts[2] = vector3_added( planepts[1], edge20 ); - } - } +inline float vector3_max_component(const Vector3 &vec3) +{ + return std::max(fabsf(vec3[0]), std::max(fabsf(vec3[1]), fabsf(vec3[2]))); } -inline PointVertex pointvertex_for_planept( const DoubleVector3& point, const Colour4b& colour ){ - return PointVertex( - Vertex3f( - static_cast( point.x() ), - static_cast( point.y() ), - static_cast( point.z() ) - ), - colour - ); +inline void edge_snap(Vector3 &edge, double snap) +{ + float scale = static_cast( ceil(fabs(snap / vector3_max_component(edge)))); + if (scale > 0.0f) { + vector3_scale(edge, scale); + } + vector3_snap(edge, snap); } -inline PointVertex pointvertex_for_windingpoint( const Vector3& point, const Colour4b& colour ){ - return PointVertex( - vertex3f_for_vector3( point ), - colour - ); +inline void planepts_snap(PlanePoints planepts, double snap) +{ + Vector3 edge01(vector3_subtracted(planepts[1], planepts[0])); + Vector3 edge12(vector3_subtracted(planepts[2], planepts[1])); + Vector3 edge20(vector3_subtracted(planepts[0], planepts[2])); + + double length_squared_01 = vector3_dot(edge01, edge01); + double length_squared_12 = vector3_dot(edge12, edge12); + double length_squared_20 = vector3_dot(edge20, edge20); + + vector3_snap(planepts[0], snap); + + if (length_squared_01 < length_squared_12) { + if (length_squared_12 < length_squared_20) { + edge_snap(edge01, snap); + edge_snap(edge12, snap); + planepts[1] = vector3_added(planepts[0], edge01); + planepts[2] = vector3_added(planepts[1], edge12); + } else { + edge_snap(edge20, snap); + edge_snap(edge01, snap); + planepts[1] = vector3_added(planepts[0], edge20); + planepts[2] = vector3_added(planepts[1], edge01); + } + } else { + if (length_squared_01 < length_squared_20) { + edge_snap(edge01, snap); + edge_snap(edge12, snap); + planepts[1] = vector3_added(planepts[0], edge01); + planepts[2] = vector3_added(planepts[1], edge12); + } else { + edge_snap(edge12, snap); + edge_snap(edge20, snap); + planepts[1] = vector3_added(planepts[0], edge12); + planepts[2] = vector3_added(planepts[1], edge20); + } + } +} + +inline PointVertex pointvertex_for_planept(const DoubleVector3 &point, const Colour4b &colour) +{ + return PointVertex( + Vertex3f( + static_cast( point.x()), + static_cast( point.y()), + static_cast( point.z()) + ), + colour + ); } -inline bool check_plane_is_integer( const PlanePoints& planePoints ){ - return !float_is_integer( planePoints[0][0] ) - || !float_is_integer( planePoints[0][1] ) - || !float_is_integer( planePoints[0][2] ) - || !float_is_integer( planePoints[1][0] ) - || !float_is_integer( planePoints[1][1] ) - || !float_is_integer( planePoints[1][2] ) - || !float_is_integer( planePoints[2][0] ) - || !float_is_integer( planePoints[2][1] ) - || !float_is_integer( planePoints[2][2] ); +inline PointVertex pointvertex_for_windingpoint(const Vector3 &point, const Colour4b &colour) +{ + return PointVertex( + vertex3f_for_vector3(point), + colour + ); } -inline void brush_check_shader( const char* name ){ - if ( !shader_valid( name ) ) { - globalErrorStream() << "brush face has invalid texture name: '" << name << "'\n"; - } +inline bool check_plane_is_integer(const PlanePoints &planePoints) +{ + return !float_is_integer(planePoints[0][0]) + || !float_is_integer(planePoints[0][1]) + || !float_is_integer(planePoints[0][2]) + || !float_is_integer(planePoints[1][0]) + || !float_is_integer(planePoints[1][1]) + || !float_is_integer(planePoints[1][2]) + || !float_is_integer(planePoints[2][0]) + || !float_is_integer(planePoints[2][1]) + || !float_is_integer(planePoints[2][2]); +} + +inline void brush_check_shader(const char *name) +{ + if (!shader_valid(name)) { + globalErrorStream() << "brush face has invalid texture name: '" << name << "'\n"; + } } -class FaceShaderObserver -{ +class FaceShaderObserver { public: -virtual void realiseShader() = 0; -virtual void unrealiseShader() = 0; + virtual void realiseShader() = 0; + + virtual void unrealiseShader() = 0; }; typedef ReferencePair FaceShaderObserverPair; -class ContentsFlagsValue -{ +class ContentsFlagsValue { public: -ContentsFlagsValue(){ -} -ContentsFlagsValue( int surfaceFlags, int contentFlags, int value, bool specified ) : - m_surfaceFlags( surfaceFlags ), - m_contentFlags( contentFlags ), - m_value( value ), - m_specified( specified ){ -} -int m_surfaceFlags; -int m_contentFlags; -int m_value; -bool m_specified; + ContentsFlagsValue() + { + } + + ContentsFlagsValue(int surfaceFlags, int contentFlags, int value, bool specified) : + m_surfaceFlags(surfaceFlags), + m_contentFlags(contentFlags), + m_value(value), + m_specified(specified) + { + } + + int m_surfaceFlags; + int m_contentFlags; + int m_value; + bool m_specified; }; -inline void ContentsFlagsValue_assignMasked( ContentsFlagsValue& flags, const ContentsFlagsValue& other ){ - bool detail = bitfield_enabled( flags.m_contentFlags, BRUSH_DETAIL_MASK ); - flags = other; - if ( detail ) { - flags.m_contentFlags = bitfield_enable( flags.m_contentFlags, BRUSH_DETAIL_MASK ); - } - else - { - flags.m_contentFlags = bitfield_disable( flags.m_contentFlags, BRUSH_DETAIL_MASK ); - } +inline void ContentsFlagsValue_assignMasked(ContentsFlagsValue &flags, const ContentsFlagsValue &other) +{ + bool detail = bitfield_enabled(flags.m_contentFlags, BRUSH_DETAIL_MASK); + flags = other; + if (detail) { + flags.m_contentFlags = bitfield_enable(flags.m_contentFlags, BRUSH_DETAIL_MASK); + } else { + flags.m_contentFlags = bitfield_disable(flags.m_contentFlags, BRUSH_DETAIL_MASK); + } } -class FaceShader : public ModuleObserver -{ -public: -class SavedState -{ +class FaceShader : public ModuleObserver { public: -CopiedString m_shader; -ContentsFlagsValue m_flags; + class SavedState { + public: + CopiedString m_shader; + ContentsFlagsValue m_flags; + + SavedState(const FaceShader &faceShader) + { + m_shader = faceShader.getShader(); + m_flags = faceShader.m_flags; + } + + void exportState(FaceShader &faceShader) const + { + faceShader.setShader(m_shader.c_str()); + faceShader.setFlags(m_flags); + } + }; + + CopiedString m_shader; + Shader *m_state; + ContentsFlagsValue m_flags; + FaceShaderObserverPair m_observers; + bool m_instanced; + bool m_realised; + + FaceShader(const char *shader, const ContentsFlagsValue &flags = ContentsFlagsValue(0, 0, 0, false)) : + m_shader(shader), + m_state(0), + m_flags(flags), + m_instanced(false), + m_realised(false) + { + captureShader(); + } + + ~FaceShader() + { + releaseShader(); + } -SavedState( const FaceShader& faceShader ){ - m_shader = faceShader.getShader(); - m_flags = faceShader.m_flags; -} - -void exportState( FaceShader& faceShader ) const { - faceShader.setShader( m_shader.c_str() ); - faceShader.setFlags( m_flags ); -} -}; - -CopiedString m_shader; -Shader* m_state; -ContentsFlagsValue m_flags; -FaceShaderObserverPair m_observers; -bool m_instanced; -bool m_realised; - -FaceShader( const char* shader, const ContentsFlagsValue& flags = ContentsFlagsValue( 0, 0, 0, false ) ) : - m_shader( shader ), - m_state( 0 ), - m_flags( flags ), - m_instanced( false ), - m_realised( false ){ - captureShader(); -} -~FaceShader(){ - releaseShader(); -} // copy-construction not supported -FaceShader( const FaceShader& other ); - -void instanceAttach(){ - m_instanced = true; - m_state->incrementUsed(); -} -void instanceDetach(){ - m_state->decrementUsed(); - m_instanced = false; -} - -void captureShader(){ - ASSERT_MESSAGE( m_state == 0, "shader cannot be captured" ); - brush_check_shader( m_shader.c_str() ); - m_state = GlobalShaderCache().capture( m_shader.c_str() ); - m_state->attach( *this ); -} -void releaseShader(){ - ASSERT_MESSAGE( m_state != 0, "shader cannot be released" ); - m_state->detach( *this ); - GlobalShaderCache().release( m_shader.c_str() ); - m_state = 0; -} - -void realise(){ - ASSERT_MESSAGE( !m_realised, "FaceTexdef::realise: already realised" ); - m_realised = true; - m_observers.forEach([](FaceShaderObserver &observer) { - observer.realiseShader(); - }); -} -void unrealise(){ - ASSERT_MESSAGE( m_realised, "FaceTexdef::unrealise: already unrealised" ); - m_observers.forEach([](FaceShaderObserver &observer) { - observer.unrealiseShader(); - }); - m_realised = false; -} - -void attach( FaceShaderObserver& observer ){ - m_observers.attach( observer ); - if ( m_realised ) { - observer.realiseShader(); - } -} - -void detach( FaceShaderObserver& observer ){ - if ( m_realised ) { - observer.unrealiseShader(); - } - m_observers.detach( observer ); -} - -const char* getShader() const { - return m_shader.c_str(); -} -void setShader( const char* name ){ - if ( m_instanced ) { - m_state->decrementUsed(); - } - releaseShader(); - m_shader = name; - captureShader(); - if ( m_instanced ) { - m_state->incrementUsed(); - } -} -ContentsFlagsValue getFlags() const { - ASSERT_MESSAGE( m_realised, "FaceShader::getFlags: flags not valid when unrealised" ); - if ( !m_flags.m_specified ) { - return ContentsFlagsValue( - m_state->getTexture().surfaceFlags, - m_state->getTexture().contentFlags, - m_state->getTexture().value, - true - ); - } - return m_flags; -} -void setFlags( const ContentsFlagsValue& flags ){ - ASSERT_MESSAGE( m_realised, "FaceShader::setFlags: flags not valid when unrealised" ); - ContentsFlagsValue_assignMasked( m_flags, flags ); -} - -Shader* state() const { - return m_state; -} - -std::size_t width() const { - if ( m_realised ) { - return m_state->getTexture().width; - } - return 1; -} -std::size_t height() const { - if ( m_realised ) { - return m_state->getTexture().height; - } - return 1; -} -unsigned int shaderFlags() const { - if ( m_realised ) { - return m_state->getFlags(); - } - return 0; -} + FaceShader(const FaceShader &other); + + void instanceAttach() + { + m_instanced = true; + m_state->incrementUsed(); + } + + void instanceDetach() + { + m_state->decrementUsed(); + m_instanced = false; + } + + void captureShader() + { + ASSERT_MESSAGE(m_state == 0, "shader cannot be captured"); + brush_check_shader(m_shader.c_str()); + m_state = GlobalShaderCache().capture(m_shader.c_str()); + m_state->attach(*this); + } + + void releaseShader() + { + ASSERT_MESSAGE(m_state != 0, "shader cannot be released"); + m_state->detach(*this); + GlobalShaderCache().release(m_shader.c_str()); + m_state = 0; + } + + void realise() + { + ASSERT_MESSAGE(!m_realised, "FaceTexdef::realise: already realised"); + m_realised = true; + m_observers.forEach([](FaceShaderObserver &observer) { + observer.realiseShader(); + }); + } + + void unrealise() + { + ASSERT_MESSAGE(m_realised, "FaceTexdef::unrealise: already unrealised"); + m_observers.forEach([](FaceShaderObserver &observer) { + observer.unrealiseShader(); + }); + m_realised = false; + } + + void attach(FaceShaderObserver &observer) + { + m_observers.attach(observer); + if (m_realised) { + observer.realiseShader(); + } + } + + void detach(FaceShaderObserver &observer) + { + if (m_realised) { + observer.unrealiseShader(); + } + m_observers.detach(observer); + } + + const char *getShader() const + { + return m_shader.c_str(); + } + + void setShader(const char *name) + { + if (m_instanced) { + m_state->decrementUsed(); + } + releaseShader(); + m_shader = name; + captureShader(); + if (m_instanced) { + m_state->incrementUsed(); + } + } + + ContentsFlagsValue getFlags() const + { + ASSERT_MESSAGE(m_realised, "FaceShader::getFlags: flags not valid when unrealised"); + if (!m_flags.m_specified) { + return ContentsFlagsValue( + m_state->getTexture().surfaceFlags, + m_state->getTexture().contentFlags, + m_state->getTexture().value, + true + ); + } + return m_flags; + } + + void setFlags(const ContentsFlagsValue &flags) + { + ASSERT_MESSAGE(m_realised, "FaceShader::setFlags: flags not valid when unrealised"); + ContentsFlagsValue_assignMasked(m_flags, flags); + } + + Shader *state() const + { + return m_state; + } + + std::size_t width() const + { + if (m_realised) { + return m_state->getTexture().width; + } + return 1; + } + + std::size_t height() const + { + if (m_realised) { + return m_state->getTexture().height; + } + return 1; + } + + unsigned int shaderFlags() const + { + if (m_realised) { + return m_state->getFlags(); + } + return 0; + } }; - - -class FaceTexdef : public FaceShaderObserver -{ +class FaceTexdef : public FaceShaderObserver { // not copyable -FaceTexdef( const FaceTexdef& other ); -// not assignable -FaceTexdef& operator=( const FaceTexdef& other ); -public: -class SavedState -{ -public: -TextureProjection m_projection; - -SavedState( const FaceTexdef& faceTexdef ){ - m_projection = faceTexdef.m_projection; -} - -void exportState( FaceTexdef& faceTexdef ) const { - Texdef_Assign( faceTexdef.m_projection, m_projection ); -} -}; - -FaceShader& m_shader; -TextureProjection m_projection; -bool m_projectionInitialised; -bool m_scaleApplied; - -FaceTexdef( - FaceShader& shader, - const TextureProjection& projection, - bool projectionInitialised = true - ) : - m_shader( shader ), - m_projection( projection ), - m_projectionInitialised( projectionInitialised ), - m_scaleApplied( false ){ - m_shader.attach( *this ); -} -~FaceTexdef(){ - m_shader.detach( *this ); -} - -void addScale(){ - ASSERT_MESSAGE( !m_scaleApplied, "texture scale aready added" ); - m_scaleApplied = true; - m_projection.m_brushprimit_texdef.addScale( m_shader.width(), m_shader.height() ); -} -void removeScale(){ - ASSERT_MESSAGE( m_scaleApplied, "texture scale aready removed" ); - m_scaleApplied = false; - m_projection.m_brushprimit_texdef.removeScale( m_shader.width(), m_shader.height() ); -} - -void realiseShader(){ - if ( m_projectionInitialised && !m_scaleApplied ) { - addScale(); - } -} -void unrealiseShader(){ - if ( m_projectionInitialised && m_scaleApplied ) { - removeScale(); - } -} - -void setTexdef( const TextureProjection& projection ){ - removeScale(); - Texdef_Assign( m_projection, projection ); - addScale(); -} + FaceTexdef(const FaceTexdef &other); -void shift( float s, float t ){ - ASSERT_MESSAGE( texdef_sane( m_projection.m_texdef ), "FaceTexdef::shift: bad texdef" ); - removeScale(); - Texdef_Shift( m_projection, s, t ); - addScale(); -} - -void scale( float s, float t ){ - removeScale(); - Texdef_Scale( m_projection, s, t ); - addScale(); -} - -void rotate( float angle ){ - removeScale(); - Texdef_Rotate( m_projection, angle ); - addScale(); -} - -void fit( const Vector3& normal, const Winding& winding, float s_repeat, float t_repeat ){ - Texdef_FitTexture( m_projection, m_shader.width(), m_shader.height(), normal, winding, s_repeat, t_repeat ); -} - -void emitTextureCoordinates( Winding& winding, const Vector3& normal, const Matrix4& localToWorld ){ - Texdef_EmitTextureCoordinates( m_projection, m_shader.width(), m_shader.height(), winding, normal, localToWorld ); -} - -void transform( const Plane3& plane, const Matrix4& matrix ){ - removeScale(); - Texdef_transformLocked( m_projection, m_shader.width(), m_shader.height(), plane, matrix ); - addScale(); -} +// not assignable + FaceTexdef &operator=(const FaceTexdef &other); -TextureProjection normalised() const { - brushprimit_texdef_t tmp( m_projection.m_brushprimit_texdef ); - tmp.removeScale( m_shader.width(), m_shader.height() ); - return TextureProjection( m_projection.m_texdef, tmp, m_projection.m_basis_s, m_projection.m_basis_t ); -} -void setBasis( const Vector3& normal ){ - Matrix4 basis; - Normal_GetTransform( normal, basis ); - m_projection.m_basis_s = Vector3( basis.xx(), basis.yx(), basis.zx() ); - m_projection.m_basis_t = Vector3( -basis.xy(), -basis.yy(), -basis.zy() ); -} +public: + class SavedState { + public: + TextureProjection m_projection; + + SavedState(const FaceTexdef &faceTexdef) + { + m_projection = faceTexdef.m_projection; + } + + void exportState(FaceTexdef &faceTexdef) const + { + Texdef_Assign(faceTexdef.m_projection, m_projection); + } + }; + + FaceShader &m_shader; + TextureProjection m_projection; + bool m_projectionInitialised; + bool m_scaleApplied; + + FaceTexdef( + FaceShader &shader, + const TextureProjection &projection, + bool projectionInitialised = true + ) : + m_shader(shader), + m_projection(projection), + m_projectionInitialised(projectionInitialised), + m_scaleApplied(false) + { + m_shader.attach(*this); + } + + ~FaceTexdef() + { + m_shader.detach(*this); + } + + void addScale() + { + ASSERT_MESSAGE(!m_scaleApplied, "texture scale aready added"); + m_scaleApplied = true; + m_projection.m_brushprimit_texdef.addScale(m_shader.width(), m_shader.height()); + } + + void removeScale() + { + ASSERT_MESSAGE(m_scaleApplied, "texture scale aready removed"); + m_scaleApplied = false; + m_projection.m_brushprimit_texdef.removeScale(m_shader.width(), m_shader.height()); + } + + void realiseShader() + { + if (m_projectionInitialised && !m_scaleApplied) { + addScale(); + } + } + + void unrealiseShader() + { + if (m_projectionInitialised && m_scaleApplied) { + removeScale(); + } + } + + void setTexdef(const TextureProjection &projection) + { + removeScale(); + Texdef_Assign(m_projection, projection); + addScale(); + } + + void shift(float s, float t) + { + ASSERT_MESSAGE(texdef_sane(m_projection.m_texdef), "FaceTexdef::shift: bad texdef"); + removeScale(); + Texdef_Shift(m_projection, s, t); + addScale(); + } + + void scale(float s, float t) + { + removeScale(); + Texdef_Scale(m_projection, s, t); + addScale(); + } + + void rotate(float angle) + { + removeScale(); + Texdef_Rotate(m_projection, angle); + addScale(); + } + + void fit(const Vector3 &normal, const Winding &winding, float s_repeat, float t_repeat) + { + Texdef_FitTexture(m_projection, m_shader.width(), m_shader.height(), normal, winding, s_repeat, t_repeat); + } + + void emitTextureCoordinates(Winding &winding, const Vector3 &normal, const Matrix4 &localToWorld) + { + Texdef_EmitTextureCoordinates(m_projection, m_shader.width(), m_shader.height(), winding, normal, localToWorld); + } + + void transform(const Plane3 &plane, const Matrix4 &matrix) + { + removeScale(); + Texdef_transformLocked(m_projection, m_shader.width(), m_shader.height(), plane, matrix); + addScale(); + } + + TextureProjection normalised() const + { + brushprimit_texdef_t tmp(m_projection.m_brushprimit_texdef); + tmp.removeScale(m_shader.width(), m_shader.height()); + return TextureProjection(m_projection.m_texdef, tmp, m_projection.m_basis_s, m_projection.m_basis_t); + } + + void setBasis(const Vector3 &normal) + { + Matrix4 basis; + Normal_GetTransform(normal, basis); + m_projection.m_basis_s = Vector3(basis.xx(), basis.yx(), basis.zx()); + m_projection.m_basis_t = Vector3(-basis.xy(), -basis.yy(), -basis.zy()); + } }; -inline void planepts_print( const PlanePoints& planePoints, TextOutputStream& ostream ){ - ostream << "( " << planePoints[0][0] << " " << planePoints[0][1] << " " << planePoints[0][2] << " ) " - << "( " << planePoints[1][0] << " " << planePoints[1][1] << " " << planePoints[1][2] << " ) " - << "( " << planePoints[2][0] << " " << planePoints[2][1] << " " << planePoints[2][2] << " )"; -} - - -inline Plane3 Plane3_applyTranslation( const Plane3& plane, const Vector3& translation ){ - Plane3 tmp( plane3_translated( Plane3( plane.normal(), -plane.dist() ), translation ) ); - return Plane3( tmp.normal(), -tmp.dist() ); +inline void planepts_print(const PlanePoints &planePoints, TextOutputStream &ostream) +{ + ostream << "( " << planePoints[0][0] << " " << planePoints[0][1] << " " << planePoints[0][2] << " ) " + << "( " << planePoints[1][0] << " " << planePoints[1][1] << " " << planePoints[1][2] << " ) " + << "( " << planePoints[2][0] << " " << planePoints[2][1] << " " << planePoints[2][2] << " )"; } -inline Plane3 Plane3_applyTransform( const Plane3& plane, const Matrix4& matrix ){ - Plane3 tmp( plane3_transformed( Plane3( plane.normal(), -plane.dist() ), matrix ) ); - return Plane3( tmp.normal(), -tmp.dist() ); -} -class FacePlane +inline Plane3 Plane3_applyTranslation(const Plane3 &plane, const Vector3 &translation) { -PlanePoints m_planepts; -Plane3 m_planeCached; -Plane3 m_plane; -public: -Vector3 m_funcStaticOrigin; - -static EBrushType m_type; - -static bool isDoom3Plane(){ - return FacePlane::m_type == eBrushTypeDoom3 || FacePlane::m_type == eBrushTypeQuake4; + Plane3 tmp(plane3_translated(Plane3(plane.normal(), -plane.dist()), translation)); + return Plane3(tmp.normal(), -tmp.dist()); } -class SavedState +inline Plane3 Plane3_applyTransform(const Plane3 &plane, const Matrix4 &matrix) { -public: -PlanePoints m_planepts; -Plane3 m_plane; - -SavedState( const FacePlane& facePlane ){ - if ( facePlane.isDoom3Plane() ) { - m_plane = facePlane.m_plane; - } - else - { - planepts_assign( m_planepts, facePlane.planePoints() ); - } -} - -void exportState( FacePlane& facePlane ) const { - if ( facePlane.isDoom3Plane() ) { - facePlane.m_plane = m_plane; - facePlane.updateTranslated(); - } - else - { - planepts_assign( facePlane.planePoints(), m_planepts ); - facePlane.MakePlane(); - } -} -}; - -FacePlane() : m_funcStaticOrigin( 0, 0, 0 ){ -} -FacePlane( const FacePlane& other ) : m_funcStaticOrigin( 0, 0, 0 ){ - if ( !isDoom3Plane() ) { - planepts_assign( m_planepts, other.m_planepts ); - MakePlane(); - } - else - { - m_plane = other.m_plane; - updateTranslated(); - } + Plane3 tmp(plane3_transformed(Plane3(plane.normal(), -plane.dist()), matrix)); + return Plane3(tmp.normal(), -tmp.dist()); } -void MakePlane(){ - if ( !isDoom3Plane() ) { +class FacePlane { + PlanePoints m_planepts; + Plane3 m_planeCached; + Plane3 m_plane; +public: + Vector3 m_funcStaticOrigin; + + static EBrushType m_type; + + static bool isDoom3Plane() + { + return FacePlane::m_type == eBrushTypeDoom3 || FacePlane::m_type == eBrushTypeQuake4; + } + + class SavedState { + public: + PlanePoints m_planepts; + Plane3 m_plane; + + SavedState(const FacePlane &facePlane) + { + if (facePlane.isDoom3Plane()) { + m_plane = facePlane.m_plane; + } else { + planepts_assign(m_planepts, facePlane.planePoints()); + } + } + + void exportState(FacePlane &facePlane) const + { + if (facePlane.isDoom3Plane()) { + facePlane.m_plane = m_plane; + facePlane.updateTranslated(); + } else { + planepts_assign(facePlane.planePoints(), m_planepts); + facePlane.MakePlane(); + } + } + }; + + FacePlane() : m_funcStaticOrigin(0, 0, 0) + { + } + + FacePlane(const FacePlane &other) : m_funcStaticOrigin(0, 0, 0) + { + if (!isDoom3Plane()) { + planepts_assign(m_planepts, other.m_planepts); + MakePlane(); + } else { + m_plane = other.m_plane; + updateTranslated(); + } + } + + void MakePlane() + { + if (!isDoom3Plane()) { #if 0 - if ( check_plane_is_integer( m_planepts ) ) { + if ( check_plane_is_integer( m_planepts ) ) { globalErrorStream() << "non-integer planepts: "; planepts_print( m_planepts, globalErrorStream() ); globalErrorStream() << "\n"; } #endif - m_planeCached = plane3_for_points( m_planepts ); - } -} - -void reverse(){ - if ( !isDoom3Plane() ) { - vector3_swap( m_planepts[0], m_planepts[2] ); - MakePlane(); - } - else - { - m_planeCached = plane3_flipped( m_plane ); - updateSource(); - } -} -void transform( const Matrix4& matrix, bool mirror ){ - if ( !isDoom3Plane() ) { + m_planeCached = plane3_for_points(m_planepts); + } + } + + void reverse() + { + if (!isDoom3Plane()) { + vector3_swap(m_planepts[0], m_planepts[2]); + MakePlane(); + } else { + m_planeCached = plane3_flipped(m_plane); + updateSource(); + } + } + + void transform(const Matrix4 &matrix, bool mirror) + { + if (!isDoom3Plane()) { #if 0 - bool off = check_plane_is_integer( planePoints() ); + bool off = check_plane_is_integer( planePoints() ); #endif - matrix4_transform_point( matrix, m_planepts[0] ); - matrix4_transform_point( matrix, m_planepts[1] ); - matrix4_transform_point( matrix, m_planepts[2] ); + matrix4_transform_point(matrix, m_planepts[0]); + matrix4_transform_point(matrix, m_planepts[1]); + matrix4_transform_point(matrix, m_planepts[2]); - if ( mirror ) { - reverse(); - } + if (mirror) { + reverse(); + } #if 0 - if ( check_plane_is_integer( planePoints() ) ) { + if ( check_plane_is_integer( planePoints() ) ) { if ( !off ) { globalErrorStream() << "caused by transform\n"; } } #endif - MakePlane(); - } - else - { - m_planeCached = Plane3_applyTransform( m_planeCached, matrix ); - updateSource(); - } -} -void offset( float offset ){ - if ( !isDoom3Plane() ) { - Vector3 move( vector3_scaled( m_planeCached.normal(), -offset ) ); - - vector3_subtract( m_planepts[0], move ); - vector3_subtract( m_planepts[1], move ); - vector3_subtract( m_planepts[2], move ); - - MakePlane(); - } - else - { - m_planeCached.d += offset; - updateSource(); - } -} - -void updateTranslated(){ - m_planeCached = Plane3_applyTranslation( m_plane, m_funcStaticOrigin ); -} -void updateSource(){ - m_plane = Plane3_applyTranslation( m_planeCached, vector3_negated( m_funcStaticOrigin ) ); -} - - -PlanePoints& planePoints(){ - return m_planepts; -} -const PlanePoints& planePoints() const { - return m_planepts; -} -const Plane3& plane3() const { - return m_planeCached; -} -void setDoom3Plane( const Plane3& plane ){ - m_plane = plane; - updateTranslated(); -} -const Plane3& getDoom3Plane() const { - return m_plane; -} - -void copy( const FacePlane& other ){ - if ( !isDoom3Plane() ) { - planepts_assign( m_planepts, other.m_planepts ); - MakePlane(); - } - else - { - m_planeCached = other.m_plane; - updateSource(); - } -} -void copy( const Vector3& p0, const Vector3& p1, const Vector3& p2 ){ - if ( !isDoom3Plane() ) { - m_planepts[0] = p0; - m_planepts[1] = p1; - m_planepts[2] = p2; - MakePlane(); - } - else - { - m_planeCached = plane3_for_points( p2, p1, p0 ); - updateSource(); - } -} + MakePlane(); + } else { + m_planeCached = Plane3_applyTransform(m_planeCached, matrix); + updateSource(); + } + } + + void offset(float offset) + { + if (!isDoom3Plane()) { + Vector3 move(vector3_scaled(m_planeCached.normal(), -offset)); + + vector3_subtract(m_planepts[0], move); + vector3_subtract(m_planepts[1], move); + vector3_subtract(m_planepts[2], move); + + MakePlane(); + } else { + m_planeCached.d += offset; + updateSource(); + } + } + + void updateTranslated() + { + m_planeCached = Plane3_applyTranslation(m_plane, m_funcStaticOrigin); + } + + void updateSource() + { + m_plane = Plane3_applyTranslation(m_planeCached, vector3_negated(m_funcStaticOrigin)); + } + + + PlanePoints &planePoints() + { + return m_planepts; + } + + const PlanePoints &planePoints() const + { + return m_planepts; + } + + const Plane3 &plane3() const + { + return m_planeCached; + } + + void setDoom3Plane(const Plane3 &plane) + { + m_plane = plane; + updateTranslated(); + } + + const Plane3 &getDoom3Plane() const + { + return m_plane; + } + + void copy(const FacePlane &other) + { + if (!isDoom3Plane()) { + planepts_assign(m_planepts, other.m_planepts); + MakePlane(); + } else { + m_planeCached = other.m_plane; + updateSource(); + } + } + + void copy(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2) + { + if (!isDoom3Plane()) { + m_planepts[0] = p0; + m_planepts[1] = p1; + m_planepts[2] = p2; + MakePlane(); + } else { + m_planeCached = plane3_for_points(p2, p1, p0); + updateSource(); + } + } }; -inline void Winding_testSelect( Winding& winding, SelectionTest& test, SelectionIntersection& best ){ - test.TestPolygon( VertexPointer( reinterpret_cast( &winding.points.data()->vertex ), sizeof( WindingVertex ) ), winding.numpoints, best ); +inline void Winding_testSelect(Winding &winding, SelectionTest &test, SelectionIntersection &best) +{ + test.TestPolygon(VertexPointer(reinterpret_cast( &winding.points.data()->vertex ), + sizeof(WindingVertex)), winding.numpoints, best); } const double GRID_MIN = 0.125; -inline double quantiseInteger( double f ){ - return float_to_integer( f ); +inline double quantiseInteger(double f) +{ + return float_to_integer(f); } -inline double quantiseFloating( double f ){ - return float_snapped( f, 1.f / ( 1 << 16 ) ); +inline double quantiseFloating(double f) +{ + return float_snapped(f, 1.f / (1 << 16)); } -typedef double ( *QuantiseFunc )( double f ); +typedef double ( *QuantiseFunc )(double f); class Face; -class FaceFilter -{ +class FaceFilter { public: -virtual bool filter( const Face& face ) const = 0; + virtual bool filter(const Face &face) const = 0; }; -bool face_filtered( Face& face ); -void add_face_filter( FaceFilter& filter, int mask, bool invert = false ); +bool face_filtered(Face &face); -void Brush_addTextureChangedCallback( const SignalHandler& callback ); -void Brush_textureChanged(); +void add_face_filter(FaceFilter &filter, int mask, bool invert = false); +void Brush_addTextureChangedCallback(const SignalHandler &callback); -extern bool g_brush_texturelock_enabled; +void Brush_textureChanged(); -class FaceObserver -{ -public: -virtual void planeChanged() = 0; -virtual void connectivityChanged() = 0; -virtual void shaderChanged() = 0; -virtual void evaluateTransform() = 0; -}; -class Face : - public OpenGLRenderable, - public Filterable, - public Undoable, - public FaceShaderObserver -{ -std::size_t m_refcount; +extern bool g_brush_texturelock_enabled; -class SavedState : public UndoMemento -{ +class FaceObserver { public: -FacePlane::SavedState m_planeState; -FaceTexdef::SavedState m_texdefState; -FaceShader::SavedState m_shaderState; + virtual void planeChanged() = 0; -SavedState( const Face& face ) : m_planeState( face.getPlane() ), m_texdefState( face.getTexdef() ), m_shaderState( face.getShader() ){ -} + virtual void connectivityChanged() = 0; -void exportState( Face& face ) const { - m_planeState.exportState( face.getPlane() ); - m_shaderState.exportState( face.getShader() ); - m_texdefState.exportState( face.getTexdef() ); -} + virtual void shaderChanged() = 0; -void release(){ - delete this; -} + virtual void evaluateTransform() = 0; }; +class Face : + public OpenGLRenderable, + public Filterable, + public Undoable, + public FaceShaderObserver { + std::size_t m_refcount; + + class SavedState : public UndoMemento { + public: + FacePlane::SavedState m_planeState; + FaceTexdef::SavedState m_texdefState; + FaceShader::SavedState m_shaderState; + + SavedState(const Face &face) : m_planeState(face.getPlane()), m_texdefState(face.getTexdef()), + m_shaderState(face.getShader()) + { + } + + void exportState(Face &face) const + { + m_planeState.exportState(face.getPlane()); + m_shaderState.exportState(face.getShader()); + m_texdefState.exportState(face.getTexdef()); + } + + void release() + { + delete this; + } + }; + public: -static QuantiseFunc m_quantise; -static EBrushType m_type; + static QuantiseFunc m_quantise; + static EBrushType m_type; -PlanePoints m_move_planepts; -PlanePoints m_move_planeptsTransformed; + PlanePoints m_move_planepts; + PlanePoints m_move_planeptsTransformed; private: -FacePlane m_plane; -FacePlane m_planeTransformed; -FaceShader m_shader; -FaceTexdef m_texdef; -TextureProjection m_texdefTransformed; + FacePlane m_plane; + FacePlane m_planeTransformed; + FaceShader m_shader; + FaceTexdef m_texdef; + TextureProjection m_texdefTransformed; -Winding m_winding; -Vector3 m_centroid; -bool m_filtered; + Winding m_winding; + Vector3 m_centroid; + bool m_filtered; -FaceObserver* m_observer; -UndoObserver* m_undoable_observer; -MapFile* m_map; + FaceObserver *m_observer; + UndoObserver *m_undoable_observer; + MapFile *m_map; // assignment not supported -Face& operator=( const Face& other ); + Face &operator=(const Face &other); + // copy-construction not supported -Face( const Face& other ); + Face(const Face &other); public: -Face( FaceObserver* observer ) : - m_refcount( 0 ), - m_shader( texdef_name_default() ), - m_texdef( m_shader, TextureProjection(), false ), - m_filtered( false ), - m_observer( observer ), - m_undoable_observer( 0 ), - m_map( 0 ){ - m_shader.attach( *this ); - m_plane.copy( Vector3( 0, 0, 0 ), Vector3( 64, 0, 0 ), Vector3( 0, 64, 0 ) ); - m_texdef.setBasis( m_plane.plane3().normal() ); - planeChanged(); -} -Face( - const Vector3& p0, - const Vector3& p1, - const Vector3& p2, - const char* shader, - const TextureProjection& projection, - FaceObserver* observer - ) : - m_refcount( 0 ), - m_shader( shader ), - m_texdef( m_shader, projection ), - m_observer( observer ), - m_undoable_observer( 0 ), - m_map( 0 ){ - m_shader.attach( *this ); - m_plane.copy( p0, p1, p2 ); - m_texdef.setBasis( m_plane.plane3().normal() ); - planeChanged(); - updateFiltered(); -} -Face( const Face& other, FaceObserver* observer ) : - m_refcount( 0 ), - m_shader( other.m_shader.getShader(), other.m_shader.m_flags ), - m_texdef( m_shader, other.getTexdef().normalised() ), - m_observer( observer ), - m_undoable_observer( 0 ), - m_map( 0 ){ - m_shader.attach( *this ); - m_plane.copy( other.m_plane ); - planepts_assign( m_move_planepts, other.m_move_planepts ); - m_texdef.setBasis( m_plane.plane3().normal() ); - planeChanged(); - updateFiltered(); -} -~Face(){ - m_shader.detach( *this ); -} + Face(FaceObserver *observer) : + m_refcount(0), + m_shader(texdef_name_default()), + m_texdef(m_shader, TextureProjection(), false), + m_filtered(false), + m_observer(observer), + m_undoable_observer(0), + m_map(0) + { + m_shader.attach(*this); + m_plane.copy(Vector3(0, 0, 0), Vector3(64, 0, 0), Vector3(0, 64, 0)); + m_texdef.setBasis(m_plane.plane3().normal()); + planeChanged(); + } + + Face( + const Vector3 &p0, + const Vector3 &p1, + const Vector3 &p2, + const char *shader, + const TextureProjection &projection, + FaceObserver *observer + ) : + m_refcount(0), + m_shader(shader), + m_texdef(m_shader, projection), + m_observer(observer), + m_undoable_observer(0), + m_map(0) + { + m_shader.attach(*this); + m_plane.copy(p0, p1, p2); + m_texdef.setBasis(m_plane.plane3().normal()); + planeChanged(); + updateFiltered(); + } + + Face(const Face &other, FaceObserver *observer) : + m_refcount(0), + m_shader(other.m_shader.getShader(), other.m_shader.m_flags), + m_texdef(m_shader, other.getTexdef().normalised()), + m_observer(observer), + m_undoable_observer(0), + m_map(0) + { + m_shader.attach(*this); + m_plane.copy(other.m_plane); + planepts_assign(m_move_planepts, other.m_move_planepts); + m_texdef.setBasis(m_plane.plane3().normal()); + planeChanged(); + updateFiltered(); + } + + ~Face() + { + m_shader.detach(*this); + } + + void planeChanged() + { + revertTransform(); + m_observer->planeChanged(); + } + + void realiseShader() + { + m_observer->shaderChanged(); + } + + void unrealiseShader() + { + } + + void instanceAttach(MapFile *map) + { + m_shader.instanceAttach(); + m_map = map; + m_undoable_observer = GlobalUndoSystem().observer(this); + GlobalFilterSystem().registerFilterable(*this); + } + + void instanceDetach(MapFile *map) + { + GlobalFilterSystem().unregisterFilterable(*this); + m_undoable_observer = 0; + GlobalUndoSystem().release(this); + m_map = 0; + m_shader.instanceDetach(); + } + + void render(RenderStateFlags state) const + { + Winding_Draw(m_winding, m_planeTransformed.plane3().normal(), state); + } + + void updateFiltered() + { + m_filtered = face_filtered(*this); + } + + bool isFiltered() const + { + return m_filtered; + } + + void undoSave() + { + if (m_map != 0) { + m_map->changed(); + } + if (m_undoable_observer != 0) { + m_undoable_observer->save(this); + } + } -void planeChanged(){ - revertTransform(); - m_observer->planeChanged(); -} +// undoable + UndoMemento *exportState() const + { + return new SavedState(*this); + } + + void importState(const UndoMemento *data) + { + undoSave(); + + static_cast( data )->exportState(*this); + + planeChanged(); + m_observer->connectivityChanged(); + texdefChanged(); + m_observer->shaderChanged(); + updateFiltered(); + } + + void IncRef() + { + ++m_refcount; + } + + void DecRef() + { + if (--m_refcount == 0) { + delete this; + } + } + + void flipWinding() + { + m_plane.reverse(); + planeChanged(); + } + + bool intersectVolume(const VolumeTest &volume, const Matrix4 &localToWorld) const + { + return volume.TestPlane(Plane3(plane3().normal(), -plane3().dist()), localToWorld); + } + + void render(Renderer &renderer, const Matrix4 &localToWorld) const + { + renderer.SetState(m_shader.state(), Renderer::eFullMaterials); + renderer.addRenderable(*this, localToWorld); + } + + void transform(const Matrix4 &matrix, bool mirror) + { + if (g_brush_texturelock_enabled) { + Texdef_transformLocked(m_texdefTransformed, m_shader.width(), m_shader.height(), m_plane.plane3(), matrix); + } + + m_planeTransformed.transform(matrix, mirror); -void realiseShader(){ - m_observer->shaderChanged(); -} -void unrealiseShader(){ -} +#if 0 + ASSERT_MESSAGE( projectionaxis_for_normal( normal ) == projectionaxis_for_normal( plane3().normal() ), "bleh" ); +#endif + m_observer->planeChanged(); -void instanceAttach( MapFile* map ){ - m_shader.instanceAttach(); - m_map = map; - m_undoable_observer = GlobalUndoSystem().observer( this ); - GlobalFilterSystem().registerFilterable( *this ); -} -void instanceDetach( MapFile* map ){ - GlobalFilterSystem().unregisterFilterable( *this ); - m_undoable_observer = 0; - GlobalUndoSystem().release( this ); - m_map = 0; - m_shader.instanceDetach(); -} + if (g_brush_texturelock_enabled) { + Brush_textureChanged(); + } + } -void render( RenderStateFlags state ) const { - Winding_Draw( m_winding, m_planeTransformed.plane3().normal(), state ); -} + void assign_planepts(const PlanePoints planepts) + { + m_planeTransformed.copy(planepts[0], planepts[1], planepts[2]); + m_observer->planeChanged(); + } -void updateFiltered(){ - m_filtered = face_filtered( *this ); -} -bool isFiltered() const { - return m_filtered; -} - -void undoSave(){ - if ( m_map != 0 ) { - m_map->changed(); - } - if ( m_undoable_observer != 0 ) { - m_undoable_observer->save( this ); - } -} - -// undoable -UndoMemento* exportState() const { - return new SavedState( *this ); -} -void importState( const UndoMemento* data ){ - undoSave(); - - static_cast( data )->exportState( *this ); - - planeChanged(); - m_observer->connectivityChanged(); - texdefChanged(); - m_observer->shaderChanged(); - updateFiltered(); -} - -void IncRef(){ - ++m_refcount; -} -void DecRef(){ - if ( --m_refcount == 0 ) { - delete this; - } -} - -void flipWinding(){ - m_plane.reverse(); - planeChanged(); -} - -bool intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) const { - return volume.TestPlane( Plane3( plane3().normal(), -plane3().dist() ), localToWorld ); -} - -void render( Renderer& renderer, const Matrix4& localToWorld ) const { - renderer.SetState( m_shader.state(), Renderer::eFullMaterials ); - renderer.addRenderable( *this, localToWorld ); -} - -void transform( const Matrix4& matrix, bool mirror ){ - if ( g_brush_texturelock_enabled ) { - Texdef_transformLocked( m_texdefTransformed, m_shader.width(), m_shader.height(), m_plane.plane3(), matrix ); - } - - m_planeTransformed.transform( matrix, mirror ); - -#if 0 - ASSERT_MESSAGE( projectionaxis_for_normal( normal ) == projectionaxis_for_normal( plane3().normal() ), "bleh" ); -#endif - m_observer->planeChanged(); - - if ( g_brush_texturelock_enabled ) { - Brush_textureChanged(); - } -} - -void assign_planepts( const PlanePoints planepts ){ - m_planeTransformed.copy( planepts[0], planepts[1], planepts[2] ); - m_observer->planeChanged(); -} - -/// \brief Reverts the transformable state of the brush to identity. -void revertTransform(){ - m_planeTransformed = m_plane; - planepts_assign( m_move_planeptsTransformed, m_move_planepts ); - m_texdefTransformed = m_texdef.m_projection; -} -void freezeTransform(){ - undoSave(); - m_plane = m_planeTransformed; - planepts_assign( m_move_planepts, m_move_planeptsTransformed ); - m_texdef.m_projection = m_texdefTransformed; -} - -void update_move_planepts_vertex( std::size_t index, PlanePoints planePoints ){ - std::size_t numpoints = getWinding().numpoints; - ASSERT_MESSAGE( index < numpoints, "update_move_planepts_vertex: invalid index" ); - - std::size_t opposite = Winding_Opposite( getWinding(), index ); - std::size_t adjacent = Winding_wrap( getWinding(), opposite + numpoints - 1 ); - planePoints[0] = getWinding()[opposite].vertex; - planePoints[1] = getWinding()[index].vertex; - planePoints[2] = getWinding()[adjacent].vertex; - // winding points are very inaccurate, so they must be quantised before using them to generate the face-plane - planepts_quantise( planePoints, GRID_MIN ); -} - -void snapto( float snap ){ - if ( contributes() ) { -#if 0 - ASSERT_MESSAGE( plane3_valid( m_plane.plane3() ), "invalid plane before snap to grid" ); - planepts_snap( m_plane.planePoints(), snap ); - ASSERT_MESSAGE( plane3_valid( m_plane.plane3() ), "invalid plane after snap to grid" ); -#else - PlanePoints planePoints; - update_move_planepts_vertex( 0, planePoints ); - vector3_snap( planePoints[0], snap ); - vector3_snap( planePoints[1], snap ); - vector3_snap( planePoints[2], snap ); - assign_planepts( planePoints ); - freezeTransform(); -#endif - SceneChangeNotify(); - if ( !plane3_valid( m_plane.plane3() ) ) { - globalErrorStream() << "WARNING: invalid plane after snap to grid\n"; - } - } -} - -void testSelect( SelectionTest& test, SelectionIntersection& best ){ - Winding_testSelect( m_winding, test, best ); -} - -void testSelect_centroid( SelectionTest& test, SelectionIntersection& best ){ - test.TestPoint( m_centroid, best ); -} - -void shaderChanged(){ - EmitTextureCoordinates(); - Brush_textureChanged(); - m_observer->shaderChanged(); - updateFiltered(); - planeChanged(); - SceneChangeNotify(); -} - -const char* GetShader() const { - return m_shader.getShader(); -} -void SetShader( const char* name ){ - undoSave(); - m_shader.setShader( name ); - shaderChanged(); -} - -void revertTexdef(){ - m_texdefTransformed = m_texdef.m_projection; -} -void texdefChanged(){ - revertTexdef(); - EmitTextureCoordinates(); - Brush_textureChanged(); -} - -void GetTexdef( TextureProjection& projection ) const { - projection = m_texdef.normalised(); -} -void SetTexdef( const TextureProjection& projection ){ - undoSave(); - m_texdef.setTexdef( projection ); - texdefChanged(); -} - -void GetFlags( ContentsFlagsValue& flags ) const { - flags = m_shader.getFlags(); -} -void SetFlags( const ContentsFlagsValue& flags ){ - undoSave(); - m_shader.setFlags( flags ); - m_observer->shaderChanged(); - updateFiltered(); -} - -void ShiftTexdef( float s, float t ){ - undoSave(); - m_texdef.shift( s, t ); - texdefChanged(); -} - -void ScaleTexdef( float s, float t ){ - undoSave(); - m_texdef.scale( s, t ); - texdefChanged(); -} - -void RotateTexdef( float angle ){ - undoSave(); - m_texdef.rotate( angle ); - texdefChanged(); -} - -void FitTexture( float s_repeat, float t_repeat ){ - undoSave(); - m_texdef.fit( m_plane.plane3().normal(), m_winding, s_repeat, t_repeat ); - texdefChanged(); -} - -void EmitTextureCoordinates(){ - Texdef_EmitTextureCoordinates( m_texdefTransformed, m_shader.width(), m_shader.height(), m_winding, plane3().normal(), g_matrix4_identity ); -} - - -const Vector3& centroid() const { - return m_centroid; -} - -void construct_centroid(){ - Winding_Centroid( m_winding, plane3(), m_centroid ); -} - -const Winding& getWinding() const { - return m_winding; -} -Winding& getWinding(){ - return m_winding; -} - -const Plane3& plane3() const { - m_observer->evaluateTransform(); - return m_planeTransformed.plane3(); -} -FacePlane& getPlane(){ - return m_plane; -} -const FacePlane& getPlane() const { - return m_plane; -} -FaceTexdef& getTexdef(){ - return m_texdef; -} -const FaceTexdef& getTexdef() const { - return m_texdef; -} -FaceShader& getShader(){ - return m_shader; -} -const FaceShader& getShader() const { - return m_shader; -} - -bool isDetail() const { - return ( m_shader.m_flags.m_contentFlags & BRUSH_DETAIL_MASK ) != 0; -} -void setDetail( bool detail ){ - undoSave(); - if ( detail && !isDetail() ) { - m_shader.m_flags.m_contentFlags |= BRUSH_DETAIL_MASK; - } - else if ( !detail && isDetail() ) { - m_shader.m_flags.m_contentFlags &= ~BRUSH_DETAIL_MASK; - } - m_observer->shaderChanged(); -} - -bool contributes() const { - return m_winding.numpoints > 2; -} -bool is_bounded() const { - for ( Winding::const_iterator i = m_winding.begin(); i != m_winding.end(); ++i ) - { - if ( ( *i ).adjacent == c_brush_maxFaces ) { - return false; - } - } - return true; -} -}; +/// \brief Reverts the transformable state of the brush to identity. + void revertTransform() + { + m_planeTransformed = m_plane; + planepts_assign(m_move_planeptsTransformed, m_move_planepts); + m_texdefTransformed = m_texdef.m_projection; + } + + void freezeTransform() + { + undoSave(); + m_plane = m_planeTransformed; + planepts_assign(m_move_planepts, m_move_planeptsTransformed); + m_texdef.m_projection = m_texdefTransformed; + } + + void update_move_planepts_vertex(std::size_t index, PlanePoints planePoints) + { + std::size_t numpoints = getWinding().numpoints; + ASSERT_MESSAGE(index < numpoints, "update_move_planepts_vertex: invalid index"); + + std::size_t opposite = Winding_Opposite(getWinding(), index); + std::size_t adjacent = Winding_wrap(getWinding(), opposite + numpoints - 1); + planePoints[0] = getWinding()[opposite].vertex; + planePoints[1] = getWinding()[index].vertex; + planePoints[2] = getWinding()[adjacent].vertex; + // winding points are very inaccurate, so they must be quantised before using them to generate the face-plane + planepts_quantise(planePoints, GRID_MIN); + } + + void snapto(float snap) + { + if (contributes()) { +#if 0 + ASSERT_MESSAGE( plane3_valid( m_plane.plane3() ), "invalid plane before snap to grid" ); + planepts_snap( m_plane.planePoints(), snap ); + ASSERT_MESSAGE( plane3_valid( m_plane.plane3() ), "invalid plane after snap to grid" ); +#else + PlanePoints planePoints; + update_move_planepts_vertex(0, planePoints); + vector3_snap(planePoints[0], snap); + vector3_snap(planePoints[1], snap); + vector3_snap(planePoints[2], snap); + assign_planepts(planePoints); + freezeTransform(); +#endif + SceneChangeNotify(); + if (!plane3_valid(m_plane.plane3())) { + globalErrorStream() << "WARNING: invalid plane after snap to grid\n"; + } + } + } + + void testSelect(SelectionTest &test, SelectionIntersection &best) + { + Winding_testSelect(m_winding, test, best); + } + + void testSelect_centroid(SelectionTest &test, SelectionIntersection &best) + { + test.TestPoint(m_centroid, best); + } + + void shaderChanged() + { + EmitTextureCoordinates(); + Brush_textureChanged(); + m_observer->shaderChanged(); + updateFiltered(); + planeChanged(); + SceneChangeNotify(); + } + + const char *GetShader() const + { + return m_shader.getShader(); + } + + void SetShader(const char *name) + { + undoSave(); + m_shader.setShader(name); + shaderChanged(); + } + + void revertTexdef() + { + m_texdefTransformed = m_texdef.m_projection; + } + + void texdefChanged() + { + revertTexdef(); + EmitTextureCoordinates(); + Brush_textureChanged(); + } + + void GetTexdef(TextureProjection &projection) const + { + projection = m_texdef.normalised(); + } + + void SetTexdef(const TextureProjection &projection) + { + undoSave(); + m_texdef.setTexdef(projection); + texdefChanged(); + } + + void GetFlags(ContentsFlagsValue &flags) const + { + flags = m_shader.getFlags(); + } + + void SetFlags(const ContentsFlagsValue &flags) + { + undoSave(); + m_shader.setFlags(flags); + m_observer->shaderChanged(); + updateFiltered(); + } + + void ShiftTexdef(float s, float t) + { + undoSave(); + m_texdef.shift(s, t); + texdefChanged(); + } + + void ScaleTexdef(float s, float t) + { + undoSave(); + m_texdef.scale(s, t); + texdefChanged(); + } + + void RotateTexdef(float angle) + { + undoSave(); + m_texdef.rotate(angle); + texdefChanged(); + } + + void FitTexture(float s_repeat, float t_repeat) + { + undoSave(); + m_texdef.fit(m_plane.plane3().normal(), m_winding, s_repeat, t_repeat); + texdefChanged(); + } + + void EmitTextureCoordinates() + { + Texdef_EmitTextureCoordinates(m_texdefTransformed, m_shader.width(), m_shader.height(), m_winding, + plane3().normal(), g_matrix4_identity); + } + + + const Vector3 ¢roid() const + { + return m_centroid; + } + + void construct_centroid() + { + Winding_Centroid(m_winding, plane3(), m_centroid); + } + + const Winding &getWinding() const + { + return m_winding; + } + + Winding &getWinding() + { + return m_winding; + } + + const Plane3 &plane3() const + { + m_observer->evaluateTransform(); + return m_planeTransformed.plane3(); + } + + FacePlane &getPlane() + { + return m_plane; + } + + const FacePlane &getPlane() const + { + return m_plane; + } + + FaceTexdef &getTexdef() + { + return m_texdef; + } + + const FaceTexdef &getTexdef() const + { + return m_texdef; + } + + FaceShader &getShader() + { + return m_shader; + } + + const FaceShader &getShader() const + { + return m_shader; + } + + bool isDetail() const + { + return (m_shader.m_flags.m_contentFlags & BRUSH_DETAIL_MASK) != 0; + } + + void setDetail(bool detail) + { + undoSave(); + if (detail && !isDetail()) { + m_shader.m_flags.m_contentFlags |= BRUSH_DETAIL_MASK; + } else if (!detail && isDetail()) { + m_shader.m_flags.m_contentFlags &= ~BRUSH_DETAIL_MASK; + } + m_observer->shaderChanged(); + } + + bool contributes() const + { + return m_winding.numpoints > 2; + } + + bool is_bounded() const + { + for (Winding::const_iterator i = m_winding.begin(); i != m_winding.end(); ++i) { + if ((*i).adjacent == c_brush_maxFaces) { + return false; + } + } + return true; + } +}; -class FaceVertexId -{ -std::size_t m_face; -std::size_t m_vertex; +class FaceVertexId { + std::size_t m_face; + std::size_t m_vertex; public: -FaceVertexId( std::size_t face, std::size_t vertex ) - : m_face( face ), m_vertex( vertex ){ -} - -std::size_t getFace() const { - return m_face; -} -std::size_t getVertex() const { - return m_vertex; -} + FaceVertexId(std::size_t face, std::size_t vertex) + : m_face(face), m_vertex(vertex) + { + } + + std::size_t getFace() const + { + return m_face; + } + + std::size_t getVertex() const + { + return m_vertex; + } }; typedef std::size_t faceIndex_t; -struct EdgeRenderIndices -{ - RenderIndex first; - RenderIndex second; +struct EdgeRenderIndices { + RenderIndex first; + RenderIndex second; - EdgeRenderIndices() - : first( 0 ), second( 0 ){ - } - EdgeRenderIndices( const RenderIndex _first, const RenderIndex _second ) - : first( _first ), second( _second ){ - } + EdgeRenderIndices() + : first(0), second(0) + { + } + + EdgeRenderIndices(const RenderIndex _first, const RenderIndex _second) + : first(_first), second(_second) + { + } }; -struct EdgeFaces -{ - faceIndex_t first; - faceIndex_t second; +struct EdgeFaces { + faceIndex_t first; + faceIndex_t second; - EdgeFaces() - : first( c_brush_maxFaces ), second( c_brush_maxFaces ){ - } - EdgeFaces( const faceIndex_t _first, const faceIndex_t _second ) - : first( _first ), second( _second ){ - } + EdgeFaces() + : first(c_brush_maxFaces), second(c_brush_maxFaces) + { + } + + EdgeFaces(const faceIndex_t _first, const faceIndex_t _second) + : first(_first), second(_second) + { + } }; -class RenderableWireframe : public OpenGLRenderable -{ +class RenderableWireframe : public OpenGLRenderable { public: -void render( RenderStateFlags state ) const { + void render(RenderStateFlags state) const + { #if 1 - glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_vertices->colour ); - glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_vertices->vertex ); - glDrawElements( GL_LINES, GLsizei( m_size << 1 ), RenderIndexTypeID, m_faceVertex.data() ); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_vertices->colour); + glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_vertices->vertex); + glDrawElements(GL_LINES, GLsizei(m_size << 1), RenderIndexTypeID, m_faceVertex.data()); #else - glBegin( GL_LINES ); + glBegin( GL_LINES ); for ( std::size_t i = 0; i < m_size; ++i ) { glVertex3fv( &m_vertices[m_faceVertex[i].first].vertex.x ); @@ -1322,2355 +1483,2581 @@ void render( RenderStateFlags state ) const { } glEnd(); #endif -} + } -Array m_faceVertex; -std::size_t m_size; -const PointVertex* m_vertices; + Array m_faceVertex; + std::size_t m_size; + const PointVertex *m_vertices; }; class Brush; -typedef std::vector brush_vector_t; -class BrushFilter -{ +typedef std::vector brush_vector_t; + +class BrushFilter { public: -virtual bool filter( const Brush& brush ) const = 0; + virtual bool filter(const Brush &brush) const = 0; }; -bool brush_filtered( Brush& brush ); -void add_brush_filter( BrushFilter& filter, int mask, bool invert = false ); +bool brush_filtered(Brush &brush); + +void add_brush_filter(BrushFilter &filter, int mask, bool invert = false); /// \brief Returns true if 'self' takes priority when building brush b-rep. -inline bool plane3_inside( const Plane3& self, const Plane3& other, bool selfIsLater ){ - if ( vector3_equal_epsilon( self.normal(), other.normal(), 0.001 ) ) { - // same plane? prefer the one with smaller index - if ( self.dist() == other.dist() ) { - return selfIsLater; - } - return self.dist() < other.dist(); - } - return true; +inline bool plane3_inside(const Plane3 &self, const Plane3 &other, bool selfIsLater) +{ + if (vector3_equal_epsilon(self.normal(), other.normal(), 0.001)) { + // same plane? prefer the one with smaller index + if (self.dist() == other.dist()) { + return selfIsLater; + } + return self.dist() < other.dist(); + } + return true; } typedef SmartPointer FaceSmartPointer; typedef std::vector Faces; /// \brief Returns the unique-id of the edge adjacent to \p faceVertex in the edge-pair for the set of \p faces. -inline FaceVertexId next_edge( const Faces& faces, FaceVertexId faceVertex ){ - std::size_t adjacent_face = faces[faceVertex.getFace()]->getWinding()[faceVertex.getVertex()].adjacent; - std::size_t adjacent_vertex = Winding_FindAdjacent( faces[adjacent_face]->getWinding(), faceVertex.getFace() ); +inline FaceVertexId next_edge(const Faces &faces, FaceVertexId faceVertex) +{ + std::size_t adjacent_face = faces[faceVertex.getFace()]->getWinding()[faceVertex.getVertex()].adjacent; + std::size_t adjacent_vertex = Winding_FindAdjacent(faces[adjacent_face]->getWinding(), faceVertex.getFace()); - ASSERT_MESSAGE( adjacent_vertex != c_brush_maxFaces, "connectivity data invalid" ); - if ( adjacent_vertex == c_brush_maxFaces ) { - return faceVertex; - } + ASSERT_MESSAGE(adjacent_vertex != c_brush_maxFaces, "connectivity data invalid"); + if (adjacent_vertex == c_brush_maxFaces) { + return faceVertex; + } - return FaceVertexId( adjacent_face, adjacent_vertex ); + return FaceVertexId(adjacent_face, adjacent_vertex); } /// \brief Returns the unique-id of the vertex adjacent to \p faceVertex in the vertex-ring for the set of \p faces. -inline FaceVertexId next_vertex( const Faces& faces, FaceVertexId faceVertex ){ - FaceVertexId nextEdge = next_edge( faces, faceVertex ); - return FaceVertexId( nextEdge.getFace(), Winding_next( faces[nextEdge.getFace()]->getWinding(), nextEdge.getVertex() ) ); -} - -class SelectableEdge +inline FaceVertexId next_vertex(const Faces &faces, FaceVertexId faceVertex) { -Vector3 getEdge() const { - const Winding& winding = getFace().getWinding(); - return vector3_mid( winding[m_faceVertex.getVertex()].vertex, winding[Winding_next( winding, m_faceVertex.getVertex() )].vertex ); -} - -public: -Faces& m_faces; -FaceVertexId m_faceVertex; - -SelectableEdge( Faces& faces, FaceVertexId faceVertex ) - : m_faces( faces ), m_faceVertex( faceVertex ){ -} -SelectableEdge& operator=( const SelectableEdge& other ){ - m_faceVertex = other.m_faceVertex; - return *this; -} - -Face& getFace() const { - return *m_faces[m_faceVertex.getFace()]; -} - -void testSelect( SelectionTest& test, SelectionIntersection& best ){ - test.TestPoint( getEdge(), best ); + FaceVertexId nextEdge = next_edge(faces, faceVertex); + return FaceVertexId(nextEdge.getFace(), + Winding_next(faces[nextEdge.getFace()]->getWinding(), nextEdge.getVertex())); } -}; -class SelectableVertex -{ -Vector3 getVertex() const { - return getFace().getWinding()[m_faceVertex.getVertex()].vertex; -} +class SelectableEdge { + Vector3 getEdge() const + { + const Winding &winding = getFace().getWinding(); + return vector3_mid(winding[m_faceVertex.getVertex()].vertex, + winding[Winding_next(winding, m_faceVertex.getVertex())].vertex); + } public: -Faces& m_faces; -FaceVertexId m_faceVertex; - -SelectableVertex( Faces& faces, FaceVertexId faceVertex ) - : m_faces( faces ), m_faceVertex( faceVertex ){ -} -SelectableVertex& operator=( const SelectableVertex& other ){ - m_faceVertex = other.m_faceVertex; - return *this; -} - -Face& getFace() const { - return *m_faces[m_faceVertex.getFace()]; -} - -void testSelect( SelectionTest& test, SelectionIntersection& best ){ - test.TestPoint( getVertex(), best ); -} + Faces &m_faces; + FaceVertexId m_faceVertex; + + SelectableEdge(Faces &faces, FaceVertexId faceVertex) + : m_faces(faces), m_faceVertex(faceVertex) + { + } + + SelectableEdge &operator=(const SelectableEdge &other) + { + m_faceVertex = other.m_faceVertex; + return *this; + } + + Face &getFace() const + { + return *m_faces[m_faceVertex.getFace()]; + } + + void testSelect(SelectionTest &test, SelectionIntersection &best) + { + test.TestPoint(getEdge(), best); + } }; -class BrushObserver -{ -public: -virtual void reserve( std::size_t size ) = 0; -virtual void clear() = 0; -virtual void push_back( Face& face ) = 0; -virtual void pop_back() = 0; -virtual void erase( std::size_t index ) = 0; -virtual void connectivityChanged() = 0; - -virtual void edge_clear() = 0; -virtual void edge_push_back( SelectableEdge& edge ) = 0; - -virtual void vertex_clear() = 0; -virtual void vertex_push_back( SelectableVertex& vertex ) = 0; - -virtual void DEBUG_verify() const = 0; -}; +class SelectableVertex { + Vector3 getVertex() const + { + return getFace().getWinding()[m_faceVertex.getVertex()].vertex; + } -class BrushVisitor -{ public: -virtual void visit( Face& face ) const = 0; + Faces &m_faces; + FaceVertexId m_faceVertex; + + SelectableVertex(Faces &faces, FaceVertexId faceVertex) + : m_faces(faces), m_faceVertex(faceVertex) + { + } + + SelectableVertex &operator=(const SelectableVertex &other) + { + m_faceVertex = other.m_faceVertex; + return *this; + } + + Face &getFace() const + { + return *m_faces[m_faceVertex.getFace()]; + } + + void testSelect(SelectionTest &test, SelectionIntersection &best) + { + test.TestPoint(getVertex(), best); + } }; -class Brush : - public TransformNode, - public Bounded, - public Cullable, - public Snappable, - public Undoable, - public FaceObserver, - public Filterable, - public Nameable, - public BrushDoom3 -{ -private: -scene::Node* m_node; -typedef UniqueSet Observers; -Observers m_observers; -UndoObserver* m_undoable_observer; -MapFile* m_map; - -// state -Faces m_faces; -// ---- - -// cached data compiled from state -Array m_faceCentroidPoints; -RenderablePointArray m_render_faces; - -Array m_uniqueVertexPoints; -typedef std::vector SelectableVertices; -SelectableVertices m_select_vertices; -RenderablePointArray m_render_vertices; - -Array m_uniqueEdgePoints; -typedef std::vector SelectableEdges; -SelectableEdges m_select_edges; -RenderablePointArray m_render_edges; - -Array m_edge_indices; -Array m_edge_faces; - -AABB m_aabb_local; -// ---- - -Callback m_evaluateTransform; -Callback m_boundsChanged; - -mutable bool m_planeChanged; // b-rep evaluation required -mutable bool m_transformChanged; // transform evaluation required -// ---- - +class BrushObserver { public: -STRING_CONSTANT( Name, "Brush" ); - -Callback m_lightsChanged; - -// static data -static Shader* m_state_point; -// ---- - -static EBrushType m_type; -static double m_maxWorldCoord; - -Brush( scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) : - m_node( &node ), - m_undoable_observer( 0 ), - m_map( 0 ), - m_render_faces( m_faceCentroidPoints, GL_POINTS ), - m_render_vertices( m_uniqueVertexPoints, GL_POINTS ), - m_render_edges( m_uniqueEdgePoints, GL_POINTS ), - m_evaluateTransform( evaluateTransform ), - m_boundsChanged( boundsChanged ), - m_planeChanged( false ), - m_transformChanged( false ){ - planeChanged(); -} -Brush( const Brush& other, scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) : - m_node( &node ), - m_undoable_observer( 0 ), - m_map( 0 ), - m_render_faces( m_faceCentroidPoints, GL_POINTS ), - m_render_vertices( m_uniqueVertexPoints, GL_POINTS ), - m_render_edges( m_uniqueEdgePoints, GL_POINTS ), - m_evaluateTransform( evaluateTransform ), - m_boundsChanged( boundsChanged ), - m_planeChanged( false ), - m_transformChanged( false ){ - copy( other ); -} -Brush( const Brush& other ) : - TransformNode( other ), - Bounded( other ), - Cullable( other ), - Snappable(), - Undoable( other ), - FaceObserver( other ), - Filterable( other ), - Nameable( other ), - BrushDoom3( other ), - m_node( 0 ), - m_undoable_observer( 0 ), - m_map( 0 ), - m_render_faces( m_faceCentroidPoints, GL_POINTS ), - m_render_vertices( m_uniqueVertexPoints, GL_POINTS ), - m_render_edges( m_uniqueEdgePoints, GL_POINTS ), - m_planeChanged( false ), - m_transformChanged( false ){ - copy( other ); -} -~Brush(){ - ASSERT_MESSAGE( m_observers.empty(), "Brush::~Brush: observers still attached" ); -} - -// assignment not supported -Brush& operator=( const Brush& other ); - -void setDoom3GroupOrigin( const Vector3& origin ){ - //globalOutputStream() << "func_static origin before: " << m_funcStaticOrigin << " after: " << origin << "\n"; - for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) - { - ( *i )->getPlane().m_funcStaticOrigin = origin; - ( *i )->getPlane().updateTranslated(); - ( *i )->planeChanged(); - } - planeChanged(); -} - -void attach( BrushObserver& observer ){ - for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) - { - observer.push_back( *( *i ) ); - } - - for ( SelectableEdges::iterator i = m_select_edges.begin(); i != m_select_edges.end(); ++i ) - { - observer.edge_push_back( *i ); - } - - for ( SelectableVertices::iterator i = m_select_vertices.begin(); i != m_select_vertices.end(); ++i ) - { - observer.vertex_push_back( *i ); - } - - m_observers.insert( &observer ); -} -void detach( BrushObserver& observer ){ - m_observers.erase( &observer ); -} - -void forEachFace( const BrushVisitor& visitor ) const { - for ( Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i ) - { - visitor.visit( *( *i ) ); - } -} + virtual void reserve(std::size_t size) = 0; -void forEachFace_instanceAttach( MapFile* map ) const { - for ( Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i ) - { - ( *i )->instanceAttach( map ); - } -} -void forEachFace_instanceDetach( MapFile* map ) const { - for ( Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i ) - { - ( *i )->instanceDetach( map ); - } -} + virtual void clear() = 0; -InstanceCounter m_instanceCounter; -void instanceAttach( const scene::Path& path ){ - if ( ++m_instanceCounter.m_count == 1 ) { - m_map = path_find_mapfile( path.begin(), path.end() ); - m_undoable_observer = GlobalUndoSystem().observer( this ); - GlobalFilterSystem().registerFilterable( *this ); - forEachFace_instanceAttach( m_map ); - } - else - { - ASSERT_MESSAGE( path_find_mapfile( path.begin(), path.end() ) == m_map, "node is instanced across more than one file" ); - } -} -void instanceDetach( const scene::Path& path ){ - if ( --m_instanceCounter.m_count == 0 ) { - forEachFace_instanceDetach( m_map ); - GlobalFilterSystem().unregisterFilterable( *this ); - m_map = 0; - m_undoable_observer = 0; - GlobalUndoSystem().release( this ); - } -} + virtual void push_back(Face &face) = 0; -// nameable -const char* name() const { - return "brush"; -} -void attach( const NameCallback& callback ){ -} -void detach( const NameCallback& callback ){ -} + virtual void pop_back() = 0; -// filterable -void updateFiltered(){ - if ( m_node != 0 ) { - if ( brush_filtered( *this ) ) { - m_node->enable( scene::Node::eFiltered ); - } - else - { - m_node->disable( scene::Node::eFiltered ); - } - } -} + virtual void erase(std::size_t index) = 0; -// observer -void planeChanged(){ - m_planeChanged = true; - aabbChanged(); - m_lightsChanged(); -} -void shaderChanged(){ - updateFiltered(); - planeChanged(); -} + virtual void connectivityChanged() = 0; -void evaluateBRep() const { - if ( m_planeChanged ) { - m_planeChanged = false; - const_cast( this )->buildBRep(); - } -} + virtual void edge_clear() = 0; -void transformChanged(){ - m_transformChanged = true; - planeChanged(); -} -typedef MemberCaller TransformChangedCaller; + virtual void edge_push_back(SelectableEdge &edge) = 0; -void evaluateTransform(){ - if ( m_transformChanged ) { - m_transformChanged = false; - revertTransform(); - m_evaluateTransform(); - } -} -const Matrix4& localToParent() const { - return g_matrix4_identity; -} -void aabbChanged(){ - m_boundsChanged(); -} -const AABB& localAABB() const { - evaluateBRep(); - return m_aabb_local; -} + virtual void vertex_clear() = 0; -VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const { - return test.TestAABB( m_aabb_local, localToWorld ); -} + virtual void vertex_push_back(SelectableVertex &vertex) = 0; -void renderComponents( SelectionSystem::EComponentMode mode, Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - switch ( mode ) - { - case SelectionSystem::eVertex: - renderer.addRenderable( m_render_vertices, localToWorld ); - break; - case SelectionSystem::eEdge: - renderer.addRenderable( m_render_edges, localToWorld ); - break; - case SelectionSystem::eFace: - renderer.addRenderable( m_render_faces, localToWorld ); - break; - default: - break; - } -} + virtual void DEBUG_verify() const = 0; +}; -void transform( const Matrix4& matrix ){ - bool mirror = matrix4_handedness( matrix ) == MATRIX4_LEFTHANDED; +class BrushVisitor { +public: + virtual void visit(Face &face) const = 0; +}; - for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) - { - ( *i )->transform( matrix, mirror ); - } -} -void snapto( float snap ){ - for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) - { - ( *i )->snapto( snap ); - } -} -void revertTransform(){ - for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) - { - ( *i )->revertTransform(); - } -} -void freezeTransform(){ - for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) - { - ( *i )->freezeTransform(); - } -} +class Brush : + public TransformNode, + public Bounded, + public Cullable, + public Snappable, + public Undoable, + public FaceObserver, + public Filterable, + public Nameable, + public BrushDoom3 { +private: + scene::Node *m_node; + typedef UniqueSet Observers; + Observers m_observers; + UndoObserver *m_undoable_observer; + MapFile *m_map; -/// \brief Returns the absolute index of the \p faceVertex. -std::size_t absoluteIndex( FaceVertexId faceVertex ){ - std::size_t index = 0; - for ( std::size_t i = 0; i < faceVertex.getFace(); ++i ) - { - index += m_faces[i]->getWinding().numpoints; - } - return index + faceVertex.getVertex(); -} - -void appendFaces( const Faces& other ){ - clear(); - for ( Faces::const_iterator i = other.begin(); i != other.end(); ++i ) - { - push_back( *i ); - } -} - -/// \brief The undo memento for a brush stores only the list of face references - the faces are not copied. -class BrushUndoMemento : public UndoMemento -{ -public: -BrushUndoMemento( const Faces& faces ) : m_faces( faces ){ -} -void release(){ - delete this; -} - -Faces m_faces; -}; - -void undoSave(){ - if ( m_map != 0 ) { - m_map->changed(); - } - if ( m_undoable_observer != 0 ) { - m_undoable_observer->save( this ); - } -} - -UndoMemento* exportState() const { - return new BrushUndoMemento( m_faces ); -} - -void importState( const UndoMemento* state ){ - undoSave(); - appendFaces( static_cast( state )->m_faces ); - planeChanged(); - - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->DEBUG_verify(); - } -} - -bool isDetail(){ - return !m_faces.empty() && m_faces.front()->isDetail(); -} - -/// \brief Appends a copy of \p face to the end of the face list. -Face* addFace( const Face& face ){ - if ( m_faces.size() == c_brush_maxFaces ) { - return 0; - } - undoSave(); - push_back( FaceSmartPointer( new Face( face, this ) ) ); - m_faces.back()->setDetail( isDetail() ); - planeChanged(); - return m_faces.back(); -} - -/// \brief Appends a new face constructed from the parameters to the end of the face list. -Face* addPlane( const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, const TextureProjection& projection ){ - if ( m_faces.size() == c_brush_maxFaces ) { - return 0; - } - undoSave(); - push_back( FaceSmartPointer( new Face( p0, p1, p2, shader, projection, this ) ) ); - m_faces.back()->setDetail( isDetail() ); - planeChanged(); - return m_faces.back(); -} - -static void constructStatic( EBrushType type ){ - m_type = type; - Face::m_type = type; - FacePlane::m_type = type; - - g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_QUAKE; - if ( m_type == eBrushTypeQuake3BP || m_type == eBrushTypeDoom3 || m_type == eBrushTypeQuake4 ) { - g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_BRUSHPRIMITIVES; - // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting - } - else if ( m_type == eBrushTypeHalfLife ) { - g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_HALFLIFE; - // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting - } - - Face::m_quantise = ( m_type == eBrushTypeQuake ) ? quantiseInteger : quantiseFloating; - - m_state_point = GlobalShaderCache().capture( "$POINT" ); -} -static void destroyStatic(){ - GlobalShaderCache().release( "$POINT" ); -} - -std::size_t DEBUG_size(){ - return m_faces.size(); -} - -typedef Faces::const_iterator const_iterator; - -const_iterator begin() const { - return m_faces.begin(); -} -const_iterator end() const { - return m_faces.end(); -} - -Face* back(){ - return m_faces.back(); -} -const Face* back() const { - return m_faces.back(); -} -void reserve( std::size_t count ){ - m_faces.reserve( count ); - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->reserve( count ); - } -} -void push_back( Faces::value_type face ){ - m_faces.push_back( face ); - if ( m_instanceCounter.m_count != 0 ) { - m_faces.back()->instanceAttach( m_map ); - } - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->push_back( *face ); - ( *i )->DEBUG_verify(); - } -} -void pop_back(){ - if ( m_instanceCounter.m_count != 0 ) { - m_faces.back()->instanceDetach( m_map ); - } - m_faces.pop_back(); - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->pop_back(); - ( *i )->DEBUG_verify(); - } -} -void erase( std::size_t index ){ - if ( m_instanceCounter.m_count != 0 ) { - m_faces[index]->instanceDetach( m_map ); - } - m_faces.erase( m_faces.begin() + index ); - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->erase( index ); - ( *i )->DEBUG_verify(); - } -} -void connectivityChanged(){ - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->connectivityChanged(); - } -} - - -void clear(){ - undoSave(); - if ( m_instanceCounter.m_count != 0 ) { - forEachFace_instanceDetach( m_map ); - } - m_faces.clear(); - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->clear(); - ( *i )->DEBUG_verify(); - } -} -std::size_t size() const { - return m_faces.size(); -} -bool empty() const { - return m_faces.empty(); -} - -/// \brief Returns true if any face of the brush contributes to the final B-Rep. -bool hasContributingFaces() const { - for ( const_iterator i = begin(); i != end(); ++i ) - { - if ( ( *i )->contributes() ) { - return true; - } - } - return false; -} - -/// \brief Removes faces that do not contribute to the brush. This is useful for cleaning up after CSG operations on the brush. -/// Note: removal of empty faces is not performed during direct brush manipulations, because it would make a manipulation irreversible if it created an empty face. -void removeEmptyFaces(){ - evaluateBRep(); - - { - std::size_t i = 0; - while ( i < m_faces.size() ) - { - if ( !m_faces[i]->contributes() ) { - erase( i ); - planeChanged(); - } - else - { - ++i; - } - } - } -} - -/// \brief Constructs \p winding from the intersection of \p plane with the other planes of the brush. -void windingForClipPlane( Winding& winding, const Plane3& plane ) const { - FixedWinding buffer[2]; - bool swap = false; - - // get a poly that covers an effectively infinite area - Winding_createInfinite( buffer[swap], plane, m_maxWorldCoord + 1 ); - - // chop the poly by all of the other faces - { - for ( std::size_t i = 0; i < m_faces.size(); ++i ) - { - const Face& clip = *m_faces[i]; - - if ( plane3_equal( clip.plane3(), plane ) - || !plane3_valid( clip.plane3() ) || !plane_unique( i ) - || plane3_opposing( plane, clip.plane3() ) ) { - continue; - } - - buffer[!swap].clear(); - -#if BRUSH_CONNECTIVITY_DEBUG - globalOutputStream() << "clip vs face: " << i << "\n"; -#endif - - { - // flip the plane, because we want to keep the back side - Plane3 clipPlane( vector3_negated( clip.plane3().normal() ), -clip.plane3().dist() ); - Winding_Clip( buffer[swap], plane, clipPlane, i, buffer[!swap] ); - } - -#if BRUSH_CONNECTIVITY_DEBUG - for ( FixedWinding::Points::iterator k = buffer[!swap].points.begin(), j = buffer[!swap].points.end() - 1; k != buffer[!swap].points.end(); j = k, ++k ) - { - if ( vector3_length_squared( vector3_subtracted( ( *k ).vertex, ( *j ).vertex ) ) < 1 ) { - globalOutputStream() << "v: " << std::distance( buffer[!swap].points.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n"; - } - } -#endif - - //ASSERT_MESSAGE(buffer[!swap].numpoints != 1, "created single-point winding"); - - swap = !swap; - } - } - - Winding_forFixedWinding( winding, buffer[swap] ); - -#if BRUSH_CONNECTIVITY_DEBUG - Winding_printConnectivity( winding ); - - for ( Winding::iterator i = winding.begin(), j = winding.end() - 1; i != winding.end(); j = i, ++i ) - { - if ( vector3_length_squared( vector3_subtracted( ( *i ).vertex, ( *j ).vertex ) ) < 1 ) { - globalOutputStream() << "v: " << std::distance( winding.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n"; - } - } -#endif -} - -void update_wireframe( RenderableWireframe& wire, const bool* faces_visible ) const { - wire.m_faceVertex.resize( m_edge_indices.size() ); - wire.m_vertices = m_uniqueVertexPoints.data(); - wire.m_size = 0; - for ( std::size_t i = 0; i < m_edge_faces.size(); ++i ) - { - if ( faces_visible[m_edge_faces[i].first] - || faces_visible[m_edge_faces[i].second] ) { - wire.m_faceVertex[wire.m_size++] = m_edge_indices[i]; - } - } -} - - -void update_faces_wireframe( Array& wire, const bool* faces_visible ) const { - std::size_t count = 0; - for ( std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i ) - { - if ( faces_visible[i] ) { - ++count; - } - } - - wire.resize( count ); - Array::iterator p = wire.begin(); - for ( std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i ) - { - if ( faces_visible[i] ) { - *p++ = m_faceCentroidPoints[i]; - } - } -} - -/// \brief Makes this brush a deep-copy of the \p other. -void copy( const Brush& other ){ - for ( Faces::const_iterator i = other.m_faces.begin(); i != other.m_faces.end(); ++i ) - { - addFace( *( *i ) ); - } - planeChanged(); -} - -private: -void edge_push_back( FaceVertexId faceVertex ){ - m_select_edges.push_back( SelectableEdge( m_faces, faceVertex ) ); - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->edge_push_back( m_select_edges.back() ); - } -} -void edge_clear(){ - m_select_edges.clear(); - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->edge_clear(); - } -} -void vertex_push_back( FaceVertexId faceVertex ){ - m_select_vertices.push_back( SelectableVertex( m_faces, faceVertex ) ); - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->vertex_push_back( m_select_vertices.back() ); - } -} -void vertex_clear(){ - m_select_vertices.clear(); - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->vertex_clear(); - } -} - -/// \brief Returns true if the face identified by \p index is preceded by another plane that takes priority over it. -bool plane_unique( std::size_t index ) const { - // duplicate plane - for ( std::size_t i = 0; i < m_faces.size(); ++i ) - { - if ( index != i && !plane3_inside( m_faces[index]->plane3(), m_faces[i]->plane3(), index < i ) ) { - return false; - } - } - return true; -} - -/// \brief Removes edges that are smaller than the tolerance used when generating brush windings. -void removeDegenerateEdges(){ - for ( std::size_t i = 0; i < m_faces.size(); ++i ) - { - Winding& winding = m_faces[i]->getWinding(); - for ( Winding::iterator j = winding.begin(); j != winding.end(); ) - { - std::size_t index = std::distance( winding.begin(), j ); - std::size_t next = Winding_next( winding, index ); - if ( Edge_isDegenerate( winding[index].vertex, winding[next].vertex ) ) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate edge adjacent to " << winding[index].adjacent << "\n"; -#endif - Winding& other = m_faces[winding[index].adjacent]->getWinding(); - std::size_t adjacent = Winding_FindAdjacent( other, i ); - if ( adjacent != c_brush_maxFaces ) { - other.erase( other.begin() + adjacent ); - } - winding.erase( j ); - } - else - { - ++j; - } - } - } -} - -/// \brief Invalidates faces that have only two vertices in their winding, while preserving edge-connectivity information. -void removeDegenerateFaces(){ - // save adjacency info for degenerate faces - for ( std::size_t i = 0; i < m_faces.size(); ++i ) - { - Winding& degen = m_faces[i]->getWinding(); - - if ( degen.numpoints == 2 ) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate winding adjacent to " << degen[0].adjacent << ", " << degen[1].adjacent << "\n"; -#endif - // this is an "edge" face, where the plane touches the edge of the brush - { - Winding& winding = m_faces[degen[0].adjacent]->getWinding(); - std::size_t index = Winding_FindAdjacent( winding, i ); - if ( index != c_brush_maxFaces ) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << degen[0].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[1].adjacent << "\n"; -#endif - winding[index].adjacent = degen[1].adjacent; - } - } - - { - Winding& winding = m_faces[degen[1].adjacent]->getWinding(); - std::size_t index = Winding_FindAdjacent( winding, i ); - if ( index != c_brush_maxFaces ) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << degen[1].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[0].adjacent << "\n"; -#endif - winding[index].adjacent = degen[0].adjacent; - } - } - - degen.resize( 0 ); - } - } -} - -/// \brief Removes edges that have the same adjacent-face as their immediate neighbour. -void removeDuplicateEdges(){ - // verify face connectivity graph - for ( std::size_t i = 0; i < m_faces.size(); ++i ) - { - //if(m_faces[i]->contributes()) - { - Winding& winding = m_faces[i]->getWinding(); - for ( std::size_t j = 0; j != winding.numpoints; ) - { - std::size_t next = Winding_next( winding, j ); - if ( winding[j].adjacent == winding[next].adjacent ) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": removed duplicate edge adjacent to face " << winding[j].adjacent << "\n"; -#endif - winding.erase( winding.begin() + next ); - } - else - { - ++j; - } - } - } - } -} - -/// \brief Removes edges that do not have a matching pair in their adjacent-face. -void verifyConnectivityGraph(){ - // verify face connectivity graph - for ( std::size_t i = 0; i < m_faces.size(); ++i ) - { - //if(m_faces[i]->contributes()) - { - Winding& winding = m_faces[i]->getWinding(); - for ( Winding::iterator j = winding.begin(); j != winding.end(); ) - { -#if BRUSH_CONNECTIVITY_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": adjacent to face " << ( *j ).adjacent << "\n"; -#endif - // remove unidirectional graph edges - if ( ( *j ).adjacent == c_brush_maxFaces - || Winding_FindAdjacent( m_faces[( *j ).adjacent]->getWinding(), i ) == c_brush_maxFaces ) { -#if BRUSH_CONNECTIVITY_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": removing unidirectional connectivity graph edge adjacent to face " << ( *j ).adjacent << "\n"; -#endif - winding.erase( j ); - } - else - { - ++j; - } - } - } - } -} - -/// \brief Returns true if the brush is a finite volume. A brush without a finite volume extends past the maximum world bounds and is not valid. -bool isBounded(){ - for ( const_iterator i = begin(); i != end(); ++i ) - { - if ( !( *i )->is_bounded() ) { - return false; - } - } - return true; -} - -/// \brief Constructs the polygon windings for each face of the brush. Also updates the brush bounding-box and face texture-coordinates. -bool buildWindings(){ - - { - m_aabb_local = AABB(); - - for ( std::size_t i = 0; i < m_faces.size(); ++i ) - { - Face& f = *m_faces[i]; - - if ( !plane3_valid( f.plane3() ) || !plane_unique( i ) ) { - f.getWinding().resize( 0 ); - } - else - { -#if BRUSH_CONNECTIVITY_DEBUG - globalOutputStream() << "face: " << i << "\n"; -#endif - windingForClipPlane( f.getWinding(), f.plane3() ); - - // update brush bounds - const Winding& winding = f.getWinding(); - for ( Winding::const_iterator i = winding.begin(); i != winding.end(); ++i ) - { - aabb_extend_by_point_safe( m_aabb_local, ( *i ).vertex ); - } - - // update texture coordinates - f.EmitTextureCoordinates(); - } - } - } - - bool degenerate = !isBounded(); - - if ( !degenerate ) { - // clean up connectivity information. - // these cleanups must be applied in a specific order. - removeDegenerateEdges(); - removeDegenerateFaces(); - removeDuplicateEdges(); - verifyConnectivityGraph(); - } - - return degenerate; -} - -/// \brief Constructs the face windings and updates anything that depends on them. -void buildBRep(); -}; - - - -class FaceInstance; - -class FaceInstanceSet -{ -typedef SelectionList FaceInstances; -FaceInstances m_faceInstances; -public: -void insert( FaceInstance& faceInstance ){ - m_faceInstances.append( faceInstance ); -} -void erase( FaceInstance& faceInstance ){ - m_faceInstances.erase( faceInstance ); -} - -template -void foreach( Functor functor ){ - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - functor( *( *i ) ); - } -} - -bool empty() const { - return m_faceInstances.empty(); -} -FaceInstance& last() const { - return m_faceInstances.back(); -} -}; - -extern FaceInstanceSet g_SelectedFaceInstances; - -typedef std::list VertexSelection; - -inline VertexSelection::iterator VertexSelection_find( VertexSelection& self, std::size_t value ){ - return std::find( self.begin(), self.end(), value ); -} - -inline VertexSelection::const_iterator VertexSelection_find( const VertexSelection& self, std::size_t value ){ - return std::find( self.begin(), self.end(), value ); -} - -inline VertexSelection::iterator VertexSelection_insert( VertexSelection& self, std::size_t value ){ - VertexSelection::iterator i = VertexSelection_find( self, value ); - if ( i == self.end() ) { - self.push_back( value ); - return --self.end(); - } - return i; -} -inline void VertexSelection_erase( VertexSelection& self, std::size_t value ){ - VertexSelection::iterator i = VertexSelection_find( self, value ); - if ( i != self.end() ) { - self.erase( i ); - } -} - -inline bool triangle_reversed( std::size_t x, std::size_t y, std::size_t z ){ - return !( ( x < y && y < z ) || ( z < x && x < y ) || ( y < z && z < x ) ); -} -template -inline Vector3 triangle_cross( const BasicVector3& x, const BasicVector3 y, const BasicVector3& z ){ - return vector3_cross( y - x, z - x ); -} -template -inline bool triangles_same_winding( const BasicVector3& x1, const BasicVector3 y1, const BasicVector3& z1, const BasicVector3& x2, const BasicVector3 y2, const BasicVector3& z2 ){ - return vector3_dot( triangle_cross( x1, y1, z1 ), triangle_cross( x2, y2, z2 ) ) > 0; -} - - -typedef const Plane3* PlanePointer; -typedef PlanePointer* PlanesIterator; - -class VectorLightList : public LightList -{ -typedef std::vector Lights; -Lights m_lights; -public: -void addLight( const RendererLight& light ){ - m_lights.push_back( &light ); -} -void clear(){ - m_lights.clear(); -} -void evaluateLights() const { -} -void lightsChanged() const { -} -void forEachLight( const RendererLightCallback& callback ) const { - for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i ) - { - callback( *( *i ) ); - } -} -}; - -class FaceInstance -{ -Face* m_face; -ObservedSelectable m_selectable; -ObservedSelectable m_selectableVertices; -ObservedSelectable m_selectableEdges; -SelectionChangeCallback m_selectionChanged; - -VertexSelection m_vertexSelection; -VertexSelection m_edgeSelection; - -public: -mutable VectorLightList m_lights; - -FaceInstance( Face& face, const SelectionChangeCallback& observer ) : - m_face( &face ), - m_selectable( SelectedChangedCaller( *this ) ), - m_selectableVertices( observer ), - m_selectableEdges( observer ), - m_selectionChanged( observer ){ -} -FaceInstance( const FaceInstance& other ) : - m_face( other.m_face ), - m_selectable( SelectedChangedCaller( *this ) ), - m_selectableVertices( other.m_selectableVertices ), - m_selectableEdges( other.m_selectableEdges ), - m_selectionChanged( other.m_selectionChanged ){ -} -FaceInstance& operator=( const FaceInstance& other ){ - m_face = other.m_face; - return *this; -} - -Face& getFace(){ - return *m_face; -} -const Face& getFace() const { - return *m_face; -} - -void selectedChanged( const Selectable& selectable ){ - if ( selectable.isSelected() ) { - g_SelectedFaceInstances.insert( *this ); - } - else - { - g_SelectedFaceInstances.erase( *this ); - } - m_selectionChanged( selectable ); -} -typedef MemberCaller SelectedChangedCaller; - -bool selectedVertices() const { - return !m_vertexSelection.empty(); -} -bool selectedEdges() const { - return !m_edgeSelection.empty(); -} -bool isSelected() const { - return m_selectable.isSelected(); -} - -bool selectedComponents() const { - return selectedVertices() || selectedEdges() || isSelected(); -} -bool selectedComponents( SelectionSystem::EComponentMode mode ) const { - switch ( mode ) - { - case SelectionSystem::eVertex: - return selectedVertices(); - case SelectionSystem::eEdge: - return selectedEdges(); - case SelectionSystem::eFace: - return isSelected(); - default: - return false; - } -} -void setSelected( SelectionSystem::EComponentMode mode, bool select ){ - switch ( mode ) - { - case SelectionSystem::eFace: - m_selectable.setSelected( select ); - break; - case SelectionSystem::eVertex: - ASSERT_MESSAGE( !select, "select-all not supported" ); - - m_vertexSelection.clear(); - m_selectableVertices.setSelected( false ); - break; - case SelectionSystem::eEdge: - ASSERT_MESSAGE( !select, "select-all not supported" ); - - m_edgeSelection.clear(); - m_selectableEdges.setSelected( false ); - break; - default: - break; - } -} - -template -void SelectedVertices_foreach( Functor functor ) const { - for ( VertexSelection::const_iterator i = m_vertexSelection.begin(); i != m_vertexSelection.end(); ++i ) - { - std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *i ); - if ( index != c_brush_maxFaces ) { - functor( getFace().getWinding()[index].vertex ); - } - } -} -template -void SelectedEdges_foreach( Functor functor ) const { - for ( VertexSelection::const_iterator i = m_edgeSelection.begin(); i != m_edgeSelection.end(); ++i ) - { - std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *i ); - if ( index != c_brush_maxFaces ) { - const Winding& winding = getFace().getWinding(); - std::size_t adjacent = Winding_next( winding, index ); - functor( vector3_mid( winding[index].vertex, winding[adjacent].vertex ) ); - } - } -} -template -void SelectedFaces_foreach( Functor functor ) const { - if ( isSelected() ) { - functor( centroid() ); - } -} - -template -void SelectedComponents_foreach( Functor functor ) const { - SelectedVertices_foreach( functor ); - SelectedEdges_foreach( functor ); - SelectedFaces_foreach( functor ); -} - -void iterate_selected( AABB& aabb ) const { - SelectedComponents_foreach([&](const Vector3 &point) { - aabb_extend_by_point_safe(aabb, point); - }); -} - -void iterate_selected( RenderablePointVector& points ) const { - SelectedComponents_foreach([&](const Vector3 &point) { - const Colour4b colour_selected(0, 0, 255, 255); - points.push_back(pointvertex_for_windingpoint(point, colour_selected)); - }); -} - -bool intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) const { - return m_face->intersectVolume( volume, localToWorld ); -} - -void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - if ( !m_face->isFiltered() && m_face->contributes() && intersectVolume( volume, localToWorld ) ) { - renderer.PushState(); - if ( selectedComponents() ) { - renderer.Highlight( Renderer::eFace ); - } - m_face->render( renderer, localToWorld ); - renderer.PopState(); - } -} - -void testSelect( SelectionTest& test, SelectionIntersection& best ){ - if ( !m_face->isFiltered() ) { - m_face->testSelect( test, best ); - } -} -void testSelect( Selector& selector, SelectionTest& test ){ - SelectionIntersection best; - testSelect( test, best ); - if ( best.valid() ) { - Selector_add( selector, m_selectable, best ); - } -} -void testSelect_centroid( Selector& selector, SelectionTest& test ){ - if ( m_face->contributes() && !m_face->isFiltered() ) { - SelectionIntersection best; - m_face->testSelect_centroid( test, best ); - if ( best.valid() ) { - Selector_add( selector, m_selectable, best ); - } - } -} - -void selectPlane( Selector& selector, const Line& line, PlanesIterator first, PlanesIterator last, const PlaneCallback& selectedPlaneCallback ){ - for ( Winding::const_iterator i = getFace().getWinding().begin(); i != getFace().getWinding().end(); ++i ) - { - Vector3 v( vector3_subtracted( line_closest_point( line, ( *i ).vertex ), ( *i ).vertex ) ); - double dot = vector3_dot( getFace().plane3().normal(), v ); - if ( dot <= 0 ) { - return; - } - } - - Selector_add( selector, m_selectable ); - - selectedPlaneCallback( getFace().plane3() ); -} -void selectReversedPlane( Selector& selector, const SelectedPlanes& selectedPlanes ){ - if ( selectedPlanes.contains( plane3_flipped( getFace().plane3() ) ) ) { - Selector_add( selector, m_selectable ); - } -} - -void transformComponents( const Matrix4& matrix ){ - if ( isSelected() ) { - m_face->transform( matrix, false ); - } - if ( selectedVertices() ) { - if ( m_vertexSelection.size() == 1 ) { - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); - m_face->assign_planepts( m_face->m_move_planeptsTransformed ); - } - else if ( m_vertexSelection.size() == 2 ) { - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[2] ); - m_face->assign_planepts( m_face->m_move_planeptsTransformed ); - } - else if ( m_vertexSelection.size() >= 3 ) { - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[0] ); - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[2] ); - m_face->assign_planepts( m_face->m_move_planeptsTransformed ); - } - } - if ( selectedEdges() ) { - if ( m_edgeSelection.size() == 1 ) { - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[0] ); - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); - m_face->assign_planepts( m_face->m_move_planeptsTransformed ); - } - else if ( m_edgeSelection.size() >= 2 ) { - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[0] ); - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); - matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[2] ); - m_face->assign_planepts( m_face->m_move_planeptsTransformed ); - } - } -} - -void snapto( float snap ){ - m_face->snapto( snap ); -} - -void snapComponents( float snap ){ - if ( isSelected() ) { - snapto( snap ); - } - if ( selectedVertices() ) { - vector3_snap( m_face->m_move_planepts[0], snap ); - vector3_snap( m_face->m_move_planepts[1], snap ); - vector3_snap( m_face->m_move_planepts[2], snap ); - m_face->assign_planepts( m_face->m_move_planepts ); - planepts_assign( m_face->m_move_planeptsTransformed, m_face->m_move_planepts ); - m_face->freezeTransform(); - } - if ( selectedEdges() ) { - vector3_snap( m_face->m_move_planepts[0], snap ); - vector3_snap( m_face->m_move_planepts[1], snap ); - vector3_snap( m_face->m_move_planepts[2], snap ); - m_face->assign_planepts( m_face->m_move_planepts ); - planepts_assign( m_face->m_move_planeptsTransformed, m_face->m_move_planepts ); - m_face->freezeTransform(); - } -} -void update_move_planepts_vertex( std::size_t index ){ - m_face->update_move_planepts_vertex( index, m_face->m_move_planepts ); -} -void update_move_planepts_vertex2( std::size_t index, std::size_t other ){ - const std::size_t numpoints = m_face->getWinding().numpoints; - ASSERT_MESSAGE( index < numpoints, "select_vertex: invalid index" ); - - const std::size_t opposite = Winding_Opposite( m_face->getWinding(), index, other ); - - if ( triangle_reversed( index, other, opposite ) ) { - std::swap( index, other ); - } - - ASSERT_MESSAGE( - triangles_same_winding( - m_face->getWinding()[opposite].vertex, - m_face->getWinding()[index].vertex, - m_face->getWinding()[other].vertex, - m_face->getWinding()[0].vertex, - m_face->getWinding()[1].vertex, - m_face->getWinding()[2].vertex - ), - "update_move_planepts_vertex2: error" - ); - - m_face->m_move_planepts[0] = m_face->getWinding()[opposite].vertex; - m_face->m_move_planepts[1] = m_face->getWinding()[index].vertex; - m_face->m_move_planepts[2] = m_face->getWinding()[other].vertex; - planepts_quantise( m_face->m_move_planepts, GRID_MIN ); // winding points are very inaccurate -} -void update_selection_vertex(){ - if ( m_vertexSelection.size() == 0 ) { - m_selectableVertices.setSelected( false ); - } - else - { - m_selectableVertices.setSelected( true ); - - if ( m_vertexSelection.size() == 1 ) { - std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *m_vertexSelection.begin() ); - - if ( index != c_brush_maxFaces ) { - update_move_planepts_vertex( index ); - } - } - else if ( m_vertexSelection.size() == 2 ) { - std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *m_vertexSelection.begin() ); - std::size_t other = Winding_FindAdjacent( getFace().getWinding(), *( ++m_vertexSelection.begin() ) ); - - if ( index != c_brush_maxFaces - && other != c_brush_maxFaces ) { - update_move_planepts_vertex2( index, other ); - } - } - } -} -void select_vertex( std::size_t index, bool select ){ - if ( select ) { - VertexSelection_insert( m_vertexSelection, getFace().getWinding()[index].adjacent ); - } - else - { - VertexSelection_erase( m_vertexSelection, getFace().getWinding()[index].adjacent ); - } - - SceneChangeNotify(); - update_selection_vertex(); -} - -bool selected_vertex( std::size_t index ) const { - return VertexSelection_find( m_vertexSelection, getFace().getWinding()[index].adjacent ) != m_vertexSelection.end(); -} - -void update_move_planepts_edge( std::size_t index ){ - std::size_t numpoints = m_face->getWinding().numpoints; - ASSERT_MESSAGE( index < numpoints, "select_edge: invalid index" ); - - std::size_t adjacent = Winding_next( m_face->getWinding(), index ); - std::size_t opposite = Winding_Opposite( m_face->getWinding(), index ); - m_face->m_move_planepts[0] = m_face->getWinding()[index].vertex; - m_face->m_move_planepts[1] = m_face->getWinding()[adjacent].vertex; - m_face->m_move_planepts[2] = m_face->getWinding()[opposite].vertex; - planepts_quantise( m_face->m_move_planepts, GRID_MIN ); // winding points are very inaccurate -} -void update_selection_edge(){ - if ( m_edgeSelection.size() == 0 ) { - m_selectableEdges.setSelected( false ); - } - else - { - m_selectableEdges.setSelected( true ); - - if ( m_edgeSelection.size() == 1 ) { - std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *m_edgeSelection.begin() ); - - if ( index != c_brush_maxFaces ) { - update_move_planepts_edge( index ); - } - } - } -} -void select_edge( std::size_t index, bool select ){ - if ( select ) { - VertexSelection_insert( m_edgeSelection, getFace().getWinding()[index].adjacent ); - } - else - { - VertexSelection_erase( m_edgeSelection, getFace().getWinding()[index].adjacent ); - } - - SceneChangeNotify(); - update_selection_edge(); -} - -bool selected_edge( std::size_t index ) const { - return VertexSelection_find( m_edgeSelection, getFace().getWinding()[index].adjacent ) != m_edgeSelection.end(); -} - -const Vector3& centroid() const { - return m_face->centroid(); -} - -void connectivityChanged(){ - // This occurs when a face is added or removed. - // The current vertex and edge selections no longer valid and must be cleared. - m_vertexSelection.clear(); - m_selectableVertices.setSelected( false ); - m_edgeSelection.clear(); - m_selectableEdges.setSelected( false ); -} -}; - -class BrushClipPlane : public OpenGLRenderable -{ -Plane3 m_plane; -Winding m_winding; -static Shader* m_state; -public: -static void constructStatic(){ - m_state = GlobalShaderCache().capture( "$CLIPPER_OVERLAY" ); -} -static void destroyStatic(){ - GlobalShaderCache().release( "$CLIPPER_OVERLAY" ); -} - -void setPlane( const Brush& brush, const Plane3& plane ){ - m_plane = plane; - if ( plane3_valid( m_plane ) ) { - brush.windingForClipPlane( m_winding, m_plane ); - } - else - { - m_winding.resize( 0 ); - } -} - -void render( RenderStateFlags state ) const { - if ( ( state & RENDER_FILL ) != 0 ) { - Winding_Draw( m_winding, m_plane.normal(), state ); - } - else - { - Winding_DrawWireframe( m_winding ); - - // also draw a line indicating the direction of the cut - Vector3 lineverts[2]; - Winding_Centroid( m_winding, m_plane, lineverts[0] ); - lineverts[1] = vector3_added( lineverts[0], vector3_scaled( m_plane.normal(), Brush::m_maxWorldCoord * 4 ) ); - - glVertexPointer( 3, GL_FLOAT, sizeof( Vector3 ), &lineverts[0] ); - glDrawArrays( GL_LINES, 0, GLsizei( 2 ) ); - } -} - -void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - renderer.SetState( m_state, Renderer::eWireframeOnly ); - renderer.SetState( m_state, Renderer::eFullMaterials ); - renderer.addRenderable( *this, localToWorld ); -} -}; - -inline void Face_addLight( const FaceInstance& face, const Matrix4& localToWorld, const RendererLight& light ){ - const Plane3& facePlane = face.getFace().plane3(); - const Vector3& origin = light.aabb().origin; - Plane3 tmp( plane3_transformed( Plane3( facePlane.normal(), -facePlane.dist() ), localToWorld ) ); - if ( !plane3_test_point( tmp, origin ) - || !plane3_test_point( tmp, vector3_added( origin, light.offset() ) ) ) { - face.m_lights.addLight( light ); - } -} - - - -typedef std::vector FaceInstances; - -class EdgeInstance : public Selectable -{ -FaceInstances& m_faceInstances; -SelectableEdge* m_edge; - -void select_edge( bool select ){ - FaceVertexId faceVertex = m_edge->m_faceVertex; - m_faceInstances[faceVertex.getFace()].select_edge( faceVertex.getVertex(), select ); - faceVertex = next_edge( m_edge->m_faces, faceVertex ); - m_faceInstances[faceVertex.getFace()].select_edge( faceVertex.getVertex(), select ); -} -bool selected_edge() const { - FaceVertexId faceVertex = m_edge->m_faceVertex; - if ( !m_faceInstances[faceVertex.getFace()].selected_edge( faceVertex.getVertex() ) ) { - return false; - } - faceVertex = next_edge( m_edge->m_faces, faceVertex ); - if ( !m_faceInstances[faceVertex.getFace()].selected_edge( faceVertex.getVertex() ) ) { - return false; - } - - return true; -} - -public: -EdgeInstance( FaceInstances& faceInstances, SelectableEdge& edge ) - : m_faceInstances( faceInstances ), m_edge( &edge ){ -} -EdgeInstance& operator=( const EdgeInstance& other ){ - m_edge = other.m_edge; - return *this; -} - -void setSelected( bool select ){ - select_edge( select ); -} -bool isSelected() const { - return selected_edge(); -} - - -void testSelect( Selector& selector, SelectionTest& test ){ - SelectionIntersection best; - m_edge->testSelect( test, best ); - if ( best.valid() ) { - Selector_add( selector, *this, best ); - } -} -}; - -class VertexInstance : public Selectable -{ -FaceInstances& m_faceInstances; -SelectableVertex* m_vertex; - -void select_vertex( bool select ){ - FaceVertexId faceVertex = m_vertex->m_faceVertex; - do - { - m_faceInstances[faceVertex.getFace()].select_vertex( faceVertex.getVertex(), select ); - faceVertex = next_vertex( m_vertex->m_faces, faceVertex ); - } - while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() ); -} -bool selected_vertex() const { - FaceVertexId faceVertex = m_vertex->m_faceVertex; - do - { - if ( !m_faceInstances[faceVertex.getFace()].selected_vertex( faceVertex.getVertex() ) ) { - return false; - } - faceVertex = next_vertex( m_vertex->m_faces, faceVertex ); - } - while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() ); - return true; -} - -public: -VertexInstance( FaceInstances& faceInstances, SelectableVertex& vertex ) - : m_faceInstances( faceInstances ), m_vertex( &vertex ){ -} -VertexInstance& operator=( const VertexInstance& other ){ - m_vertex = other.m_vertex; - return *this; -} - -void setSelected( bool select ){ - select_vertex( select ); -} -bool isSelected() const { - return selected_vertex(); -} - -void testSelect( Selector& selector, SelectionTest& test ){ - SelectionIntersection best; - m_vertex->testSelect( test, best ); - if ( best.valid() ) { - Selector_add( selector, *this, best ); - } -} -}; - -class BrushInstanceVisitor -{ -public: -virtual void visit( FaceInstance& face ) const = 0; -}; - -class BrushInstance : - public BrushObserver, - public scene::Instance, - public Selectable, - public Renderable, - public SelectionTestable, - public ComponentSelectionTestable, - public ComponentEditable, - public ComponentSnappable, - public PlaneSelectable, - public LightCullable -{ -class TypeCasts -{ -InstanceTypeCastTable m_casts; -public: -TypeCasts(){ - InstanceStaticCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceIdentityCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} -}; +// state + Faces m_faces; +// ---- +// cached data compiled from state + Array m_faceCentroidPoints; + RenderablePointArray m_render_faces; -Brush& m_brush; + Array m_uniqueVertexPoints; + typedef std::vector SelectableVertices; + SelectableVertices m_select_vertices; + RenderablePointArray m_render_vertices; -FaceInstances m_faceInstances; + Array m_uniqueEdgePoints; + typedef std::vector SelectableEdges; + SelectableEdges m_select_edges; + RenderablePointArray m_render_edges; -typedef std::vector EdgeInstances; -EdgeInstances m_edgeInstances; -typedef std::vector VertexInstances; -VertexInstances m_vertexInstances; + Array m_edge_indices; + Array m_edge_faces; -ObservedSelectable m_selectable; + AABB m_aabb_local; +// ---- -mutable RenderableWireframe m_render_wireframe; -mutable RenderablePointVector m_render_selected; -mutable AABB m_aabb_component; -mutable Array m_faceCentroidPointsCulled; -RenderablePointArray m_render_faces_wireframe; -mutable bool m_viewChanged; // requires re-evaluation of view-dependent cached data + Callback m_evaluateTransform; + Callback m_boundsChanged; -BrushClipPlane m_clipPlane; + mutable bool m_planeChanged; // b-rep evaluation required + mutable bool m_transformChanged; // transform evaluation required +// ---- -static Shader* m_state_selpoint; +public: + STRING_CONSTANT(Name, "Brush"); -const LightList* m_lightList; + Callback m_lightsChanged; -TransformModifier m_transform; +// static data + static Shader *m_state_point; +// ---- -BrushInstance( const BrushInstance& other ); // NOT COPYABLE -BrushInstance& operator=( const BrushInstance& other ); // NOT ASSIGNABLE -public: -static Counter* m_counter; + static EBrushType m_type; + static double m_maxWorldCoord; + + Brush(scene::Node &node, const Callback &evaluateTransform, const Callback &boundsChanged) : + m_node(&node), + m_undoable_observer(0), + m_map(0), + m_render_faces(m_faceCentroidPoints, GL_POINTS), + m_render_vertices(m_uniqueVertexPoints, GL_POINTS), + m_render_edges(m_uniqueEdgePoints, GL_POINTS), + m_evaluateTransform(evaluateTransform), + m_boundsChanged(boundsChanged), + m_planeChanged(false), + m_transformChanged(false) + { + planeChanged(); + } + + Brush(const Brush &other, scene::Node &node, const Callback &evaluateTransform, + const Callback &boundsChanged) : + m_node(&node), + m_undoable_observer(0), + m_map(0), + m_render_faces(m_faceCentroidPoints, GL_POINTS), + m_render_vertices(m_uniqueVertexPoints, GL_POINTS), + m_render_edges(m_uniqueEdgePoints, GL_POINTS), + m_evaluateTransform(evaluateTransform), + m_boundsChanged(boundsChanged), + m_planeChanged(false), + m_transformChanged(false) + { + copy(other); + } + + Brush(const Brush &other) : + TransformNode(other), + Bounded(other), + Cullable(other), + Snappable(), + Undoable(other), + FaceObserver(other), + Filterable(other), + Nameable(other), + BrushDoom3(other), + m_node(0), + m_undoable_observer(0), + m_map(0), + m_render_faces(m_faceCentroidPoints, GL_POINTS), + m_render_vertices(m_uniqueVertexPoints, GL_POINTS), + m_render_edges(m_uniqueEdgePoints, GL_POINTS), + m_planeChanged(false), + m_transformChanged(false) + { + copy(other); + } + + ~Brush() + { + ASSERT_MESSAGE(m_observers.empty(), "Brush::~Brush: observers still attached"); + } -typedef LazyStatic StaticTypeCasts; +// assignment not supported + Brush &operator=(const Brush &other); + + void setDoom3GroupOrigin(const Vector3 &origin) + { + //globalOutputStream() << "func_static origin before: " << m_funcStaticOrigin << " after: " << origin << "\n"; + for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { + (*i)->getPlane().m_funcStaticOrigin = origin; + (*i)->getPlane().updateTranslated(); + (*i)->planeChanged(); + } + planeChanged(); + } + + void attach(BrushObserver &observer) + { + for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { + observer.push_back(*(*i)); + } + + for (SelectableEdges::iterator i = m_select_edges.begin(); i != m_select_edges.end(); ++i) { + observer.edge_push_back(*i); + } + + for (SelectableVertices::iterator i = m_select_vertices.begin(); i != m_select_vertices.end(); ++i) { + observer.vertex_push_back(*i); + } + + m_observers.insert(&observer); + } + + void detach(BrushObserver &observer) + { + m_observers.erase(&observer); + } + + void forEachFace(const BrushVisitor &visitor) const + { + for (Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i) { + visitor.visit(*(*i)); + } + } + + void forEachFace_instanceAttach(MapFile *map) const + { + for (Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i) { + (*i)->instanceAttach(map); + } + } + + void forEachFace_instanceDetach(MapFile *map) const + { + for (Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i) { + (*i)->instanceDetach(map); + } + } + + InstanceCounter m_instanceCounter; + + void instanceAttach(const scene::Path &path) + { + if (++m_instanceCounter.m_count == 1) { + m_map = path_find_mapfile(path.begin(), path.end()); + m_undoable_observer = GlobalUndoSystem().observer(this); + GlobalFilterSystem().registerFilterable(*this); + forEachFace_instanceAttach(m_map); + } else { + ASSERT_MESSAGE(path_find_mapfile(path.begin(), path.end()) == m_map, + "node is instanced across more than one file"); + } + } + + void instanceDetach(const scene::Path &path) + { + if (--m_instanceCounter.m_count == 0) { + forEachFace_instanceDetach(m_map); + GlobalFilterSystem().unregisterFilterable(*this); + m_map = 0; + m_undoable_observer = 0; + GlobalUndoSystem().release(this); + } + } -void lightsChanged(){ - m_lightList->lightsChanged(); -} -typedef MemberCaller LightsChangedCaller; - -STRING_CONSTANT( Name, "BrushInstance" ); - -BrushInstance( const scene::Path& path, scene::Instance* parent, Brush& brush ) : - Instance( path, parent, this, StaticTypeCasts::instance().get() ), - m_brush( brush ), - m_selectable( SelectedChangedCaller( *this ) ), - m_render_selected( GL_POINTS ), - m_render_faces_wireframe( m_faceCentroidPointsCulled, GL_POINTS ), - m_viewChanged( false ), - m_transform( Brush::TransformChangedCaller( m_brush ), ApplyTransformCaller( *this ) ){ - m_brush.instanceAttach( Instance::path() ); - m_brush.attach( *this ); - m_counter->increment(); - - m_lightList = &GlobalShaderCache().attach( *this ); - m_brush.m_lightsChanged = LightsChangedCaller( *this ); ///\todo Make this work with instancing. - - Instance::setTransformChangedCallback( LightsChangedCaller( *this ) ); -} -~BrushInstance(){ - Instance::setTransformChangedCallback( Callback() ); +// nameable + const char *name() const + { + return "brush"; + } - m_brush.m_lightsChanged = Callback(); - GlobalShaderCache().detach( *this ); + void attach(const NameCallback &callback) + { + } - m_counter->decrement(); - m_brush.detach( *this ); - m_brush.instanceDetach( Instance::path() ); -} + void detach(const NameCallback &callback) + { + } -Brush& getBrush(){ - return m_brush; -} -const Brush& getBrush() const { - return m_brush; -} +// filterable + void updateFiltered() + { + if (m_node != 0) { + if (brush_filtered(*this)) { + m_node->enable(scene::Node::eFiltered); + } else { + m_node->disable(scene::Node::eFiltered); + } + } + } -Bounded& get( NullType){ - return m_brush; -} -Cullable& get( NullType){ - return m_brush; -} -Transformable& get( NullType){ - return m_transform; -} +// observer + void planeChanged() + { + m_planeChanged = true; + aabbChanged(); + m_lightsChanged(); + } + + void shaderChanged() + { + updateFiltered(); + planeChanged(); + } + + void evaluateBRep() const + { + if (m_planeChanged) { + m_planeChanged = false; + const_cast( this )->buildBRep(); + } + } + + void transformChanged() + { + m_transformChanged = true; + planeChanged(); + } + + typedef MemberCaller TransformChangedCaller; + + void evaluateTransform() + { + if (m_transformChanged) { + m_transformChanged = false; + revertTransform(); + m_evaluateTransform(); + } + } + + const Matrix4 &localToParent() const + { + return g_matrix4_identity; + } + + void aabbChanged() + { + m_boundsChanged(); + } + + const AABB &localAABB() const + { + evaluateBRep(); + return m_aabb_local; + } + + VolumeIntersectionValue intersectVolume(const VolumeTest &test, const Matrix4 &localToWorld) const + { + return test.TestAABB(m_aabb_local, localToWorld); + } + + void renderComponents(SelectionSystem::EComponentMode mode, Renderer &renderer, const VolumeTest &volume, + const Matrix4 &localToWorld) const + { + switch (mode) { + case SelectionSystem::eVertex: + renderer.addRenderable(m_render_vertices, localToWorld); + break; + case SelectionSystem::eEdge: + renderer.addRenderable(m_render_edges, localToWorld); + break; + case SelectionSystem::eFace: + renderer.addRenderable(m_render_faces, localToWorld); + break; + default: + break; + } + } + + void transform(const Matrix4 &matrix) + { + bool mirror = matrix4_handedness(matrix) == MATRIX4_LEFTHANDED; + + for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { + (*i)->transform(matrix, mirror); + } + } + + void snapto(float snap) + { + for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { + (*i)->snapto(snap); + } + } + + void revertTransform() + { + for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { + (*i)->revertTransform(); + } + } + + void freezeTransform() + { + for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { + (*i)->freezeTransform(); + } + } -void selectedChanged( const Selectable& selectable ){ - GlobalSelectionSystem().getObserver ( SelectionSystem::ePrimitive )( selectable ); - GlobalSelectionSystem().onSelectedChanged( *this, selectable ); +/// \brief Returns the absolute index of the \p faceVertex. + std::size_t absoluteIndex(FaceVertexId faceVertex) + { + std::size_t index = 0; + for (std::size_t i = 0; i < faceVertex.getFace(); ++i) { + index += m_faces[i]->getWinding().numpoints; + } + return index + faceVertex.getVertex(); + } + + void appendFaces(const Faces &other) + { + clear(); + for (Faces::const_iterator i = other.begin(); i != other.end(); ++i) { + push_back(*i); + } + } - Instance::selectedChanged(); -} -typedef MemberCaller SelectedChangedCaller; +/// \brief The undo memento for a brush stores only the list of face references - the faces are not copied. + class BrushUndoMemento : public UndoMemento { + public: + BrushUndoMemento(const Faces &faces) : m_faces(faces) + { + } + + void release() + { + delete this; + } + + Faces m_faces; + }; + + void undoSave() + { + if (m_map != 0) { + m_map->changed(); + } + if (m_undoable_observer != 0) { + m_undoable_observer->save(this); + } + } + + UndoMemento *exportState() const + { + return new BrushUndoMemento(m_faces); + } + + void importState(const UndoMemento *state) + { + undoSave(); + appendFaces(static_cast( state )->m_faces); + planeChanged(); + + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->DEBUG_verify(); + } + } + + bool isDetail() + { + return !m_faces.empty() && m_faces.front()->isDetail(); + } -void selectedChangedComponent( const Selectable& selectable ){ - GlobalSelectionSystem().getObserver ( SelectionSystem::eComponent )( selectable ); - GlobalSelectionSystem().onComponentSelection( *this, selectable ); -} -typedef MemberCaller SelectedChangedComponentCaller; +/// \brief Appends a copy of \p face to the end of the face list. + Face *addFace(const Face &face) + { + if (m_faces.size() == c_brush_maxFaces) { + return 0; + } + undoSave(); + push_back(FaceSmartPointer(new Face(face, this))); + m_faces.back()->setDetail(isDetail()); + planeChanged(); + return m_faces.back(); + } -const BrushInstanceVisitor& forEachFaceInstance( const BrushInstanceVisitor& visitor ){ - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - visitor.visit( *i ); - } - return visitor; -} +/// \brief Appends a new face constructed from the parameters to the end of the face list. + Face *addPlane(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, const char *shader, + const TextureProjection &projection) + { + if (m_faces.size() == c_brush_maxFaces) { + return 0; + } + undoSave(); + push_back(FaceSmartPointer(new Face(p0, p1, p2, shader, projection, this))); + m_faces.back()->setDetail(isDetail()); + planeChanged(); + return m_faces.back(); + } + + static void constructStatic(EBrushType type) + { + m_type = type; + Face::m_type = type; + FacePlane::m_type = type; + + g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_QUAKE; + if (m_type == eBrushTypeQuake3BP || m_type == eBrushTypeDoom3 || m_type == eBrushTypeQuake4) { + g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_BRUSHPRIMITIVES; + // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting + } else if (m_type == eBrushTypeHalfLife) { + g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_HALFLIFE; + // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting + } + + Face::m_quantise = (m_type == eBrushTypeQuake) ? quantiseInteger : quantiseFloating; + + m_state_point = GlobalShaderCache().capture("$POINT"); + } + + static void destroyStatic() + { + GlobalShaderCache().release("$POINT"); + } + + std::size_t DEBUG_size() + { + return m_faces.size(); + } + + typedef Faces::const_iterator const_iterator; + + const_iterator begin() const + { + return m_faces.begin(); + } + + const_iterator end() const + { + return m_faces.end(); + } + + Face *back() + { + return m_faces.back(); + } + + const Face *back() const + { + return m_faces.back(); + } + + void reserve(std::size_t count) + { + m_faces.reserve(count); + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->reserve(count); + } + } + + void push_back(Faces::value_type face) + { + m_faces.push_back(face); + if (m_instanceCounter.m_count != 0) { + m_faces.back()->instanceAttach(m_map); + } + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->push_back(*face); + (*i)->DEBUG_verify(); + } + } + + void pop_back() + { + if (m_instanceCounter.m_count != 0) { + m_faces.back()->instanceDetach(m_map); + } + m_faces.pop_back(); + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->pop_back(); + (*i)->DEBUG_verify(); + } + } + + void erase(std::size_t index) + { + if (m_instanceCounter.m_count != 0) { + m_faces[index]->instanceDetach(m_map); + } + m_faces.erase(m_faces.begin() + index); + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->erase(index); + (*i)->DEBUG_verify(); + } + } + + void connectivityChanged() + { + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->connectivityChanged(); + } + } + + + void clear() + { + undoSave(); + if (m_instanceCounter.m_count != 0) { + forEachFace_instanceDetach(m_map); + } + m_faces.clear(); + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->clear(); + (*i)->DEBUG_verify(); + } + } + + std::size_t size() const + { + return m_faces.size(); + } + + bool empty() const + { + return m_faces.empty(); + } -static void constructStatic(){ - m_state_selpoint = GlobalShaderCache().capture( "$SELPOINT" ); -} -static void destroyStatic(){ - GlobalShaderCache().release( "$SELPOINT" ); -} +/// \brief Returns true if any face of the brush contributes to the final B-Rep. + bool hasContributingFaces() const + { + for (const_iterator i = begin(); i != end(); ++i) { + if ((*i)->contributes()) { + return true; + } + } + return false; + } -void clear(){ - m_faceInstances.clear(); -} -void reserve( std::size_t size ){ - m_faceInstances.reserve( size ); -} +/// \brief Removes faces that do not contribute to the brush. This is useful for cleaning up after CSG operations on the brush. +/// Note: removal of empty faces is not performed during direct brush manipulations, because it would make a manipulation irreversible if it created an empty face. + void removeEmptyFaces() + { + evaluateBRep(); + + { + std::size_t i = 0; + while (i < m_faces.size()) { + if (!m_faces[i]->contributes()) { + erase(i); + planeChanged(); + } else { + ++i; + } + } + } + } -void push_back( Face& face ){ - m_faceInstances.push_back( FaceInstance( face, SelectedChangedComponentCaller( *this ) ) ); -} -void pop_back(){ - ASSERT_MESSAGE( !m_faceInstances.empty(), "erasing invalid element" ); - m_faceInstances.pop_back(); -} -void erase( std::size_t index ){ - ASSERT_MESSAGE( index < m_faceInstances.size(), "erasing invalid element" ); - m_faceInstances.erase( m_faceInstances.begin() + index ); -} -void connectivityChanged(){ - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).connectivityChanged(); - } -} +/// \brief Constructs \p winding from the intersection of \p plane with the other planes of the brush. + void windingForClipPlane(Winding &winding, const Plane3 &plane) const + { + FixedWinding buffer[2]; + bool swap = false; -void edge_clear(){ - m_edgeInstances.clear(); -} -void edge_push_back( SelectableEdge& edge ){ - m_edgeInstances.push_back( EdgeInstance( m_faceInstances, edge ) ); -} + // get a poly that covers an effectively infinite area + Winding_createInfinite(buffer[swap], plane, m_maxWorldCoord + 1); -void vertex_clear(){ - m_vertexInstances.clear(); -} -void vertex_push_back( SelectableVertex& vertex ){ - m_vertexInstances.push_back( VertexInstance( m_faceInstances, vertex ) ); -} + // chop the poly by all of the other faces + { + for (std::size_t i = 0; i < m_faces.size(); ++i) { + const Face &clip = *m_faces[i]; -void DEBUG_verify() const { - ASSERT_MESSAGE( m_faceInstances.size() == m_brush.DEBUG_size(), "FATAL: mismatch" ); -} + if (plane3_equal(clip.plane3(), plane) + || !plane3_valid(clip.plane3()) || !plane_unique(i) + || plane3_opposing(plane, clip.plane3())) { + continue; + } -bool isSelected() const { - return m_selectable.isSelected(); -} -void setSelected( bool select ){ - m_selectable.setSelected( select ); -} + buffer[!swap].clear(); -void update_selected() const { - m_render_selected.clear(); - for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - if ( ( *i ).getFace().contributes() ) { - ( *i ).iterate_selected( m_render_selected ); - } - } -} +#if BRUSH_CONNECTIVITY_DEBUG + globalOutputStream() << "clip vs face: " << i << "\n"; +#endif -void evaluateViewDependent( const VolumeTest& volume, const Matrix4& localToWorld ) const { - if ( m_viewChanged ) { - m_viewChanged = false; + { + // flip the plane, because we want to keep the back side + Plane3 clipPlane(vector3_negated(clip.plane3().normal()), -clip.plane3().dist()); + Winding_Clip(buffer[swap], plane, clipPlane, i, buffer[!swap]); + } - bool faces_visible[c_brush_maxFaces]; - { - bool* j = faces_visible; - for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i, ++j ) +#if BRUSH_CONNECTIVITY_DEBUG + for ( FixedWinding::Points::iterator k = buffer[!swap].points.begin(), j = buffer[!swap].points.end() - 1; k != buffer[!swap].points.end(); j = k, ++k ) { - *j = ( *i ).intersectVolume( volume, localToWorld ); + if ( vector3_length_squared( vector3_subtracted( ( *k ).vertex, ( *j ).vertex ) ) < 1 ) { + globalOutputStream() << "v: " << std::distance( buffer[!swap].points.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n"; + } } - } - - m_brush.update_wireframe( m_render_wireframe, faces_visible ); - m_brush.update_faces_wireframe( m_faceCentroidPointsCulled, faces_visible ); - } -} - -void renderComponentsSelected( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - m_brush.evaluateBRep(); +#endif - update_selected(); - if ( !m_render_selected.empty() ) { - renderer.Highlight( Renderer::ePrimitive, false ); - renderer.SetState( m_state_selpoint, Renderer::eWireframeOnly ); - renderer.SetState( m_state_selpoint, Renderer::eFullMaterials ); - renderer.addRenderable( m_render_selected, localToWorld ); - } -} + //ASSERT_MESSAGE(buffer[!swap].numpoints != 1, "created single-point winding"); -void renderComponents( Renderer& renderer, const VolumeTest& volume ) const { - m_brush.evaluateBRep(); + swap = !swap; + } + } - const Matrix4& localToWorld = Instance::localToWorld(); + Winding_forFixedWinding(winding, buffer[swap]); - renderer.SetState( m_brush.m_state_point, Renderer::eWireframeOnly ); - renderer.SetState( m_brush.m_state_point, Renderer::eFullMaterials ); +#if BRUSH_CONNECTIVITY_DEBUG + Winding_printConnectivity( winding ); - if ( volume.fill() && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace ) { - evaluateViewDependent( volume, localToWorld ); - renderer.addRenderable( m_render_faces_wireframe, localToWorld ); - } - else + for ( Winding::iterator i = winding.begin(), j = winding.end() - 1; i != winding.end(); j = i, ++i ) { - m_brush.renderComponents( GlobalSelectionSystem().ComponentMode(), renderer, volume, localToWorld ); + if ( vector3_length_squared( vector3_subtracted( ( *i ).vertex, ( *j ).vertex ) ) < 1 ) { + globalOutputStream() << "v: " << std::distance( winding.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n"; + } } -} +#endif + } + + void update_wireframe(RenderableWireframe &wire, const bool *faces_visible) const + { + wire.m_faceVertex.resize(m_edge_indices.size()); + wire.m_vertices = m_uniqueVertexPoints.data(); + wire.m_size = 0; + for (std::size_t i = 0; i < m_edge_faces.size(); ++i) { + if (faces_visible[m_edge_faces[i].first] + || faces_visible[m_edge_faces[i].second]) { + wire.m_faceVertex[wire.m_size++] = m_edge_indices[i]; + } + } + } + + + void update_faces_wireframe(Array &wire, const bool *faces_visible) const + { + std::size_t count = 0; + for (std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i) { + if (faces_visible[i]) { + ++count; + } + } + + wire.resize(count); + Array::iterator p = wire.begin(); + for (std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i) { + if (faces_visible[i]) { + *p++ = m_faceCentroidPoints[i]; + } + } + } -void renderClipPlane( Renderer& renderer, const VolumeTest& volume ) const { - if ( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip && isSelected() ) { - m_clipPlane.render( renderer, volume, localToWorld() ); - } -} +/// \brief Makes this brush a deep-copy of the \p other. + void copy(const Brush &other) + { + for (Faces::const_iterator i = other.m_faces.begin(); i != other.m_faces.end(); ++i) { + addFace(*(*i)); + } + planeChanged(); + } -void renderCommon( Renderer& renderer, const VolumeTest& volume ) const { - bool componentMode = GlobalSelectionSystem().Mode() == SelectionSystem::eComponent; +private: + void edge_push_back(FaceVertexId faceVertex) + { + m_select_edges.push_back(SelectableEdge(m_faces, faceVertex)); + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->edge_push_back(m_select_edges.back()); + } + } + + void edge_clear() + { + m_select_edges.clear(); + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->edge_clear(); + } + } + + void vertex_push_back(FaceVertexId faceVertex) + { + m_select_vertices.push_back(SelectableVertex(m_faces, faceVertex)); + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->vertex_push_back(m_select_vertices.back()); + } + } + + void vertex_clear() + { + m_select_vertices.clear(); + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->vertex_clear(); + } + } - if ( componentMode && isSelected() ) { - renderComponents( renderer, volume ); - } +/// \brief Returns true if the face identified by \p index is preceded by another plane that takes priority over it. + bool plane_unique(std::size_t index) const + { + // duplicate plane + for (std::size_t i = 0; i < m_faces.size(); ++i) { + if (index != i && !plane3_inside(m_faces[index]->plane3(), m_faces[i]->plane3(), index < i)) { + return false; + } + } + return true; + } - if ( parentSelected() ) { - if ( !componentMode ) { - renderer.Highlight( Renderer::eFace ); - } - renderer.Highlight( Renderer::ePrimitive ); - } -} +/// \brief Removes edges that are smaller than the tolerance used when generating brush windings. + void removeDegenerateEdges() + { + for (std::size_t i = 0; i < m_faces.size(); ++i) { + Winding &winding = m_faces[i]->getWinding(); + for (Winding::iterator j = winding.begin(); j != winding.end();) { + std::size_t index = std::distance(winding.begin(), j); + std::size_t next = Winding_next(winding, index); + if (Edge_isDegenerate(winding[index].vertex, winding[next].vertex)) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate edge adjacent to " << winding[index].adjacent << "\n"; +#endif + Winding &other = m_faces[winding[index].adjacent]->getWinding(); + std::size_t adjacent = Winding_FindAdjacent(other, i); + if (adjacent != c_brush_maxFaces) { + other.erase(other.begin() + adjacent); + } + winding.erase(j); + } else { + ++j; + } + } + } + } + +/// \brief Invalidates faces that have only two vertices in their winding, while preserving edge-connectivity information. + void removeDegenerateFaces() + { + // save adjacency info for degenerate faces + for (std::size_t i = 0; i < m_faces.size(); ++i) { + Winding °en = m_faces[i]->getWinding(); + + if (degen.numpoints == 2) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate winding adjacent to " << degen[0].adjacent << ", " << degen[1].adjacent << "\n"; +#endif + // this is an "edge" face, where the plane touches the edge of the brush + { + Winding &winding = m_faces[degen[0].adjacent]->getWinding(); + std::size_t index = Winding_FindAdjacent(winding, i); + if (index != c_brush_maxFaces) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << degen[0].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[1].adjacent << "\n"; +#endif + winding[index].adjacent = degen[1].adjacent; + } + } + + { + Winding &winding = m_faces[degen[1].adjacent]->getWinding(); + std::size_t index = Winding_FindAdjacent(winding, i); + if (index != c_brush_maxFaces) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << degen[1].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[0].adjacent << "\n"; +#endif + winding[index].adjacent = degen[0].adjacent; + } + } -void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - //renderCommon(renderer, volume); + degen.resize(0); + } + } + } - m_lightList->evaluateLights(); +/// \brief Removes edges that have the same adjacent-face as their immediate neighbour. + void removeDuplicateEdges() + { + // verify face connectivity graph + for (std::size_t i = 0; i < m_faces.size(); ++i) { + //if(m_faces[i]->contributes()) + { + Winding &winding = m_faces[i]->getWinding(); + for (std::size_t j = 0; j != winding.numpoints;) { + std::size_t next = Winding_next(winding, j); + if (winding[j].adjacent == winding[next].adjacent) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": removed duplicate edge adjacent to face " << winding[j].adjacent << "\n"; +#endif + winding.erase(winding.begin() + next); + } else { + ++j; + } + } + } + } + } - for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - renderer.setLights( ( *i ).m_lights ); - ( *i ).render( renderer, volume, localToWorld ); - } +/// \brief Removes edges that do not have a matching pair in their adjacent-face. + void verifyConnectivityGraph() + { + // verify face connectivity graph + for (std::size_t i = 0; i < m_faces.size(); ++i) { + //if(m_faces[i]->contributes()) + { + Winding &winding = m_faces[i]->getWinding(); + for (Winding::iterator j = winding.begin(); j != winding.end();) { +#if BRUSH_CONNECTIVITY_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": adjacent to face " << ( *j ).adjacent << "\n"; +#endif + // remove unidirectional graph edges + if ((*j).adjacent == c_brush_maxFaces + || Winding_FindAdjacent(m_faces[(*j).adjacent]->getWinding(), i) == c_brush_maxFaces) { +#if BRUSH_CONNECTIVITY_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": removing unidirectional connectivity graph edge adjacent to face " << ( *j ).adjacent << "\n"; +#endif + winding.erase(j); + } else { + ++j; + } + } + } + } + } - renderComponentsSelected( renderer, volume, localToWorld ); -} +/// \brief Returns true if the brush is a finite volume. A brush without a finite volume extends past the maximum world bounds and is not valid. + bool isBounded() + { + for (const_iterator i = begin(); i != end(); ++i) { + if (!(*i)->is_bounded()) { + return false; + } + } + return true; + } -void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - //renderCommon(renderer, volume); +/// \brief Constructs the polygon windings for each face of the brush. Also updates the brush bounding-box and face texture-coordinates. + bool buildWindings() + { - evaluateViewDependent( volume, localToWorld ); + { + m_aabb_local = AABB(); - if ( m_render_wireframe.m_size != 0 ) { - renderer.addRenderable( m_render_wireframe, localToWorld ); - } + for (std::size_t i = 0; i < m_faces.size(); ++i) { + Face &f = *m_faces[i]; - renderComponentsSelected( renderer, volume, localToWorld ); -} + if (!plane3_valid(f.plane3()) || !plane_unique(i)) { + f.getWinding().resize(0); + } else { +#if BRUSH_CONNECTIVITY_DEBUG + globalOutputStream() << "face: " << i << "\n"; +#endif + windingForClipPlane(f.getWinding(), f.plane3()); + + // update brush bounds + const Winding &winding = f.getWinding(); + for (Winding::const_iterator i = winding.begin(); i != winding.end(); ++i) { + aabb_extend_by_point_safe(m_aabb_local, (*i).vertex); + } + + // update texture coordinates + f.EmitTextureCoordinates(); + } + } + } + + bool degenerate = !isBounded(); + + if (!degenerate) { + // clean up connectivity information. + // these cleanups must be applied in a specific order. + removeDegenerateEdges(); + removeDegenerateFaces(); + removeDuplicateEdges(); + verifyConnectivityGraph(); + } + + return degenerate; + } + +/// \brief Constructs the face windings and updates anything that depends on them. + void buildBRep(); +}; -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_brush.evaluateBRep(); - renderClipPlane( renderer, volume ); +class FaceInstance; - renderSolid( renderer, volume, localToWorld() ); -} +class FaceInstanceSet { + typedef SelectionList FaceInstances; + FaceInstances m_faceInstances; +public: + void insert(FaceInstance &faceInstance) + { + m_faceInstances.append(faceInstance); + } + + void erase(FaceInstance &faceInstance) + { + m_faceInstances.erase(faceInstance); + } + + template + void foreach(Functor functor) + { + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + functor(*(*i)); + } + } + + bool empty() const + { + return m_faceInstances.empty(); + } + + FaceInstance &last() const + { + return m_faceInstances.back(); + } +}; -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_brush.evaluateBRep(); +extern FaceInstanceSet g_SelectedFaceInstances; - renderClipPlane( renderer, volume ); +typedef std::list VertexSelection; - renderWireframe( renderer, volume, localToWorld() ); +inline VertexSelection::iterator VertexSelection_find(VertexSelection &self, std::size_t value) +{ + return std::find(self.begin(), self.end(), value); } -void viewChanged() const { - m_viewChanged = true; +inline VertexSelection::const_iterator VertexSelection_find(const VertexSelection &self, std::size_t value) +{ + return std::find(self.begin(), self.end(), value); } -void testSelect( Selector& selector, SelectionTest& test ){ - test.BeginMesh( localToWorld() ); +inline VertexSelection::iterator VertexSelection_insert(VertexSelection &self, std::size_t value) +{ + VertexSelection::iterator i = VertexSelection_find(self, value); + if (i == self.end()) { + self.push_back(value); + return --self.end(); + } + return i; +} - SelectionIntersection best; - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).testSelect( test, best ); - } - if ( best.valid() ) { - selector.addIntersection( best ); - } +inline void VertexSelection_erase(VertexSelection &self, std::size_t value) +{ + VertexSelection::iterator i = VertexSelection_find(self, value); + if (i != self.end()) { + self.erase(i); + } } -bool isSelectedComponents() const { - for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - if ( ( *i ).selectedComponents() ) { - return true; - } - } - return false; +inline bool triangle_reversed(std::size_t x, std::size_t y, std::size_t z) +{ + return !((x < y && y < z) || (z < x && x < y) || (y < z && z < x)); } -void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ){ - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).setSelected( mode, select ); - } + +template +inline Vector3 +triangle_cross(const BasicVector3 &x, const BasicVector3 y, const BasicVector3 &z) +{ + return vector3_cross(y - x, z - x); } -void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ){ - test.BeginMesh( localToWorld() ); - switch ( mode ) - { - case SelectionSystem::eVertex: - { - for ( VertexInstances::iterator i = m_vertexInstances.begin(); i != m_vertexInstances.end(); ++i ) - { - ( *i ).testSelect( selector, test ); - } - } - break; - case SelectionSystem::eEdge: - { - for ( EdgeInstances::iterator i = m_edgeInstances.begin(); i != m_edgeInstances.end(); ++i ) - { - ( *i ).testSelect( selector, test ); - } - } - break; - case SelectionSystem::eFace: - { - if ( test.getVolume().fill() ) { - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).testSelect( selector, test ); - } - } - else - { - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).testSelect_centroid( selector, test ); - } - } - } - break; - default: - break; - } +template +inline bool +triangles_same_winding(const BasicVector3 &x1, const BasicVector3 y1, const BasicVector3 &z1, + const BasicVector3 &x2, const BasicVector3 y2, const BasicVector3 &z2) +{ + return vector3_dot(triangle_cross(x1, y1, z1), triangle_cross(x2, y2, z2)) > 0; } -void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){ - test.BeginMesh( localToWorld() ); - PlanePointer brushPlanes[c_brush_maxFaces]; - PlanesIterator j = brushPlanes; +typedef const Plane3 *PlanePointer; +typedef PlanePointer *PlanesIterator; - for ( Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i ) - { - *j++ = &( *i )->plane3(); - } +class VectorLightList : public LightList { + typedef std::vector Lights; + Lights m_lights; +public: + void addLight(const RendererLight &light) + { + m_lights.push_back(&light); + } + + void clear() + { + m_lights.clear(); + } + + void evaluateLights() const + { + } + + void lightsChanged() const + { + } + + void forEachLight(const RendererLightCallback &callback) const + { + for (Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i) { + callback(*(*i)); + } + } +}; - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).selectPlane( selector, Line( test.getNear(), test.getFar() ), brushPlanes, j, selectedPlaneCallback ); - } -} -void selectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ){ - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).selectReversedPlane( selector, selectedPlanes ); - } -} +class FaceInstance { + Face *m_face; + ObservedSelectable m_selectable; + ObservedSelectable m_selectableVertices; + ObservedSelectable m_selectableEdges; + SelectionChangeCallback m_selectionChanged; + VertexSelection m_vertexSelection; + VertexSelection m_edgeSelection; -void transformComponents( const Matrix4& matrix ){ - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).transformComponents( matrix ); - } -} -const AABB& getSelectedComponentsBounds() const { - m_aabb_component = AABB(); +public: + mutable VectorLightList m_lights; + + FaceInstance(Face &face, const SelectionChangeCallback &observer) : + m_face(&face), + m_selectable(SelectedChangedCaller(*this)), + m_selectableVertices(observer), + m_selectableEdges(observer), + m_selectionChanged(observer) + { + } + + FaceInstance(const FaceInstance &other) : + m_face(other.m_face), + m_selectable(SelectedChangedCaller(*this)), + m_selectableVertices(other.m_selectableVertices), + m_selectableEdges(other.m_selectableEdges), + m_selectionChanged(other.m_selectionChanged) + { + } + + FaceInstance &operator=(const FaceInstance &other) + { + m_face = other.m_face; + return *this; + } + + Face &getFace() + { + return *m_face; + } + + const Face &getFace() const + { + return *m_face; + } + + void selectedChanged(const Selectable &selectable) + { + if (selectable.isSelected()) { + g_SelectedFaceInstances.insert(*this); + } else { + g_SelectedFaceInstances.erase(*this); + } + m_selectionChanged(selectable); + } + + typedef MemberCaller SelectedChangedCaller; + + bool selectedVertices() const + { + return !m_vertexSelection.empty(); + } + + bool selectedEdges() const + { + return !m_edgeSelection.empty(); + } + + bool isSelected() const + { + return m_selectable.isSelected(); + } + + bool selectedComponents() const + { + return selectedVertices() || selectedEdges() || isSelected(); + } + + bool selectedComponents(SelectionSystem::EComponentMode mode) const + { + switch (mode) { + case SelectionSystem::eVertex: + return selectedVertices(); + case SelectionSystem::eEdge: + return selectedEdges(); + case SelectionSystem::eFace: + return isSelected(); + default: + return false; + } + } + + void setSelected(SelectionSystem::EComponentMode mode, bool select) + { + switch (mode) { + case SelectionSystem::eFace: + m_selectable.setSelected(select); + break; + case SelectionSystem::eVertex: + ASSERT_MESSAGE(!select, "select-all not supported"); + + m_vertexSelection.clear(); + m_selectableVertices.setSelected(false); + break; + case SelectionSystem::eEdge: + ASSERT_MESSAGE(!select, "select-all not supported"); + + m_edgeSelection.clear(); + m_selectableEdges.setSelected(false); + break; + default: + break; + } + } + + template + void SelectedVertices_foreach(Functor functor) const + { + for (VertexSelection::const_iterator i = m_vertexSelection.begin(); i != m_vertexSelection.end(); ++i) { + std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *i); + if (index != c_brush_maxFaces) { + functor(getFace().getWinding()[index].vertex); + } + } + } + + template + void SelectedEdges_foreach(Functor functor) const + { + for (VertexSelection::const_iterator i = m_edgeSelection.begin(); i != m_edgeSelection.end(); ++i) { + std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *i); + if (index != c_brush_maxFaces) { + const Winding &winding = getFace().getWinding(); + std::size_t adjacent = Winding_next(winding, index); + functor(vector3_mid(winding[index].vertex, winding[adjacent].vertex)); + } + } + } + + template + void SelectedFaces_foreach(Functor functor) const + { + if (isSelected()) { + functor(centroid()); + } + } + + template + void SelectedComponents_foreach(Functor functor) const + { + SelectedVertices_foreach(functor); + SelectedEdges_foreach(functor); + SelectedFaces_foreach(functor); + } + + void iterate_selected(AABB &aabb) const + { + SelectedComponents_foreach([&](const Vector3 &point) { + aabb_extend_by_point_safe(aabb, point); + }); + } + + void iterate_selected(RenderablePointVector &points) const + { + SelectedComponents_foreach([&](const Vector3 &point) { + const Colour4b colour_selected(0, 0, 255, 255); + points.push_back(pointvertex_for_windingpoint(point, colour_selected)); + }); + } + + bool intersectVolume(const VolumeTest &volume, const Matrix4 &localToWorld) const + { + return m_face->intersectVolume(volume, localToWorld); + } + + void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + if (!m_face->isFiltered() && m_face->contributes() && intersectVolume(volume, localToWorld)) { + renderer.PushState(); + if (selectedComponents()) { + renderer.Highlight(Renderer::eFace); + } + m_face->render(renderer, localToWorld); + renderer.PopState(); + } + } + + void testSelect(SelectionTest &test, SelectionIntersection &best) + { + if (!m_face->isFiltered()) { + m_face->testSelect(test, best); + } + } + + void testSelect(Selector &selector, SelectionTest &test) + { + SelectionIntersection best; + testSelect(test, best); + if (best.valid()) { + Selector_add(selector, m_selectable, best); + } + } + + void testSelect_centroid(Selector &selector, SelectionTest &test) + { + if (m_face->contributes() && !m_face->isFiltered()) { + SelectionIntersection best; + m_face->testSelect_centroid(test, best); + if (best.valid()) { + Selector_add(selector, m_selectable, best); + } + } + } + + void selectPlane(Selector &selector, const Line &line, PlanesIterator first, PlanesIterator last, + const PlaneCallback &selectedPlaneCallback) + { + for (Winding::const_iterator i = getFace().getWinding().begin(); i != getFace().getWinding().end(); ++i) { + Vector3 v(vector3_subtracted(line_closest_point(line, (*i).vertex), (*i).vertex)); + double dot = vector3_dot(getFace().plane3().normal(), v); + if (dot <= 0) { + return; + } + } + + Selector_add(selector, m_selectable); + + selectedPlaneCallback(getFace().plane3()); + } + + void selectReversedPlane(Selector &selector, const SelectedPlanes &selectedPlanes) + { + if (selectedPlanes.contains(plane3_flipped(getFace().plane3()))) { + Selector_add(selector, m_selectable); + } + } + + void transformComponents(const Matrix4 &matrix) + { + if (isSelected()) { + m_face->transform(matrix, false); + } + if (selectedVertices()) { + if (m_vertexSelection.size() == 1) { + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); + m_face->assign_planepts(m_face->m_move_planeptsTransformed); + } else if (m_vertexSelection.size() == 2) { + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[2]); + m_face->assign_planepts(m_face->m_move_planeptsTransformed); + } else if (m_vertexSelection.size() >= 3) { + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[0]); + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[2]); + m_face->assign_planepts(m_face->m_move_planeptsTransformed); + } + } + if (selectedEdges()) { + if (m_edgeSelection.size() == 1) { + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[0]); + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); + m_face->assign_planepts(m_face->m_move_planeptsTransformed); + } else if (m_edgeSelection.size() >= 2) { + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[0]); + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); + matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[2]); + m_face->assign_planepts(m_face->m_move_planeptsTransformed); + } + } + } + + void snapto(float snap) + { + m_face->snapto(snap); + } + + void snapComponents(float snap) + { + if (isSelected()) { + snapto(snap); + } + if (selectedVertices()) { + vector3_snap(m_face->m_move_planepts[0], snap); + vector3_snap(m_face->m_move_planepts[1], snap); + vector3_snap(m_face->m_move_planepts[2], snap); + m_face->assign_planepts(m_face->m_move_planepts); + planepts_assign(m_face->m_move_planeptsTransformed, m_face->m_move_planepts); + m_face->freezeTransform(); + } + if (selectedEdges()) { + vector3_snap(m_face->m_move_planepts[0], snap); + vector3_snap(m_face->m_move_planepts[1], snap); + vector3_snap(m_face->m_move_planepts[2], snap); + m_face->assign_planepts(m_face->m_move_planepts); + planepts_assign(m_face->m_move_planeptsTransformed, m_face->m_move_planepts); + m_face->freezeTransform(); + } + } + + void update_move_planepts_vertex(std::size_t index) + { + m_face->update_move_planepts_vertex(index, m_face->m_move_planepts); + } + + void update_move_planepts_vertex2(std::size_t index, std::size_t other) + { + const std::size_t numpoints = m_face->getWinding().numpoints; + ASSERT_MESSAGE(index < numpoints, "select_vertex: invalid index"); + + const std::size_t opposite = Winding_Opposite(m_face->getWinding(), index, other); + + if (triangle_reversed(index, other, opposite)) { + std::swap(index, other); + } + + ASSERT_MESSAGE( + triangles_same_winding( + m_face->getWinding()[opposite].vertex, + m_face->getWinding()[index].vertex, + m_face->getWinding()[other].vertex, + m_face->getWinding()[0].vertex, + m_face->getWinding()[1].vertex, + m_face->getWinding()[2].vertex + ), + "update_move_planepts_vertex2: error" + ); + + m_face->m_move_planepts[0] = m_face->getWinding()[opposite].vertex; + m_face->m_move_planepts[1] = m_face->getWinding()[index].vertex; + m_face->m_move_planepts[2] = m_face->getWinding()[other].vertex; + planepts_quantise(m_face->m_move_planepts, GRID_MIN); // winding points are very inaccurate + } + + void update_selection_vertex() + { + if (m_vertexSelection.size() == 0) { + m_selectableVertices.setSelected(false); + } else { + m_selectableVertices.setSelected(true); + + if (m_vertexSelection.size() == 1) { + std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *m_vertexSelection.begin()); + + if (index != c_brush_maxFaces) { + update_move_planepts_vertex(index); + } + } else if (m_vertexSelection.size() == 2) { + std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *m_vertexSelection.begin()); + std::size_t other = Winding_FindAdjacent(getFace().getWinding(), *(++m_vertexSelection.begin())); + + if (index != c_brush_maxFaces + && other != c_brush_maxFaces) { + update_move_planepts_vertex2(index, other); + } + } + } + } + + void select_vertex(std::size_t index, bool select) + { + if (select) { + VertexSelection_insert(m_vertexSelection, getFace().getWinding()[index].adjacent); + } else { + VertexSelection_erase(m_vertexSelection, getFace().getWinding()[index].adjacent); + } + + SceneChangeNotify(); + update_selection_vertex(); + } + + bool selected_vertex(std::size_t index) const + { + return VertexSelection_find(m_vertexSelection, getFace().getWinding()[index].adjacent) != + m_vertexSelection.end(); + } + + void update_move_planepts_edge(std::size_t index) + { + std::size_t numpoints = m_face->getWinding().numpoints; + ASSERT_MESSAGE(index < numpoints, "select_edge: invalid index"); + + std::size_t adjacent = Winding_next(m_face->getWinding(), index); + std::size_t opposite = Winding_Opposite(m_face->getWinding(), index); + m_face->m_move_planepts[0] = m_face->getWinding()[index].vertex; + m_face->m_move_planepts[1] = m_face->getWinding()[adjacent].vertex; + m_face->m_move_planepts[2] = m_face->getWinding()[opposite].vertex; + planepts_quantise(m_face->m_move_planepts, GRID_MIN); // winding points are very inaccurate + } + + void update_selection_edge() + { + if (m_edgeSelection.size() == 0) { + m_selectableEdges.setSelected(false); + } else { + m_selectableEdges.setSelected(true); + + if (m_edgeSelection.size() == 1) { + std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *m_edgeSelection.begin()); + + if (index != c_brush_maxFaces) { + update_move_planepts_edge(index); + } + } + } + } + + void select_edge(std::size_t index, bool select) + { + if (select) { + VertexSelection_insert(m_edgeSelection, getFace().getWinding()[index].adjacent); + } else { + VertexSelection_erase(m_edgeSelection, getFace().getWinding()[index].adjacent); + } + + SceneChangeNotify(); + update_selection_edge(); + } + + bool selected_edge(std::size_t index) const + { + return VertexSelection_find(m_edgeSelection, getFace().getWinding()[index].adjacent) != m_edgeSelection.end(); + } + + const Vector3 ¢roid() const + { + return m_face->centroid(); + } + + void connectivityChanged() + { + // This occurs when a face is added or removed. + // The current vertex and edge selections no longer valid and must be cleared. + m_vertexSelection.clear(); + m_selectableVertices.setSelected(false); + m_edgeSelection.clear(); + m_selectableEdges.setSelected(false); + } +}; - for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).iterate_selected( m_aabb_component ); - } +class BrushClipPlane : public OpenGLRenderable { + Plane3 m_plane; + Winding m_winding; + static Shader *m_state; +public: + static void constructStatic() + { + m_state = GlobalShaderCache().capture("$CLIPPER_OVERLAY"); + } + + static void destroyStatic() + { + GlobalShaderCache().release("$CLIPPER_OVERLAY"); + } + + void setPlane(const Brush &brush, const Plane3 &plane) + { + m_plane = plane; + if (plane3_valid(m_plane)) { + brush.windingForClipPlane(m_winding, m_plane); + } else { + m_winding.resize(0); + } + } + + void render(RenderStateFlags state) const + { + if ((state & RENDER_FILL) != 0) { + Winding_Draw(m_winding, m_plane.normal(), state); + } else { + Winding_DrawWireframe(m_winding); + + // also draw a line indicating the direction of the cut + Vector3 lineverts[2]; + Winding_Centroid(m_winding, m_plane, lineverts[0]); + lineverts[1] = vector3_added(lineverts[0], vector3_scaled(m_plane.normal(), Brush::m_maxWorldCoord * 4)); + + glVertexPointer(3, GL_FLOAT, sizeof(Vector3), &lineverts[0]); + glDrawArrays(GL_LINES, 0, GLsizei(2)); + } + } + + void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + renderer.SetState(m_state, Renderer::eWireframeOnly); + renderer.SetState(m_state, Renderer::eFullMaterials); + renderer.addRenderable(*this, localToWorld); + } +}; - return m_aabb_component; +inline void Face_addLight(const FaceInstance &face, const Matrix4 &localToWorld, const RendererLight &light) +{ + const Plane3 &facePlane = face.getFace().plane3(); + const Vector3 &origin = light.aabb().origin; + Plane3 tmp(plane3_transformed(Plane3(facePlane.normal(), -facePlane.dist()), localToWorld)); + if (!plane3_test_point(tmp, origin) + || !plane3_test_point(tmp, vector3_added(origin, light.offset()))) { + face.m_lights.addLight(light); + } } -void snapComponents( float snap ){ - for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).snapComponents( snap ); - } -} -void evaluateTransform(){ - Matrix4 matrix( m_transform.calculateTransform() ); - //globalOutputStream() << "matrix: " << matrix << "\n"; - if ( m_transform.getType() == TRANSFORM_PRIMITIVE ) { - m_brush.transform( matrix ); - } - else - { - transformComponents( matrix ); - } -} -void applyTransform(){ - m_brush.revertTransform(); - evaluateTransform(); - m_brush.freezeTransform(); -} -typedef MemberCaller ApplyTransformCaller; +typedef std::vector FaceInstances; -void setClipPlane( const Plane3& plane ){ - m_clipPlane.setPlane( m_brush, plane ); -} +class EdgeInstance : public Selectable { + FaceInstances &m_faceInstances; + SelectableEdge *m_edge; + + void select_edge(bool select) + { + FaceVertexId faceVertex = m_edge->m_faceVertex; + m_faceInstances[faceVertex.getFace()].select_edge(faceVertex.getVertex(), select); + faceVertex = next_edge(m_edge->m_faces, faceVertex); + m_faceInstances[faceVertex.getFace()].select_edge(faceVertex.getVertex(), select); + } + + bool selected_edge() const + { + FaceVertexId faceVertex = m_edge->m_faceVertex; + if (!m_faceInstances[faceVertex.getFace()].selected_edge(faceVertex.getVertex())) { + return false; + } + faceVertex = next_edge(m_edge->m_faces, faceVertex); + if (!m_faceInstances[faceVertex.getFace()].selected_edge(faceVertex.getVertex())) { + return false; + } + + return true; + } -bool testLight( const RendererLight& light ) const { - return light.testAABB( worldAABB() ); -} -void insertLight( const RendererLight& light ){ - const Matrix4& localToWorld = Instance::localToWorld(); - for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - Face_addLight( *i, localToWorld, light ); - } -} -void clearLights(){ - for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) - { - ( *i ).m_lights.clear(); - } -} +public: + EdgeInstance(FaceInstances &faceInstances, SelectableEdge &edge) + : m_faceInstances(faceInstances), m_edge(&edge) + { + } + + EdgeInstance &operator=(const EdgeInstance &other) + { + m_edge = other.m_edge; + return *this; + } + + void setSelected(bool select) + { + select_edge(select); + } + + bool isSelected() const + { + return selected_edge(); + } + + + void testSelect(Selector &selector, SelectionTest &test) + { + SelectionIntersection best; + m_edge->testSelect(test, best); + if (best.valid()) { + Selector_add(selector, *this, best); + } + } +}; + +class VertexInstance : public Selectable { + FaceInstances &m_faceInstances; + SelectableVertex *m_vertex; + + void select_vertex(bool select) + { + FaceVertexId faceVertex = m_vertex->m_faceVertex; + do { + m_faceInstances[faceVertex.getFace()].select_vertex(faceVertex.getVertex(), select); + faceVertex = next_vertex(m_vertex->m_faces, faceVertex); + } while (faceVertex.getFace() != m_vertex->m_faceVertex.getFace()); + } + + bool selected_vertex() const + { + FaceVertexId faceVertex = m_vertex->m_faceVertex; + do { + if (!m_faceInstances[faceVertex.getFace()].selected_vertex(faceVertex.getVertex())) { + return false; + } + faceVertex = next_vertex(m_vertex->m_faces, faceVertex); + } while (faceVertex.getFace() != m_vertex->m_faceVertex.getFace()); + return true; + } + +public: + VertexInstance(FaceInstances &faceInstances, SelectableVertex &vertex) + : m_faceInstances(faceInstances), m_vertex(&vertex) + { + } + + VertexInstance &operator=(const VertexInstance &other) + { + m_vertex = other.m_vertex; + return *this; + } + + void setSelected(bool select) + { + select_vertex(select); + } + + bool isSelected() const + { + return selected_vertex(); + } + + void testSelect(Selector &selector, SelectionTest &test) + { + SelectionIntersection best; + m_vertex->testSelect(test, best); + if (best.valid()) { + Selector_add(selector, *this, best); + } + } +}; + +class BrushInstanceVisitor { +public: + virtual void visit(FaceInstance &face) const = 0; +}; + +class BrushInstance : + public BrushObserver, + public scene::Instance, + public Selectable, + public Renderable, + public SelectionTestable, + public ComponentSelectionTestable, + public ComponentEditable, + public ComponentSnappable, + public PlaneSelectable, + public LightCullable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + InstanceStaticCast::install(m_casts); + InstanceContainedCast::install(m_casts); + InstanceContainedCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceIdentityCast::install(m_casts); + InstanceContainedCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + + Brush &m_brush; + + FaceInstances m_faceInstances; + + typedef std::vector EdgeInstances; + EdgeInstances m_edgeInstances; + typedef std::vector VertexInstances; + VertexInstances m_vertexInstances; + + ObservedSelectable m_selectable; + + mutable RenderableWireframe m_render_wireframe; + mutable RenderablePointVector m_render_selected; + mutable AABB m_aabb_component; + mutable Array m_faceCentroidPointsCulled; + RenderablePointArray m_render_faces_wireframe; + mutable bool m_viewChanged; // requires re-evaluation of view-dependent cached data + + BrushClipPlane m_clipPlane; + + static Shader *m_state_selpoint; + + const LightList *m_lightList; + + TransformModifier m_transform; + + BrushInstance(const BrushInstance &other); // NOT COPYABLE + BrushInstance &operator=(const BrushInstance &other); // NOT ASSIGNABLE +public: + static Counter *m_counter; + + typedef LazyStatic StaticTypeCasts; + + void lightsChanged() + { + m_lightList->lightsChanged(); + } + + typedef MemberCaller LightsChangedCaller; + + STRING_CONSTANT(Name, "BrushInstance"); + + BrushInstance(const scene::Path &path, scene::Instance *parent, Brush &brush) : + Instance(path, parent, this, StaticTypeCasts::instance().get()), + m_brush(brush), + m_selectable(SelectedChangedCaller(*this)), + m_render_selected(GL_POINTS), + m_render_faces_wireframe(m_faceCentroidPointsCulled, GL_POINTS), + m_viewChanged(false), + m_transform(Brush::TransformChangedCaller(m_brush), ApplyTransformCaller(*this)) + { + m_brush.instanceAttach(Instance::path()); + m_brush.attach(*this); + m_counter->increment(); + + m_lightList = &GlobalShaderCache().attach(*this); + m_brush.m_lightsChanged = LightsChangedCaller(*this); ///\todo Make this work with instancing. + + Instance::setTransformChangedCallback(LightsChangedCaller(*this)); + } + + ~BrushInstance() + { + Instance::setTransformChangedCallback(Callback()); + + m_brush.m_lightsChanged = Callback(); + GlobalShaderCache().detach(*this); + + m_counter->decrement(); + m_brush.detach(*this); + m_brush.instanceDetach(Instance::path()); + } + + Brush &getBrush() + { + return m_brush; + } + + const Brush &getBrush() const + { + return m_brush; + } + + Bounded &get(NullType) + { + return m_brush; + } + + Cullable &get(NullType) + { + return m_brush; + } + + Transformable &get(NullType) + { + return m_transform; + } + + void selectedChanged(const Selectable &selectable) + { + GlobalSelectionSystem().getObserver(SelectionSystem::ePrimitive)(selectable); + GlobalSelectionSystem().onSelectedChanged(*this, selectable); + + Instance::selectedChanged(); + } + + typedef MemberCaller SelectedChangedCaller; + + void selectedChangedComponent(const Selectable &selectable) + { + GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable); + GlobalSelectionSystem().onComponentSelection(*this, selectable); + } + + typedef MemberCaller SelectedChangedComponentCaller; + + const BrushInstanceVisitor &forEachFaceInstance(const BrushInstanceVisitor &visitor) + { + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + visitor.visit(*i); + } + return visitor; + } + + static void constructStatic() + { + m_state_selpoint = GlobalShaderCache().capture("$SELPOINT"); + } + + static void destroyStatic() + { + GlobalShaderCache().release("$SELPOINT"); + } + + void clear() + { + m_faceInstances.clear(); + } + + void reserve(std::size_t size) + { + m_faceInstances.reserve(size); + } + + void push_back(Face &face) + { + m_faceInstances.push_back(FaceInstance(face, SelectedChangedComponentCaller(*this))); + } + + void pop_back() + { + ASSERT_MESSAGE(!m_faceInstances.empty(), "erasing invalid element"); + m_faceInstances.pop_back(); + } + + void erase(std::size_t index) + { + ASSERT_MESSAGE(index < m_faceInstances.size(), "erasing invalid element"); + m_faceInstances.erase(m_faceInstances.begin() + index); + } + + void connectivityChanged() + { + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).connectivityChanged(); + } + } + + void edge_clear() + { + m_edgeInstances.clear(); + } + + void edge_push_back(SelectableEdge &edge) + { + m_edgeInstances.push_back(EdgeInstance(m_faceInstances, edge)); + } + + void vertex_clear() + { + m_vertexInstances.clear(); + } + + void vertex_push_back(SelectableVertex &vertex) + { + m_vertexInstances.push_back(VertexInstance(m_faceInstances, vertex)); + } + + void DEBUG_verify() const + { + ASSERT_MESSAGE(m_faceInstances.size() == m_brush.DEBUG_size(), "FATAL: mismatch"); + } + + bool isSelected() const + { + return m_selectable.isSelected(); + } + + void setSelected(bool select) + { + m_selectable.setSelected(select); + } + + void update_selected() const + { + m_render_selected.clear(); + for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + if ((*i).getFace().contributes()) { + (*i).iterate_selected(m_render_selected); + } + } + } + + void evaluateViewDependent(const VolumeTest &volume, const Matrix4 &localToWorld) const + { + if (m_viewChanged) { + m_viewChanged = false; + + bool faces_visible[c_brush_maxFaces]; + { + bool *j = faces_visible; + for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i, ++j) { + *j = (*i).intersectVolume(volume, localToWorld); + } + } + + m_brush.update_wireframe(m_render_wireframe, faces_visible); + m_brush.update_faces_wireframe(m_faceCentroidPointsCulled, faces_visible); + } + } + + void renderComponentsSelected(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + m_brush.evaluateBRep(); + + update_selected(); + if (!m_render_selected.empty()) { + renderer.Highlight(Renderer::ePrimitive, false); + renderer.SetState(m_state_selpoint, Renderer::eWireframeOnly); + renderer.SetState(m_state_selpoint, Renderer::eFullMaterials); + renderer.addRenderable(m_render_selected, localToWorld); + } + } + + void renderComponents(Renderer &renderer, const VolumeTest &volume) const + { + m_brush.evaluateBRep(); + + const Matrix4 &localToWorld = Instance::localToWorld(); + + renderer.SetState(m_brush.m_state_point, Renderer::eWireframeOnly); + renderer.SetState(m_brush.m_state_point, Renderer::eFullMaterials); + + if (volume.fill() && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace) { + evaluateViewDependent(volume, localToWorld); + renderer.addRenderable(m_render_faces_wireframe, localToWorld); + } else { + m_brush.renderComponents(GlobalSelectionSystem().ComponentMode(), renderer, volume, localToWorld); + } + } + + void renderClipPlane(Renderer &renderer, const VolumeTest &volume) const + { + if (GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip && isSelected()) { + m_clipPlane.render(renderer, volume, localToWorld()); + } + } + + void renderCommon(Renderer &renderer, const VolumeTest &volume) const + { + bool componentMode = GlobalSelectionSystem().Mode() == SelectionSystem::eComponent; + + if (componentMode && isSelected()) { + renderComponents(renderer, volume); + } + + if (parentSelected()) { + if (!componentMode) { + renderer.Highlight(Renderer::eFace); + } + renderer.Highlight(Renderer::ePrimitive); + } + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + //renderCommon(renderer, volume); + + m_lightList->evaluateLights(); + + for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + renderer.setLights((*i).m_lights); + (*i).render(renderer, volume, localToWorld); + } + + renderComponentsSelected(renderer, volume, localToWorld); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + //renderCommon(renderer, volume); + + evaluateViewDependent(volume, localToWorld); + + if (m_render_wireframe.m_size != 0) { + renderer.addRenderable(m_render_wireframe, localToWorld); + } + + renderComponentsSelected(renderer, volume, localToWorld); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_brush.evaluateBRep(); + + renderClipPlane(renderer, volume); + + renderSolid(renderer, volume, localToWorld()); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + m_brush.evaluateBRep(); + + renderClipPlane(renderer, volume); + + renderWireframe(renderer, volume, localToWorld()); + } + + void viewChanged() const + { + m_viewChanged = true; + } + + void testSelect(Selector &selector, SelectionTest &test) + { + test.BeginMesh(localToWorld()); + + SelectionIntersection best; + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).testSelect(test, best); + } + if (best.valid()) { + selector.addIntersection(best); + } + } + + bool isSelectedComponents() const + { + for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + if ((*i).selectedComponents()) { + return true; + } + } + return false; + } + + void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) + { + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).setSelected(mode, select); + } + } + + void testSelectComponents(Selector &selector, SelectionTest &test, SelectionSystem::EComponentMode mode) + { + test.BeginMesh(localToWorld()); + + switch (mode) { + case SelectionSystem::eVertex: { + for (VertexInstances::iterator i = m_vertexInstances.begin(); i != m_vertexInstances.end(); ++i) { + (*i).testSelect(selector, test); + } + } + break; + case SelectionSystem::eEdge: { + for (EdgeInstances::iterator i = m_edgeInstances.begin(); i != m_edgeInstances.end(); ++i) { + (*i).testSelect(selector, test); + } + } + break; + case SelectionSystem::eFace: { + if (test.getVolume().fill()) { + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).testSelect(selector, test); + } + } else { + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).testSelect_centroid(selector, test); + } + } + } + break; + default: + break; + } + } + + void selectPlanes(Selector &selector, SelectionTest &test, const PlaneCallback &selectedPlaneCallback) + { + test.BeginMesh(localToWorld()); + + PlanePointer brushPlanes[c_brush_maxFaces]; + PlanesIterator j = brushPlanes; + + for (Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i) { + *j++ = &(*i)->plane3(); + } + + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).selectPlane(selector, Line(test.getNear(), test.getFar()), brushPlanes, j, selectedPlaneCallback); + } + } + + void selectReversedPlanes(Selector &selector, const SelectedPlanes &selectedPlanes) + { + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).selectReversedPlane(selector, selectedPlanes); + } + } + + + void transformComponents(const Matrix4 &matrix) + { + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).transformComponents(matrix); + } + } + + const AABB &getSelectedComponentsBounds() const + { + m_aabb_component = AABB(); + + for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).iterate_selected(m_aabb_component); + } + + return m_aabb_component; + } + + void snapComponents(float snap) + { + for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).snapComponents(snap); + } + } + + void evaluateTransform() + { + Matrix4 matrix(m_transform.calculateTransform()); + //globalOutputStream() << "matrix: " << matrix << "\n"; + + if (m_transform.getType() == TRANSFORM_PRIMITIVE) { + m_brush.transform(matrix); + } else { + transformComponents(matrix); + } + } + + void applyTransform() + { + m_brush.revertTransform(); + evaluateTransform(); + m_brush.freezeTransform(); + } + + typedef MemberCaller ApplyTransformCaller; + + void setClipPlane(const Plane3 &plane) + { + m_clipPlane.setPlane(m_brush, plane); + } + + bool testLight(const RendererLight &light) const + { + return light.testAABB(worldAABB()); + } + + void insertLight(const RendererLight &light) + { + const Matrix4 &localToWorld = Instance::localToWorld(); + for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + Face_addLight(*i, localToWorld, light); + } + } + + void clearLights() + { + for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { + (*i).m_lights.clear(); + } + } }; -inline BrushInstance* Instance_getBrush( scene::Instance& instance ){ - return InstanceTypeCast::cast( instance ); +inline BrushInstance *Instance_getBrush(scene::Instance &instance) +{ + return InstanceTypeCast::cast(instance); } template -class BrushSelectedVisitor : public SelectionSystem::Visitor -{ -const Functor& m_functor; +class BrushSelectedVisitor : public SelectionSystem::Visitor { + const Functor &m_functor; public: -BrushSelectedVisitor( const Functor& functor ) : m_functor( functor ){ -} -void visit( scene::Instance& instance ) const { - BrushInstance* brush = Instance_getBrush( instance ); - if ( brush != 0 ) { - m_functor( *brush ); - } -} + BrushSelectedVisitor(const Functor &functor) : m_functor(functor) + { + } + + void visit(scene::Instance &instance) const + { + BrushInstance *brush = Instance_getBrush(instance); + if (brush != 0) { + m_functor(*brush); + } + } }; template -inline const Functor& Scene_forEachSelectedBrush( const Functor& functor ){ - GlobalSelectionSystem().foreachSelected( BrushSelectedVisitor( functor ) ); - return functor; +inline const Functor &Scene_forEachSelectedBrush(const Functor &functor) +{ + GlobalSelectionSystem().foreachSelected(BrushSelectedVisitor(functor)); + return functor; } template -class BrushVisibleSelectedVisitor : public SelectionSystem::Visitor -{ -const Functor& m_functor; +class BrushVisibleSelectedVisitor : public SelectionSystem::Visitor { + const Functor &m_functor; public: -BrushVisibleSelectedVisitor( const Functor& functor ) : m_functor( functor ){ -} -void visit( scene::Instance& instance ) const { - BrushInstance* brush = Instance_getBrush( instance ); - if ( brush != 0 - && instance.path().top().get().visible() ) { - m_functor( *brush ); - } -} + BrushVisibleSelectedVisitor(const Functor &functor) : m_functor(functor) + { + } + + void visit(scene::Instance &instance) const + { + BrushInstance *brush = Instance_getBrush(instance); + if (brush != 0 + && instance.path().top().get().visible()) { + m_functor(*brush); + } + } }; template -inline const Functor& Scene_forEachVisibleSelectedBrush( const Functor& functor ){ - GlobalSelectionSystem().foreachSelected( BrushVisibleSelectedVisitor( functor ) ); - return functor; +inline const Functor &Scene_forEachVisibleSelectedBrush(const Functor &functor) +{ + GlobalSelectionSystem().foreachSelected(BrushVisibleSelectedVisitor(functor)); + return functor; } -class BrushForEachFace -{ -const BrushInstanceVisitor& m_visitor; +class BrushForEachFace { + const BrushInstanceVisitor &m_visitor; public: -BrushForEachFace( const BrushInstanceVisitor& visitor ) : m_visitor( visitor ){ -} -void operator()( BrushInstance& brush ) const { - brush.forEachFaceInstance( m_visitor ); -} + BrushForEachFace(const BrushInstanceVisitor &visitor) : m_visitor(visitor) + { + } + + void operator()(BrushInstance &brush) const + { + brush.forEachFaceInstance(m_visitor); + } }; template -class FaceInstanceVisitFace : public BrushInstanceVisitor -{ -const Functor& functor; +class FaceInstanceVisitFace : public BrushInstanceVisitor { + const Functor &functor; public: -FaceInstanceVisitFace( const Functor& functor ) - : functor( functor ){ -} -void visit( FaceInstance& face ) const { - functor( face.getFace() ); -} + FaceInstanceVisitFace(const Functor &functor) + : functor(functor) + { + } + + void visit(FaceInstance &face) const + { + functor(face.getFace()); + } }; template -inline const Functor& Brush_forEachFace( BrushInstance& brush, const Functor& functor ){ - brush.forEachFaceInstance( FaceInstanceVisitFace( functor ) ); - return functor; +inline const Functor &Brush_forEachFace(BrushInstance &brush, const Functor &functor) +{ + brush.forEachFaceInstance(FaceInstanceVisitFace(functor)); + return functor; } template -class FaceVisitAll : public BrushVisitor -{ -const Functor& functor; +class FaceVisitAll : public BrushVisitor { + const Functor &functor; public: -FaceVisitAll( const Functor& functor ) - : functor( functor ){ -} -void visit( Face& face ) const { - functor( face ); -} + FaceVisitAll(const Functor &functor) + : functor(functor) + { + } + + void visit(Face &face) const + { + functor(face); + } }; template -inline const Functor& Brush_forEachFace( const Brush& brush, const Functor& functor ){ - brush.forEachFace( FaceVisitAll( functor ) ); - return functor; +inline const Functor &Brush_forEachFace(const Brush &brush, const Functor &functor) +{ + brush.forEachFace(FaceVisitAll(functor)); + return functor; } template -inline const Functor& Brush_forEachFace( Brush& brush, const Functor& functor ){ - brush.forEachFace( FaceVisitAll( functor ) ); - return functor; +inline const Functor &Brush_forEachFace(Brush &brush, const Functor &functor) +{ + brush.forEachFace(FaceVisitAll(functor)); + return functor; } template -class FaceInstanceVisitAll : public BrushInstanceVisitor -{ -const Functor& functor; +class FaceInstanceVisitAll : public BrushInstanceVisitor { + const Functor &functor; public: -FaceInstanceVisitAll( const Functor& functor ) - : functor( functor ){ -} -void visit( FaceInstance& face ) const { - functor( face ); -} + FaceInstanceVisitAll(const Functor &functor) + : functor(functor) + { + } + + void visit(FaceInstance &face) const + { + functor(face); + } }; template -inline const Functor& Brush_ForEachFaceInstance( BrushInstance& brush, const Functor& functor ){ - brush.forEachFaceInstance( FaceInstanceVisitAll( functor ) ); - return functor; +inline const Functor &Brush_ForEachFaceInstance(BrushInstance &brush, const Functor &functor) +{ + brush.forEachFaceInstance(FaceInstanceVisitAll(functor)); + return functor; } template -inline const Functor& Scene_forEachBrush( scene::Graph& graph, const Functor& functor ){ - graph.traverse( InstanceWalker< InstanceApply >( functor ) ); - return functor; +inline const Functor &Scene_forEachBrush(scene::Graph &graph, const Functor &functor) +{ + graph.traverse(InstanceWalker >(functor)); + return functor; } template -class InstanceIfVisible : public Functor -{ +class InstanceIfVisible : public Functor { public: -InstanceIfVisible( const Functor& functor ) : Functor( functor ){ -} -void operator()( scene::Instance& instance ){ - if ( instance.path().top().get().visible() ) { - Functor::operator()( instance ); - } -} + InstanceIfVisible(const Functor &functor) : Functor(functor) + { + } + + void operator()(scene::Instance &instance) + { + if (instance.path().top().get().visible()) { + Functor::operator()(instance); + } + } }; template -class BrushVisibleWalker : public scene::Graph::Walker -{ -const Functor& m_functor; +class BrushVisibleWalker : public scene::Graph::Walker { + const Functor &m_functor; public: -BrushVisibleWalker( const Functor& functor ) : m_functor( functor ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - BrushInstance* brush = Instance_getBrush( instance ); - if ( brush != 0 ) { - m_functor( *brush ); - } - } - return true; -} + BrushVisibleWalker(const Functor &functor) : m_functor(functor) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + BrushInstance *brush = Instance_getBrush(instance); + if (brush != 0) { + m_functor(*brush); + } + } + return true; + } }; template -inline const Functor& Scene_forEachVisibleBrush( scene::Graph& graph, const Functor& functor ){ - graph.traverse( BrushVisibleWalker( functor ) ); - return functor; +inline const Functor &Scene_forEachVisibleBrush(scene::Graph &graph, const Functor &functor) +{ + graph.traverse(BrushVisibleWalker(functor)); + return functor; } template -inline const Functor& Scene_ForEachBrush_ForEachFace( scene::Graph& graph, const Functor& functor ){ - Scene_forEachBrush( graph, BrushForEachFace( FaceInstanceVisitFace( functor ) ) ); - return functor; +inline const Functor &Scene_ForEachBrush_ForEachFace(scene::Graph &graph, const Functor &functor) +{ + Scene_forEachBrush(graph, BrushForEachFace(FaceInstanceVisitFace(functor))); + return functor; } // d1223m template -inline const Functor& Scene_ForEachBrush_ForEachFaceInstance( scene::Graph& graph, const Functor& functor ){ - Scene_forEachBrush( graph, BrushForEachFace( FaceInstanceVisitAll( functor ) ) ); - return functor; +inline const Functor &Scene_ForEachBrush_ForEachFaceInstance(scene::Graph &graph, const Functor &functor) +{ + Scene_forEachBrush(graph, BrushForEachFace(FaceInstanceVisitAll(functor))); + return functor; } template -inline const Functor& Scene_ForEachSelectedBrush_ForEachFace( scene::Graph& graph, const Functor& functor ){ - Scene_forEachSelectedBrush( BrushForEachFace( FaceInstanceVisitFace( functor ) ) ); - return functor; +inline const Functor &Scene_ForEachSelectedBrush_ForEachFace(scene::Graph &graph, const Functor &functor) +{ + Scene_forEachSelectedBrush(BrushForEachFace(FaceInstanceVisitFace(functor))); + return functor; } template -inline const Functor& Scene_ForEachSelectedBrush_ForEachFaceInstance( scene::Graph& graph, const Functor& functor ){ - Scene_forEachSelectedBrush( BrushForEachFace( FaceInstanceVisitAll( functor ) ) ); - return functor; +inline const Functor &Scene_ForEachSelectedBrush_ForEachFaceInstance(scene::Graph &graph, const Functor &functor) +{ + Scene_forEachSelectedBrush(BrushForEachFace(FaceInstanceVisitAll(functor))); + return functor; } template -class FaceVisitorWrapper -{ -const Functor& functor; +class FaceVisitorWrapper { + const Functor &functor; public: -FaceVisitorWrapper( const Functor& functor ) : functor( functor ){ -} - -void operator()( FaceInstance& faceInstance ) const { - functor( faceInstance.getFace() ); -} + FaceVisitorWrapper(const Functor &functor) : functor(functor) + { + } + + void operator()(FaceInstance &faceInstance) const + { + functor(faceInstance.getFace()); + } }; template -inline const Functor& Scene_ForEachSelectedBrushFace( scene::Graph& graph, const Functor& functor ){ - g_SelectedFaceInstances.foreach( FaceVisitorWrapper( functor ) ); - return functor; +inline const Functor &Scene_ForEachSelectedBrushFace(scene::Graph &graph, const Functor &functor) +{ + g_SelectedFaceInstances.foreach(FaceVisitorWrapper(functor)); + return functor; } diff --git a/radiant/brush_primit.cpp b/radiant/brush_primit.cpp index 2b11807e..a7bae544 100644 --- a/radiant/brush_primit.cpp +++ b/radiant/brush_primit.cpp @@ -44,51 +44,51 @@ This will be one of three axis-aligned spaces, depending on the surface normal. NOTE: could also be done by swapping values. */ -void Normal_GetTransform( const Vector3& normal, Matrix4& transform ){ - switch ( projectionaxis_for_normal( normal ) ) - { - case eProjectionAxisZ: - transform[0] = 1; - transform[1] = 0; - transform[2] = 0; - - transform[4] = 0; - transform[5] = 1; - transform[6] = 0; - - transform[8] = 0; - transform[9] = 0; - transform[10] = 1; - break; - case eProjectionAxisY: - transform[0] = 1; - transform[1] = 0; - transform[2] = 0; - - transform[4] = 0; - transform[5] = 0; - transform[6] = -1; - - transform[8] = 0; - transform[9] = 1; - transform[10] = 0; - break; - case eProjectionAxisX: - transform[0] = 0; - transform[1] = 0; - transform[2] = 1; - - transform[4] = 1; - transform[5] = 0; - transform[6] = 0; - - transform[8] = 0; - transform[9] = 1; - transform[10] = 0; - break; - } - transform[3] = transform[7] = transform[11] = transform[12] = transform[13] = transform[14] = 0; - transform[15] = 1; +void Normal_GetTransform(const Vector3 &normal, Matrix4 &transform) +{ + switch (projectionaxis_for_normal(normal)) { + case eProjectionAxisZ: + transform[0] = 1; + transform[1] = 0; + transform[2] = 0; + + transform[4] = 0; + transform[5] = 1; + transform[6] = 0; + + transform[8] = 0; + transform[9] = 0; + transform[10] = 1; + break; + case eProjectionAxisY: + transform[0] = 1; + transform[1] = 0; + transform[2] = 0; + + transform[4] = 0; + transform[5] = 0; + transform[6] = -1; + + transform[8] = 0; + transform[9] = 1; + transform[10] = 0; + break; + case eProjectionAxisX: + transform[0] = 0; + transform[1] = 0; + transform[2] = 1; + + transform[4] = 1; + transform[5] = 0; + transform[6] = 0; + + transform[8] = 0; + transform[9] = 1; + transform[10] = 0; + break; + } + transform[3] = transform[7] = transform[11] = transform[12] = transform[13] = transform[14] = 0; + transform[15] = 1; } /*! @@ -96,310 +96,322 @@ void Normal_GetTransform( const Vector3& normal, Matrix4& transform ){ Transforms constructed from quake's texdef format are (-shift)*(1/scale)*(-rotate) with x translation sign flipped. This would really make more sense if it was inverseof(shift*rotate*scale).. oh well. */ -inline void Texdef_toTransform( const texdef_t& texdef, float width, float height, Matrix4& transform ){ - double inverse_scale[2]; - - // transform to texdef shift/scale/rotate - inverse_scale[0] = 1 / ( texdef.scale[0] * width ); - inverse_scale[1] = 1 / ( texdef.scale[1] * -height ); - transform[12] = texdef.shift[0] / width; - transform[13] = -texdef.shift[1] / -height; - double c = cos( degrees_to_radians( -texdef.rotate ) ); - double s = sin( degrees_to_radians( -texdef.rotate ) ); - transform[0] = static_cast( c * inverse_scale[0] ); - transform[1] = static_cast( s * inverse_scale[1] ); - transform[4] = static_cast( -s * inverse_scale[0] ); - transform[5] = static_cast( c * inverse_scale[1] ); - transform[2] = transform[3] = transform[6] = transform[7] = transform[8] = transform[9] = transform[11] = transform[14] = 0; - transform[10] = transform[15] = 1; -} - -inline void BPTexdef_toTransform( const brushprimit_texdef_t& bp_texdef, Matrix4& transform ){ - transform = g_matrix4_identity; - transform.xx() = bp_texdef.coords[0][0]; - transform.yx() = bp_texdef.coords[0][1]; - transform.tx() = bp_texdef.coords[0][2]; - transform.xy() = bp_texdef.coords[1][0]; - transform.yy() = bp_texdef.coords[1][1]; - transform.ty() = bp_texdef.coords[1][2]; -} - -inline void Texdef_toTransform( const TextureProjection& projection, float width, float height, Matrix4& transform ){ - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - BPTexdef_toTransform( projection.m_brushprimit_texdef, transform ); - } - else - { - Texdef_toTransform( projection.m_texdef, width, height, transform ); - } +inline void Texdef_toTransform(const texdef_t &texdef, float width, float height, Matrix4 &transform) +{ + double inverse_scale[2]; + + // transform to texdef shift/scale/rotate + inverse_scale[0] = 1 / (texdef.scale[0] * width); + inverse_scale[1] = 1 / (texdef.scale[1] * -height); + transform[12] = texdef.shift[0] / width; + transform[13] = -texdef.shift[1] / -height; + double c = cos(degrees_to_radians(-texdef.rotate)); + double s = sin(degrees_to_radians(-texdef.rotate)); + transform[0] = static_cast( c * inverse_scale[0] ); + transform[1] = static_cast( s * inverse_scale[1] ); + transform[4] = static_cast( -s * inverse_scale[0] ); + transform[5] = static_cast( c * inverse_scale[1] ); + transform[2] = transform[3] = transform[6] = transform[7] = transform[8] = transform[9] = transform[11] = transform[14] = 0; + transform[10] = transform[15] = 1; +} + +inline void BPTexdef_toTransform(const brushprimit_texdef_t &bp_texdef, Matrix4 &transform) +{ + transform = g_matrix4_identity; + transform.xx() = bp_texdef.coords[0][0]; + transform.yx() = bp_texdef.coords[0][1]; + transform.tx() = bp_texdef.coords[0][2]; + transform.xy() = bp_texdef.coords[1][0]; + transform.yy() = bp_texdef.coords[1][1]; + transform.ty() = bp_texdef.coords[1][2]; +} + +inline void Texdef_toTransform(const TextureProjection &projection, float width, float height, Matrix4 &transform) +{ + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + BPTexdef_toTransform(projection.m_brushprimit_texdef, transform); + } else { + Texdef_toTransform(projection.m_texdef, width, height, transform); + } } // handles degenerate cases, just in case library atan2 doesn't -inline double arctangent_yx( double y, double x ){ - if ( fabs( x ) > 1.0E-6 ) { - return atan2( y, x ); - } - else if ( y > 0 ) { - return c_half_pi; - } - else - { - return -c_half_pi; - } -} - -inline void Texdef_fromTransform( texdef_t& texdef, float width, float height, const Matrix4& transform ){ - texdef.scale[0] = static_cast( ( 1.0 / vector2_length( Vector2( transform[0], transform[4] ) ) ) / width ); - texdef.scale[1] = static_cast( ( 1.0 / vector2_length( Vector2( transform[1], transform[5] ) ) ) / height ); - - texdef.rotate = static_cast( -radians_to_degrees( arctangent_yx( -transform[4], transform[0] ) ) ); - - if ( texdef.rotate == -180.0f ) { - texdef.rotate = 180.0f; - } - - texdef.shift[0] = transform[12] * width; - texdef.shift[1] = transform[13] * height; - - // If the 2d cross-product of the x and y axes is positive, one of the axes has a negative scale. - if ( vector2_cross( Vector2( transform[0], transform[4] ), Vector2( transform[1], transform[5] ) ) > 0 ) { - if ( texdef.rotate >= 180.0f ) { - texdef.rotate -= 180.0f; - texdef.scale[0] = -texdef.scale[0]; - } - else - { - texdef.scale[1] = -texdef.scale[1]; - } - } - //globalOutputStream() << "fromTransform: " << texdef.shift[0] << " " << texdef.shift[1] << " " << texdef.scale[0] << " " << texdef.scale[1] << " " << texdef.rotate << "\n"; -} - -inline void BPTexdef_fromTransform( brushprimit_texdef_t& bp_texdef, const Matrix4& transform ){ - bp_texdef.coords[0][0] = transform.xx(); - bp_texdef.coords[0][1] = transform.yx(); - bp_texdef.coords[0][2] = transform.tx(); - bp_texdef.coords[1][0] = transform.xy(); - bp_texdef.coords[1][1] = transform.yy(); - bp_texdef.coords[1][2] = transform.ty(); -} - -inline void Texdef_fromTransform( TextureProjection& projection, float width, float height, const Matrix4& transform ){ - ASSERT_MESSAGE( ( transform[0] != 0 || transform[4] != 0 ) - && ( transform[1] != 0 || transform[5] != 0 ), "invalid texture matrix" ); - - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - BPTexdef_fromTransform( projection.m_brushprimit_texdef, transform ); - } - else - { - Texdef_fromTransform( projection.m_texdef, width, height, transform ); - } -} - -inline void Texdef_normalise( texdef_t& texdef, float width, float height ){ - // it may be useful to also normalise the rotation here, if this function is used elsewhere. - texdef.shift[0] = float_mod( texdef.shift[0], width ); - texdef.shift[1] = float_mod( texdef.shift[1], height ); - //globalOutputStream() << "normalise: " << texdef.shift[0] << " " << texdef.shift[1] << " " << texdef.scale[0] << " " << texdef.scale[1] << " " << texdef.rotate << "\n"; -} - -inline void BPTexdef_normalise( brushprimit_texdef_t& bp_texdef, float width, float height ){ - bp_texdef.coords[0][2] = float_mod( bp_texdef.coords[0][2], width ); - bp_texdef.coords[1][2] = float_mod( bp_texdef.coords[1][2], height ); +inline double arctangent_yx(double y, double x) +{ + if (fabs(x) > 1.0E-6) { + return atan2(y, x); + } else if (y > 0) { + return c_half_pi; + } else { + return -c_half_pi; + } +} + +inline void Texdef_fromTransform(texdef_t &texdef, float width, float height, const Matrix4 &transform) +{ + texdef.scale[0] = static_cast((1.0 / vector2_length(Vector2(transform[0], transform[4]))) / width ); + texdef.scale[1] = static_cast((1.0 / vector2_length(Vector2(transform[1], transform[5]))) / height ); + + texdef.rotate = static_cast( -radians_to_degrees(arctangent_yx(-transform[4], transform[0]))); + + if (texdef.rotate == -180.0f) { + texdef.rotate = 180.0f; + } + + texdef.shift[0] = transform[12] * width; + texdef.shift[1] = transform[13] * height; + + // If the 2d cross-product of the x and y axes is positive, one of the axes has a negative scale. + if (vector2_cross(Vector2(transform[0], transform[4]), Vector2(transform[1], transform[5])) > 0) { + if (texdef.rotate >= 180.0f) { + texdef.rotate -= 180.0f; + texdef.scale[0] = -texdef.scale[0]; + } else { + texdef.scale[1] = -texdef.scale[1]; + } + } + //globalOutputStream() << "fromTransform: " << texdef.shift[0] << " " << texdef.shift[1] << " " << texdef.scale[0] << " " << texdef.scale[1] << " " << texdef.rotate << "\n"; +} + +inline void BPTexdef_fromTransform(brushprimit_texdef_t &bp_texdef, const Matrix4 &transform) +{ + bp_texdef.coords[0][0] = transform.xx(); + bp_texdef.coords[0][1] = transform.yx(); + bp_texdef.coords[0][2] = transform.tx(); + bp_texdef.coords[1][0] = transform.xy(); + bp_texdef.coords[1][1] = transform.yy(); + bp_texdef.coords[1][2] = transform.ty(); +} + +inline void Texdef_fromTransform(TextureProjection &projection, float width, float height, const Matrix4 &transform) +{ + ASSERT_MESSAGE((transform[0] != 0 || transform[4] != 0) + && (transform[1] != 0 || transform[5] != 0), "invalid texture matrix"); + + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + BPTexdef_fromTransform(projection.m_brushprimit_texdef, transform); + } else { + Texdef_fromTransform(projection.m_texdef, width, height, transform); + } +} + +inline void Texdef_normalise(texdef_t &texdef, float width, float height) +{ + // it may be useful to also normalise the rotation here, if this function is used elsewhere. + texdef.shift[0] = float_mod(texdef.shift[0], width); + texdef.shift[1] = float_mod(texdef.shift[1], height); + //globalOutputStream() << "normalise: " << texdef.shift[0] << " " << texdef.shift[1] << " " << texdef.scale[0] << " " << texdef.scale[1] << " " << texdef.rotate << "\n"; +} + +inline void BPTexdef_normalise(brushprimit_texdef_t &bp_texdef, float width, float height) +{ + bp_texdef.coords[0][2] = float_mod(bp_texdef.coords[0][2], width); + bp_texdef.coords[1][2] = float_mod(bp_texdef.coords[1][2], height); } /// \brief Normalise \p projection for a given texture \p width and \p height. /// /// All texture-projection translation (shift) values are congruent modulo the dimensions of the texture. /// This function normalises shift values to the smallest positive congruent values. -void Texdef_normalise( TextureProjection& projection, float width, float height ){ - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - BPTexdef_normalise( projection.m_brushprimit_texdef, width, height ); - } - else - { - Texdef_normalise( projection.m_texdef, width, height ); - } -} - -void ComputeAxisBase( const Vector3& normal, Vector3& texS, Vector3& texT ); - -inline void DebugAxisBase( const Vector3& normal ){ - Vector3 x, y; - ComputeAxisBase( normal, x, y ); - globalOutputStream() << "BP debug: " << x << y << normal << "\n"; -} - -void Texdef_basisForNormal( const TextureProjection& projection, const Vector3& normal, Matrix4& basis ){ - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - basis = g_matrix4_identity; - ComputeAxisBase( normal, vector4_to_vector3( basis.x() ), vector4_to_vector3( basis.y() ) ); - vector4_to_vector3( basis.z() ) = normal; - matrix4_transpose( basis ); - //DebugAxisBase(normal); - } - else if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_HALFLIFE ) { - basis = g_matrix4_identity; - vector4_to_vector3( basis.x() ) = projection.m_basis_s; - vector4_to_vector3( basis.y() ) = vector3_negated( projection.m_basis_t ); - vector4_to_vector3( basis.z() ) = vector3_normalised( vector3_cross( vector4_to_vector3( basis.x() ), vector4_to_vector3( basis.y() ) ) ); - matrix4_multiply_by_matrix4( basis, matrix4_rotation_for_z_degrees( -projection.m_texdef.rotate ) ); - //globalOutputStream() << "debug: " << projection.m_basis_s << projection.m_basis_t << normal << "\n"; - matrix4_transpose( basis ); - } - else - { - Normal_GetTransform( normal, basis ); - } -} - -void Texdef_EmitTextureCoordinates( const TextureProjection& projection, std::size_t width, std::size_t height, Winding& w, const Vector3& normal, const Matrix4& localToWorld ){ - if ( w.numpoints < 3 ) { - return; - } - //globalOutputStream() << "normal: " << normal << "\n"; - - Matrix4 local2tex; - Texdef_toTransform( projection, (float)width, (float)height, local2tex ); - //globalOutputStream() << "texdef: " << static_cast(local2tex.x()) << static_cast(local2tex.y()) << "\n"; +void Texdef_normalise(TextureProjection &projection, float width, float height) +{ + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + BPTexdef_normalise(projection.m_brushprimit_texdef, width, height); + } else { + Texdef_normalise(projection.m_texdef, width, height); + } +} + +void ComputeAxisBase(const Vector3 &normal, Vector3 &texS, Vector3 &texT); + +inline void DebugAxisBase(const Vector3 &normal) +{ + Vector3 x, y; + ComputeAxisBase(normal, x, y); + globalOutputStream() << "BP debug: " << x << y << normal << "\n"; +} + +void Texdef_basisForNormal(const TextureProjection &projection, const Vector3 &normal, Matrix4 &basis) +{ + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + basis = g_matrix4_identity; + ComputeAxisBase(normal, vector4_to_vector3(basis.x()), vector4_to_vector3(basis.y())); + vector4_to_vector3(basis.z()) = normal; + matrix4_transpose(basis); + //DebugAxisBase(normal); + } else if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_HALFLIFE) { + basis = g_matrix4_identity; + vector4_to_vector3(basis.x()) = projection.m_basis_s; + vector4_to_vector3(basis.y()) = vector3_negated(projection.m_basis_t); + vector4_to_vector3(basis.z()) = vector3_normalised( + vector3_cross(vector4_to_vector3(basis.x()), vector4_to_vector3(basis.y()))); + matrix4_multiply_by_matrix4(basis, matrix4_rotation_for_z_degrees(-projection.m_texdef.rotate)); + //globalOutputStream() << "debug: " << projection.m_basis_s << projection.m_basis_t << normal << "\n"; + matrix4_transpose(basis); + } else { + Normal_GetTransform(normal, basis); + } +} + +void +Texdef_EmitTextureCoordinates(const TextureProjection &projection, std::size_t width, std::size_t height, Winding &w, + const Vector3 &normal, const Matrix4 &localToWorld) +{ + if (w.numpoints < 3) { + return; + } + //globalOutputStream() << "normal: " << normal << "\n"; + + Matrix4 local2tex; + Texdef_toTransform(projection, (float) width, (float) height, local2tex); + //globalOutputStream() << "texdef: " << static_cast(local2tex.x()) << static_cast(local2tex.y()) << "\n"; #if 0 - { - TextureProjection tmp; - Texdef_fromTransform( tmp, (float)width, (float)height, local2tex ); - Matrix4 tmpTransform; - Texdef_toTransform( tmp, (float)width, (float)height, tmpTransform ); - ASSERT_MESSAGE( matrix4_equal_epsilon( local2tex, tmpTransform, 0.0001f ), "bleh" ); - } + { + TextureProjection tmp; + Texdef_fromTransform( tmp, (float)width, (float)height, local2tex ); + Matrix4 tmpTransform; + Texdef_toTransform( tmp, (float)width, (float)height, tmpTransform ); + ASSERT_MESSAGE( matrix4_equal_epsilon( local2tex, tmpTransform, 0.0001f ), "bleh" ); + } #endif - { - Matrix4 xyz2st; - // we don't care if it's not normalised... - Texdef_basisForNormal( projection, matrix4_transformed_direction( localToWorld, normal ), xyz2st ); - //globalOutputStream() << "basis: " << static_cast(xyz2st.x()) << static_cast(xyz2st.y()) << static_cast(xyz2st.z()) << "\n"; - matrix4_multiply_by_matrix4( local2tex, xyz2st ); - } + { + Matrix4 xyz2st; + // we don't care if it's not normalised... + Texdef_basisForNormal(projection, matrix4_transformed_direction(localToWorld, normal), xyz2st); + //globalOutputStream() << "basis: " << static_cast(xyz2st.x()) << static_cast(xyz2st.y()) << static_cast(xyz2st.z()) << "\n"; + matrix4_multiply_by_matrix4(local2tex, xyz2st); + } - Vector3 tangent( vector3_normalised( vector4_to_vector3( matrix4_transposed( local2tex ).x() ) ) ); - Vector3 bitangent( vector3_normalised( vector4_to_vector3( matrix4_transposed( local2tex ).y() ) ) ); + Vector3 tangent(vector3_normalised(vector4_to_vector3(matrix4_transposed(local2tex).x()))); + Vector3 bitangent(vector3_normalised(vector4_to_vector3(matrix4_transposed(local2tex).y()))); - matrix4_multiply_by_matrix4( local2tex, localToWorld ); + matrix4_multiply_by_matrix4(local2tex, localToWorld); - for ( Winding::iterator i = w.begin(); i != w.end(); ++i ) - { - Vector3 texcoord = matrix4_transformed_point( local2tex, ( *i ).vertex ); - ( *i ).texcoord[0] = texcoord[0]; - ( *i ).texcoord[1] = texcoord[1]; + for (Winding::iterator i = w.begin(); i != w.end(); ++i) { + Vector3 texcoord = matrix4_transformed_point(local2tex, (*i).vertex); + (*i).texcoord[0] = texcoord[0]; + (*i).texcoord[1] = texcoord[1]; - ( *i ).tangent = tangent; - ( *i ).bitangent = bitangent; - } + (*i).tangent = tangent; + (*i).bitangent = bitangent; + } } /*! \brief Provides the axis-base of the texture ST space for this normal, as they had been transformed to world XYZ space. */ -void TextureAxisFromNormal( const Vector3& normal, Vector3& s, Vector3& t ){ - switch ( projectionaxis_for_normal( normal ) ) - { - case eProjectionAxisZ: - s[0] = 1; - s[1] = 0; - s[2] = 0; +void TextureAxisFromNormal(const Vector3 &normal, Vector3 &s, Vector3 &t) +{ + switch (projectionaxis_for_normal(normal)) { + case eProjectionAxisZ: + s[0] = 1; + s[1] = 0; + s[2] = 0; - t[0] = 0; - t[1] = -1; - t[2] = 0; + t[0] = 0; + t[1] = -1; + t[2] = 0; - break; - case eProjectionAxisY: - s[0] = 1; - s[1] = 0; - s[2] = 0; + break; + case eProjectionAxisY: + s[0] = 1; + s[1] = 0; + s[2] = 0; - t[0] = 0; - t[1] = 0; - t[2] = -1; + t[0] = 0; + t[1] = 0; + t[2] = -1; - break; - case eProjectionAxisX: - s[0] = 0; - s[1] = 1; - s[2] = 0; + break; + case eProjectionAxisX: + s[0] = 0; + s[1] = 1; + s[2] = 0; - t[0] = 0; - t[1] = 0; - t[2] = -1; + t[0] = 0; + t[1] = 0; + t[2] = -1; - break; - } + break; + } } -void Texdef_Assign( texdef_t& td, const texdef_t& other ){ - td = other; +void Texdef_Assign(texdef_t &td, const texdef_t &other) +{ + td = other; } -void Texdef_Shift( texdef_t& td, float s, float t ){ - td.shift[0] += s; - td.shift[1] += t; +void Texdef_Shift(texdef_t &td, float s, float t) +{ + td.shift[0] += s; + td.shift[1] += t; } -void Texdef_Scale( texdef_t& td, float s, float t ){ - td.scale[0] += s; - td.scale[1] += t; +void Texdef_Scale(texdef_t &td, float s, float t) +{ + td.scale[0] += s; + td.scale[1] += t; } -void Texdef_Rotate( texdef_t& td, float angle ){ - td.rotate += angle; - td.rotate = static_cast( float_to_integer( td.rotate ) % 360 ); +void Texdef_Rotate(texdef_t &td, float angle) +{ + td.rotate += angle; + td.rotate = static_cast( float_to_integer(td.rotate) % 360 ); } // NOTE: added these from Ritual's Q3Radiant -void ClearBounds( Vector3& mins, Vector3& maxs ){ - mins[0] = mins[1] = mins[2] = 99999; - maxs[0] = maxs[1] = maxs[2] = -99999; +void ClearBounds(Vector3 &mins, Vector3 &maxs) +{ + mins[0] = mins[1] = mins[2] = 99999; + maxs[0] = maxs[1] = maxs[2] = -99999; } -void AddPointToBounds( const Vector3& v, Vector3& mins, Vector3& maxs ){ - int i; - float val; +void AddPointToBounds(const Vector3 &v, Vector3 &mins, Vector3 &maxs) +{ + int i; + float val; - for ( i = 0 ; i < 3 ; i++ ) - { - val = v[i]; - if ( val < mins[i] ) { - mins[i] = val; - } - if ( val > maxs[i] ) { - maxs[i] = val; - } - } + for (i = 0; i < 3; i++) { + val = v[i]; + if (val < mins[i]) { + mins[i] = val; + } + if (val > maxs[i]) { + maxs[i] = val; + } + } } template -inline BasicVector3 vector3_inverse( const BasicVector3& self ){ - return BasicVector3( - Element( 1.0 / self.x() ), - Element( 1.0 / self.y() ), - Element( 1.0 / self.z() ) - ); +inline BasicVector3 vector3_inverse(const BasicVector3 &self) +{ + return BasicVector3( + Element(1.0 / self.x()), + Element(1.0 / self.y()), + Element(1.0 / self.z()) + ); } // low level functions .. put in mathlib? -#define BPMatCopy( a,b ) {b[0][0] = a[0][0]; b[0][1] = a[0][1]; b[0][2] = a[0][2]; b[1][0] = a[1][0]; b[1][1] = a[1][1]; b[1][2] = a[1][2]; } +#define BPMatCopy(a, b) {b[0][0] = a[0][0]; b[0][1] = a[0][1]; b[0][2] = a[0][2]; b[1][0] = a[1][0]; b[1][1] = a[1][1]; b[1][2] = a[1][2]; } // apply a scale transformation to the BP matrix -#define BPMatScale( m,sS,sT ) {m[0][0] *= sS; m[1][0] *= sS; m[0][1] *= sT; m[1][1] *= sT; } +#define BPMatScale(m, sS, sT) {m[0][0] *= sS; m[1][0] *= sS; m[0][1] *= sT; m[1][1] *= sT; } // apply a translation transformation to a BP matrix -#define BPMatTranslate( m,s,t ) {m[0][2] += m[0][0] * s + m[0][1] * t; m[1][2] += m[1][0] * s + m[1][1] * t; } +#define BPMatTranslate(m, s, t) {m[0][2] += m[0][0] * s + m[0][1] * t; m[1][2] += m[1][0] * s + m[1][1] * t; } + // 2D homogeneous matrix product C = A*B -void BPMatMul( float A[2][3], float B[2][3], float C[2][3] ); +void BPMatMul(float A[2][3], float B[2][3], float C[2][3]); + // apply a rotation (degrees) -void BPMatRotate( float A[2][3], float theta ); +void BPMatRotate(float A[2][3], float theta); + #if GDEF_DEBUG -void BPMatDump( float A[2][3] ); + +void BPMatDump(float A[2][3]); + #endif #if GDEF_DEBUG @@ -413,9 +425,10 @@ float g_texdef_default_scale; // compute a determinant using Sarrus rule //++timo "inline" this with a macro // NOTE : the three vectors are understood as columns of the matrix -inline float SarrusDet( const Vector3& a, const Vector3& b, const Vector3& c ){ - return a[0] * b[1] * c[2] + b[0] * c[1] * a[2] + c[0] * a[1] * b[2] - - c[0] * b[1] * a[2] - a[1] * b[0] * c[2] - a[0] * b[2] * c[1]; +inline float SarrusDet(const Vector3 &a, const Vector3 &b, const Vector3 &c) +{ + return a[0] * b[1] * c[2] + b[0] * c[1] * a[2] + c[0] * a[1] * b[2] + - c[0] * b[1] * a[2] - a[1] * b[0] * c[2] - a[0] * b[2] * c[1]; } // in many case we know three points A,B,C in two axis base B1 and B2 @@ -425,205 +438,210 @@ inline float SarrusDet( const Vector3& a, const Vector3& b, const Vector3& c ){ // NOTE: the third coord of the A,B,C point is ignored // NOTE: see the commented out section to fill M and D //++timo TODO: update the other members to use this when possible -void MatrixForPoints( Vector3 M[3], Vector3 D[2], brushprimit_texdef_t *T ){ +void MatrixForPoints(Vector3 M[3], Vector3 D[2], brushprimit_texdef_t *T) +{ // Vector3 M[3]; // columns of the matrix .. easier that way (the indexing is not standard! it's column-line .. later computations are easier that way) - float det; + float det; // Vector3 D[2]; - M[2][0] = 1.0f; M[2][1] = 1.0f; M[2][2] = 1.0f; + M[2][0] = 1.0f; + M[2][1] = 1.0f; + M[2][2] = 1.0f; #if 0 - // fill the data vectors - M[0][0] = A2[0]; M[0][1] = B2[0]; M[0][2] = C2[0]; - M[1][0] = A2[1]; M[1][1] = B2[1]; M[1][2] = C2[1]; - M[2][0] = 1.0f; M[2][1] = 1.0f; M[2][2] = 1.0f; - D[0][0] = A1[0]; - D[0][1] = B1[0]; - D[0][2] = C1[0]; - D[1][0] = A1[1]; - D[1][1] = B1[1]; - D[1][2] = C1[1]; + // fill the data vectors + M[0][0] = A2[0]; M[0][1] = B2[0]; M[0][2] = C2[0]; + M[1][0] = A2[1]; M[1][1] = B2[1]; M[1][2] = C2[1]; + M[2][0] = 1.0f; M[2][1] = 1.0f; M[2][2] = 1.0f; + D[0][0] = A1[0]; + D[0][1] = B1[0]; + D[0][2] = C1[0]; + D[1][0] = A1[1]; + D[1][1] = B1[1]; + D[1][2] = C1[1]; #endif - // solve - det = SarrusDet( M[0], M[1], M[2] ); - T->coords[0][0] = SarrusDet( D[0], M[1], M[2] ) / det; - T->coords[0][1] = SarrusDet( M[0], D[0], M[2] ) / det; - T->coords[0][2] = SarrusDet( M[0], M[1], D[0] ) / det; - T->coords[1][0] = SarrusDet( D[1], M[1], M[2] ) / det; - T->coords[1][1] = SarrusDet( M[0], D[1], M[2] ) / det; - T->coords[1][2] = SarrusDet( M[0], M[1], D[1] ) / det; + // solve + det = SarrusDet(M[0], M[1], M[2]); + T->coords[0][0] = SarrusDet(D[0], M[1], M[2]) / det; + T->coords[0][1] = SarrusDet(M[0], D[0], M[2]) / det; + T->coords[0][2] = SarrusDet(M[0], M[1], D[0]) / det; + T->coords[1][0] = SarrusDet(D[1], M[1], M[2]) / det; + T->coords[1][1] = SarrusDet(M[0], D[1], M[2]) / det; + T->coords[1][2] = SarrusDet(M[0], M[1], D[1]) / det; } //++timo replace everywhere texX by texS etc. ( ----> and in q3map !) // NOTE : ComputeAxisBase here and in q3map code must always BE THE SAME ! // WARNING : special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere when x == 0 // rotation by (0,RotY,RotZ) assigns X to normal -void ComputeAxisBase( const Vector3& normal, Vector3& texS, Vector3& texT ){ +void ComputeAxisBase(const Vector3 &normal, Vector3 &texS, Vector3 &texT) +{ #if 1 - const Vector3 up( 0, 0, 1 ); - const Vector3 down( 0, 0, -1 ); - - if ( vector3_equal_epsilon( normal, up, float(1e-6) ) ) { - texS = Vector3( 0, 1, 0 ); - texT = Vector3( 1, 0, 0 ); - } - else if ( vector3_equal_epsilon( normal, down, float(1e-6) ) ) { - texS = Vector3( 0, 1, 0 ); - texT = Vector3( -1, 0, 0 ); - } - else - { - texS = vector3_normalised( vector3_cross( normal, up ) ); - texT = vector3_normalised( vector3_cross( normal, texS ) ); - vector3_negate( texS ); - } + const Vector3 up(0, 0, 1); + const Vector3 down(0, 0, -1); + + if (vector3_equal_epsilon(normal, up, float(1e-6))) { + texS = Vector3(0, 1, 0); + texT = Vector3(1, 0, 0); + } else if (vector3_equal_epsilon(normal, down, float(1e-6))) { + texS = Vector3(0, 1, 0); + texT = Vector3(-1, 0, 0); + } else { + texS = vector3_normalised(vector3_cross(normal, up)); + texT = vector3_normalised(vector3_cross(normal, texS)); + vector3_negate(texS); + } #else - float RotY,RotZ; - // do some cleaning - /* - if (fabs(normal[0])<1e-6) - normal[0]=0.0f; - if (fabs(normal[1])<1e-6) - normal[1]=0.0f; - if (fabs(normal[2])<1e-6) - normal[2]=0.0f; - */ - RotY = -atan2( normal[2],sqrt( normal[1] * normal[1] + normal[0] * normal[0] ) ); - RotZ = atan2( normal[1],normal[0] ); - // rotate (0,1,0) and (0,0,1) to compute texS and texT - texS[0] = -sin( RotZ ); - texS[1] = cos( RotZ ); - texS[2] = 0; - // the texT vector is along -Z ( T texture coorinates axis ) - texT[0] = -sin( RotY ) * cos( RotZ ); - texT[1] = -sin( RotY ) * sin( RotZ ); - texT[2] = -cos( RotY ); + float RotY,RotZ; + // do some cleaning + /* + if (fabs(normal[0])<1e-6) + normal[0]=0.0f; + if (fabs(normal[1])<1e-6) + normal[1]=0.0f; + if (fabs(normal[2])<1e-6) + normal[2]=0.0f; + */ + RotY = -atan2( normal[2],sqrt( normal[1] * normal[1] + normal[0] * normal[0] ) ); + RotZ = atan2( normal[1],normal[0] ); + // rotate (0,1,0) and (0,0,1) to compute texS and texT + texS[0] = -sin( RotZ ); + texS[1] = cos( RotZ ); + texS[2] = 0; + // the texT vector is along -Z ( T texture coorinates axis ) + texT[0] = -sin( RotY ) * cos( RotZ ); + texT[1] = -sin( RotY ) * sin( RotZ ); + texT[2] = -cos( RotY ); #endif } #if 0 // texdef conversion void FaceToBrushPrimitFace( face_t *f ){ - Vector3 texX,texY; - Vector3 proj; - // ST of (0,0) (1,0) (0,1) - float ST[3][5]; // [ point index ] [ xyz ST ] - //++timo not used as long as brushprimit_texdef and texdef are static + Vector3 texX,texY; + Vector3 proj; + // ST of (0,0) (1,0) (0,1) + float ST[3][5]; // [ point index ] [ xyz ST ] + //++timo not used as long as brushprimit_texdef and texdef are static /* f->brushprimit_texdef.contents=f->texdef.contents; f->brushprimit_texdef.flags=f->texdef.flags; f->brushprimit_texdef.value=f->texdef.value; strcpy(f->brushprimit_texdef.name,f->texdef.name); */ #ifdef DBG_BP - if ( f->plane.normal[0] == 0.0f && f->plane.normal[1] == 0.0f && f->plane.normal[2] == 0.0f ) { - globalOutputStream() << "Warning : f->plane.normal is (0,0,0) in FaceToBrushPrimitFace\n"; - } - // check d_texture - if ( !f->d_texture ) { - globalOutputStream() << "Warning : f.d_texture is 0 in FaceToBrushPrimitFace\n"; - return; - } + if ( f->plane.normal[0] == 0.0f && f->plane.normal[1] == 0.0f && f->plane.normal[2] == 0.0f ) { + globalOutputStream() << "Warning : f->plane.normal is (0,0,0) in FaceToBrushPrimitFace\n"; + } + // check d_texture + if ( !f->d_texture ) { + globalOutputStream() << "Warning : f.d_texture is 0 in FaceToBrushPrimitFace\n"; + return; + } #endif - // compute axis base - ComputeAxisBase( f->plane.normal,texX,texY ); - // compute projection vector - VectorCopy( f->plane.normal,proj ); - VectorScale( proj,f->plane.dist,proj ); - // (0,0) in plane axis base is (0,0,0) in world coordinates + projection on the affine plane - // (1,0) in plane axis base is texX in world coordinates + projection on the affine plane - // (0,1) in plane axis base is texY in world coordinates + projection on the affine plane - // use old texture code to compute the ST coords of these points - VectorCopy( proj,ST[0] ); - EmitTextureCoordinates( ST[0], f->pShader->getTexture(), f ); - VectorCopy( texX,ST[1] ); - VectorAdd( ST[1],proj,ST[1] ); - EmitTextureCoordinates( ST[1], f->pShader->getTexture(), f ); - VectorCopy( texY,ST[2] ); - VectorAdd( ST[2],proj,ST[2] ); - EmitTextureCoordinates( ST[2], f->pShader->getTexture(), f ); - // compute texture matrix - f->brushprimit_texdef.coords[0][2] = ST[0][3]; - f->brushprimit_texdef.coords[1][2] = ST[0][4]; - f->brushprimit_texdef.coords[0][0] = ST[1][3] - f->brushprimit_texdef.coords[0][2]; - f->brushprimit_texdef.coords[1][0] = ST[1][4] - f->brushprimit_texdef.coords[1][2]; - f->brushprimit_texdef.coords[0][1] = ST[2][3] - f->brushprimit_texdef.coords[0][2]; - f->brushprimit_texdef.coords[1][1] = ST[2][4] - f->brushprimit_texdef.coords[1][2]; + // compute axis base + ComputeAxisBase( f->plane.normal,texX,texY ); + // compute projection vector + VectorCopy( f->plane.normal,proj ); + VectorScale( proj,f->plane.dist,proj ); + // (0,0) in plane axis base is (0,0,0) in world coordinates + projection on the affine plane + // (1,0) in plane axis base is texX in world coordinates + projection on the affine plane + // (0,1) in plane axis base is texY in world coordinates + projection on the affine plane + // use old texture code to compute the ST coords of these points + VectorCopy( proj,ST[0] ); + EmitTextureCoordinates( ST[0], f->pShader->getTexture(), f ); + VectorCopy( texX,ST[1] ); + VectorAdd( ST[1],proj,ST[1] ); + EmitTextureCoordinates( ST[1], f->pShader->getTexture(), f ); + VectorCopy( texY,ST[2] ); + VectorAdd( ST[2],proj,ST[2] ); + EmitTextureCoordinates( ST[2], f->pShader->getTexture(), f ); + // compute texture matrix + f->brushprimit_texdef.coords[0][2] = ST[0][3]; + f->brushprimit_texdef.coords[1][2] = ST[0][4]; + f->brushprimit_texdef.coords[0][0] = ST[1][3] - f->brushprimit_texdef.coords[0][2]; + f->brushprimit_texdef.coords[1][0] = ST[1][4] - f->brushprimit_texdef.coords[1][2]; + f->brushprimit_texdef.coords[0][1] = ST[2][3] - f->brushprimit_texdef.coords[0][2]; + f->brushprimit_texdef.coords[1][1] = ST[2][4] - f->brushprimit_texdef.coords[1][2]; } // compute texture coordinates for the winding points void EmitBrushPrimitTextureCoordinates( face_t * f, Winding * w ){ - Vector3 texX,texY; - float x,y; - // compute axis base - ComputeAxisBase( f->plane.normal,texX,texY ); - // in case the texcoords matrix is empty, build a default one - // same behaviour as if scale[0]==0 && scale[1]==0 in old code - if ( f->brushprimit_texdef.coords[0][0] == 0 && f->brushprimit_texdef.coords[1][0] == 0 && f->brushprimit_texdef.coords[0][1] == 0 && f->brushprimit_texdef.coords[1][1] == 0 ) { - f->brushprimit_texdef.coords[0][0] = 1.0f; - f->brushprimit_texdef.coords[1][1] = 1.0f; - ConvertTexMatWithQTexture( &f->brushprimit_texdef, 0, &f->brushprimit_texdef, f->pShader->getTexture() ); - } - int i; - for ( i = 0 ; i < w.numpoints ; i++ ) - { - x = vector3_dot( w.point_at( i ),texX ); - y = vector3_dot( w.point_at( i ),texY ); + Vector3 texX,texY; + float x,y; + // compute axis base + ComputeAxisBase( f->plane.normal,texX,texY ); + // in case the texcoords matrix is empty, build a default one + // same behaviour as if scale[0]==0 && scale[1]==0 in old code + if ( f->brushprimit_texdef.coords[0][0] == 0 && f->brushprimit_texdef.coords[1][0] == 0 && f->brushprimit_texdef.coords[0][1] == 0 && f->brushprimit_texdef.coords[1][1] == 0 ) { + f->brushprimit_texdef.coords[0][0] = 1.0f; + f->brushprimit_texdef.coords[1][1] = 1.0f; + ConvertTexMatWithQTexture( &f->brushprimit_texdef, 0, &f->brushprimit_texdef, f->pShader->getTexture() ); + } + int i; + for ( i = 0 ; i < w.numpoints ; i++ ) + { + x = vector3_dot( w.point_at( i ),texX ); + y = vector3_dot( w.point_at( i ),texY ); #if 0 #ifdef DBG_BP - if ( g_bp_globals.bNeedConvert ) { - // check we compute the same ST as the traditional texture computation used before - float S = f->brushprimit_texdef.coords[0][0] * x + f->brushprimit_texdef.coords[0][1] * y + f->brushprimit_texdef.coords[0][2]; - float T = f->brushprimit_texdef.coords[1][0] * x + f->brushprimit_texdef.coords[1][1] * y + f->brushprimit_texdef.coords[1][2]; - if ( fabs( S - w.point_at( i )[3] ) > 1e-2 || fabs( T - w.point_at( i )[4] ) > 1e-2 ) { - if ( fabs( S - w.point_at( i )[3] ) > 1e-4 || fabs( T - w.point_at( i )[4] ) > 1e-4 ) { - globalOutputStream() << "Warning : precision loss in brush -> brush primitive texture computation\n"; - } - else{ - globalOutputStream() << "Warning : brush -> brush primitive texture computation bug detected\n"; - } - } - } + if ( g_bp_globals.bNeedConvert ) { + // check we compute the same ST as the traditional texture computation used before + float S = f->brushprimit_texdef.coords[0][0] * x + f->brushprimit_texdef.coords[0][1] * y + f->brushprimit_texdef.coords[0][2]; + float T = f->brushprimit_texdef.coords[1][0] * x + f->brushprimit_texdef.coords[1][1] * y + f->brushprimit_texdef.coords[1][2]; + if ( fabs( S - w.point_at( i )[3] ) > 1e-2 || fabs( T - w.point_at( i )[4] ) > 1e-2 ) { + if ( fabs( S - w.point_at( i )[3] ) > 1e-4 || fabs( T - w.point_at( i )[4] ) > 1e-4 ) { + globalOutputStream() << "Warning : precision loss in brush -> brush primitive texture computation\n"; + } + else{ + globalOutputStream() << "Warning : brush -> brush primitive texture computation bug detected\n"; + } + } + } #endif #endif - w.point_at( i )[3] = f->brushprimit_texdef.coords[0][0] * x + f->brushprimit_texdef.coords[0][1] * y + f->brushprimit_texdef.coords[0][2]; - w.point_at( i )[4] = f->brushprimit_texdef.coords[1][0] * x + f->brushprimit_texdef.coords[1][1] * y + f->brushprimit_texdef.coords[1][2]; - } + w.point_at( i )[3] = f->brushprimit_texdef.coords[0][0] * x + f->brushprimit_texdef.coords[0][1] * y + f->brushprimit_texdef.coords[0][2]; + w.point_at( i )[4] = f->brushprimit_texdef.coords[1][0] * x + f->brushprimit_texdef.coords[1][1] * y + f->brushprimit_texdef.coords[1][2]; + } } #endif typedef float texmat_t[2][3]; -void TexMat_Scale( texmat_t texmat, float s, float t ){ - texmat[0][0] *= s; - texmat[0][1] *= s; - texmat[0][2] *= s; - texmat[1][0] *= t; - texmat[1][1] *= t; - texmat[1][2] *= t; +void TexMat_Scale(texmat_t texmat, float s, float t) +{ + texmat[0][0] *= s; + texmat[0][1] *= s; + texmat[0][2] *= s; + texmat[1][0] *= t; + texmat[1][1] *= t; + texmat[1][2] *= t; } -void TexMat_Assign( texmat_t texmat, const texmat_t other ){ - texmat[0][0] = other[0][0]; - texmat[0][1] = other[0][1]; - texmat[0][2] = other[0][2]; - texmat[1][0] = other[1][0]; - texmat[1][1] = other[1][1]; - texmat[1][2] = other[1][2]; +void TexMat_Assign(texmat_t texmat, const texmat_t other) +{ + texmat[0][0] = other[0][0]; + texmat[0][1] = other[0][1]; + texmat[0][2] = other[0][2]; + texmat[1][0] = other[1][0]; + texmat[1][1] = other[1][1]; + texmat[1][2] = other[1][2]; } -void ConvertTexMatWithDimensions( const texmat_t texmat1, std::size_t w1, std::size_t h1, - texmat_t texmat2, std::size_t w2, std::size_t h2 ){ - TexMat_Assign( texmat2, texmat1 ); - TexMat_Scale( texmat2, static_cast( w1 ) / static_cast( w2 ), static_cast( h1 ) / static_cast( h2 ) ); +void ConvertTexMatWithDimensions(const texmat_t texmat1, std::size_t w1, std::size_t h1, + texmat_t texmat2, std::size_t w2, std::size_t h2) +{ + TexMat_Assign(texmat2, texmat1); + TexMat_Scale(texmat2, static_cast( w1 ) / static_cast( w2 ), + static_cast( h1 ) / static_cast( h2 )); } #if 0 // convert a texture matrix between two qtexture_t // if 0 for qtexture_t, basic 2x2 texture is assumed ( straight mapping between s/t coordinates and geometric coordinates ) void ConvertTexMatWithQTexture( const float texMat1[2][3], const qtexture_t *qtex1, float texMat2[2][3], const qtexture_t *qtex2 ){ - ConvertTexMatWithDimensions( texMat1, ( qtex1 ) ? qtex1->width : 2, ( qtex1 ) ? qtex1->height : 2, - texMat2, ( qtex2 ) ? qtex2->width : 2, ( qtex2 ) ? qtex2->height : 2 ); + ConvertTexMatWithDimensions( texMat1, ( qtex1 ) ? qtex1->width : 2, ( qtex1 ) ? qtex1->height : 2, + texMat2, ( qtex2 ) ? qtex2->width : 2, ( qtex2 ) ? qtex2->height : 2 ); } void ConvertTexMatWithQTexture( const brushprimit_texdef_t *texMat1, const qtexture_t *qtex1, brushprimit_texdef_t *texMat2, const qtexture_t *qtex2 ){ - ConvertTexMatWithQTexture( texMat1->coords, qtex1, texMat2->coords, qtex2 ); + ConvertTexMatWithQTexture( texMat1->coords, qtex1, texMat2->coords, qtex2 ); } #endif @@ -631,136 +649,137 @@ void ConvertTexMatWithQTexture( const brushprimit_texdef_t *texMat1, const qtext // these shift scale rot values are to be understood in the local axis base // Note: this code looks similar to Texdef_fromTransform, but the algorithm is slightly different. -void TexMatToFakeTexCoords( const brushprimit_texdef_t& bp_texdef, texdef_t& texdef ){ - texdef.scale[0] = static_cast( 1.0 / vector2_length( Vector2( bp_texdef.coords[0][0], bp_texdef.coords[1][0] ) ) ); - texdef.scale[1] = static_cast( 1.0 / vector2_length( Vector2( bp_texdef.coords[0][1], bp_texdef.coords[1][1] ) ) ); - - texdef.rotate = -static_cast( radians_to_degrees( arctangent_yx( bp_texdef.coords[1][0], bp_texdef.coords[0][0] ) ) ); - - texdef.shift[0] = -bp_texdef.coords[0][2]; - texdef.shift[1] = bp_texdef.coords[1][2]; - - // determine whether or not an axis is flipped using a 2d cross-product - double cross = vector2_cross( Vector2( bp_texdef.coords[0][0], bp_texdef.coords[0][1] ), Vector2( bp_texdef.coords[1][0], bp_texdef.coords[1][1] ) ); - if ( cross < 0 ) { - // This is a bit of a compromise when using BPs--since we don't know *which* axis was flipped, - // we pick one (rather arbitrarily) using the following convention: If the X-axis is between - // 0 and 180, we assume it's the Y-axis that flipped, otherwise we assume it's the X-axis and - // subtract out 180 degrees to compensate. - if ( texdef.rotate >= 180.0f ) { - texdef.rotate -= 180.0f; - texdef.scale[0] = -texdef.scale[0]; - } - else - { - texdef.scale[1] = -texdef.scale[1]; - } - } +void TexMatToFakeTexCoords(const brushprimit_texdef_t &bp_texdef, texdef_t &texdef) +{ + texdef.scale[0] = static_cast( 1.0 / + vector2_length(Vector2(bp_texdef.coords[0][0], bp_texdef.coords[1][0]))); + texdef.scale[1] = static_cast( 1.0 / + vector2_length(Vector2(bp_texdef.coords[0][1], bp_texdef.coords[1][1]))); + + texdef.rotate = -static_cast( radians_to_degrees( + arctangent_yx(bp_texdef.coords[1][0], bp_texdef.coords[0][0]))); + + texdef.shift[0] = -bp_texdef.coords[0][2]; + texdef.shift[1] = bp_texdef.coords[1][2]; + + // determine whether or not an axis is flipped using a 2d cross-product + double cross = vector2_cross(Vector2(bp_texdef.coords[0][0], bp_texdef.coords[0][1]), + Vector2(bp_texdef.coords[1][0], bp_texdef.coords[1][1])); + if (cross < 0) { + // This is a bit of a compromise when using BPs--since we don't know *which* axis was flipped, + // we pick one (rather arbitrarily) using the following convention: If the X-axis is between + // 0 and 180, we assume it's the Y-axis that flipped, otherwise we assume it's the X-axis and + // subtract out 180 degrees to compensate. + if (texdef.rotate >= 180.0f) { + texdef.rotate -= 180.0f; + texdef.scale[0] = -texdef.scale[0]; + } else { + texdef.scale[1] = -texdef.scale[1]; + } + } } // compute back the texture matrix from fake shift scale rot -void FakeTexCoordsToTexMat( const texdef_t& texdef, brushprimit_texdef_t& bp_texdef ){ - double r = degrees_to_radians( -texdef.rotate ); - double c = cos( r ); - double s = sin( r ); - double x = 1.0f / texdef.scale[0]; - double y = 1.0f / texdef.scale[1]; - bp_texdef.coords[0][0] = static_cast( x * c ); - bp_texdef.coords[1][0] = static_cast( x * s ); - bp_texdef.coords[0][1] = static_cast( y * -s ); - bp_texdef.coords[1][1] = static_cast( y * c ); - bp_texdef.coords[0][2] = -texdef.shift[0]; - bp_texdef.coords[1][2] = texdef.shift[1]; +void FakeTexCoordsToTexMat(const texdef_t &texdef, brushprimit_texdef_t &bp_texdef) +{ + double r = degrees_to_radians(-texdef.rotate); + double c = cos(r); + double s = sin(r); + double x = 1.0f / texdef.scale[0]; + double y = 1.0f / texdef.scale[1]; + bp_texdef.coords[0][0] = static_cast( x * c ); + bp_texdef.coords[1][0] = static_cast( x * s ); + bp_texdef.coords[0][1] = static_cast( y * -s ); + bp_texdef.coords[1][1] = static_cast( y * c ); + bp_texdef.coords[0][2] = -texdef.shift[0]; + bp_texdef.coords[1][2] = texdef.shift[1]; } #if 0 // texture locking (brush primit) // used for texture locking // will move the texture according to a geometric vector void ShiftTextureGeometric_BrushPrimit( face_t *f, Vector3& delta ){ - Vector3 texS,texT; - float tx,ty; - Vector3 M[3]; // columns of the matrix .. easier that way - float det; - Vector3 D[2]; - // compute plane axis base ( doesn't change with translation ) - ComputeAxisBase( f->plane.normal, texS, texT ); - // compute translation vector in plane axis base - tx = vector3_dot( delta, texS ); - ty = vector3_dot( delta, texT ); - // fill the data vectors - M[0][0] = tx; M[0][1] = 1.0f + tx; M[0][2] = tx; - M[1][0] = ty; M[1][1] = ty; M[1][2] = 1.0f + ty; - M[2][0] = 1.0f; M[2][1] = 1.0f; M[2][2] = 1.0f; - D[0][0] = f->brushprimit_texdef.coords[0][2]; - D[0][1] = f->brushprimit_texdef.coords[0][0] + f->brushprimit_texdef.coords[0][2]; - D[0][2] = f->brushprimit_texdef.coords[0][1] + f->brushprimit_texdef.coords[0][2]; - D[1][0] = f->brushprimit_texdef.coords[1][2]; - D[1][1] = f->brushprimit_texdef.coords[1][0] + f->brushprimit_texdef.coords[1][2]; - D[1][2] = f->brushprimit_texdef.coords[1][1] + f->brushprimit_texdef.coords[1][2]; - // solve - det = SarrusDet( M[0], M[1], M[2] ); - f->brushprimit_texdef.coords[0][0] = SarrusDet( D[0], M[1], M[2] ) / det; - f->brushprimit_texdef.coords[0][1] = SarrusDet( M[0], D[0], M[2] ) / det; - f->brushprimit_texdef.coords[0][2] = SarrusDet( M[0], M[1], D[0] ) / det; - f->brushprimit_texdef.coords[1][0] = SarrusDet( D[1], M[1], M[2] ) / det; - f->brushprimit_texdef.coords[1][1] = SarrusDet( M[0], D[1], M[2] ) / det; - f->brushprimit_texdef.coords[1][2] = SarrusDet( M[0], M[1], D[1] ) / det; + Vector3 texS,texT; + float tx,ty; + Vector3 M[3]; // columns of the matrix .. easier that way + float det; + Vector3 D[2]; + // compute plane axis base ( doesn't change with translation ) + ComputeAxisBase( f->plane.normal, texS, texT ); + // compute translation vector in plane axis base + tx = vector3_dot( delta, texS ); + ty = vector3_dot( delta, texT ); + // fill the data vectors + M[0][0] = tx; M[0][1] = 1.0f + tx; M[0][2] = tx; + M[1][0] = ty; M[1][1] = ty; M[1][2] = 1.0f + ty; + M[2][0] = 1.0f; M[2][1] = 1.0f; M[2][2] = 1.0f; + D[0][0] = f->brushprimit_texdef.coords[0][2]; + D[0][1] = f->brushprimit_texdef.coords[0][0] + f->brushprimit_texdef.coords[0][2]; + D[0][2] = f->brushprimit_texdef.coords[0][1] + f->brushprimit_texdef.coords[0][2]; + D[1][0] = f->brushprimit_texdef.coords[1][2]; + D[1][1] = f->brushprimit_texdef.coords[1][0] + f->brushprimit_texdef.coords[1][2]; + D[1][2] = f->brushprimit_texdef.coords[1][1] + f->brushprimit_texdef.coords[1][2]; + // solve + det = SarrusDet( M[0], M[1], M[2] ); + f->brushprimit_texdef.coords[0][0] = SarrusDet( D[0], M[1], M[2] ) / det; + f->brushprimit_texdef.coords[0][1] = SarrusDet( M[0], D[0], M[2] ) / det; + f->brushprimit_texdef.coords[0][2] = SarrusDet( M[0], M[1], D[0] ) / det; + f->brushprimit_texdef.coords[1][0] = SarrusDet( D[1], M[1], M[2] ) / det; + f->brushprimit_texdef.coords[1][1] = SarrusDet( M[0], D[1], M[2] ) / det; + f->brushprimit_texdef.coords[1][2] = SarrusDet( M[0], M[1], D[1] ) / det; } // shift a texture (texture adjustments) along it's current texture axes // x and y are geometric values, which we must compute as ST increments // this depends on the texture size and the pixel/texel ratio void ShiftTextureRelative_BrushPrimit( face_t *f, float x, float y ){ - float s,t; - // as a ratio against texture size - // the scale of the texture is not relevant here (we work directly on a transformation from the base vectors) - s = ( x * 2.0 ) / (float)f->pShader->getTexture().width; - t = ( y * 2.0 ) / (float)f->pShader->getTexture().height; - f->brushprimit_texdef.coords[0][2] -= s; - f->brushprimit_texdef.coords[1][2] -= t; + float s,t; + // as a ratio against texture size + // the scale of the texture is not relevant here (we work directly on a transformation from the base vectors) + s = ( x * 2.0 ) / (float)f->pShader->getTexture().width; + t = ( y * 2.0 ) / (float)f->pShader->getTexture().height; + f->brushprimit_texdef.coords[0][2] -= s; + f->brushprimit_texdef.coords[1][2] -= t; } #endif // TTimo: FIXME: I don't like that, it feels broken // (and it's likely that it's not used anymore) // best fitted 2D vector is x.X+y.Y -void ComputeBest2DVector( Vector3& v, Vector3& X, Vector3& Y, int &x, int &y ){ - double sx,sy; - sx = vector3_dot( v, X ); - sy = vector3_dot( v, Y ); - if ( fabs( sy ) > fabs( sx ) ) { - x = 0; - if ( sy > 0.0 ) { - y = 1; - } - else{ - y = -1; - } - } - else - { - y = 0; - if ( sx > 0.0 ) { - x = 1; - } - else{ - x = -1; - } - } +void ComputeBest2DVector(Vector3 &v, Vector3 &X, Vector3 &Y, int &x, int &y) +{ + double sx, sy; + sx = vector3_dot(v, X); + sy = vector3_dot(v, Y); + if (fabs(sy) > fabs(sx)) { + x = 0; + if (sy > 0.0) { + y = 1; + } else { + y = -1; + } + } else { + y = 0; + if (sx > 0.0) { + x = 1; + } else { + x = -1; + } + } } #if 0 // texdef conversion void BrushPrimitFaceToFace( face_t *face ){ - // we have parsed brush primitives and need conversion back to standard format - // NOTE: converting back is a quick hack, there's some information lost and we can't do anything about it - // FIXME: if we normalize the texture matrix to a standard 2x2 size, we end up with wrong scaling - // I tried various tweaks, no luck .. seems shifting is lost - brushprimit_texdef_t aux; - ConvertTexMatWithQTexture( &face->brushprimit_texdef, face->pShader->getTexture(), &aux, 0 ); - TexMatToFakeTexCoords( aux.coords, face->texdef.shift, &face->texdef.rotate, face->texdef.scale ); - face->texdef.scale[0] /= 2.0; - face->texdef.scale[1] /= 2.0; + // we have parsed brush primitives and need conversion back to standard format + // NOTE: converting back is a quick hack, there's some information lost and we can't do anything about it + // FIXME: if we normalize the texture matrix to a standard 2x2 size, we end up with wrong scaling + // I tried various tweaks, no luck .. seems shifting is lost + brushprimit_texdef_t aux; + ConvertTexMatWithQTexture( &face->brushprimit_texdef, face->pShader->getTexture(), &aux, 0 ); + TexMatToFakeTexCoords( aux.coords, face->texdef.shift, &face->texdef.rotate, face->texdef.scale ); + face->texdef.scale[0] /= 2.0; + face->texdef.scale[1] /= 2.0; } #endif @@ -787,87 +806,87 @@ Vector3 txl_matrix[3]; Vector3 txl_origin; void TextureLockTransformation_BrushPrimit( face_t *f ){ - Vector3 Orig,texS,texT; // axis base of initial plane - // used by transformation algo - Vector3 temp; int j; - Vector3 vRotate; // rotation vector - - Vector3 rOrig,rvecS,rvecT; // geometric transformation of (0,0) (1,0) (0,1) { initial plane axis base } - Vector3 rNormal,rtexS,rtexT; // axis base for the transformed plane - Vector3 lOrig,lvecS,lvecT; // [2] are not used ( but usefull for debugging ) - Vector3 M[3]; - float det; - Vector3 D[2]; - - // compute plane axis base - ComputeAxisBase( f->plane.normal, texS, texT ); - VectorSet( Orig, 0.0f, 0.0f, 0.0f ); - - // compute coordinates of (0,0) (1,0) (0,1) ( expressed in initial plane axis base ) after transformation - // (0,0) (1,0) (0,1) ( expressed in initial plane axis base ) <-> (0,0,0) texS texT ( expressed world axis base ) - // input: Orig, texS, texT (and the global locking params) - // ouput: rOrig, rvecS, rvecT, rNormal - if ( txlock_bRotation ) { - // rotation vector - VectorSet( vRotate, 0.0f, 0.0f, 0.0f ); - vRotate[txl_nAxis] = txl_fDeg; - VectorRotateOrigin( Orig, vRotate, txl_vOrigin, rOrig ); - VectorRotateOrigin( texS, vRotate, txl_vOrigin, rvecS ); - VectorRotateOrigin( texT, vRotate, txl_vOrigin, rvecT ); - // compute normal of plane after rotation - VectorRotate( f->plane.normal, vRotate, rNormal ); - } - else - { - for ( j = 0 ; j < 3 ; j++ ) - rOrig[j] = vector3_dot( vector3_subtracted( Orig, txl_origin ), txl_matrix[j] ) + txl_origin[j]; - for ( j = 0 ; j < 3 ; j++ ) - rvecS[j] = vector3_dot( vector3_subtracted( texS, txl_origin ), txl_matrix[j] ) + txl_origin[j]; - for ( j = 0 ; j < 3 ; j++ ) - rvecT[j] = vector3_dot( vector3_subtracted( texT, txl_origin ), txl_matrix[j] ) + txl_origin[j]; - // we also need the axis base of the target plane, apply the transformation matrix to the normal too.. - for ( j = 0 ; j < 3 ; j++ ) - rNormal[j] = vector3_dot( f->plane.normal, txl_matrix[j] ); - } - - // compute rotated plane axis base - ComputeAxisBase( rNormal, rtexS, rtexT ); - // compute S/T coordinates of the three points in rotated axis base ( in M matrix ) - lOrig[0] = vector3_dot( rOrig, rtexS ); - lOrig[1] = vector3_dot( rOrig, rtexT ); - lvecS[0] = vector3_dot( rvecS, rtexS ); - lvecS[1] = vector3_dot( rvecS, rtexT ); - lvecT[0] = vector3_dot( rvecT, rtexS ); - lvecT[1] = vector3_dot( rvecT, rtexT ); - M[0][0] = lOrig[0]; M[1][0] = lOrig[1]; M[2][0] = 1.0f; - M[0][1] = lvecS[0]; M[1][1] = lvecS[1]; M[2][1] = 1.0f; - M[0][2] = lvecT[0]; M[1][2] = lvecT[1]; M[2][2] = 1.0f; - // fill data vector - D[0][0] = f->brushprimit_texdef.coords[0][2]; - D[0][1] = f->brushprimit_texdef.coords[0][0] + f->brushprimit_texdef.coords[0][2]; - D[0][2] = f->brushprimit_texdef.coords[0][1] + f->brushprimit_texdef.coords[0][2]; - D[1][0] = f->brushprimit_texdef.coords[1][2]; - D[1][1] = f->brushprimit_texdef.coords[1][0] + f->brushprimit_texdef.coords[1][2]; - D[1][2] = f->brushprimit_texdef.coords[1][1] + f->brushprimit_texdef.coords[1][2]; - // solve - det = SarrusDet( M[0], M[1], M[2] ); - f->brushprimit_texdef.coords[0][0] = SarrusDet( D[0], M[1], M[2] ) / det; - f->brushprimit_texdef.coords[0][1] = SarrusDet( M[0], D[0], M[2] ) / det; - f->brushprimit_texdef.coords[0][2] = SarrusDet( M[0], M[1], D[0] ) / det; - f->brushprimit_texdef.coords[1][0] = SarrusDet( D[1], M[1], M[2] ) / det; - f->brushprimit_texdef.coords[1][1] = SarrusDet( M[0], D[1], M[2] ) / det; - f->brushprimit_texdef.coords[1][2] = SarrusDet( M[0], M[1], D[1] ) / det; + Vector3 Orig,texS,texT; // axis base of initial plane + // used by transformation algo + Vector3 temp; int j; + Vector3 vRotate; // rotation vector + + Vector3 rOrig,rvecS,rvecT; // geometric transformation of (0,0) (1,0) (0,1) { initial plane axis base } + Vector3 rNormal,rtexS,rtexT; // axis base for the transformed plane + Vector3 lOrig,lvecS,lvecT; // [2] are not used ( but usefull for debugging ) + Vector3 M[3]; + float det; + Vector3 D[2]; + + // compute plane axis base + ComputeAxisBase( f->plane.normal, texS, texT ); + VectorSet( Orig, 0.0f, 0.0f, 0.0f ); + + // compute coordinates of (0,0) (1,0) (0,1) ( expressed in initial plane axis base ) after transformation + // (0,0) (1,0) (0,1) ( expressed in initial plane axis base ) <-> (0,0,0) texS texT ( expressed world axis base ) + // input: Orig, texS, texT (and the global locking params) + // ouput: rOrig, rvecS, rvecT, rNormal + if ( txlock_bRotation ) { + // rotation vector + VectorSet( vRotate, 0.0f, 0.0f, 0.0f ); + vRotate[txl_nAxis] = txl_fDeg; + VectorRotateOrigin( Orig, vRotate, txl_vOrigin, rOrig ); + VectorRotateOrigin( texS, vRotate, txl_vOrigin, rvecS ); + VectorRotateOrigin( texT, vRotate, txl_vOrigin, rvecT ); + // compute normal of plane after rotation + VectorRotate( f->plane.normal, vRotate, rNormal ); + } + else + { + for ( j = 0 ; j < 3 ; j++ ) + rOrig[j] = vector3_dot( vector3_subtracted( Orig, txl_origin ), txl_matrix[j] ) + txl_origin[j]; + for ( j = 0 ; j < 3 ; j++ ) + rvecS[j] = vector3_dot( vector3_subtracted( texS, txl_origin ), txl_matrix[j] ) + txl_origin[j]; + for ( j = 0 ; j < 3 ; j++ ) + rvecT[j] = vector3_dot( vector3_subtracted( texT, txl_origin ), txl_matrix[j] ) + txl_origin[j]; + // we also need the axis base of the target plane, apply the transformation matrix to the normal too.. + for ( j = 0 ; j < 3 ; j++ ) + rNormal[j] = vector3_dot( f->plane.normal, txl_matrix[j] ); + } + + // compute rotated plane axis base + ComputeAxisBase( rNormal, rtexS, rtexT ); + // compute S/T coordinates of the three points in rotated axis base ( in M matrix ) + lOrig[0] = vector3_dot( rOrig, rtexS ); + lOrig[1] = vector3_dot( rOrig, rtexT ); + lvecS[0] = vector3_dot( rvecS, rtexS ); + lvecS[1] = vector3_dot( rvecS, rtexT ); + lvecT[0] = vector3_dot( rvecT, rtexS ); + lvecT[1] = vector3_dot( rvecT, rtexT ); + M[0][0] = lOrig[0]; M[1][0] = lOrig[1]; M[2][0] = 1.0f; + M[0][1] = lvecS[0]; M[1][1] = lvecS[1]; M[2][1] = 1.0f; + M[0][2] = lvecT[0]; M[1][2] = lvecT[1]; M[2][2] = 1.0f; + // fill data vector + D[0][0] = f->brushprimit_texdef.coords[0][2]; + D[0][1] = f->brushprimit_texdef.coords[0][0] + f->brushprimit_texdef.coords[0][2]; + D[0][2] = f->brushprimit_texdef.coords[0][1] + f->brushprimit_texdef.coords[0][2]; + D[1][0] = f->brushprimit_texdef.coords[1][2]; + D[1][1] = f->brushprimit_texdef.coords[1][0] + f->brushprimit_texdef.coords[1][2]; + D[1][2] = f->brushprimit_texdef.coords[1][1] + f->brushprimit_texdef.coords[1][2]; + // solve + det = SarrusDet( M[0], M[1], M[2] ); + f->brushprimit_texdef.coords[0][0] = SarrusDet( D[0], M[1], M[2] ) / det; + f->brushprimit_texdef.coords[0][1] = SarrusDet( M[0], D[0], M[2] ) / det; + f->brushprimit_texdef.coords[0][2] = SarrusDet( M[0], M[1], D[0] ) / det; + f->brushprimit_texdef.coords[1][0] = SarrusDet( D[1], M[1], M[2] ) / det; + f->brushprimit_texdef.coords[1][1] = SarrusDet( M[0], D[1], M[2] ) / det; + f->brushprimit_texdef.coords[1][2] = SarrusDet( M[0], M[1], D[1] ) / det; } // texture locking // called before the points on the face are actually rotated void RotateFaceTexture_BrushPrimit( face_t *f, int nAxis, float fDeg, Vector3& vOrigin ){ - // this is a placeholder to call the general texture locking algorithm - txlock_bRotation = true; - txl_nAxis = nAxis; - txl_fDeg = fDeg; - VectorCopy( vOrigin, txl_vOrigin ); - TextureLockTransformation_BrushPrimit( f ); + // this is a placeholder to call the general texture locking algorithm + txlock_bRotation = true; + txl_nAxis = nAxis; + txl_fDeg = fDeg; + VectorCopy( vOrigin, txl_vOrigin ); + TextureLockTransformation_BrushPrimit( f ); } // compute the new brush primit texture matrix for a transformation matrix and a flip order flag (change plane orientation) @@ -875,489 +894,508 @@ void RotateFaceTexture_BrushPrimit( face_t *f, int nAxis, float fDeg, Vector3& v // this needs to be called on the face BEFORE any geometric transformation // it will compute the texture matrix that will represent the same texture on the face after the geometric transformation is done void ApplyMatrix_BrushPrimit( face_t *f, Vector3 matrix[3], Vector3& origin ){ - // this is a placeholder to call the general texture locking algorithm - txlock_bRotation = false; - VectorCopy( matrix[0], txl_matrix[0] ); - VectorCopy( matrix[1], txl_matrix[1] ); - VectorCopy( matrix[2], txl_matrix[2] ); - VectorCopy( origin, txl_origin ); - TextureLockTransformation_BrushPrimit( f ); + // this is a placeholder to call the general texture locking algorithm + txlock_bRotation = false; + VectorCopy( matrix[0], txl_matrix[0] ); + VectorCopy( matrix[1], txl_matrix[1] ); + VectorCopy( matrix[2], txl_matrix[2] ); + VectorCopy( origin, txl_origin ); + TextureLockTransformation_BrushPrimit( f ); } #endif // don't do C==A! -void BPMatMul( float A[2][3], float B[2][3], float C[2][3] ){ - C[0][0] = A[0][0] * B[0][0] + A[0][1] * B[1][0]; - C[1][0] = A[1][0] * B[0][0] + A[1][1] * B[1][0]; - C[0][1] = A[0][0] * B[0][1] + A[0][1] * B[1][1]; - C[1][1] = A[1][0] * B[0][1] + A[1][1] * B[1][1]; - C[0][2] = A[0][0] * B[0][2] + A[0][1] * B[1][2] + A[0][2]; - C[1][2] = A[1][0] * B[0][2] + A[1][1] * B[1][2] + A[1][2]; -} - -void BPMatDump( float A[2][3] ){ - globalOutputStream() << "" << A[0][0] - << " " << A[0][1] - << " " << A[0][2] - << "\n" << A[1][0] - << " " << A[1][2] - << " " << A[1][2] - << "\n0 0 1\n"; -} - -void BPMatRotate( float A[2][3], float theta ){ - float m[2][3]; - float aux[2][3]; - memset( &m, 0, sizeof( float ) * 6 ); - m[0][0] = static_cast( cos( degrees_to_radians( theta ) ) ); - m[0][1] = static_cast( -sin( degrees_to_radians( theta ) ) ); - m[1][0] = -m[0][1]; - m[1][1] = m[0][0]; - BPMatMul( A, m, aux ); - BPMatCopy( aux,A ); +void BPMatMul(float A[2][3], float B[2][3], float C[2][3]) +{ + C[0][0] = A[0][0] * B[0][0] + A[0][1] * B[1][0]; + C[1][0] = A[1][0] * B[0][0] + A[1][1] * B[1][0]; + C[0][1] = A[0][0] * B[0][1] + A[0][1] * B[1][1]; + C[1][1] = A[1][0] * B[0][1] + A[1][1] * B[1][1]; + C[0][2] = A[0][0] * B[0][2] + A[0][1] * B[1][2] + A[0][2]; + C[1][2] = A[1][0] * B[0][2] + A[1][1] * B[1][2] + A[1][2]; +} + +void BPMatDump(float A[2][3]) +{ + globalOutputStream() << "" << A[0][0] + << " " << A[0][1] + << " " << A[0][2] + << "\n" << A[1][0] + << " " << A[1][2] + << " " << A[1][2] + << "\n0 0 1\n"; +} + +void BPMatRotate(float A[2][3], float theta) +{ + float m[2][3]; + float aux[2][3]; + memset(&m, 0, sizeof(float) * 6); + m[0][0] = static_cast( cos(degrees_to_radians(theta))); + m[0][1] = static_cast( -sin(degrees_to_radians(theta))); + m[1][0] = -m[0][1]; + m[1][1] = m[0][0]; + BPMatMul(A, m, aux); + BPMatCopy(aux, A); } #if 0 // camera-relative texture shift // get the relative axes of the current texturing void BrushPrimit_GetRelativeAxes( face_t *f, Vector3& vecS, Vector3& vecT ){ - float vS[2],vT[2]; - // first we compute them as expressed in plane axis base - // BP matrix has coordinates of plane axis base expressed in geometric axis base - // so we use the line vectors - vS[0] = f->brushprimit_texdef.coords[0][0]; - vS[1] = f->brushprimit_texdef.coords[0][1]; - vT[0] = f->brushprimit_texdef.coords[1][0]; - vT[1] = f->brushprimit_texdef.coords[1][1]; - // now compute those vectors in geometric space - Vector3 texS, texT; // axis base of the plane (geometric) - ComputeAxisBase( f->plane.normal, texS, texT ); - // vecS[] = vS[0].texS[] + vS[1].texT[] - // vecT[] = vT[0].texS[] + vT[1].texT[] - vecS[0] = vS[0] * texS[0] + vS[1] * texT[0]; - vecS[1] = vS[0] * texS[1] + vS[1] * texT[1]; - vecS[2] = vS[0] * texS[2] + vS[1] * texT[2]; - vecT[0] = vT[0] * texS[0] + vT[1] * texT[0]; - vecT[1] = vT[0] * texS[1] + vT[1] * texT[1]; - vecT[2] = vT[0] * texS[2] + vT[1] * texT[2]; + float vS[2],vT[2]; + // first we compute them as expressed in plane axis base + // BP matrix has coordinates of plane axis base expressed in geometric axis base + // so we use the line vectors + vS[0] = f->brushprimit_texdef.coords[0][0]; + vS[1] = f->brushprimit_texdef.coords[0][1]; + vT[0] = f->brushprimit_texdef.coords[1][0]; + vT[1] = f->brushprimit_texdef.coords[1][1]; + // now compute those vectors in geometric space + Vector3 texS, texT; // axis base of the plane (geometric) + ComputeAxisBase( f->plane.normal, texS, texT ); + // vecS[] = vS[0].texS[] + vS[1].texT[] + // vecT[] = vT[0].texS[] + vT[1].texT[] + vecS[0] = vS[0] * texS[0] + vS[1] * texT[0]; + vecS[1] = vS[0] * texS[1] + vS[1] * texT[1]; + vecS[2] = vS[0] * texS[2] + vS[1] * texT[2]; + vecT[0] = vT[0] * texS[0] + vT[1] * texT[0]; + vecT[1] = vT[0] * texS[1] + vT[1] * texT[1]; + vecT[2] = vT[0] * texS[2] + vT[1] * texT[2]; } // brush primitive texture adjustments, use the camera view to map adjustments // ShiftTextureRelative_BrushPrimit ( s , t ) will shift relative to the texture void ShiftTextureRelative_Camera( face_t *f, int x, int y ){ - Vector3 vecS, vecT; - float XY[2]; // the values we are going to send for translation - float sgn[2]; // +1 or -1 - int axis[2]; - CamWnd* pCam; - - // get the two relative texture axes for the current texturing - BrushPrimit_GetRelativeAxes( f, vecS, vecT ); - - // center point of the face, project it on the camera space - Vector3 C; - VectorClear( C ); - int i; - for ( i = 0; i < f->face_winding->numpoints; i++ ) - { - VectorAdd( C,f->face_winding->point_at( i ),C ); - } - VectorScale( C,1.0 / f->face_winding->numpoints,C ); - - pCam = g_pParentWnd->GetCamWnd(); - pCam->MatchViewAxes( C, vecS, axis[0], sgn[0] ); - pCam->MatchViewAxes( C, vecT, axis[1], sgn[1] ); - - // this happens when the two directions can't be mapped on two different directions on the screen - // then the move will occur against a single axis - // (i.e. the user is not positioned well enough to send understandable shift commands) - // NOTE: in most cases this warning is not very relevant because the user would use one of the two axes - // for which the solution is easy (the other one being unknown) - // so this warning could be removed - if ( axis[0] == axis[1] ) { - globalOutputStream() << "Warning: degenerate in ShiftTextureRelative_Camera\n"; - } - - // compute the X Y geometric increments - // those geometric increments will be applied along the texture axes (the ones we computed above) - XY[0] = 0; - XY[1] = 0; - if ( x != 0 ) { - // moving right/left - XY[axis[0]] += sgn[0] * x; - } - if ( y != 0 ) { - XY[axis[1]] += sgn[1] * y; - } - // we worked out a move along vecS vecT, and we now it's geometric amplitude - // apply it - ShiftTextureRelative_BrushPrimit( f, XY[0], XY[1] ); + Vector3 vecS, vecT; + float XY[2]; // the values we are going to send for translation + float sgn[2]; // +1 or -1 + int axis[2]; + CamWnd* pCam; + + // get the two relative texture axes for the current texturing + BrushPrimit_GetRelativeAxes( f, vecS, vecT ); + + // center point of the face, project it on the camera space + Vector3 C; + VectorClear( C ); + int i; + for ( i = 0; i < f->face_winding->numpoints; i++ ) + { + VectorAdd( C,f->face_winding->point_at( i ),C ); + } + VectorScale( C,1.0 / f->face_winding->numpoints,C ); + + pCam = g_pParentWnd->GetCamWnd(); + pCam->MatchViewAxes( C, vecS, axis[0], sgn[0] ); + pCam->MatchViewAxes( C, vecT, axis[1], sgn[1] ); + + // this happens when the two directions can't be mapped on two different directions on the screen + // then the move will occur against a single axis + // (i.e. the user is not positioned well enough to send understandable shift commands) + // NOTE: in most cases this warning is not very relevant because the user would use one of the two axes + // for which the solution is easy (the other one being unknown) + // so this warning could be removed + if ( axis[0] == axis[1] ) { + globalOutputStream() << "Warning: degenerate in ShiftTextureRelative_Camera\n"; + } + + // compute the X Y geometric increments + // those geometric increments will be applied along the texture axes (the ones we computed above) + XY[0] = 0; + XY[1] = 0; + if ( x != 0 ) { + // moving right/left + XY[axis[0]] += sgn[0] * x; + } + if ( y != 0 ) { + XY[axis[1]] += sgn[1] * y; + } + // we worked out a move along vecS vecT, and we now it's geometric amplitude + // apply it + ShiftTextureRelative_BrushPrimit( f, XY[0], XY[1] ); } #endif -void BPTexdef_Assign( brushprimit_texdef_t& bp_td, const brushprimit_texdef_t& bp_other ){ - bp_td = bp_other; -} - -void BPTexdef_Shift( brushprimit_texdef_t& bp_td, float s, float t ){ - // shift a texture (texture adjustments) along it's current texture axes - // x and y are geometric values, which we must compute as ST increments - // this depends on the texture size and the pixel/texel ratio - // as a ratio against texture size - // the scale of the texture is not relevant here (we work directly on a transformation from the base vectors) - bp_td.coords[0][2] -= s; - bp_td.coords[1][2] += t; -} - -void BPTexdef_Scale( brushprimit_texdef_t& bp_td, float s, float t ){ - // apply same scale as the spinner button of the surface inspector - texdef_t texdef; - // compute fake shift scale rot - TexMatToFakeTexCoords( bp_td, texdef ); - // update - texdef.scale[0] += s; - texdef.scale[1] += t; - // compute new normalized texture matrix - FakeTexCoordsToTexMat( texdef, bp_td ); -} - -void BPTexdef_Rotate( brushprimit_texdef_t& bp_td, float angle ){ - // apply same scale as the spinner button of the surface inspector - texdef_t texdef; - // compute fake shift scale rot - TexMatToFakeTexCoords( bp_td, texdef ); - // update - texdef.rotate += angle; - // compute new normalized texture matrix - FakeTexCoordsToTexMat( texdef, bp_td ); -} - -void BPTexdef_Construct( brushprimit_texdef_t& bp_td, std::size_t width, std::size_t height ){ - bp_td.coords[0][0] = 1.0f; - bp_td.coords[1][1] = 1.0f; - ConvertTexMatWithDimensions( bp_td.coords, 2, 2, bp_td.coords, width, height ); -} - -void Texdef_Assign( TextureProjection& projection, const TextureProjection& other ){ - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - BPTexdef_Assign( projection.m_brushprimit_texdef, other.m_brushprimit_texdef ); - } - else - { - Texdef_Assign( projection.m_texdef, other.m_texdef ); - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_HALFLIFE ) { - projection.m_basis_s = other.m_basis_s; - projection.m_basis_t = other.m_basis_t; - } - } -} - -void Texdef_Shift( TextureProjection& projection, float s, float t ){ - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - BPTexdef_Shift( projection.m_brushprimit_texdef, s, t ); - } - else - { - Texdef_Shift( projection.m_texdef, s, t ); - } -} - -void Texdef_Scale( TextureProjection& projection, float s, float t ){ - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - BPTexdef_Scale( projection.m_brushprimit_texdef, s, t ); - } - else - { - Texdef_Scale( projection.m_texdef, s, t ); - } -} - -void Texdef_Rotate( TextureProjection& projection, float angle ){ - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - BPTexdef_Rotate( projection.m_brushprimit_texdef, angle ); - } - else - { - Texdef_Rotate( projection.m_texdef, 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 ){ - if ( w.numpoints < 3 ) { - return; - } - - Matrix4 st2tex; - Texdef_toTransform( projection, (float)width, (float)height, st2tex ); - - // the current texture transform - Matrix4 local2tex = st2tex; - { - Matrix4 xyz2st; - Texdef_basisForNormal( projection, normal, xyz2st ); - matrix4_multiply_by_matrix4( local2tex, xyz2st ); - } - - // the bounds of the current texture transform - AABB bounds; - for ( Winding::const_iterator i = w.begin(); i != w.end(); ++i ) - { - Vector3 texcoord = matrix4_transformed_point( local2tex, ( *i ).vertex ); - aabb_extend_by_point_safe( bounds, texcoord ); - } - bounds.origin.z() = 0; - bounds.extents.z() = 1; - - // the bounds of a perfectly fitted texture transform - AABB perfect( Vector3( s_repeat * 0.5, t_repeat * 0.5, 0 ), Vector3( s_repeat * 0.5, t_repeat * 0.5, 1 ) ); - - // the difference between the current texture transform and the perfectly fitted transform - Matrix4 matrix( matrix4_translation_for_vec3( bounds.origin - perfect.origin ) ); - matrix4_pivoted_scale_by_vec3( matrix, bounds.extents / perfect.extents, perfect.origin ); - matrix4_affine_invert( matrix ); +void BPTexdef_Assign(brushprimit_texdef_t &bp_td, const brushprimit_texdef_t &bp_other) +{ + bp_td = bp_other; +} + +void BPTexdef_Shift(brushprimit_texdef_t &bp_td, float s, float t) +{ + // shift a texture (texture adjustments) along it's current texture axes + // x and y are geometric values, which we must compute as ST increments + // this depends on the texture size and the pixel/texel ratio + // as a ratio against texture size + // the scale of the texture is not relevant here (we work directly on a transformation from the base vectors) + bp_td.coords[0][2] -= s; + bp_td.coords[1][2] += t; +} + +void BPTexdef_Scale(brushprimit_texdef_t &bp_td, float s, float t) +{ + // apply same scale as the spinner button of the surface inspector + texdef_t texdef; + // compute fake shift scale rot + TexMatToFakeTexCoords(bp_td, texdef); + // update + texdef.scale[0] += s; + texdef.scale[1] += t; + // compute new normalized texture matrix + FakeTexCoordsToTexMat(texdef, bp_td); +} + +void BPTexdef_Rotate(brushprimit_texdef_t &bp_td, float angle) +{ + // apply same scale as the spinner button of the surface inspector + texdef_t texdef; + // compute fake shift scale rot + TexMatToFakeTexCoords(bp_td, texdef); + // update + texdef.rotate += angle; + // compute new normalized texture matrix + FakeTexCoordsToTexMat(texdef, bp_td); +} + +void BPTexdef_Construct(brushprimit_texdef_t &bp_td, std::size_t width, std::size_t height) +{ + bp_td.coords[0][0] = 1.0f; + bp_td.coords[1][1] = 1.0f; + ConvertTexMatWithDimensions(bp_td.coords, 2, 2, bp_td.coords, width, height); +} + +void Texdef_Assign(TextureProjection &projection, const TextureProjection &other) +{ + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + BPTexdef_Assign(projection.m_brushprimit_texdef, other.m_brushprimit_texdef); + } else { + Texdef_Assign(projection.m_texdef, other.m_texdef); + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_HALFLIFE) { + projection.m_basis_s = other.m_basis_s; + projection.m_basis_t = other.m_basis_t; + } + } +} + +void Texdef_Shift(TextureProjection &projection, float s, float t) +{ + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + BPTexdef_Shift(projection.m_brushprimit_texdef, s, t); + } else { + Texdef_Shift(projection.m_texdef, s, t); + } +} + +void Texdef_Scale(TextureProjection &projection, float s, float t) +{ + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + BPTexdef_Scale(projection.m_brushprimit_texdef, s, t); + } else { + Texdef_Scale(projection.m_texdef, s, t); + } +} + +void Texdef_Rotate(TextureProjection &projection, float angle) +{ + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + BPTexdef_Rotate(projection.m_brushprimit_texdef, angle); + } else { + Texdef_Rotate(projection.m_texdef, 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) +{ + if (w.numpoints < 3) { + return; + } + + Matrix4 st2tex; + Texdef_toTransform(projection, (float) width, (float) height, st2tex); + + // the current texture transform + Matrix4 local2tex = st2tex; + { + Matrix4 xyz2st; + Texdef_basisForNormal(projection, normal, xyz2st); + matrix4_multiply_by_matrix4(local2tex, xyz2st); + } + + // the bounds of the current texture transform + AABB bounds; + for (Winding::const_iterator i = w.begin(); i != w.end(); ++i) { + Vector3 texcoord = matrix4_transformed_point(local2tex, (*i).vertex); + aabb_extend_by_point_safe(bounds, texcoord); + } + bounds.origin.z() = 0; + bounds.extents.z() = 1; + + // the bounds of a perfectly fitted texture transform + AABB perfect(Vector3(s_repeat * 0.5, t_repeat * 0.5, 0), Vector3(s_repeat * 0.5, t_repeat * 0.5, 1)); + + // the difference between the current texture transform and the perfectly fitted transform + Matrix4 matrix(matrix4_translation_for_vec3(bounds.origin - perfect.origin)); + matrix4_pivoted_scale_by_vec3(matrix, bounds.extents / perfect.extents, perfect.origin); + matrix4_affine_invert(matrix); - // apply the difference to the current texture transform - matrix4_premultiply_by_matrix4( st2tex, matrix ); + // apply the difference to the current texture transform + matrix4_premultiply_by_matrix4(st2tex, matrix); + + Texdef_fromTransform(projection, (float) width, (float) height, st2tex); + Texdef_normalise(projection, (float) width, (float) height); +} + +float Texdef_getDefaultTextureScale() +{ + return g_texdef_default_scale; +} + +void TexDef_Construct_Default(TextureProjection &projection) +{ + projection.m_texdef.scale[0] = Texdef_getDefaultTextureScale(); + projection.m_texdef.scale[1] = Texdef_getDefaultTextureScale(); + + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + FakeTexCoordsToTexMat(projection.m_texdef, projection.m_brushprimit_texdef); + } +} + + +void ShiftScaleRotate_fromFace(texdef_t &shiftScaleRotate, const TextureProjection &projection) +{ + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + TexMatToFakeTexCoords(projection.m_brushprimit_texdef, shiftScaleRotate); + } else { + shiftScaleRotate = projection.m_texdef; + } +} + +void ShiftScaleRotate_toFace(const texdef_t &shiftScaleRotate, TextureProjection &projection) +{ + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES) { + // compute texture matrix + // the matrix returned must be understood as a qtexture_t with width=2 height=2 + FakeTexCoordsToTexMat(shiftScaleRotate, projection.m_brushprimit_texdef); + } else { + projection.m_texdef = shiftScaleRotate; + } +} - Texdef_fromTransform( projection, (float)width, (float)height, st2tex ); - Texdef_normalise( projection, (float)width, (float)height ); -} - -float Texdef_getDefaultTextureScale(){ - return g_texdef_default_scale; -} - -void TexDef_Construct_Default( TextureProjection& projection ){ - projection.m_texdef.scale[0] = Texdef_getDefaultTextureScale(); - projection.m_texdef.scale[1] = Texdef_getDefaultTextureScale(); - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - FakeTexCoordsToTexMat( projection.m_texdef, projection.m_brushprimit_texdef ); - } -} - - - -void ShiftScaleRotate_fromFace( texdef_t& shiftScaleRotate, const TextureProjection& projection ){ - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - TexMatToFakeTexCoords( projection.m_brushprimit_texdef, shiftScaleRotate ); - } - else - { - shiftScaleRotate = projection.m_texdef; - } -} - -void ShiftScaleRotate_toFace( const texdef_t& shiftScaleRotate, TextureProjection& projection ){ - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - // compute texture matrix - // the matrix returned must be understood as a qtexture_t with width=2 height=2 - FakeTexCoordsToTexMat( shiftScaleRotate, projection.m_brushprimit_texdef ); - } - else - { - projection.m_texdef = shiftScaleRotate; - } +inline void print_vector3(const Vector3 &v) +{ + globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )\n"; +} + +inline void print_3x3(const Matrix4 &m) +{ + globalOutputStream() << "( " << m.xx() << " " << m.xy() << " " << m.xz() << " ) " + << "( " << m.yx() << " " << m.yy() << " " << m.yz() << " ) " + << "( " << m.zx() << " " << m.zy() << " " << m.zz() << " )\n"; } -inline void print_vector3( const Vector3& v ){ - globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )\n"; -} - -inline void print_3x3( const Matrix4& m ){ - globalOutputStream() << "( " << m.xx() << " " << m.xy() << " " << m.xz() << " ) " - << "( " << m.yx() << " " << m.yy() << " " << m.yz() << " ) " - << "( " << m.zx() << " " << m.zy() << " " << m.zz() << " )\n"; -} +inline Matrix4 matrix4_rotation_for_vector3(const Vector3 &x, const Vector3 &y, const Vector3 &z) +{ + return Matrix4( + x.x(), x.y(), x.z(), 0, + y.x(), y.y(), y.z(), 0, + z.x(), z.y(), z.z(), 0, + 0, 0, 0, 1 + ); +} + +inline Matrix4 matrix4_swap_axes(const Vector3 &from, const Vector3 &to) +{ + if (from.x() != 0 && to.y() != 0) { + return matrix4_rotation_for_vector3(to, from, g_vector3_axis_z); + } + + if (from.x() != 0 && to.z() != 0) { + return matrix4_rotation_for_vector3(to, g_vector3_axis_y, from); + } + if (from.y() != 0 && to.z() != 0) { + return matrix4_rotation_for_vector3(g_vector3_axis_x, to, from); + } -inline Matrix4 matrix4_rotation_for_vector3( const Vector3& x, const Vector3& y, const Vector3& z ){ - return Matrix4( - x.x(), x.y(), x.z(), 0, - y.x(), y.y(), y.z(), 0, - z.x(), z.y(), z.z(), 0, - 0, 0, 0, 1 - ); -} + if (from.y() != 0 && to.x() != 0) { + return matrix4_rotation_for_vector3(from, to, g_vector3_axis_z); + } -inline Matrix4 matrix4_swap_axes( const Vector3& from, const Vector3& to ){ - if ( from.x() != 0 && to.y() != 0 ) { - return matrix4_rotation_for_vector3( to, from, g_vector3_axis_z ); - } + if (from.z() != 0 && to.x() != 0) { + return matrix4_rotation_for_vector3(from, g_vector3_axis_y, to); + } - if ( from.x() != 0 && to.z() != 0 ) { - return matrix4_rotation_for_vector3( to, g_vector3_axis_y, from ); - } + if (from.z() != 0 && to.y() != 0) { + return matrix4_rotation_for_vector3(g_vector3_axis_x, from, to); + } - if ( from.y() != 0 && to.z() != 0 ) { - return matrix4_rotation_for_vector3( g_vector3_axis_x, to, from ); - } + ERROR_MESSAGE("unhandled axis swap case"); - if ( from.y() != 0 && to.x() != 0 ) { - return matrix4_rotation_for_vector3( from, to, g_vector3_axis_z ); - } - - if ( from.z() != 0 && to.x() != 0 ) { - return matrix4_rotation_for_vector3( from, g_vector3_axis_y, to ); - } - - if ( from.z() != 0 && to.y() != 0 ) { - return matrix4_rotation_for_vector3( g_vector3_axis_x, from, to ); - } - - ERROR_MESSAGE( "unhandled axis swap case" ); - - return g_matrix4_identity; + return g_matrix4_identity; } -inline Matrix4 matrix4_reflection_for_plane( const Plane3& plane ){ - return Matrix4( - static_cast( 1 - ( 2 * plane.a * plane.a ) ), - static_cast( -2 * plane.a * plane.b ), - static_cast( -2 * plane.a * plane.c ), - 0, - static_cast( -2 * plane.b * plane.a ), - static_cast( 1 - ( 2 * plane.b * plane.b ) ), - static_cast( -2 * plane.b * plane.c ), - 0, - static_cast( -2 * plane.c * plane.a ), - static_cast( -2 * plane.c * plane.b ), - static_cast( 1 - ( 2 * plane.c * plane.c ) ), - 0, - static_cast( -2 * plane.d * plane.a ), - static_cast( -2 * plane.d * plane.b ), - static_cast( -2 * plane.d * plane.c ), - 1 - ); +inline Matrix4 matrix4_reflection_for_plane(const Plane3 &plane) +{ + return Matrix4( + static_cast( 1 - (2 * plane.a * plane.a)), + static_cast( -2 * plane.a * plane.b ), + static_cast( -2 * plane.a * plane.c ), + 0, + static_cast( -2 * plane.b * plane.a ), + static_cast( 1 - (2 * plane.b * plane.b)), + static_cast( -2 * plane.b * plane.c ), + 0, + static_cast( -2 * plane.c * plane.a ), + static_cast( -2 * plane.c * plane.b ), + static_cast( 1 - (2 * plane.c * plane.c)), + 0, + static_cast( -2 * plane.d * plane.a ), + static_cast( -2 * plane.d * plane.b ), + static_cast( -2 * plane.d * plane.c ), + 1 + ); } -inline Matrix4 matrix4_reflection_for_plane45( const Plane3& plane, const Vector3& from, const Vector3& to ){ - Vector3 first = from; - Vector3 second = to; - - if ( (vector3_dot( from, plane.normal() ) > 0) == (vector3_dot( to, plane.normal() ) > 0) ) { - first = vector3_negated( first ); - second = vector3_negated( second ); - } +inline Matrix4 matrix4_reflection_for_plane45(const Plane3 &plane, const Vector3 &from, const Vector3 &to) +{ + Vector3 first = from; + Vector3 second = to; + + if ((vector3_dot(from, plane.normal()) > 0) == (vector3_dot(to, plane.normal()) > 0)) { + first = vector3_negated(first); + second = vector3_negated(second); + } #if 0 - globalOutputStream() << "normal: "; - print_vector3( plane.normal() ); + globalOutputStream() << "normal: "; + print_vector3( plane.normal() ); - globalOutputStream() << "from: "; - print_vector3( first ); + globalOutputStream() << "from: "; + print_vector3( first ); - globalOutputStream() << "to: "; - print_vector3( second ); + globalOutputStream() << "to: "; + print_vector3( second ); #endif - Matrix4 swap = matrix4_swap_axes( first, second ); + Matrix4 swap = matrix4_swap_axes(first, second); - swap.tx() = -static_cast( -2 * plane.a * plane.d ); - swap.ty() = -static_cast( -2 * plane.b * plane.d ); - swap.tz() = -static_cast( -2 * plane.c * plane.d ); + swap.tx() = -static_cast( -2 * plane.a * plane.d ); + swap.ty() = -static_cast( -2 * plane.b * plane.d ); + swap.tz() = -static_cast( -2 * plane.c * plane.d ); - return swap; + return swap; } -void Texdef_transformLocked( TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const Matrix4& identity2transformed ){ - //globalOutputStream() << "identity2transformed: " << identity2transformed << "\n"; +void Texdef_transformLocked(TextureProjection &projection, std::size_t width, std::size_t height, const Plane3 &plane, + const Matrix4 &identity2transformed) +{ + //globalOutputStream() << "identity2transformed: " << identity2transformed << "\n"; - //globalOutputStream() << "plane.normal(): " << plane.normal() << "\n"; + //globalOutputStream() << "plane.normal(): " << plane.normal() << "\n"; - Vector3 normalTransformed( matrix4_transformed_direction( identity2transformed, plane.normal() ) ); + Vector3 normalTransformed(matrix4_transformed_direction(identity2transformed, plane.normal())); - //globalOutputStream() << "normalTransformed: " << normalTransformed << "\n"; + //globalOutputStream() << "normalTransformed: " << normalTransformed << "\n"; - // identity: identity space - // transformed: transformation - // stIdentity: base st projection space before transformation - // stTransformed: base st projection space after transformation - // stOriginal: original texdef space + // identity: identity space + // transformed: transformation + // stIdentity: base st projection space before transformation + // stTransformed: base st projection space after transformation + // stOriginal: original texdef space - // stTransformed2stOriginal = stTransformed -> transformed -> identity -> stIdentity -> stOriginal + // stTransformed2stOriginal = stTransformed -> transformed -> identity -> stIdentity -> stOriginal - Matrix4 identity2stIdentity; - Texdef_basisForNormal( projection, plane.normal(), identity2stIdentity ); - //globalOutputStream() << "identity2stIdentity: " << identity2stIdentity << "\n"; + Matrix4 identity2stIdentity; + Texdef_basisForNormal(projection, plane.normal(), identity2stIdentity); + //globalOutputStream() << "identity2stIdentity: " << identity2stIdentity << "\n"; - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_HALFLIFE ) { - matrix4_transform_direction( identity2transformed, projection.m_basis_s ); - matrix4_transform_direction( identity2transformed, projection.m_basis_t ); - } + if (g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_HALFLIFE) { + matrix4_transform_direction(identity2transformed, projection.m_basis_s); + matrix4_transform_direction(identity2transformed, projection.m_basis_t); + } - Matrix4 transformed2stTransformed; - Texdef_basisForNormal( projection, normalTransformed, transformed2stTransformed ); + Matrix4 transformed2stTransformed; + Texdef_basisForNormal(projection, normalTransformed, transformed2stTransformed); - Matrix4 stTransformed2identity( matrix4_affine_inverse( matrix4_multiplied_by_matrix4( transformed2stTransformed, identity2transformed ) ) ); + Matrix4 stTransformed2identity( + matrix4_affine_inverse(matrix4_multiplied_by_matrix4(transformed2stTransformed, identity2transformed))); - Vector3 originalProjectionAxis( vector4_to_vector3( matrix4_affine_inverse( identity2stIdentity ).z() ) ); + Vector3 originalProjectionAxis(vector4_to_vector3(matrix4_affine_inverse(identity2stIdentity).z())); - Vector3 transformedProjectionAxis( vector4_to_vector3( stTransformed2identity.z() ) ); + Vector3 transformedProjectionAxis(vector4_to_vector3(stTransformed2identity.z())); - Matrix4 stIdentity2stOriginal; - Texdef_toTransform( projection, (float)width, (float)height, stIdentity2stOriginal ); - Matrix4 identity2stOriginal( matrix4_multiplied_by_matrix4( stIdentity2stOriginal, identity2stIdentity ) ); + Matrix4 stIdentity2stOriginal; + Texdef_toTransform(projection, (float) width, (float) height, stIdentity2stOriginal); + Matrix4 identity2stOriginal(matrix4_multiplied_by_matrix4(stIdentity2stOriginal, identity2stIdentity)); - //globalOutputStream() << "originalProj: " << originalProjectionAxis << "\n"; - //globalOutputStream() << "transformedProj: " << transformedProjectionAxis << "\n"; - double dot = vector3_dot( originalProjectionAxis, transformedProjectionAxis ); - //globalOutputStream() << "dot: " << dot << "\n"; - if ( dot == 0 ) { - // The projection axis chosen for the transformed normal is at 90 degrees - // to the transformed projection axis chosen for the original normal. - // This happens when the projection axis is ambiguous - e.g. for the plane - // 'X == Y' the projection axis could be either X or Y. - //globalOutputStream() << "flipped\n"; + //globalOutputStream() << "originalProj: " << originalProjectionAxis << "\n"; + //globalOutputStream() << "transformedProj: " << transformedProjectionAxis << "\n"; + double dot = vector3_dot(originalProjectionAxis, transformedProjectionAxis); + //globalOutputStream() << "dot: " << dot << "\n"; + if (dot == 0) { + // The projection axis chosen for the transformed normal is at 90 degrees + // to the transformed projection axis chosen for the original normal. + // This happens when the projection axis is ambiguous - e.g. for the plane + // 'X == Y' the projection axis could be either X or Y. + //globalOutputStream() << "flipped\n"; #if 0 - globalOutputStream() << "projection off by 90\n"; - globalOutputStream() << "normal: "; - print_vector3( plane.normal() ); - globalOutputStream() << "original projection: "; - print_vector3( originalProjectionAxis ); - globalOutputStream() << "transformed projection: "; - print_vector3( transformedProjectionAxis ); + globalOutputStream() << "projection off by 90\n"; + globalOutputStream() << "normal: "; + print_vector3( plane.normal() ); + globalOutputStream() << "original projection: "; + print_vector3( originalProjectionAxis ); + globalOutputStream() << "transformed projection: "; + print_vector3( transformedProjectionAxis ); #endif - Matrix4 identityCorrected = matrix4_reflection_for_plane45( plane, originalProjectionAxis, transformedProjectionAxis ); + Matrix4 identityCorrected = matrix4_reflection_for_plane45(plane, originalProjectionAxis, + transformedProjectionAxis); - identity2stOriginal = matrix4_multiplied_by_matrix4( identity2stOriginal, identityCorrected ); - } + identity2stOriginal = matrix4_multiplied_by_matrix4(identity2stOriginal, identityCorrected); + } - Matrix4 stTransformed2stOriginal = matrix4_multiplied_by_matrix4( identity2stOriginal, stTransformed2identity ); + Matrix4 stTransformed2stOriginal = matrix4_multiplied_by_matrix4(identity2stOriginal, stTransformed2identity); - Texdef_fromTransform( projection, (float)width, (float)height, stTransformed2stOriginal ); - Texdef_normalise( projection, (float)width, (float)height ); + Texdef_fromTransform(projection, (float) width, (float) height, stTransformed2stOriginal); + Texdef_normalise(projection, (float) width, (float) height); } #if 1 -void Q3_to_matrix( const texdef_t& texdef, float width, float height, const Vector3& normal, Matrix4& matrix ){ - Normal_GetTransform( normal, matrix ); - Matrix4 transform; +void Q3_to_matrix(const texdef_t &texdef, float width, float height, const Vector3 &normal, Matrix4 &matrix) +{ + Normal_GetTransform(normal, matrix); + + Matrix4 transform; - Texdef_toTransform( texdef, width, height, transform ); + Texdef_toTransform(texdef, width, height, transform); - matrix4_multiply_by_matrix4( matrix, transform ); + matrix4_multiply_by_matrix4(matrix, transform); } -void BP_from_matrix( brushprimit_texdef_t& bp_texdef, const Vector3& normal, const Matrix4& transform ){ - Matrix4 basis; - basis = g_matrix4_identity; - ComputeAxisBase( normal, vector4_to_vector3( basis.x() ), vector4_to_vector3( basis.y() ) ); - vector4_to_vector3( basis.z() ) = normal; - matrix4_transpose( basis ); - matrix4_affine_invert( basis ); +void BP_from_matrix(brushprimit_texdef_t &bp_texdef, const Vector3 &normal, const Matrix4 &transform) +{ + Matrix4 basis; + basis = g_matrix4_identity; + ComputeAxisBase(normal, vector4_to_vector3(basis.x()), vector4_to_vector3(basis.y())); + vector4_to_vector3(basis.z()) = normal; + matrix4_transpose(basis); + matrix4_affine_invert(basis); - Matrix4 basis2texture = matrix4_multiplied_by_matrix4( basis, transform ); + Matrix4 basis2texture = matrix4_multiplied_by_matrix4(basis, transform); - BPTexdef_fromTransform( bp_texdef, basis2texture ); + BPTexdef_fromTransform(bp_texdef, basis2texture); } -void Q3_to_BP( const texdef_t& texdef, float width, float height, const Vector3& normal, brushprimit_texdef_t& bp_texdef ){ - Matrix4 matrix; - Q3_to_matrix( texdef, width, height, normal, matrix ); - BP_from_matrix( bp_texdef, normal, matrix ); +void Q3_to_BP(const texdef_t &texdef, float width, float height, const Vector3 &normal, brushprimit_texdef_t &bp_texdef) +{ + Matrix4 matrix; + Q3_to_matrix(texdef, width, height, normal, matrix); + BP_from_matrix(bp_texdef, normal, matrix); } + #endif diff --git a/radiant/brush_primit.h b/radiant/brush_primit.h index 79d27f3e..0420b4dc 100644 --- a/radiant/brush_primit.h +++ b/radiant/brush_primit.h @@ -25,113 +25,139 @@ #include "math/vector.h" #include "itexdef.h" #include "debugging/debugging.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 ){ +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; + 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 ){ + } + + void addScale(std::size_t width, std::size_t height) + { #if 1 - ASSERT_MESSAGE( width > 0, "shader-width is 0" ); - ASSERT_MESSAGE( height > 0, "shader-height is 0" ); - coords[0][0] /= width; - coords[0][1] /= width; - coords[0][2] /= width; - coords[1][0] /= height; - coords[1][1] /= height; - coords[1][2] /= height; + ASSERT_MESSAGE(width > 0, "shader-width is 0"); + ASSERT_MESSAGE(height > 0, "shader-height is 0"); + 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]; + } + + float coords[2][3]; }; -class TextureProjection -{ +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 ){ -} + 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 class BasicVector3; + +template +class BasicVector3; + typedef BasicVector3 Vector3; -template class BasicVector4; + +template +class BasicVector4; + typedef BasicVector4 Vector4; typedef Vector4 Quaternion; + class Matrix4; + class Plane3; -void Normal_GetTransform( const Vector3& normal, Matrix4& transform ); +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 TexDef_Construct_Default( TextureProjection& projection ); +void ShiftScaleRotate_fromFace(texdef_t &shiftScaleRotate, const 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_toFace(const texdef_t &shiftScaleRotate, TextureProjection &projection); -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_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 ); +void Texdef_normalise(TextureProjection &projection, float width, float height); -enum TexdefTypeId -{ - TEXDEFTYPEID_QUAKE, - TEXDEFTYPEID_BRUSHPRIMITIVES, - TEXDEFTYPEID_HALFLIFE, +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; +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; -void ComputeAxisBase( const Vector3& normal, Vector3& texS, Vector3& texT ); +void ComputeAxisBase(const Vector3 &normal, Vector3 &texS, Vector3 &texT); #endif diff --git a/radiant/brushmanip.cpp b/radiant/brushmanip.cpp index abee96d0..68c8a5ba 100644 --- a/radiant/brushmanip.cpp +++ b/radiant/brushmanip.cpp @@ -38,895 +38,951 @@ #include #include -void Brush_ConstructCuboid( Brush& brush, const AABB& bounds, const char* shader, const TextureProjection& projection ){ - const unsigned char box[3][2] = { { 0, 1 }, { 2, 0 }, { 1, 2 } }; - Vector3 mins( vector3_subtracted( bounds.origin, bounds.extents ) ); - Vector3 maxs( vector3_added( bounds.origin, bounds.extents ) ); - - brush.clear(); - brush.reserve( 6 ); - - { - for ( int i = 0; i < 3; ++i ) - { - Vector3 planepts1( maxs ); - Vector3 planepts2( maxs ); - planepts2[box[i][0]] = mins[box[i][0]]; - planepts1[box[i][1]] = mins[box[i][1]]; - - brush.addPlane( maxs, planepts1, planepts2, shader, projection ); - } - } - { - for ( int i = 0; i < 3; ++i ) - { - Vector3 planepts1( mins ); - Vector3 planepts2( mins ); - planepts1[box[i][0]] = maxs[box[i][0]]; - planepts2[box[i][1]] = maxs[box[i][1]]; - - brush.addPlane( mins, planepts1, planepts2, shader, projection ); - } - } -} - -inline float max_extent( const Vector3& extents ){ - return std::max( std::max( extents[0], extents[1] ), extents[2] ); -} - -inline float max_extent_2d( const Vector3& extents, int axis ){ - switch ( axis ) - { - case 0: - return std::max( extents[1], extents[2] ); - case 1: - return std::max( extents[0], extents[2] ); - default: - return std::max( extents[0], extents[1] ); - } +void Brush_ConstructCuboid(Brush &brush, const AABB &bounds, const char *shader, const TextureProjection &projection) +{ + const unsigned char box[3][2] = {{0, 1}, + {2, 0}, + {1, 2}}; + Vector3 mins(vector3_subtracted(bounds.origin, bounds.extents)); + Vector3 maxs(vector3_added(bounds.origin, bounds.extents)); + + brush.clear(); + brush.reserve(6); + + { + for (int i = 0; i < 3; ++i) { + Vector3 planepts1(maxs); + Vector3 planepts2(maxs); + planepts2[box[i][0]] = mins[box[i][0]]; + planepts1[box[i][1]] = mins[box[i][1]]; + + brush.addPlane(maxs, planepts1, planepts2, shader, projection); + } + } + { + for (int i = 0; i < 3; ++i) { + Vector3 planepts1(mins); + Vector3 planepts2(mins); + planepts1[box[i][0]] = maxs[box[i][0]]; + planepts2[box[i][1]] = maxs[box[i][1]]; + + brush.addPlane(mins, planepts1, planepts2, shader, projection); + } + } +} + +inline float max_extent(const Vector3 &extents) +{ + return std::max(std::max(extents[0], extents[1]), extents[2]); +} + +inline float max_extent_2d(const Vector3 &extents, int axis) +{ + switch (axis) { + case 0: + return std::max(extents[1], extents[2]); + case 1: + return std::max(extents[0], extents[2]); + default: + return std::max(extents[0], extents[1]); + } } const std::size_t c_brushPrism_minSides = 3; const std::size_t c_brushPrism_maxSides = c_brush_maxFaces - 2; -const char* const c_brushPrism_name = "brushPrism"; - -void Brush_ConstructPrism( Brush& brush, const AABB& bounds, std::size_t sides, int axis, const char* shader, const TextureProjection& projection ){ - if ( sides < c_brushPrism_minSides ) { - globalErrorStream() << c_brushPrism_name << ": sides " << Unsigned( sides ) << ": too few sides, minimum is " << Unsigned( c_brushPrism_minSides ) << "\n"; - return; - } - if ( sides > c_brushPrism_maxSides ) { - globalErrorStream() << c_brushPrism_name << ": sides " << Unsigned( sides ) << ": too many sides, maximum is " << Unsigned( c_brushPrism_maxSides ) << "\n"; - return; - } - - brush.clear(); - brush.reserve( sides + 2 ); - - Vector3 mins( vector3_subtracted( bounds.origin, bounds.extents ) ); - Vector3 maxs( vector3_added( bounds.origin, bounds.extents ) ); - - float radius = max_extent_2d( bounds.extents, axis ); - const Vector3& mid = bounds.origin; - Vector3 planepts[3]; - - planepts[2][( axis + 1 ) % 3] = mins[( axis + 1 ) % 3]; - planepts[2][( axis + 2 ) % 3] = mins[( axis + 2 ) % 3]; - planepts[2][axis] = maxs[axis]; - planepts[1][( axis + 1 ) % 3] = maxs[( axis + 1 ) % 3]; - planepts[1][( axis + 2 ) % 3] = mins[( axis + 2 ) % 3]; - planepts[1][axis] = maxs[axis]; - planepts[0][( axis + 1 ) % 3] = maxs[( axis + 1 ) % 3]; - planepts[0][( axis + 2 ) % 3] = maxs[( axis + 2 ) % 3]; - planepts[0][axis] = maxs[axis]; - - brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); - - planepts[0][( axis + 1 ) % 3] = mins[( axis + 1 ) % 3]; - planepts[0][( axis + 2 ) % 3] = mins[( axis + 2 ) % 3]; - planepts[0][axis] = mins[axis]; - planepts[1][( axis + 1 ) % 3] = maxs[( axis + 1 ) % 3]; - planepts[1][( axis + 2 ) % 3] = mins[( axis + 2 ) % 3]; - planepts[1][axis] = mins[axis]; - planepts[2][( axis + 1 ) % 3] = maxs[( axis + 1 ) % 3]; - planepts[2][( axis + 2 ) % 3] = maxs[( axis + 2 ) % 3]; - planepts[2][axis] = mins[axis]; - - brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); - - for ( std::size_t i = 0 ; i < sides ; ++i ) - { - double sv = sin( i * 3.14159265 * 2 / sides ); - double cv = cos( i * 3.14159265 * 2 / sides ); - - planepts[0][( axis + 1 ) % 3] = static_cast( floor( mid[( axis + 1 ) % 3] + radius * cv + 0.5 ) ); - planepts[0][( axis + 2 ) % 3] = static_cast( floor( mid[( axis + 2 ) % 3] + radius * sv + 0.5 ) ); - planepts[0][axis] = mins[axis]; - - planepts[1][( axis + 1 ) % 3] = planepts[0][( axis + 1 ) % 3]; - planepts[1][( axis + 2 ) % 3] = planepts[0][( axis + 2 ) % 3]; - planepts[1][axis] = maxs[axis]; - - planepts[2][( axis + 1 ) % 3] = static_cast( floor( planepts[0][( axis + 1 ) % 3] - radius * sv + 0.5 ) ); - planepts[2][( axis + 2 ) % 3] = static_cast( floor( planepts[0][( axis + 2 ) % 3] + radius * cv + 0.5 ) ); - planepts[2][axis] = maxs[axis]; - - brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); - } +const char *const c_brushPrism_name = "brushPrism"; + +void Brush_ConstructPrism(Brush &brush, const AABB &bounds, std::size_t sides, int axis, const char *shader, + const TextureProjection &projection) +{ + if (sides < c_brushPrism_minSides) { + globalErrorStream() << c_brushPrism_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " + << Unsigned(c_brushPrism_minSides) << "\n"; + return; + } + if (sides > c_brushPrism_maxSides) { + globalErrorStream() << c_brushPrism_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " + << Unsigned(c_brushPrism_maxSides) << "\n"; + return; + } + + brush.clear(); + brush.reserve(sides + 2); + + Vector3 mins(vector3_subtracted(bounds.origin, bounds.extents)); + Vector3 maxs(vector3_added(bounds.origin, bounds.extents)); + + float radius = max_extent_2d(bounds.extents, axis); + const Vector3 &mid = bounds.origin; + Vector3 planepts[3]; + + planepts[2][(axis + 1) % 3] = mins[(axis + 1) % 3]; + planepts[2][(axis + 2) % 3] = mins[(axis + 2) % 3]; + planepts[2][axis] = maxs[axis]; + planepts[1][(axis + 1) % 3] = maxs[(axis + 1) % 3]; + planepts[1][(axis + 2) % 3] = mins[(axis + 2) % 3]; + planepts[1][axis] = maxs[axis]; + planepts[0][(axis + 1) % 3] = maxs[(axis + 1) % 3]; + planepts[0][(axis + 2) % 3] = maxs[(axis + 2) % 3]; + planepts[0][axis] = maxs[axis]; + + brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); + + planepts[0][(axis + 1) % 3] = mins[(axis + 1) % 3]; + planepts[0][(axis + 2) % 3] = mins[(axis + 2) % 3]; + planepts[0][axis] = mins[axis]; + planepts[1][(axis + 1) % 3] = maxs[(axis + 1) % 3]; + planepts[1][(axis + 2) % 3] = mins[(axis + 2) % 3]; + planepts[1][axis] = mins[axis]; + planepts[2][(axis + 1) % 3] = maxs[(axis + 1) % 3]; + planepts[2][(axis + 2) % 3] = maxs[(axis + 2) % 3]; + planepts[2][axis] = mins[axis]; + + brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); + + for (std::size_t i = 0; i < sides; ++i) { + double sv = sin(i * 3.14159265 * 2 / sides); + double cv = cos(i * 3.14159265 * 2 / sides); + + planepts[0][(axis + 1) % 3] = static_cast( floor(mid[(axis + 1) % 3] + radius * cv + 0.5)); + planepts[0][(axis + 2) % 3] = static_cast( floor(mid[(axis + 2) % 3] + radius * sv + 0.5)); + planepts[0][axis] = mins[axis]; + + planepts[1][(axis + 1) % 3] = planepts[0][(axis + 1) % 3]; + planepts[1][(axis + 2) % 3] = planepts[0][(axis + 2) % 3]; + planepts[1][axis] = maxs[axis]; + + planepts[2][(axis + 1) % 3] = static_cast( floor(planepts[0][(axis + 1) % 3] - radius * sv + 0.5)); + planepts[2][(axis + 2) % 3] = static_cast( floor(planepts[0][(axis + 2) % 3] + radius * cv + 0.5)); + planepts[2][axis] = maxs[axis]; + + brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); + } } const std::size_t c_brushCone_minSides = 3; const std::size_t c_brushCone_maxSides = 32; -const char* const c_brushCone_name = "brushCone"; - -void Brush_ConstructCone( Brush& brush, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection ){ - if ( sides < c_brushCone_minSides ) { - globalErrorStream() << c_brushCone_name << ": sides " << Unsigned( sides ) << ": too few sides, minimum is " << Unsigned( c_brushCone_minSides ) << "\n"; - return; - } - if ( sides > c_brushCone_maxSides ) { - globalErrorStream() << c_brushCone_name << ": sides " << Unsigned( sides ) << ": too many sides, maximum is " << Unsigned( c_brushCone_maxSides ) << "\n"; - return; - } - - brush.clear(); - brush.reserve( sides + 1 ); - - Vector3 mins( vector3_subtracted( bounds.origin, bounds.extents ) ); - Vector3 maxs( vector3_added( bounds.origin, bounds.extents ) ); - - float radius = max_extent( bounds.extents ); - const Vector3& mid = bounds.origin; - Vector3 planepts[3]; - - planepts[0][0] = mins[0]; planepts[0][1] = mins[1]; planepts[0][2] = mins[2]; - planepts[1][0] = maxs[0]; planepts[1][1] = mins[1]; planepts[1][2] = mins[2]; - planepts[2][0] = maxs[0]; planepts[2][1] = maxs[1]; planepts[2][2] = mins[2]; - - brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); - - for ( std::size_t i = 0 ; i < sides ; ++i ) - { - double sv = sin( i * 3.14159265 * 2 / sides ); - double cv = cos( i * 3.14159265 * 2 / sides ); - - planepts[0][0] = static_cast( floor( mid[0] + radius * cv + 0.5 ) ); - planepts[0][1] = static_cast( floor( mid[1] + radius * sv + 0.5 ) ); - planepts[0][2] = mins[2]; +const char *const c_brushCone_name = "brushCone"; - planepts[1][0] = mid[0]; - planepts[1][1] = mid[1]; - planepts[1][2] = maxs[2]; - - planepts[2][0] = static_cast( floor( planepts[0][0] - radius * sv + 0.5 ) ); - planepts[2][1] = static_cast( floor( planepts[0][1] + radius * cv + 0.5 ) ); - planepts[2][2] = maxs[2]; - - brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); - } +void Brush_ConstructCone(Brush &brush, const AABB &bounds, std::size_t sides, const char *shader, + const TextureProjection &projection) +{ + if (sides < c_brushCone_minSides) { + globalErrorStream() << c_brushCone_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " + << Unsigned(c_brushCone_minSides) << "\n"; + return; + } + if (sides > c_brushCone_maxSides) { + globalErrorStream() << c_brushCone_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " + << Unsigned(c_brushCone_maxSides) << "\n"; + return; + } + + brush.clear(); + brush.reserve(sides + 1); + + Vector3 mins(vector3_subtracted(bounds.origin, bounds.extents)); + Vector3 maxs(vector3_added(bounds.origin, bounds.extents)); + + float radius = max_extent(bounds.extents); + const Vector3 &mid = bounds.origin; + Vector3 planepts[3]; + + planepts[0][0] = mins[0]; + planepts[0][1] = mins[1]; + planepts[0][2] = mins[2]; + planepts[1][0] = maxs[0]; + planepts[1][1] = mins[1]; + planepts[1][2] = mins[2]; + planepts[2][0] = maxs[0]; + planepts[2][1] = maxs[1]; + planepts[2][2] = mins[2]; + + brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); + + for (std::size_t i = 0; i < sides; ++i) { + double sv = sin(i * 3.14159265 * 2 / sides); + double cv = cos(i * 3.14159265 * 2 / sides); + + planepts[0][0] = static_cast( floor(mid[0] + radius * cv + 0.5)); + planepts[0][1] = static_cast( floor(mid[1] + radius * sv + 0.5)); + planepts[0][2] = mins[2]; + + planepts[1][0] = mid[0]; + planepts[1][1] = mid[1]; + planepts[1][2] = maxs[2]; + + planepts[2][0] = static_cast( floor(planepts[0][0] - radius * sv + 0.5)); + planepts[2][1] = static_cast( floor(planepts[0][1] + radius * cv + 0.5)); + planepts[2][2] = maxs[2]; + + brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); + } } const std::size_t c_brushSphere_minSides = 3; const std::size_t c_brushSphere_maxSides = 31; -const char* const c_brushSphere_name = "brushSphere"; - -void Brush_ConstructSphere( Brush& brush, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection ){ - if ( sides < c_brushSphere_minSides ) { - globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned( sides ) << ": too few sides, minimum is " << Unsigned( c_brushSphere_minSides ) << "\n"; - return; - } - if ( sides > c_brushSphere_maxSides ) { - globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned( sides ) << ": too many sides, maximum is " << Unsigned( c_brushSphere_maxSides ) << "\n"; - return; - } - - brush.clear(); - brush.reserve( sides * sides ); - - float radius = max_extent( bounds.extents ); - const Vector3& mid = bounds.origin; - Vector3 planepts[3]; - - double dt = 2 * c_pi / sides; - double dp = c_pi / sides; - for ( std::size_t i = 0; i < sides; i++ ) - { - for ( std::size_t j = 0; j < sides - 1; j++ ) - { - double t = i * dt; - double p = float(j * dp - c_pi / 2); - - planepts[0] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t, p ), radius ) ); - planepts[1] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t, p + dp ), radius ) ); - planepts[2] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t + dt, p + dp ), radius ) ); - - brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); - } - } - - { - double p = ( sides - 1 ) * dp - c_pi / 2; - for ( std::size_t i = 0; i < sides; i++ ) - { - double t = i * dt; - - planepts[0] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t, p ), radius ) ); - planepts[1] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t + dt, p + dp ), radius ) ); - planepts[2] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t + dt, p ), radius ) ); - - brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); - } - } +const char *const c_brushSphere_name = "brushSphere"; + +void Brush_ConstructSphere(Brush &brush, const AABB &bounds, std::size_t sides, const char *shader, + const TextureProjection &projection) +{ + if (sides < c_brushSphere_minSides) { + globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " + << Unsigned(c_brushSphere_minSides) << "\n"; + return; + } + if (sides > c_brushSphere_maxSides) { + globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " + << Unsigned(c_brushSphere_maxSides) << "\n"; + return; + } + + brush.clear(); + brush.reserve(sides * sides); + + float radius = max_extent(bounds.extents); + const Vector3 &mid = bounds.origin; + Vector3 planepts[3]; + + double dt = 2 * c_pi / sides; + double dp = c_pi / sides; + for (std::size_t i = 0; i < sides; i++) { + for (std::size_t j = 0; j < sides - 1; j++) { + double t = i * dt; + double p = float(j * dp - c_pi / 2); + + planepts[0] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t, p), radius)); + planepts[1] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t, p + dp), radius)); + planepts[2] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t + dt, p + dp), radius)); + + brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); + } + } + + { + double p = (sides - 1) * dp - c_pi / 2; + for (std::size_t i = 0; i < sides; i++) { + double t = i * dt; + + planepts[0] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t, p), radius)); + planepts[1] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t + dt, p + dp), radius)); + planepts[2] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t + dt, p), radius)); + + brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); + } + } } const std::size_t c_brushRock_minSides = 10; const std::size_t c_brushRock_maxSides = 1000; -const char* const c_brushRock_name = "brushRock"; - -void Brush_ConstructRock( Brush& brush, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection ){ - if ( sides < c_brushRock_minSides ) { - globalErrorStream() << c_brushRock_name << ": sides " << Unsigned( sides ) << ": too few sides, minimum is " << Unsigned( c_brushRock_minSides ) << "\n"; - return; - } - if ( sides > c_brushRock_maxSides ) { - globalErrorStream() << c_brushRock_name << ": sides " << Unsigned( sides ) << ": too many sides, maximum is " << Unsigned( c_brushRock_maxSides ) << "\n"; - return; - } - - brush.clear(); - brush.reserve( sides * sides ); - - float radius = max_extent( bounds.extents ); - const Vector3& mid = bounds.origin; - Vector3 planepts[3]; - - for ( std::size_t j = 0; j < sides; j++ ) - { - planepts[0][0] = rand() - ( RAND_MAX / 2 ); - planepts[0][1] = rand() - ( RAND_MAX / 2 ); - planepts[0][2] = rand() - ( RAND_MAX / 2 ); - vector3_normalise( planepts[0] ); - - // find two vectors that are perpendicular to planepts[0] - ComputeAxisBase( planepts[0], planepts[1], planepts[2] ); - - planepts[0] = vector3_added( mid, vector3_scaled( planepts[0], radius ) ); - planepts[1] = vector3_added( planepts[0], vector3_scaled( planepts[1], radius ) ); - planepts[2] = vector3_added( planepts[0], vector3_scaled( planepts[2], radius ) ); +const char *const c_brushRock_name = "brushRock"; + +void Brush_ConstructRock(Brush &brush, const AABB &bounds, std::size_t sides, const char *shader, + const TextureProjection &projection) +{ + if (sides < c_brushRock_minSides) { + globalErrorStream() << c_brushRock_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " + << Unsigned(c_brushRock_minSides) << "\n"; + return; + } + if (sides > c_brushRock_maxSides) { + globalErrorStream() << c_brushRock_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " + << Unsigned(c_brushRock_maxSides) << "\n"; + return; + } + + brush.clear(); + brush.reserve(sides * sides); + + float radius = max_extent(bounds.extents); + const Vector3 &mid = bounds.origin; + Vector3 planepts[3]; + + for (std::size_t j = 0; j < sides; j++) { + planepts[0][0] = rand() - (RAND_MAX / 2); + planepts[0][1] = rand() - (RAND_MAX / 2); + planepts[0][2] = rand() - (RAND_MAX / 2); + vector3_normalise(planepts[0]); + + // find two vectors that are perpendicular to planepts[0] + ComputeAxisBase(planepts[0], planepts[1], planepts[2]); + + planepts[0] = vector3_added(mid, vector3_scaled(planepts[0], radius)); + planepts[1] = vector3_added(planepts[0], vector3_scaled(planepts[1], radius)); + planepts[2] = vector3_added(planepts[0], vector3_scaled(planepts[2], radius)); #if 0 - // make sure the orientation is right - if ( vector3_dot( vector3_subtracted( planepts[0], mid ), vector3_cross( vector3_subtracted( planepts[1], mid ), vector3_subtracted( planepts[2], mid ) ) ) > 0 ) { - Vector3 h; - h = planepts[1]; - planepts[1] = planepts[2]; - planepts[2] = h; - globalOutputStream() << "flip\n"; - } - else{ - globalOutputStream() << "no flip\n"; - } + // make sure the orientation is right + if ( vector3_dot( vector3_subtracted( planepts[0], mid ), vector3_cross( vector3_subtracted( planepts[1], mid ), vector3_subtracted( planepts[2], mid ) ) ) > 0 ) { + Vector3 h; + h = planepts[1]; + planepts[1] = planepts[2]; + planepts[2] = h; + globalOutputStream() << "flip\n"; + } + else{ + globalOutputStream() << "no flip\n"; + } #endif - brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); - } -} - -int GetViewAxis(){ - switch ( GlobalXYWnd_getCurrentViewType() ) - { - case XY: - return 2; - case XZ: - return 1; - case YZ: - return 0; - } - return 2; -} - -void Brush_ConstructPrefab( Brush& brush, EBrushPrefab type, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection ){ - switch ( type ) - { - case eBrushCuboid: - { - UndoableCommand undo( "brushCuboid" ); - - Brush_ConstructCuboid( brush, bounds, shader, projection ); - } - break; - case eBrushPrism: - { - int axis = GetViewAxis(); - StringOutputStream command; - command << c_brushPrism_name << " -sides " << Unsigned( sides ) << " -axis " << axis; - UndoableCommand undo( command.c_str() ); - - Brush_ConstructPrism( brush, bounds, sides, axis, shader, projection ); - } - break; - case eBrushCone: - { - StringOutputStream command; - command << c_brushCone_name << " -sides " << Unsigned( sides ); - UndoableCommand undo( command.c_str() ); - - Brush_ConstructCone( brush, bounds, sides, shader, projection ); - } - break; - case eBrushSphere: - { - StringOutputStream command; - command << c_brushSphere_name << " -sides " << Unsigned( sides ); - UndoableCommand undo( command.c_str() ); - - Brush_ConstructSphere( brush, bounds, sides, shader, projection ); - } - break; - case eBrushRock: - { - StringOutputStream command; - command << c_brushRock_name << " -sides " << Unsigned( sides ); - UndoableCommand undo( command.c_str() ); - - Brush_ConstructRock( brush, bounds, sides, shader, projection ); - } - break; - } -} - - -void ConstructRegionBrushes( scene::Node* brushes[6], const Vector3& region_mins, const Vector3& region_maxs ){ - { - // set mins - Vector3 mins( region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 ); - - // vary maxs - for ( std::size_t i = 0; i < 3; i++ ) - { - Vector3 maxs( region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 ); - maxs[i] = region_mins[i]; - Brush_ConstructCuboid( *Node_getBrush( *brushes[i] ), aabb_for_minmax( mins, maxs ), texdef_name_default(), TextureProjection() ); - } - } - - { - // set maxs - Vector3 maxs( region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 ); - - // vary mins - for ( std::size_t i = 0; i < 3; i++ ) - { - Vector3 mins( region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 ); - mins[i] = region_maxs[i]; - Brush_ConstructCuboid( *Node_getBrush( *brushes[i + 3] ), aabb_for_minmax( mins, maxs ), texdef_name_default(), TextureProjection() ); - } - } -} - - -void Scene_BrushSetTexdef_Selected( scene::Graph& graph, const TextureProjection& projection ){ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.SetTexdef(projection); - }); - SceneChangeNotify(); + brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); + } +} + +int GetViewAxis() +{ + switch (GlobalXYWnd_getCurrentViewType()) { + case XY: + return 2; + case XZ: + return 1; + case YZ: + return 0; + } + return 2; +} + +void Brush_ConstructPrefab(Brush &brush, EBrushPrefab type, const AABB &bounds, std::size_t sides, const char *shader, + const TextureProjection &projection) +{ + switch (type) { + case eBrushCuboid: { + UndoableCommand undo("brushCuboid"); + + Brush_ConstructCuboid(brush, bounds, shader, projection); + } + break; + case eBrushPrism: { + int axis = GetViewAxis(); + StringOutputStream command; + command << c_brushPrism_name << " -sides " << Unsigned(sides) << " -axis " << axis; + UndoableCommand undo(command.c_str()); + + Brush_ConstructPrism(brush, bounds, sides, axis, shader, projection); + } + break; + case eBrushCone: { + StringOutputStream command; + command << c_brushCone_name << " -sides " << Unsigned(sides); + UndoableCommand undo(command.c_str()); + + Brush_ConstructCone(brush, bounds, sides, shader, projection); + } + break; + case eBrushSphere: { + StringOutputStream command; + command << c_brushSphere_name << " -sides " << Unsigned(sides); + UndoableCommand undo(command.c_str()); + + Brush_ConstructSphere(brush, bounds, sides, shader, projection); + } + break; + case eBrushRock: { + StringOutputStream command; + command << c_brushRock_name << " -sides " << Unsigned(sides); + UndoableCommand undo(command.c_str()); + + Brush_ConstructRock(brush, bounds, sides, shader, projection); + } + break; + } +} + + +void ConstructRegionBrushes(scene::Node *brushes[6], const Vector3 ®ion_mins, const Vector3 ®ion_maxs) +{ + { + // set mins + Vector3 mins(region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32); + + // vary maxs + for (std::size_t i = 0; i < 3; i++) { + Vector3 maxs(region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32); + maxs[i] = region_mins[i]; + Brush_ConstructCuboid(*Node_getBrush(*brushes[i]), aabb_for_minmax(mins, maxs), texdef_name_default(), + TextureProjection()); + } + } + + { + // set maxs + Vector3 maxs(region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32); + + // vary mins + for (std::size_t i = 0; i < 3; i++) { + Vector3 mins(region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32); + mins[i] = region_maxs[i]; + Brush_ConstructCuboid(*Node_getBrush(*brushes[i + 3]), aabb_for_minmax(mins, maxs), texdef_name_default(), + TextureProjection()); + } + } +} + + +void Scene_BrushSetTexdef_Selected(scene::Graph &graph, const TextureProjection &projection) +{ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.SetTexdef(projection); + }); + SceneChangeNotify(); +} + +void Scene_BrushSetTexdef_Component_Selected(scene::Graph &graph, const TextureProjection &projection) +{ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.SetTexdef(projection); + }); + SceneChangeNotify(); } - -void Scene_BrushSetTexdef_Component_Selected( scene::Graph& graph, const TextureProjection& projection ){ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.SetTexdef(projection); - }); - SceneChangeNotify(); -} - - -void Scene_BrushSetFlags_Selected( scene::Graph& graph, const ContentsFlagsValue& flags ){ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.SetFlags(flags); - }); - SceneChangeNotify(); -} - -void Scene_BrushSetFlags_Component_Selected( scene::Graph& graph, const ContentsFlagsValue& flags ){ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.SetFlags(flags); - }); - SceneChangeNotify(); -} - -void Scene_BrushShiftTexdef_Selected( scene::Graph& graph, float s, float t ){ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.ShiftTexdef(s, t); - }); - SceneChangeNotify(); -} - -void Scene_BrushShiftTexdef_Component_Selected( scene::Graph& graph, float s, float t ){ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.ShiftTexdef(s, t); - }); - SceneChangeNotify(); + + +void Scene_BrushSetFlags_Selected(scene::Graph &graph, const ContentsFlagsValue &flags) +{ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.SetFlags(flags); + }); + SceneChangeNotify(); } -void Scene_BrushScaleTexdef_Selected( scene::Graph& graph, float s, float t ){ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.ScaleTexdef(s, t); - }); - SceneChangeNotify(); +void Scene_BrushSetFlags_Component_Selected(scene::Graph &graph, const ContentsFlagsValue &flags) +{ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.SetFlags(flags); + }); + SceneChangeNotify(); } -void Scene_BrushScaleTexdef_Component_Selected( scene::Graph& graph, float s, float t ){ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.ScaleTexdef(s, t); - }); - SceneChangeNotify(); +void Scene_BrushShiftTexdef_Selected(scene::Graph &graph, float s, float t) +{ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.ShiftTexdef(s, t); + }); + SceneChangeNotify(); } -void Scene_BrushRotateTexdef_Selected( scene::Graph& graph, float angle ){ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.RotateTexdef(angle); - }); - SceneChangeNotify(); +void Scene_BrushShiftTexdef_Component_Selected(scene::Graph &graph, float s, float t) +{ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.ShiftTexdef(s, t); + }); + SceneChangeNotify(); } -void Scene_BrushRotateTexdef_Component_Selected( scene::Graph& graph, float angle ){ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.RotateTexdef(angle); - }); - SceneChangeNotify(); +void Scene_BrushScaleTexdef_Selected(scene::Graph &graph, float s, float t) +{ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.ScaleTexdef(s, t); + }); + SceneChangeNotify(); } +void Scene_BrushScaleTexdef_Component_Selected(scene::Graph &graph, float s, float t) +{ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.ScaleTexdef(s, t); + }); + SceneChangeNotify(); +} -void Scene_BrushSetShader_Selected( scene::Graph& graph, const char* name ){ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.SetShader(name); - }); - SceneChangeNotify(); +void Scene_BrushRotateTexdef_Selected(scene::Graph &graph, float angle) +{ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.RotateTexdef(angle); + }); + SceneChangeNotify(); } -void Scene_BrushSetShader_Component_Selected( scene::Graph& graph, const char* name ){ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.SetShader(name); - }); - SceneChangeNotify(); +void Scene_BrushRotateTexdef_Component_Selected(scene::Graph &graph, float angle) +{ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.RotateTexdef(angle); + }); + SceneChangeNotify(); } -void Scene_BrushSetDetail_Selected( scene::Graph& graph, bool detail ){ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.setDetail(detail); - }); - SceneChangeNotify(); + +void Scene_BrushSetShader_Selected(scene::Graph &graph, const char *name) +{ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.SetShader(name); + }); + SceneChangeNotify(); } -bool Face_FindReplaceShader( Face& face, const char* find, const char* replace ){ - if ( shader_equal( face.GetShader(), find ) ) { - face.SetShader( replace ); - return true; - } - return false; +void Scene_BrushSetShader_Component_Selected(scene::Graph &graph, const char *name) +{ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.SetShader(name); + }); + SceneChangeNotify(); } -bool DoingSearch( const char *repl ){ - return ( repl == NULL || ( strcmp( "textures/", repl ) == 0 ) ); +void Scene_BrushSetDetail_Selected(scene::Graph &graph, bool detail) +{ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.setDetail(detail); + }); + SceneChangeNotify(); } -void Scene_BrushFindReplaceShader( scene::Graph& graph, const char* find, const char* replace ){ - if ( DoingSearch( replace ) ) { - Scene_ForEachBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) { - if (shader_equal(faceinst.getFace().GetShader(), find)) { - faceinst.setSelected(SelectionSystem::eFace, true); - } - }); - } - else - { - Scene_ForEachBrush_ForEachFace(graph, [&](Face &face) { Face_FindReplaceShader(face, find, replace); }); - } +bool Face_FindReplaceShader(Face &face, const char *find, const char *replace) +{ + if (shader_equal(face.GetShader(), find)) { + face.SetShader(replace); + return true; + } + return false; } -void Scene_BrushFindReplaceShader_Selected( scene::Graph& graph, const char* find, const char* replace ){ - if ( DoingSearch( replace ) ) { - Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) { - if (shader_equal(faceinst.getFace().GetShader(), find)) { - faceinst.setSelected(SelectionSystem::eFace, true); - } - }); - } - else - { - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - Face_FindReplaceShader(face, find, replace); - }); - } +bool DoingSearch(const char *repl) +{ + return (repl == NULL || (strcmp("textures/", repl) == 0)); +} + +void Scene_BrushFindReplaceShader(scene::Graph &graph, const char *find, const char *replace) +{ + if (DoingSearch(replace)) { + Scene_ForEachBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) { + if (shader_equal(faceinst.getFace().GetShader(), find)) { + faceinst.setSelected(SelectionSystem::eFace, true); + } + }); + } else { + Scene_ForEachBrush_ForEachFace(graph, [&](Face &face) { Face_FindReplaceShader(face, find, replace); }); + } +} + +void Scene_BrushFindReplaceShader_Selected(scene::Graph &graph, const char *find, const char *replace) +{ + if (DoingSearch(replace)) { + Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) { + if (shader_equal(faceinst.getFace().GetShader(), find)) { + faceinst.setSelected(SelectionSystem::eFace, true); + } + }); + } else { + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + Face_FindReplaceShader(face, find, replace); + }); + } } // TODO: find for components // d1223m: dont even know what they are... -void Scene_BrushFindReplaceShader_Component_Selected( scene::Graph& graph, const char* find, const char* replace ){ - if ( DoingSearch( replace ) ) { +void Scene_BrushFindReplaceShader_Component_Selected(scene::Graph &graph, const char *find, const char *replace) +{ + if (DoingSearch(replace)) { - } - else - { - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - Face_FindReplaceShader(face, find, replace); - }); - } + } else { + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + Face_FindReplaceShader(face, find, replace); + }); + } } -void Scene_BrushFitTexture_Selected( scene::Graph& graph, float s_repeat, float t_repeat ){ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.FitTexture(s_repeat, t_repeat); - }); - SceneChangeNotify(); +void Scene_BrushFitTexture_Selected(scene::Graph &graph, float s_repeat, float t_repeat) +{ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.FitTexture(s_repeat, t_repeat); + }); + SceneChangeNotify(); } -void Scene_BrushFitTexture_Component_Selected( scene::Graph& graph, float s_repeat, float t_repeat ){ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.FitTexture(s_repeat, t_repeat); - }); - SceneChangeNotify(); +void Scene_BrushFitTexture_Component_Selected(scene::Graph &graph, float s_repeat, float t_repeat) +{ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.FitTexture(s_repeat, t_repeat); + }); + SceneChangeNotify(); } TextureProjection g_defaultTextureProjection; -const TextureProjection& TextureTransform_getDefault(){ - TexDef_Construct_Default( g_defaultTextureProjection ); - return g_defaultTextureProjection; + +const TextureProjection &TextureTransform_getDefault() +{ + TexDef_Construct_Default(g_defaultTextureProjection); + return g_defaultTextureProjection; } -void Scene_BrushConstructPrefab( scene::Graph& graph, EBrushPrefab type, std::size_t sides, const char* shader ){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path(); +void Scene_BrushConstructPrefab(scene::Graph &graph, EBrushPrefab type, std::size_t sides, const char *shader) +{ + if (GlobalSelectionSystem().countSelected() != 0) { + const scene::Path &path = GlobalSelectionSystem().ultimateSelected().path(); - Brush* brush = Node_getBrush( path.top() ); - if ( brush != 0 ) { - AABB bounds = brush->localAABB(); // copy bounds because the brush will be modified - Brush_ConstructPrefab( *brush, type, bounds, sides, shader, TextureTransform_getDefault() ); - SceneChangeNotify(); - } - } + Brush *brush = Node_getBrush(path.top()); + if (brush != 0) { + AABB bounds = brush->localAABB(); // copy bounds because the brush will be modified + Brush_ConstructPrefab(*brush, type, bounds, sides, shader, TextureTransform_getDefault()); + SceneChangeNotify(); + } + } } -void Scene_BrushResize_Selected( scene::Graph& graph, const AABB& bounds, const char* shader ){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path(); +void Scene_BrushResize_Selected(scene::Graph &graph, const AABB &bounds, const char *shader) +{ + if (GlobalSelectionSystem().countSelected() != 0) { + const scene::Path &path = GlobalSelectionSystem().ultimateSelected().path(); - Brush* brush = Node_getBrush( path.top() ); - if ( brush != 0 ) { - Brush_ConstructCuboid( *brush, bounds, shader, TextureTransform_getDefault() ); - SceneChangeNotify(); - } - } + Brush *brush = Node_getBrush(path.top()); + if (brush != 0) { + Brush_ConstructCuboid(*brush, bounds, shader, TextureTransform_getDefault()); + SceneChangeNotify(); + } + } } -bool Brush_hasShader( const Brush& brush, const char* name ){ - for ( Brush::const_iterator i = brush.begin(); i != brush.end(); ++i ) - { - if ( shader_equal( ( *i )->GetShader(), name ) ) { - return true; - } - } - return false; +bool Brush_hasShader(const Brush &brush, const char *name) +{ + for (Brush::const_iterator i = brush.begin(); i != brush.end(); ++i) { + if (shader_equal((*i)->GetShader(), name)) { + return true; + } + } + return false; } -class BrushSelectByShaderWalker : public scene::Graph::Walker -{ -const char* m_name; +class BrushSelectByShaderWalker : public scene::Graph::Walker { + const char *m_name; public: -BrushSelectByShaderWalker( const char* name ) - : m_name( name ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - Brush* brush = Node_getBrush( path.top() ); - if ( brush != 0 && Brush_hasShader( *brush, m_name ) ) { - Instance_getSelectable( instance )->setSelected( true ); - } - } - return true; -} + BrushSelectByShaderWalker(const char *name) + : m_name(name) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + Brush *brush = Node_getBrush(path.top()); + if (brush != 0 && Brush_hasShader(*brush, m_name)) { + Instance_getSelectable(instance)->setSelected(true); + } + } + return true; + } }; -void Scene_BrushSelectByShader( scene::Graph& graph, const char* name ){ - graph.traverse( BrushSelectByShaderWalker( name ) ); +void Scene_BrushSelectByShader(scene::Graph &graph, const char *name) +{ + graph.traverse(BrushSelectByShaderWalker(name)); } -void Scene_BrushSelectByShader_Component( scene::Graph& graph, const char* name ){ - Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &face) { - printf("checking %s = %s\n", face.getFace().GetShader(), name); - if (shader_equal(face.getFace().GetShader(), name)) { - face.setSelected(SelectionSystem::eFace, true); - } - }); +void Scene_BrushSelectByShader_Component(scene::Graph &graph, const char *name) +{ + Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &face) { + printf("checking %s = %s\n", face.getFace().GetShader(), name); + if (shader_equal(face.getFace().GetShader(), name)) { + face.setSelected(SelectionSystem::eFace, true); + } + }); } -void Scene_BrushGetTexdef_Selected( scene::Graph& graph, TextureProjection& projection ){ - bool done = false; - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - if (!done) { - done = true; - face.GetTexdef(projection); - } - }); +void Scene_BrushGetTexdef_Selected(scene::Graph &graph, TextureProjection &projection) +{ + bool done = false; + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + if (!done) { + done = true; + face.GetTexdef(projection); + } + }); } -void Scene_BrushGetTexdef_Component_Selected( scene::Graph& graph, TextureProjection& projection ){ +void Scene_BrushGetTexdef_Component_Selected(scene::Graph &graph, TextureProjection &projection) +{ #if 1 - if ( !g_SelectedFaceInstances.empty() ) { - FaceInstance& faceInstance = g_SelectedFaceInstances.last(); - faceInstance.getFace().GetTexdef( projection ); - } + if (!g_SelectedFaceInstances.empty()) { + FaceInstance &faceInstance = g_SelectedFaceInstances.last(); + faceInstance.getFace().GetTexdef(projection); + } #else - FaceGetTexdef visitor( projection ); - Scene_ForEachSelectedBrushFace( graph, visitor ); + FaceGetTexdef visitor( projection ); + Scene_ForEachSelectedBrushFace( graph, visitor ); #endif } -void Scene_BrushGetShaderSize_Component_Selected( scene::Graph& graph, size_t& width, size_t& height ){ - if ( !g_SelectedFaceInstances.empty() ) { - FaceInstance& faceInstance = g_SelectedFaceInstances.last(); - width = faceInstance.getFace().getShader().width(); - height = faceInstance.getFace().getShader().height(); - } +void Scene_BrushGetShaderSize_Component_Selected(scene::Graph &graph, size_t &width, size_t &height) +{ + if (!g_SelectedFaceInstances.empty()) { + FaceInstance &faceInstance = g_SelectedFaceInstances.last(); + width = faceInstance.getFace().getShader().width(); + height = faceInstance.getFace().getShader().height(); + } } -void Scene_BrushGetFlags_Selected( scene::Graph& graph, ContentsFlagsValue& flags ){ +void Scene_BrushGetFlags_Selected(scene::Graph &graph, ContentsFlagsValue &flags) +{ #if 1 - if ( GlobalSelectionSystem().countSelected() != 0 ) { - BrushInstance* brush = Instance_getBrush( GlobalSelectionSystem().ultimateSelected() ); - if ( brush != 0 ) { - bool done = false; - Brush_forEachFace(*brush, [&](Face &face) { - if (!done) { - done = true; - face.GetFlags(flags); - } - }); - } - } + if (GlobalSelectionSystem().countSelected() != 0) { + BrushInstance *brush = Instance_getBrush(GlobalSelectionSystem().ultimateSelected()); + if (brush != 0) { + bool done = false; + Brush_forEachFace(*brush, [&](Face &face) { + if (!done) { + done = true; + face.GetFlags(flags); + } + }); + } + } #else - Scene_ForEachSelectedBrush_ForEachFace( graph, FaceGetFlags( flags ) ); + Scene_ForEachSelectedBrush_ForEachFace( graph, FaceGetFlags( flags ) ); #endif } -void Scene_BrushGetFlags_Component_Selected( scene::Graph& graph, ContentsFlagsValue& flags ){ +void Scene_BrushGetFlags_Component_Selected(scene::Graph &graph, ContentsFlagsValue &flags) +{ #if 1 - if ( !g_SelectedFaceInstances.empty() ) { - FaceInstance& faceInstance = g_SelectedFaceInstances.last(); - faceInstance.getFace().GetFlags( flags ); - } + if (!g_SelectedFaceInstances.empty()) { + FaceInstance &faceInstance = g_SelectedFaceInstances.last(); + faceInstance.getFace().GetFlags(flags); + } #else - Scene_ForEachSelectedBrushFace( graph, FaceGetFlags( flags ) ); + Scene_ForEachSelectedBrushFace( graph, FaceGetFlags( flags ) ); #endif } -void Scene_BrushGetShader_Selected( scene::Graph& graph, CopiedString& shader ){ +void Scene_BrushGetShader_Selected(scene::Graph &graph, CopiedString &shader) +{ #if 1 - if ( GlobalSelectionSystem().countSelected() != 0 ) { - BrushInstance* brush = Instance_getBrush( GlobalSelectionSystem().ultimateSelected() ); - if ( brush != 0 ) { - bool done = false; - Brush_forEachFace(*brush, [&](Face &face) { - if (!done) { - done = true; - shader = face.GetShader(); - } - }); - } - } + if (GlobalSelectionSystem().countSelected() != 0) { + BrushInstance *brush = Instance_getBrush(GlobalSelectionSystem().ultimateSelected()); + if (brush != 0) { + bool done = false; + Brush_forEachFace(*brush, [&](Face &face) { + if (!done) { + done = true; + shader = face.GetShader(); + } + }); + } + } #else - Scene_ForEachSelectedBrush_ForEachFace( graph, FaceGetShader( shader ) ); + Scene_ForEachSelectedBrush_ForEachFace( graph, FaceGetShader( shader ) ); #endif } -void Scene_BrushGetShader_Component_Selected( scene::Graph& graph, CopiedString& shader ){ +void Scene_BrushGetShader_Component_Selected(scene::Graph &graph, CopiedString &shader) +{ #if 1 - if ( !g_SelectedFaceInstances.empty() ) { - FaceInstance& faceInstance = g_SelectedFaceInstances.last(); - shader = faceInstance.getFace().GetShader(); - } + if (!g_SelectedFaceInstances.empty()) { + FaceInstance &faceInstance = g_SelectedFaceInstances.last(); + shader = faceInstance.getFace().GetShader(); + } #else - FaceGetShader visitor( shader ); - Scene_ForEachSelectedBrushFace( graph, visitor ); + FaceGetShader visitor( shader ); + Scene_ForEachSelectedBrushFace( graph, visitor ); #endif } -class filter_face_shader : public FaceFilter -{ -const char* m_shader; +class filter_face_shader : public FaceFilter { + const char *m_shader; public: -filter_face_shader( const char* shader ) : m_shader( shader ){ -} -bool filter( const Face& face ) const { - return shader_equal( face.GetShader(), m_shader ); -} + filter_face_shader(const char *shader) : m_shader(shader) + { + } + + bool filter(const Face &face) const + { + return shader_equal(face.GetShader(), m_shader); + } }; -class filter_face_shader_prefix : public FaceFilter -{ -const char* m_prefix; +class filter_face_shader_prefix : public FaceFilter { + const char *m_prefix; public: -filter_face_shader_prefix( const char* prefix ) : m_prefix( prefix ){ -} -bool filter( const Face& face ) const { - return shader_equal_n( face.GetShader(), m_prefix, strlen( m_prefix ) ); -} + filter_face_shader_prefix(const char *prefix) : m_prefix(prefix) + { + } + + bool filter(const Face &face) const + { + return shader_equal_n(face.GetShader(), m_prefix, strlen(m_prefix)); + } }; -class filter_face_flags : public FaceFilter -{ -int m_flags; +class filter_face_flags : public FaceFilter { + int m_flags; public: -filter_face_flags( int flags ) : m_flags( flags ){ -} -bool filter( const Face& face ) const { - return ( face.getShader().shaderFlags() & m_flags ) != 0; -} + filter_face_flags(int flags) : m_flags(flags) + { + } + + bool filter(const Face &face) const + { + return (face.getShader().shaderFlags() & m_flags) != 0; + } }; -class filter_face_contents : public FaceFilter -{ -int m_contents; +class filter_face_contents : public FaceFilter { + int m_contents; public: -filter_face_contents( int contents ) : m_contents( contents ){ -} -bool filter( const Face& face ) const { - return ( face.getShader().m_flags.m_contentFlags & m_contents ) != 0; -} + filter_face_contents(int contents) : m_contents(contents) + { + } + + bool filter(const Face &face) const + { + return (face.getShader().m_flags.m_contentFlags & m_contents) != 0; + } }; - -class filter_brush_any_face : public BrushFilter -{ -FaceFilter* m_filter; +class filter_brush_any_face : public BrushFilter { + FaceFilter *m_filter; public: -filter_brush_any_face( FaceFilter* filter ) : m_filter( filter ){ -} -bool filter( const Brush& brush ) const { - bool filtered = false; - Brush_forEachFace(brush, [&](Face &face) { - if (m_filter->filter(face)) { - filtered = true; - } - }); - return filtered; -} + filter_brush_any_face(FaceFilter *filter) : m_filter(filter) + { + } + + bool filter(const Brush &brush) const + { + bool filtered = false; + Brush_forEachFace(brush, [&](Face &face) { + if (m_filter->filter(face)) { + filtered = true; + } + }); + return filtered; + } }; -class filter_brush_all_faces : public BrushFilter -{ -FaceFilter* m_filter; +class filter_brush_all_faces : public BrushFilter { + FaceFilter *m_filter; public: -filter_brush_all_faces( FaceFilter* filter ) : m_filter( filter ){ -} -bool filter( const Brush& brush ) const { - bool filtered = true; - Brush_forEachFace(brush, [&](Face &face) { - if (!m_filter->filter(face)) { - filtered = false; - } - }); - return filtered; -} + filter_brush_all_faces(FaceFilter *filter) : m_filter(filter) + { + } + + bool filter(const Brush &brush) const + { + bool filtered = true; + Brush_forEachFace(brush, [&](Face &face) { + if (!m_filter->filter(face)) { + filtered = false; + } + }); + return filtered; + } }; -filter_face_flags g_filter_face_clip( QER_CLIP ); -filter_brush_all_faces g_filter_brush_clip( &g_filter_face_clip ); +filter_face_flags g_filter_face_clip(QER_CLIP); +filter_brush_all_faces g_filter_brush_clip(&g_filter_face_clip); -filter_face_shader g_filter_face_clip_q2( "textures/clip" ); -filter_brush_all_faces g_filter_brush_clip_q2( &g_filter_face_clip_q2 ); +filter_face_shader g_filter_face_clip_q2("textures/clip"); +filter_brush_all_faces g_filter_brush_clip_q2(&g_filter_face_clip_q2); -filter_face_shader g_filter_face_weapclip( "textures/common/weapclip" ); -filter_brush_all_faces g_filter_brush_weapclip( &g_filter_face_weapclip ); +filter_face_shader g_filter_face_weapclip("textures/common/weapclip"); +filter_brush_all_faces g_filter_brush_weapclip(&g_filter_face_weapclip); -filter_face_shader g_filter_face_commonclip( "textures/common/clip" ); -filter_brush_all_faces g_filter_brush_commonclip( &g_filter_face_commonclip ); +filter_face_shader g_filter_face_commonclip("textures/common/clip"); +filter_brush_all_faces g_filter_brush_commonclip(&g_filter_face_commonclip); -filter_face_shader g_filter_face_fullclip( "textures/common/fullclip" ); -filter_brush_all_faces g_filter_brush_fullclip( &g_filter_face_fullclip ); +filter_face_shader g_filter_face_fullclip("textures/common/fullclip"); +filter_brush_all_faces g_filter_brush_fullclip(&g_filter_face_fullclip); -filter_face_shader g_filter_face_botclip( "textures/common/botclip" ); -filter_brush_all_faces g_filter_brush_botclip( &g_filter_face_botclip ); +filter_face_shader g_filter_face_botclip("textures/common/botclip"); +filter_brush_all_faces g_filter_brush_botclip(&g_filter_face_botclip); -filter_face_shader_prefix g_filter_face_caulk( "textures/common/caulk" ); -filter_brush_all_faces g_filter_brush_caulk( &g_filter_face_caulk ); +filter_face_shader_prefix g_filter_face_caulk("textures/common/caulk"); +filter_brush_all_faces g_filter_brush_caulk(&g_filter_face_caulk); -filter_face_shader_prefix g_filter_face_caulk_ja( "textures/system/caulk" ); -filter_brush_all_faces g_filter_brush_caulk_ja( &g_filter_face_caulk_ja ); +filter_face_shader_prefix g_filter_face_caulk_ja("textures/system/caulk"); +filter_brush_all_faces g_filter_brush_caulk_ja(&g_filter_face_caulk_ja); -filter_face_shader_prefix g_filter_face_liquids( "textures/liquids/" ); -filter_brush_any_face g_filter_brush_liquids( &g_filter_face_liquids ); +filter_face_shader_prefix g_filter_face_liquids("textures/liquids/"); +filter_brush_any_face g_filter_brush_liquids(&g_filter_face_liquids); -filter_face_shader g_filter_face_hint( "textures/common/hint" ); -filter_brush_any_face g_filter_brush_hint( &g_filter_face_hint ); +filter_face_shader g_filter_face_hint("textures/common/hint"); +filter_brush_any_face g_filter_brush_hint(&g_filter_face_hint); -filter_face_shader g_filter_face_hint_q2( "textures/hint" ); -filter_brush_any_face g_filter_brush_hint_q2( &g_filter_face_hint_q2 ); +filter_face_shader g_filter_face_hint_q2("textures/hint"); +filter_brush_any_face g_filter_brush_hint_q2(&g_filter_face_hint_q2); -filter_face_shader g_filter_face_hint_ja( "textures/system/hint" ); -filter_brush_any_face g_filter_brush_hint_ja( &g_filter_face_hint_ja ); +filter_face_shader g_filter_face_hint_ja("textures/system/hint"); +filter_brush_any_face g_filter_brush_hint_ja(&g_filter_face_hint_ja); -filter_face_shader g_filter_face_areaportal( "textures/common/areaportal" ); -filter_brush_all_faces g_filter_brush_areaportal( &g_filter_face_areaportal ); +filter_face_shader g_filter_face_areaportal("textures/common/areaportal"); +filter_brush_all_faces g_filter_brush_areaportal(&g_filter_face_areaportal); -filter_face_shader g_filter_face_visportal( "textures/editor/visportal" ); -filter_brush_any_face g_filter_brush_visportal( &g_filter_face_visportal ); +filter_face_shader g_filter_face_visportal("textures/editor/visportal"); +filter_brush_any_face g_filter_brush_visportal(&g_filter_face_visportal); -filter_face_shader g_filter_face_clusterportal( "textures/common/clusterportal" ); -filter_brush_all_faces g_filter_brush_clusterportal( &g_filter_face_clusterportal ); +filter_face_shader g_filter_face_clusterportal("textures/common/clusterportal"); +filter_brush_all_faces g_filter_brush_clusterportal(&g_filter_face_clusterportal); -filter_face_shader g_filter_face_lightgrid( "textures/common/lightgrid" ); -filter_brush_all_faces g_filter_brush_lightgrid( &g_filter_face_lightgrid ); +filter_face_shader g_filter_face_lightgrid("textures/common/lightgrid"); +filter_brush_all_faces g_filter_brush_lightgrid(&g_filter_face_lightgrid); -filter_face_flags g_filter_face_translucent( QER_TRANS ); -filter_brush_all_faces g_filter_brush_translucent( &g_filter_face_translucent ); +filter_face_flags g_filter_face_translucent(QER_TRANS); +filter_brush_all_faces g_filter_brush_translucent(&g_filter_face_translucent); -filter_face_contents g_filter_face_detail( BRUSH_DETAIL_MASK ); -filter_brush_all_faces g_filter_brush_detail( &g_filter_face_detail ); +filter_face_contents g_filter_face_detail(BRUSH_DETAIL_MASK); +filter_brush_all_faces g_filter_brush_detail(&g_filter_face_detail); -filter_face_shader_prefix g_filter_face_decals( "textures/decals/" ); -filter_brush_any_face g_filter_brush_decals( &g_filter_face_decals ); +filter_face_shader_prefix g_filter_face_decals("textures/decals/"); +filter_brush_any_face g_filter_brush_decals(&g_filter_face_decals); -void BrushFilters_construct(){ - add_brush_filter( g_filter_brush_clip, EXCLUDE_CLIP ); - add_brush_filter( g_filter_brush_clip_q2, EXCLUDE_CLIP ); - add_brush_filter( g_filter_brush_weapclip, EXCLUDE_CLIP ); - add_brush_filter( g_filter_brush_fullclip, EXCLUDE_CLIP ); - add_brush_filter( g_filter_brush_commonclip, EXCLUDE_CLIP ); - add_brush_filter( g_filter_brush_botclip, EXCLUDE_BOTCLIP ); - add_brush_filter( g_filter_brush_caulk, EXCLUDE_CAULK ); - add_brush_filter( g_filter_brush_caulk_ja, EXCLUDE_CAULK ); - add_face_filter( g_filter_face_caulk, EXCLUDE_CAULK ); - add_face_filter( g_filter_face_caulk_ja, EXCLUDE_CAULK ); - add_brush_filter( g_filter_brush_liquids, EXCLUDE_LIQUIDS ); - add_brush_filter( g_filter_brush_hint, EXCLUDE_HINTSSKIPS ); - add_brush_filter( g_filter_brush_hint_q2, EXCLUDE_HINTSSKIPS ); - add_brush_filter( g_filter_brush_hint_ja, EXCLUDE_HINTSSKIPS ); - add_brush_filter( g_filter_brush_clusterportal, EXCLUDE_CLUSTERPORTALS ); - add_brush_filter( g_filter_brush_visportal, EXCLUDE_VISPORTALS ); - add_brush_filter( g_filter_brush_areaportal, EXCLUDE_AREAPORTALS ); - add_brush_filter( g_filter_brush_translucent, EXCLUDE_TRANSLUCENT ); - add_brush_filter( g_filter_brush_detail, EXCLUDE_DETAILS ); - add_brush_filter( g_filter_brush_detail, EXCLUDE_STRUCTURAL, true ); - add_brush_filter( g_filter_brush_lightgrid, EXCLUDE_LIGHTGRID ); - add_brush_filter( g_filter_brush_decals, EXCLUDE_DECALS ); +void BrushFilters_construct() +{ + add_brush_filter(g_filter_brush_clip, EXCLUDE_CLIP); + add_brush_filter(g_filter_brush_clip_q2, EXCLUDE_CLIP); + add_brush_filter(g_filter_brush_weapclip, EXCLUDE_CLIP); + add_brush_filter(g_filter_brush_fullclip, EXCLUDE_CLIP); + add_brush_filter(g_filter_brush_commonclip, EXCLUDE_CLIP); + add_brush_filter(g_filter_brush_botclip, EXCLUDE_BOTCLIP); + add_brush_filter(g_filter_brush_caulk, EXCLUDE_CAULK); + add_brush_filter(g_filter_brush_caulk_ja, EXCLUDE_CAULK); + add_face_filter(g_filter_face_caulk, EXCLUDE_CAULK); + add_face_filter(g_filter_face_caulk_ja, EXCLUDE_CAULK); + add_brush_filter(g_filter_brush_liquids, EXCLUDE_LIQUIDS); + add_brush_filter(g_filter_brush_hint, EXCLUDE_HINTSSKIPS); + add_brush_filter(g_filter_brush_hint_q2, EXCLUDE_HINTSSKIPS); + add_brush_filter(g_filter_brush_hint_ja, EXCLUDE_HINTSSKIPS); + add_brush_filter(g_filter_brush_clusterportal, EXCLUDE_CLUSTERPORTALS); + add_brush_filter(g_filter_brush_visportal, EXCLUDE_VISPORTALS); + add_brush_filter(g_filter_brush_areaportal, EXCLUDE_AREAPORTALS); + add_brush_filter(g_filter_brush_translucent, EXCLUDE_TRANSLUCENT); + add_brush_filter(g_filter_brush_detail, EXCLUDE_DETAILS); + add_brush_filter(g_filter_brush_detail, EXCLUDE_STRUCTURAL, true); + add_brush_filter(g_filter_brush_lightgrid, EXCLUDE_LIGHTGRID); + add_brush_filter(g_filter_brush_decals, EXCLUDE_DECALS); } #if 0 void normalquantisation_draw(){ - glPointSize( 1 ); - glBegin( GL_POINTS ); - for ( std::size_t i = 0; i <= c_quantise_normal; ++i ) - { - for ( std::size_t j = 0; j <= c_quantise_normal; ++j ) - { - Normal3f vertex( normal3f_normalised( Normal3f( - static_cast( c_quantise_normal - j - i ), - static_cast( i ), - static_cast( j ) - ) ) ); - VectorScale( normal3f_to_array( vertex ), 64.f, normal3f_to_array( vertex ) ); - glVertex3fv( normal3f_to_array( vertex ) ); - vertex.x = -vertex.x; - glVertex3fv( normal3f_to_array( vertex ) ); - } - } - glEnd(); + glPointSize( 1 ); + glBegin( GL_POINTS ); + for ( std::size_t i = 0; i <= c_quantise_normal; ++i ) + { + for ( std::size_t j = 0; j <= c_quantise_normal; ++j ) + { + Normal3f vertex( normal3f_normalised( Normal3f( + static_cast( c_quantise_normal - j - i ), + static_cast( i ), + static_cast( j ) + ) ) ); + VectorScale( normal3f_to_array( vertex ), 64.f, normal3f_to_array( vertex ) ); + glVertex3fv( normal3f_to_array( vertex ) ); + vertex.x = -vertex.x; + glVertex3fv( normal3f_to_array( vertex ) ); + } + } + glEnd(); } class RenderableNormalQuantisation : public OpenGLRenderable { public: void render( RenderStateFlags state ) const { - normalquantisation_draw(); + normalquantisation_draw(); } }; @@ -935,104 +991,104 @@ const float g_test_quantise_normal = 1.f / static_cast( 1 << 3 ); class TestNormalQuantisation { void check_normal( const Normal3f& normal, const Normal3f& other ){ - spherical_t spherical = spherical_from_normal3f( normal ); - double longditude = RAD2DEG( spherical.longditude ); - double latitude = RAD2DEG( spherical.latitude ); - double x = cos( spherical.longditude ) * sin( spherical.latitude ); - double y = sin( spherical.longditude ) * sin( spherical.latitude ); - double z = cos( spherical.latitude ); + spherical_t spherical = spherical_from_normal3f( normal ); + double longditude = RAD2DEG( spherical.longditude ); + double latitude = RAD2DEG( spherical.latitude ); + double x = cos( spherical.longditude ) * sin( spherical.latitude ); + double y = sin( spherical.longditude ) * sin( spherical.latitude ); + double z = cos( spherical.latitude ); - ASSERT_MESSAGE( normal3f_dot( normal, other ) > 0.99, "bleh" ); + ASSERT_MESSAGE( normal3f_dot( normal, other ) > 0.99, "bleh" ); } void test_normal( const Normal3f& normal ){ - Normal3f test = normal3f_from_spherical( spherical_from_normal3f( normal ) ); - check_normal( normal, test ); + Normal3f test = normal3f_from_spherical( spherical_from_normal3f( normal ) ); + check_normal( normal, test ); - EOctant octant = normal3f_classify_octant( normal ); - Normal3f folded = normal3f_fold_octant( normal, octant ); - ESextant sextant = normal3f_classify_sextant( folded ); - folded = normal3f_fold_sextant( folded, sextant ); + EOctant octant = normal3f_classify_octant( normal ); + Normal3f folded = normal3f_fold_octant( normal, octant ); + ESextant sextant = normal3f_classify_sextant( folded ); + folded = normal3f_fold_sextant( folded, sextant ); - double scale = static_cast( c_quantise_normal ) / ( folded.x + folded.y + folded.z ); + double scale = static_cast( c_quantise_normal ) / ( folded.x + folded.y + folded.z ); - double zbits = folded.z * scale; - double ybits = folded.y * scale; + double zbits = folded.z * scale; + double ybits = folded.y * scale; - std::size_t zbits_q = static_cast( zbits ); - std::size_t ybits_q = static_cast( ybits ); + std::size_t zbits_q = static_cast( zbits ); + std::size_t ybits_q = static_cast( ybits ); - ASSERT_MESSAGE( zbits_q <= ( c_quantise_normal / 8 ) * 3, "bleh" ); - ASSERT_MESSAGE( ybits_q <= ( c_quantise_normal / 2 ), "bleh" ); - ASSERT_MESSAGE( zbits_q + ( ( c_quantise_normal / 2 ) - ybits_q ) <= ( c_quantise_normal / 2 ), "bleh" ); + ASSERT_MESSAGE( zbits_q <= ( c_quantise_normal / 8 ) * 3, "bleh" ); + ASSERT_MESSAGE( ybits_q <= ( c_quantise_normal / 2 ), "bleh" ); + ASSERT_MESSAGE( zbits_q + ( ( c_quantise_normal / 2 ) - ybits_q ) <= ( c_quantise_normal / 2 ), "bleh" ); - std::size_t y_t = ( zbits_q < ( c_quantise_normal / 4 ) ) ? ybits_q : ( c_quantise_normal / 2 ) - ybits_q; - std::size_t z_t = ( zbits_q < ( c_quantise_normal / 4 ) ) ? zbits_q : ( c_quantise_normal / 2 ) - zbits_q; - std::size_t index = ( c_quantise_normal / 4 ) * y_t + z_t; - ASSERT_MESSAGE( index <= ( c_quantise_normal / 4 ) * ( c_quantise_normal / 2 ), "bleh" ); + std::size_t y_t = ( zbits_q < ( c_quantise_normal / 4 ) ) ? ybits_q : ( c_quantise_normal / 2 ) - ybits_q; + std::size_t z_t = ( zbits_q < ( c_quantise_normal / 4 ) ) ? zbits_q : ( c_quantise_normal / 2 ) - zbits_q; + std::size_t index = ( c_quantise_normal / 4 ) * y_t + z_t; + ASSERT_MESSAGE( index <= ( c_quantise_normal / 4 ) * ( c_quantise_normal / 2 ), "bleh" ); - Normal3f tmp( c_quantise_normal - zbits_q - ybits_q, ybits_q, zbits_q ); - tmp = normal3f_normalised( tmp ); + Normal3f tmp( c_quantise_normal - zbits_q - ybits_q, ybits_q, zbits_q ); + tmp = normal3f_normalised( tmp ); - Normal3f unfolded = normal3f_unfold_octant( normal3f_unfold_sextant( tmp, sextant ), octant ); + Normal3f unfolded = normal3f_unfold_octant( normal3f_unfold_sextant( tmp, sextant ), octant ); - check_normal( normal, unfolded ); + check_normal( normal, unfolded ); - double dot = normal3f_dot( normal, unfolded ); - float length = VectorLength( normal3f_to_array( unfolded ) ); - float inv_length = 1 / length; + double dot = normal3f_dot( normal, unfolded ); + float length = VectorLength( normal3f_to_array( unfolded ) ); + float inv_length = 1 / length; - Normal3f quantised = normal3f_quantised( normal ); - check_normal( normal, quantised ); + Normal3f quantised = normal3f_quantised( normal ); + check_normal( normal, quantised ); } void test2( const Normal3f& normal, const Normal3f& other ){ - if ( normal3f_quantised( normal ) != normal3f_quantised( other ) ) { - int bleh = 0; - } + if ( normal3f_quantised( normal ) != normal3f_quantised( other ) ) { + int bleh = 0; + } } static Normal3f normalise( float x, float y, float z ){ - return normal3f_normalised( Normal3f( x, y, z ) ); + return normal3f_normalised( Normal3f( x, y, z ) ); } float vec_rand(){ - return static_cast( rand() - ( RAND_MAX / 2 ) ); + return static_cast( rand() - ( RAND_MAX / 2 ) ); } Normal3f normal3f_rand(){ - return normalise( vec_rand(), vec_rand(), vec_rand() ); + return normalise( vec_rand(), vec_rand(), vec_rand() ); } public: TestNormalQuantisation(){ - for ( int i = 4096; i > 0; --i ) - test_normal( normal3f_rand() ); - - test_normal( normalise( 1, 0, 0 ) ); - test_normal( normalise( 0, 1, 0 ) ); - test_normal( normalise( 0, 0, 1 ) ); - test_normal( normalise( 1, 1, 0 ) ); - test_normal( normalise( 1, 0, 1 ) ); - test_normal( normalise( 0, 1, 1 ) ); - - test_normal( normalise( 10000, 10000, 10000 ) ); - test_normal( normalise( 10000, 10000, 10001 ) ); - test_normal( normalise( 10000, 10000, 10002 ) ); - test_normal( normalise( 10000, 10000, 10010 ) ); - test_normal( normalise( 10000, 10000, 10020 ) ); - test_normal( normalise( 10000, 10000, 10030 ) ); - test_normal( normalise( 10000, 10000, 10100 ) ); - test_normal( normalise( 10000, 10000, 10101 ) ); - test_normal( normalise( 10000, 10000, 10102 ) ); - test_normal( normalise( 10000, 10000, 10200 ) ); - test_normal( normalise( 10000, 10000, 10201 ) ); - test_normal( normalise( 10000, 10000, 10202 ) ); - test_normal( normalise( 10000, 10000, 10203 ) ); - test_normal( normalise( 10000, 10000, 10300 ) ); - - - test2( normalise( 10000, 10000, 10000 ), normalise( 10000, 10000, 10001 ) ); - test2( normalise( 10000, 10000, 10001 ), normalise( 10000, 10001, 10000 ) ); + for ( int i = 4096; i > 0; --i ) + test_normal( normal3f_rand() ); + + test_normal( normalise( 1, 0, 0 ) ); + test_normal( normalise( 0, 1, 0 ) ); + test_normal( normalise( 0, 0, 1 ) ); + test_normal( normalise( 1, 1, 0 ) ); + test_normal( normalise( 1, 0, 1 ) ); + test_normal( normalise( 0, 1, 1 ) ); + + test_normal( normalise( 10000, 10000, 10000 ) ); + test_normal( normalise( 10000, 10000, 10001 ) ); + test_normal( normalise( 10000, 10000, 10002 ) ); + test_normal( normalise( 10000, 10000, 10010 ) ); + test_normal( normalise( 10000, 10000, 10020 ) ); + test_normal( normalise( 10000, 10000, 10030 ) ); + test_normal( normalise( 10000, 10000, 10100 ) ); + test_normal( normalise( 10000, 10000, 10101 ) ); + test_normal( normalise( 10000, 10000, 10102 ) ); + test_normal( normalise( 10000, 10000, 10200 ) ); + test_normal( normalise( 10000, 10000, 10201 ) ); + test_normal( normalise( 10000, 10000, 10202 ) ); + test_normal( normalise( 10000, 10000, 10203 ) ); + test_normal( normalise( 10000, 10000, 10300 ) ); + + + test2( normalise( 10000, 10000, 10000 ), normalise( 10000, 10000, 10001 ) ); + test2( normalise( 10000, 10000, 10001 ), normalise( 10000, 10001, 10000 ) ); } }; @@ -1046,23 +1102,23 @@ class TestSelectableObserver : public observer_template { public: void notify( const Selectable& arguments ){ - bool bleh = arguments.isSelected(); + bool bleh = arguments.isSelected(); } }; inline void test_bleh(){ - TestSelectableObserver test; - ObservableSelectableInstance< SingleObservable< SelectionChangeCallback > > bleh; - bleh.attach( test ); - bleh.setSelected( true ); - bleh.detach( test ); + TestSelectableObserver test; + ObservableSelectableInstance< SingleObservable< SelectionChangeCallback > > bleh; + bleh.attach( test ); + bleh.setSelected( true ); + bleh.detach( test ); } class TestBleh { public: TestBleh(){ - test_bleh(); + test_bleh(); } }; @@ -1075,35 +1131,35 @@ class TestRefcountedString { public: TestRefcountedString(){ - { - // copy construct - SmartString string1( "string1" ); - SmartString string2( string1 ); - SmartString string3( string2 ); - } - { - // refcounted assignment - SmartString string1( "string1" ); - SmartString string2( "string2" ); - string1 = string2; - } - { - // copy assignment - SmartString string1( "string1" ); - SmartString string2( "string2" ); - string1 = string2.c_str(); - } - { - // self-assignment - SmartString string1( "string1" ); - string1 = string1; - } - { - // self-assignment via another reference - SmartString string1( "string1" ); - SmartString string2( string1 ); - string1 = string2; - } + { + // copy construct + SmartString string1( "string1" ); + SmartString string2( string1 ); + SmartString string3( string2 ); + } + { + // refcounted assignment + SmartString string1( "string1" ); + SmartString string2( "string2" ); + string1 = string2; + } + { + // copy assignment + SmartString string1( "string1" ); + SmartString string2( "string2" ); + string1 = string2.c_str(); + } + { + // self-assignment + SmartString string1( "string1" ); + string1 = string1; + } + { + // self-assignment via another reference + SmartString string1( "string1" ); + SmartString string2( string1 ); + string1 = string2; + } } }; @@ -1111,175 +1167,205 @@ const TestRefcountedString g_testRefcountedString; #endif -void Select_MakeDetail(){ - UndoableCommand undo( "brushSetDetail" ); - Scene_BrushSetDetail_Selected( GlobalSceneGraph(), true ); +void Select_MakeDetail() +{ + UndoableCommand undo("brushSetDetail"); + Scene_BrushSetDetail_Selected(GlobalSceneGraph(), true); } -void Select_MakeStructural(){ - UndoableCommand undo( "brushClearDetail" ); - Scene_BrushSetDetail_Selected( GlobalSceneGraph(), false ); +void Select_MakeStructural() +{ + UndoableCommand undo("brushClearDetail"); + Scene_BrushSetDetail_Selected(GlobalSceneGraph(), false); } -class BrushMakeSided -{ -std::size_t m_count; +class BrushMakeSided { + std::size_t m_count; public: -BrushMakeSided( std::size_t count ) - : m_count( count ){ -} -void set(){ - Scene_BrushConstructPrefab( GlobalSceneGraph(), eBrushPrism, m_count, TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); -} -typedef MemberCaller SetCaller; + BrushMakeSided(std::size_t count) + : m_count(count) + { + } + + void set() + { + Scene_BrushConstructPrefab(GlobalSceneGraph(), eBrushPrism, m_count, + TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); + } + + typedef MemberCaller SetCaller; }; -BrushMakeSided g_brushmakesided3( 3 ); -BrushMakeSided g_brushmakesided4( 4 ); -BrushMakeSided g_brushmakesided5( 5 ); -BrushMakeSided g_brushmakesided6( 6 ); -BrushMakeSided g_brushmakesided7( 7 ); -BrushMakeSided g_brushmakesided8( 8 ); -BrushMakeSided g_brushmakesided9( 9 ); - -inline int axis_for_viewtype( int viewtype ){ - switch ( viewtype ) - { - case XY: - return 2; - case XZ: - return 1; - case YZ: - return 0; - } - return 2; -} - -class BrushPrefab +BrushMakeSided g_brushmakesided3(3); +BrushMakeSided g_brushmakesided4(4); +BrushMakeSided g_brushmakesided5(5); +BrushMakeSided g_brushmakesided6(6); +BrushMakeSided g_brushmakesided7(7); +BrushMakeSided g_brushmakesided8(8); +BrushMakeSided g_brushmakesided9(9); + +inline int axis_for_viewtype(int viewtype) { -EBrushPrefab m_type; + switch (viewtype) { + case XY: + return 2; + case XZ: + return 1; + case YZ: + return 0; + } + return 2; +} + +class BrushPrefab { + EBrushPrefab m_type; public: -BrushPrefab( EBrushPrefab type ) - : m_type( type ){ -} -void set(){ - DoSides( m_type, axis_for_viewtype( GetViewAxis() ) ); -} -typedef MemberCaller SetCaller; + BrushPrefab(EBrushPrefab type) + : m_type(type) + { + } + + void set() + { + DoSides(m_type, axis_for_viewtype(GetViewAxis())); + } + + typedef MemberCaller SetCaller; }; -BrushPrefab g_brushprism( eBrushPrism ); -BrushPrefab g_brushcone( eBrushCone ); -BrushPrefab g_brushsphere( eBrushSphere ); -BrushPrefab g_brushrock( eBrushRock ); +BrushPrefab g_brushprism(eBrushPrism); +BrushPrefab g_brushcone(eBrushCone); +BrushPrefab g_brushsphere(eBrushSphere); +BrushPrefab g_brushrock(eBrushRock); void FlipClip(); + void SplitClip(); + void Clip(); -void OnClipMode( bool enable ); + +void OnClipMode(bool enable); + bool ClipMode(); -void ClipSelected(){ - if ( ClipMode() ) { - UndoableCommand undo( "clipperClip" ); - Clip(); - } +void ClipSelected() +{ + if (ClipMode()) { + UndoableCommand undo("clipperClip"); + Clip(); + } } -void SplitSelected(){ - if ( ClipMode() ) { - UndoableCommand undo( "clipperSplit" ); - SplitClip(); - } +void SplitSelected() +{ + if (ClipMode()) { + UndoableCommand undo("clipperSplit"); + SplitClip(); + } } -void FlipClipper(){ - FlipClip(); +void FlipClipper() +{ + FlipClip(); } Callback g_texture_lock_status_changed; -ConstReferenceCaller &), PropertyImpl::Export> g_texdef_movelock_caller( g_brush_texturelock_enabled ); -ToggleItem g_texdef_movelock_item( g_texdef_movelock_caller ); - -void Texdef_ToggleMoveLock(){ - g_brush_texturelock_enabled = !g_brush_texturelock_enabled; - g_texdef_movelock_item.update(); - g_texture_lock_status_changed(); -} - - - - - -void Brush_registerCommands(){ - GlobalToggles_insert( "TogTexLock", makeCallbackF(Texdef_ToggleMoveLock), ToggleItem::AddCallbackCaller( g_texdef_movelock_item ), Accelerator( 'T', (GdkModifierType)GDK_SHIFT_MASK ) ); - - GlobalCommands_insert( "BrushPrism", BrushPrefab::SetCaller( g_brushprism ) ); - GlobalCommands_insert( "BrushCone", BrushPrefab::SetCaller( g_brushcone ) ); - GlobalCommands_insert( "BrushSphere", BrushPrefab::SetCaller( g_brushsphere ) ); - GlobalCommands_insert( "BrushRock", BrushPrefab::SetCaller( g_brushrock ) ); - - GlobalCommands_insert( "Brush3Sided", BrushMakeSided::SetCaller( g_brushmakesided3 ), Accelerator( '3', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "Brush4Sided", BrushMakeSided::SetCaller( g_brushmakesided4 ), Accelerator( '4', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "Brush5Sided", BrushMakeSided::SetCaller( g_brushmakesided5 ), Accelerator( '5', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "Brush6Sided", BrushMakeSided::SetCaller( g_brushmakesided6 ), Accelerator( '6', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "Brush7Sided", BrushMakeSided::SetCaller( g_brushmakesided7 ), Accelerator( '7', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "Brush8Sided", BrushMakeSided::SetCaller( g_brushmakesided8 ), Accelerator( '8', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "Brush9Sided", BrushMakeSided::SetCaller( g_brushmakesided9 ), Accelerator( '9', (GdkModifierType)GDK_CONTROL_MASK ) ); - - GlobalCommands_insert( "ClipSelected", makeCallbackF(ClipSelected), Accelerator( GDK_KEY_Return ) ); - GlobalCommands_insert( "SplitSelected", makeCallbackF(SplitSelected), Accelerator( GDK_KEY_Return, (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "FlipClip", makeCallbackF(FlipClipper), Accelerator( GDK_KEY_Return, (GdkModifierType)GDK_CONTROL_MASK ) ); - - GlobalCommands_insert( "MakeDetail", makeCallbackF(Select_MakeDetail), Accelerator( 'M', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "MakeStructural", makeCallbackF(Select_MakeStructural), Accelerator( 'S', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); -} - -void Brush_constructMenu( ui::Menu menu ){ - create_menu_item_with_mnemonic( menu, "Prism...", "BrushPrism" ); - create_menu_item_with_mnemonic( menu, "Cone...", "BrushCone" ); - create_menu_item_with_mnemonic( menu, "Sphere...", "BrushSphere" ); - create_menu_item_with_mnemonic( menu, "Rock...", "BrushRock" ); - menu_separator( menu ); - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "CSG" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Make _Hollow", "CSGHollow" ); - create_menu_item_with_mnemonic( menu_in_menu, "CSG _Subtract", "CSGSubtract" ); - create_menu_item_with_mnemonic( menu_in_menu, "CSG _Merge", "CSGMerge" ); - } - menu_separator( menu ); - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Clipper" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - - create_menu_item_with_mnemonic( menu_in_menu, "Clip selection", "ClipSelected" ); - create_menu_item_with_mnemonic( menu_in_menu, "Split selection", "SplitSelected" ); - create_menu_item_with_mnemonic( menu_in_menu, "Flip Clip orientation", "FlipClip" ); - } - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Make detail", "MakeDetail" ); - create_menu_item_with_mnemonic( menu, "Make structural", "MakeStructural" ); - create_menu_item_with_mnemonic( menu, "Snap selection to _grid", "SnapToGrid" ); - - create_check_menu_item_with_mnemonic( menu, "Texture Lock", "TogTexLock" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Copy Face Texture", "FaceCopyTexture" ); - create_menu_item_with_mnemonic( menu, "Paste Face Texture", "FacePasteTexture" ); - - command_connect_accelerator( "Brush3Sided" ); - command_connect_accelerator( "Brush4Sided" ); - command_connect_accelerator( "Brush5Sided" ); - command_connect_accelerator( "Brush6Sided" ); - command_connect_accelerator( "Brush7Sided" ); - command_connect_accelerator( "Brush8Sided" ); - command_connect_accelerator( "Brush9Sided" ); +ConstReferenceCaller &), PropertyImpl::Export> g_texdef_movelock_caller( + g_brush_texturelock_enabled); +ToggleItem g_texdef_movelock_item(g_texdef_movelock_caller); + +void Texdef_ToggleMoveLock() +{ + g_brush_texturelock_enabled = !g_brush_texturelock_enabled; + g_texdef_movelock_item.update(); + g_texture_lock_status_changed(); +} + + +void Brush_registerCommands() +{ + GlobalToggles_insert("TogTexLock", makeCallbackF(Texdef_ToggleMoveLock), + ToggleItem::AddCallbackCaller(g_texdef_movelock_item), + Accelerator('T', (GdkModifierType) GDK_SHIFT_MASK)); + + GlobalCommands_insert("BrushPrism", BrushPrefab::SetCaller(g_brushprism)); + GlobalCommands_insert("BrushCone", BrushPrefab::SetCaller(g_brushcone)); + GlobalCommands_insert("BrushSphere", BrushPrefab::SetCaller(g_brushsphere)); + GlobalCommands_insert("BrushRock", BrushPrefab::SetCaller(g_brushrock)); + + GlobalCommands_insert("Brush3Sided", BrushMakeSided::SetCaller(g_brushmakesided3), + Accelerator('3', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("Brush4Sided", BrushMakeSided::SetCaller(g_brushmakesided4), + Accelerator('4', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("Brush5Sided", BrushMakeSided::SetCaller(g_brushmakesided5), + Accelerator('5', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("Brush6Sided", BrushMakeSided::SetCaller(g_brushmakesided6), + Accelerator('6', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("Brush7Sided", BrushMakeSided::SetCaller(g_brushmakesided7), + Accelerator('7', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("Brush8Sided", BrushMakeSided::SetCaller(g_brushmakesided8), + Accelerator('8', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("Brush9Sided", BrushMakeSided::SetCaller(g_brushmakesided9), + Accelerator('9', (GdkModifierType) GDK_CONTROL_MASK)); + + GlobalCommands_insert("ClipSelected", makeCallbackF(ClipSelected), Accelerator(GDK_KEY_Return)); + GlobalCommands_insert("SplitSelected", makeCallbackF(SplitSelected), + Accelerator(GDK_KEY_Return, (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("FlipClip", makeCallbackF(FlipClipper), + Accelerator(GDK_KEY_Return, (GdkModifierType) GDK_CONTROL_MASK)); + + GlobalCommands_insert("MakeDetail", makeCallbackF(Select_MakeDetail), + Accelerator('M', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("MakeStructural", makeCallbackF(Select_MakeStructural), + Accelerator('S', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); +} + +void Brush_constructMenu(ui::Menu menu) +{ + create_menu_item_with_mnemonic(menu, "Prism...", "BrushPrism"); + create_menu_item_with_mnemonic(menu, "Cone...", "BrushCone"); + create_menu_item_with_mnemonic(menu, "Sphere...", "BrushSphere"); + create_menu_item_with_mnemonic(menu, "Rock...", "BrushRock"); + menu_separator(menu); + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "CSG"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Make _Hollow", "CSGHollow"); + create_menu_item_with_mnemonic(menu_in_menu, "CSG _Subtract", "CSGSubtract"); + create_menu_item_with_mnemonic(menu_in_menu, "CSG _Merge", "CSGMerge"); + } + menu_separator(menu); + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Clipper"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + + create_menu_item_with_mnemonic(menu_in_menu, "Clip selection", "ClipSelected"); + create_menu_item_with_mnemonic(menu_in_menu, "Split selection", "SplitSelected"); + create_menu_item_with_mnemonic(menu_in_menu, "Flip Clip orientation", "FlipClip"); + } + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Make detail", "MakeDetail"); + create_menu_item_with_mnemonic(menu, "Make structural", "MakeStructural"); + create_menu_item_with_mnemonic(menu, "Snap selection to _grid", "SnapToGrid"); + + create_check_menu_item_with_mnemonic(menu, "Texture Lock", "TogTexLock"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Copy Face Texture", "FaceCopyTexture"); + create_menu_item_with_mnemonic(menu, "Paste Face Texture", "FacePasteTexture"); + + command_connect_accelerator("Brush3Sided"); + command_connect_accelerator("Brush4Sided"); + command_connect_accelerator("Brush5Sided"); + command_connect_accelerator("Brush6Sided"); + command_connect_accelerator("Brush7Sided"); + command_connect_accelerator("Brush8Sided"); + command_connect_accelerator("Brush9Sided"); } diff --git a/radiant/brushmanip.h b/radiant/brushmanip.h index 5a1f62b0..4fa36a0b 100644 --- a/radiant/brushmanip.h +++ b/radiant/brushmanip.h @@ -27,56 +27,85 @@ #include "string/stringfwd.h" #include "generic/callback.h" -enum EBrushPrefab -{ - eBrushCuboid, - eBrushPrism, - eBrushCone, - eBrushSphere, - eBrushRock, +enum EBrushPrefab { + eBrushCuboid, + eBrushPrism, + eBrushCone, + eBrushSphere, + eBrushRock, }; class TextureProjection; + class ContentsFlagsValue; -namespace scene -{ -class Graph; +namespace scene { + class Graph; } -void Scene_BrushConstructPrefab( scene::Graph& graph, EBrushPrefab type, std::size_t sides, const char* shader ); + +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_BrushGetShaderSize_Component_Selected( scene::Graph& graph, size_t& width, size_t& height ); -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 ); - -void Brush_constructMenu( ui::Menu menu ); + +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_BrushGetShaderSize_Component_Selected(scene::Graph &graph, size_t &width, size_t &height); + +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); + +void Brush_constructMenu(ui::Menu menu); extern Callback g_texture_lock_status_changed; void BrushFilters_construct(); + void Brush_registerCommands(); #endif diff --git a/radiant/brushmodule.cpp b/radiant/brushmodule.cpp index 2ab573e5..af5a240c 100644 --- a/radiant/brushmodule.cpp +++ b/radiant/brushmodule.cpp @@ -34,182 +34,207 @@ #include "mainframe.h" #include "preferences.h" -LatchedValue g_useAlternativeTextureProjection( false, "Use alternative texture-projection (\"brush primitives\")" ); +LatchedValue g_useAlternativeTextureProjection(false, + "Use alternative texture-projection (\"brush primitives\")"); bool g_showAlternativeTextureProjectionOption = false; bool g_brush_always_caulk; -bool getTextureLockEnabled(){ - return g_brush_texturelock_enabled; +bool getTextureLockEnabled() +{ + return g_brush_texturelock_enabled; } struct Face_SnapPlanes { - static void Export(const QuantiseFunc &self, const Callback &returnz) { - returnz(self == quantiseInteger); - } - - static void Import(QuantiseFunc &self, bool value) { - self = value ? quantiseInteger : quantiseFloating; - } + static void Export(const QuantiseFunc &self, const Callback &returnz) + { + returnz(self == quantiseInteger); + } + + static void Import(QuantiseFunc &self, bool value) + { + self = value ? quantiseInteger : quantiseFloating; + } }; -void Brush_constructPreferences( PreferencesPage& page ){ - page.appendCheckBox( - "", "Snap planes to integer grid", - make_property(Face::m_quantise) - ); - page.appendEntry( - "Default texture scale", - g_texdef_default_scale - ); - if ( g_showAlternativeTextureProjectionOption ) { - page.appendCheckBox( - "", "Use alternative texture-projection (\"brush primitives\")", - make_property(g_useAlternativeTextureProjection) - ); - } - // d1223m - page.appendCheckBox( "", - "Always use caulk for new brushes", - g_brush_always_caulk - ); +void Brush_constructPreferences(PreferencesPage &page) +{ + page.appendCheckBox( + "", "Snap planes to integer grid", + make_property(Face::m_quantise) + ); + page.appendEntry( + "Default texture scale", + g_texdef_default_scale + ); + if (g_showAlternativeTextureProjectionOption) { + page.appendCheckBox( + "", "Use alternative texture-projection (\"brush primitives\")", + make_property(g_useAlternativeTextureProjection) + ); + } + // d1223m + page.appendCheckBox("", + "Always use caulk for new brushes", + g_brush_always_caulk + ); } -void Brush_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Brush", "Brush Settings" ) ); - Brush_constructPreferences( page ); + +void Brush_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Brush", "Brush Settings")); + Brush_constructPreferences(page); } -void Brush_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage( makeCallbackF(Brush_constructPage) ); + +void Brush_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(Brush_constructPage)); } -void Brush_unlatchPreferences(){ - Brush_toggleFormat( 0 ); +void Brush_unlatchPreferences() +{ + Brush_toggleFormat(0); } -void Brush_toggleFormat( int i ){ - if ( g_showAlternativeTextureProjectionOption ) { - g_useAlternativeTextureProjection.m_value = g_useAlternativeTextureProjection.m_latched ^ i; - Brush::destroyStatic(); - Brush::constructStatic( g_useAlternativeTextureProjection.m_value ? eBrushTypeQuake3BP : eBrushTypeQuake3 ); - } +void Brush_toggleFormat(int i) +{ + if (g_showAlternativeTextureProjectionOption) { + g_useAlternativeTextureProjection.m_value = g_useAlternativeTextureProjection.m_latched ^ i; + Brush::destroyStatic(); + Brush::constructStatic(g_useAlternativeTextureProjection.m_value ? eBrushTypeQuake3BP : eBrushTypeQuake3); + } } -int Brush_toggleFormatCount(){ - if ( g_showAlternativeTextureProjectionOption ) { - return 2; - } - return 1; +int Brush_toggleFormatCount() +{ + if (g_showAlternativeTextureProjectionOption) { + return 2; + } + return 1; } -void Brush_Construct( EBrushType type ){ - if ( type == eBrushTypeQuake3 ) { - g_showAlternativeTextureProjectionOption = true; - - const char *value = g_pGameDescription->getKeyValue( "brush_primit" ); - if ( !string_empty( value ) ) { - g_useAlternativeTextureProjection.m_latched = atoi( value ); - } - - GlobalPreferenceSystem().registerPreference( - "AlternativeTextureProjection", - make_property_string( g_useAlternativeTextureProjection.m_latched ) - ); - g_useAlternativeTextureProjection.useLatched(); - - if ( g_useAlternativeTextureProjection.m_value ) { - type = eBrushTypeQuake3BP; - } - - // d1223m - GlobalPreferenceSystem().registerPreference( - "BrushAlwaysCaulk", - make_property_string( g_brush_always_caulk ) +void Brush_Construct(EBrushType type) +{ + if (type == eBrushTypeQuake3) { + g_showAlternativeTextureProjectionOption = true; + + const char *value = g_pGameDescription->getKeyValue("brush_primit"); + if (!string_empty(value)) { + g_useAlternativeTextureProjection.m_latched = atoi(value); + } + + GlobalPreferenceSystem().registerPreference( + "AlternativeTextureProjection", + make_property_string(g_useAlternativeTextureProjection.m_latched) ); - } - - 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( atof( value ) ); - if ( scale != 0 ) { - g_texdef_default_scale = scale; - } - else - { - globalErrorStream() << "error parsing \"default_scale\" attribute\n"; - } - } - - GlobalPreferenceSystem().registerPreference( "TextureLock", make_property_string( g_brush_texturelock_enabled ) ); - GlobalPreferenceSystem().registerPreference("BrushSnapPlanes", make_property_string(Face::m_quantise)); - GlobalPreferenceSystem().registerPreference( "TexdefDefaultScale", make_property_string( g_texdef_default_scale ) ); - - GridStatus_getTextureLockEnabled = getTextureLockEnabled; - g_texture_lock_status_changed = makeCallbackF(GridStatus_onTextureLockEnabledChanged); -} + g_useAlternativeTextureProjection.useLatched(); + + if (g_useAlternativeTextureProjection.m_value) { + type = eBrushTypeQuake3BP; + } + + // d1223m + GlobalPreferenceSystem().registerPreference( + "BrushAlwaysCaulk", + make_property_string(g_brush_always_caulk) + ); + } + + Brush_registerCommands(); + Brush_registerPreferencesPage(); -void Brush_Destroy(){ - Brush::m_maxWorldCoord = 0; - BrushInstance::m_counter = 0; + BrushFilters_construct(); - Brush::destroyStatic(); - BrushInstance::destroyStatic(); - BrushClipPlane::destroyStatic(); + 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( atof(value)); + if (scale != 0) { + g_texdef_default_scale = scale; + } else { + globalErrorStream() << "error parsing \"default_scale\" attribute\n"; + } + } + + GlobalPreferenceSystem().registerPreference("TextureLock", make_property_string(g_brush_texturelock_enabled)); + GlobalPreferenceSystem().registerPreference("BrushSnapPlanes", + make_property_string(Face::m_quantise)); + GlobalPreferenceSystem().registerPreference("TexdefDefaultScale", make_property_string(g_texdef_default_scale)); + + GridStatus_getTextureLockEnabled = getTextureLockEnabled; + g_texture_lock_status_changed = makeCallbackF(GridStatus_onTextureLockEnabledChanged); } -void Brush_clipperColourChanged(){ - BrushClipPlane::destroyStatic(); - BrushClipPlane::constructStatic(); +void Brush_Destroy() +{ + Brush::m_maxWorldCoord = 0; + BrushInstance::m_counter = 0; + + Brush::destroyStatic(); + BrushInstance::destroyStatic(); + BrushClipPlane::destroyStatic(); } -void BrushFaceData_fromFace( const BrushFaceDataCallback& callback, Face& face ){ - _QERFaceData faceData; - faceData.m_p0 = face.getPlane().planePoints()[0]; - faceData.m_p1 = face.getPlane().planePoints()[1]; - faceData.m_p2 = face.getPlane().planePoints()[2]; - faceData.m_shader = face.GetShader(); - faceData.m_texdef = face.getTexdef().m_projection.m_texdef; - faceData.contents = face.getShader().m_flags.m_contentFlags; - faceData.flags = face.getShader().m_flags.m_surfaceFlags; - faceData.value = face.getShader().m_flags.m_value; - callback( faceData ); +void Brush_clipperColourChanged() +{ + BrushClipPlane::destroyStatic(); + BrushClipPlane::constructStatic(); } -typedef ConstReferenceCaller BrushFaceDataFromFaceCaller; -typedef Callback FaceCallback; -class Quake3BrushCreator : public BrushCreator +void BrushFaceData_fromFace(const BrushFaceDataCallback &callback, Face &face) { + _QERFaceData faceData; + faceData.m_p0 = face.getPlane().planePoints()[0]; + faceData.m_p1 = face.getPlane().planePoints()[1]; + faceData.m_p2 = face.getPlane().planePoints()[2]; + faceData.m_shader = face.GetShader(); + faceData.m_texdef = face.getTexdef().m_projection.m_texdef; + faceData.contents = face.getShader().m_flags.m_contentFlags; + faceData.flags = face.getShader().m_flags.m_surfaceFlags; + faceData.value = face.getShader().m_flags.m_value; + callback(faceData); +} + +typedef ConstReferenceCaller BrushFaceDataFromFaceCaller; +typedef Callback FaceCallback; + +class Quake3BrushCreator : public BrushCreator { public: -scene::Node& createBrush(){ - return ( new BrushNode )->node(); -} -bool useAlternativeTextureProjection() const { - return g_useAlternativeTextureProjection.m_value; -} -void Brush_forEachFace( scene::Node& brush, const BrushFaceDataCallback& callback ){ - ::Brush_forEachFace( *Node_getBrush( brush ), FaceCallback( BrushFaceDataFromFaceCaller( callback ) ) ); -} -bool Brush_addFace( scene::Node& brush, const _QERFaceData& faceData ){ - Node_getBrush( brush )->undoSave(); - return Node_getBrush( brush )->addPlane( faceData.m_p0, faceData.m_p1, faceData.m_p2, faceData.m_shader, TextureProjection( faceData.m_texdef, brushprimit_texdef_t(), Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ) ) ) != 0; -} + scene::Node &createBrush() + { + return (new BrushNode)->node(); + } + + bool useAlternativeTextureProjection() const + { + return g_useAlternativeTextureProjection.m_value; + } + + void Brush_forEachFace(scene::Node &brush, const BrushFaceDataCallback &callback) + { + ::Brush_forEachFace(*Node_getBrush(brush), FaceCallback(BrushFaceDataFromFaceCaller(callback))); + } + + bool Brush_addFace(scene::Node &brush, const _QERFaceData &faceData) + { + Node_getBrush(brush)->undoSave(); + return Node_getBrush(brush)->addPlane(faceData.m_p0, faceData.m_p1, faceData.m_p2, faceData.m_shader, + TextureProjection(faceData.m_texdef, brushprimit_texdef_t(), + Vector3(0, 0, 0), Vector3(0, 0, 0))) != 0; + } }; Quake3BrushCreator g_Quake3BrushCreator; -BrushCreator& GetBrushCreator(){ - return g_Quake3BrushCreator; +BrushCreator &GetBrushCreator() +{ + return g_Quake3BrushCreator; } #include "modulesystem/singletonmodule.h" @@ -217,161 +242,190 @@ BrushCreator& GetBrushCreator(){ class BrushDependencies : - public GlobalRadiantModuleRef, - public GlobalSceneGraphModuleRef, - public GlobalShaderCacheModuleRef, - public GlobalSelectionModuleRef, - public GlobalOpenGLModuleRef, - public GlobalUndoModuleRef, - public GlobalFilterModuleRef -{ + public GlobalRadiantModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalSelectionModuleRef, + public GlobalOpenGLModuleRef, + public GlobalUndoModuleRef, + public GlobalFilterModuleRef { }; -class BrushDoom3API : public TypeSystemRef -{ -BrushCreator* m_brushdoom3; +class BrushDoom3API : public TypeSystemRef { + BrushCreator *m_brushdoom3; public: -typedef BrushCreator Type; -STRING_CONSTANT( Name, "doom3" ); + typedef BrushCreator Type; -BrushDoom3API(){ - Brush_Construct( eBrushTypeDoom3 ); + STRING_CONSTANT(Name, "doom3"); - m_brushdoom3 = &GetBrushCreator(); -} -~BrushDoom3API(){ - Brush_Destroy(); -} -BrushCreator* getTable(){ - return m_brushdoom3; -} + BrushDoom3API() + { + Brush_Construct(eBrushTypeDoom3); + + m_brushdoom3 = &GetBrushCreator(); + } + + ~BrushDoom3API() + { + Brush_Destroy(); + } + + BrushCreator *getTable() + { + return m_brushdoom3; + } }; typedef SingletonModule BrushDoom3Module; typedef Static StaticBrushDoom3Module; -StaticRegisterModule staticRegisterBrushDoom3( StaticBrushDoom3Module::instance() ); +StaticRegisterModule staticRegisterBrushDoom3(StaticBrushDoom3Module::instance()); -class BrushQuake4API : public TypeSystemRef -{ -BrushCreator* m_brushquake4; +class BrushQuake4API : public TypeSystemRef { + BrushCreator *m_brushquake4; public: -typedef BrushCreator Type; -STRING_CONSTANT( Name, "quake4" ); + typedef BrushCreator Type; -BrushQuake4API(){ - Brush_Construct( eBrushTypeQuake4 ); + STRING_CONSTANT(Name, "quake4"); - m_brushquake4 = &GetBrushCreator(); -} -~BrushQuake4API(){ - Brush_Destroy(); -} -BrushCreator* getTable(){ - return m_brushquake4; -} + BrushQuake4API() + { + Brush_Construct(eBrushTypeQuake4); + + m_brushquake4 = &GetBrushCreator(); + } + + ~BrushQuake4API() + { + Brush_Destroy(); + } + + BrushCreator *getTable() + { + return m_brushquake4; + } }; typedef SingletonModule BrushQuake4Module; typedef Static StaticBrushQuake4Module; -StaticRegisterModule staticRegisterBrushQuake4( StaticBrushQuake4Module::instance() ); +StaticRegisterModule staticRegisterBrushQuake4(StaticBrushQuake4Module::instance()); -class BrushQuake3API : public TypeSystemRef -{ -BrushCreator* m_brushquake3; +class BrushQuake3API : public TypeSystemRef { + BrushCreator *m_brushquake3; public: -typedef BrushCreator Type; -STRING_CONSTANT( Name, "quake3" ); + typedef BrushCreator Type; -BrushQuake3API(){ - Brush_Construct( eBrushTypeQuake3 ); + STRING_CONSTANT(Name, "quake3"); - m_brushquake3 = &GetBrushCreator(); -} -~BrushQuake3API(){ - Brush_Destroy(); -} -BrushCreator* getTable(){ - return m_brushquake3; -} + BrushQuake3API() + { + Brush_Construct(eBrushTypeQuake3); + + m_brushquake3 = &GetBrushCreator(); + } + + ~BrushQuake3API() + { + Brush_Destroy(); + } + + BrushCreator *getTable() + { + return m_brushquake3; + } }; typedef SingletonModule BrushQuake3Module; typedef Static StaticBrushQuake3Module; -StaticRegisterModule staticRegisterBrushQuake3( StaticBrushQuake3Module::instance() ); +StaticRegisterModule staticRegisterBrushQuake3(StaticBrushQuake3Module::instance()); -class BrushQuake2API : public TypeSystemRef -{ -BrushCreator* m_brushquake2; +class BrushQuake2API : public TypeSystemRef { + BrushCreator *m_brushquake2; public: -typedef BrushCreator Type; -STRING_CONSTANT( Name, "quake2" ); + typedef BrushCreator Type; -BrushQuake2API(){ - Brush_Construct( eBrushTypeQuake2 ); + STRING_CONSTANT(Name, "quake2"); - m_brushquake2 = &GetBrushCreator(); -} -~BrushQuake2API(){ - Brush_Destroy(); -} -BrushCreator* getTable(){ - return m_brushquake2; -} + BrushQuake2API() + { + Brush_Construct(eBrushTypeQuake2); + + m_brushquake2 = &GetBrushCreator(); + } + + ~BrushQuake2API() + { + Brush_Destroy(); + } + + BrushCreator *getTable() + { + return m_brushquake2; + } }; typedef SingletonModule BrushQuake2Module; typedef Static StaticBrushQuake2Module; -StaticRegisterModule staticRegisterBrushQuake2( StaticBrushQuake2Module::instance() ); +StaticRegisterModule staticRegisterBrushQuake2(StaticBrushQuake2Module::instance()); -class BrushQuake1API : public TypeSystemRef -{ -BrushCreator* m_brushquake1; +class BrushQuake1API : public TypeSystemRef { + BrushCreator *m_brushquake1; public: -typedef BrushCreator Type; -STRING_CONSTANT( Name, "quake" ); + typedef BrushCreator Type; -BrushQuake1API(){ - Brush_Construct( eBrushTypeQuake ); + STRING_CONSTANT(Name, "quake"); - m_brushquake1 = &GetBrushCreator(); -} -~BrushQuake1API(){ - Brush_Destroy(); -} -BrushCreator* getTable(){ - return m_brushquake1; -} + BrushQuake1API() + { + Brush_Construct(eBrushTypeQuake); + + m_brushquake1 = &GetBrushCreator(); + } + + ~BrushQuake1API() + { + Brush_Destroy(); + } + + BrushCreator *getTable() + { + return m_brushquake1; + } }; typedef SingletonModule BrushQuake1Module; typedef Static StaticBrushQuake1Module; -StaticRegisterModule staticRegisterBrushQuake1( StaticBrushQuake1Module::instance() ); +StaticRegisterModule staticRegisterBrushQuake1(StaticBrushQuake1Module::instance()); -class BrushHalfLifeAPI : public TypeSystemRef -{ -BrushCreator* m_brushhalflife; +class BrushHalfLifeAPI : public TypeSystemRef { + BrushCreator *m_brushhalflife; public: -typedef BrushCreator Type; -STRING_CONSTANT( Name, "halflife" ); + typedef BrushCreator Type; -BrushHalfLifeAPI(){ - Brush_Construct( eBrushTypeHalfLife ); + STRING_CONSTANT(Name, "halflife"); - m_brushhalflife = &GetBrushCreator(); -} -~BrushHalfLifeAPI(){ - Brush_Destroy(); -} -BrushCreator* getTable(){ - return m_brushhalflife; -} + BrushHalfLifeAPI() + { + Brush_Construct(eBrushTypeHalfLife); + + m_brushhalflife = &GetBrushCreator(); + } + + ~BrushHalfLifeAPI() + { + Brush_Destroy(); + } + + BrushCreator *getTable() + { + return m_brushhalflife; + } }; typedef SingletonModule BrushHalfLifeModule; typedef Static StaticBrushHalfLifeModule; -StaticRegisterModule staticRegisterBrushHalfLife( StaticBrushHalfLifeModule::instance() ); +StaticRegisterModule staticRegisterBrushHalfLife(StaticBrushHalfLifeModule::instance()); diff --git a/radiant/brushmodule.h b/radiant/brushmodule.h index a5c67e3c..b7806493 100644 --- a/radiant/brushmodule.h +++ b/radiant/brushmodule.h @@ -23,8 +23,11 @@ #define INCLUDED_BRUSHMODULE_H void Brush_clipperColourChanged(); + void Brush_unlatchPreferences(); + int Brush_toggleFormatCount(); -void Brush_toggleFormat( int i ); + +void Brush_toggleFormat(int i); #endif diff --git a/radiant/brushnode.h b/radiant/brushnode.h index ac899d9b..ad6b636a 100644 --- a/radiant/brushnode.h +++ b/radiant/brushnode.h @@ -28,119 +28,155 @@ #include "brushxml.h" class BrushNode : - public scene::Node::Symbiot, - public scene::Instantiable, - public scene::Cloneable -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; -public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); - NodeStaticCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::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 scene::Node::Symbiot, + public scene::Instantiable, + public scene::Cloneable { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + NodeStaticCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::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 StaticTypeCasts; - -Snappable& get( NullType){ - return m_brush; -} -TransformNode& get( NullType){ - return m_brush; -} -Brush& get( NullType){ - return m_brush; -} -XMLImporter& get( NullType){ - return m_xmlImporter; -} -XMLExporter& get( NullType){ - return m_xmlExporter; -} -MapImporter& get( NullType){ - return m_mapImporter; -} -MapExporter& get( NullType){ - return m_mapExporter; -} -Nameable& get( NullType){ - return m_brush; -} -BrushDoom3& get( NullType){ - return m_brush; -} - -BrushNode() : - m_node( this, this, StaticTypeCasts::instance().get() ), - m_brush( m_node, InstanceSetEvaluateTransform::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::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 ); -} + typedef LazyStatic StaticTypeCasts; + + Snappable &get(NullType) + { + return m_brush; + } + + TransformNode &get(NullType) + { + return m_brush; + } + + Brush &get(NullType) + { + return m_brush; + } + + XMLImporter &get(NullType) + { + return m_xmlImporter; + } + + XMLExporter &get(NullType) + { + return m_xmlExporter; + } + + MapImporter &get(NullType) + { + return m_mapImporter; + } + + MapExporter &get(NullType) + { + return m_mapExporter; + } + + Nameable &get(NullType) + { + return m_brush; + } + + BrushDoom3 &get(NullType) + { + return m_brush; + } + + BrushNode() : + m_node(this, this, StaticTypeCasts::instance().get()), + m_brush(m_node, InstanceSetEvaluateTransform::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::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::cast( node ); +inline Brush *Node_getBrush(scene::Node &node) +{ + return NodeTypeCast::cast(node); } #endif diff --git a/radiant/brushtokens.h b/radiant/brushtokens.h index 9b4d4fab..67ed452f 100644 --- a/radiant/brushtokens.h +++ b/radiant/brushtokens.h @@ -26,648 +26,667 @@ #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 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 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 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])); -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; + ASSERT_MESSAGE(texdef_sane(texdef.m_projection.m_texdef), "FaceTexdef_importTokens: bad texdef"); + 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 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, ")")); -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; + facePlane.setDoom3Plane(plane); + return true; } - - - -class Doom3FaceTokenImporter +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) { -Face& m_face; + 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; -} + 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; +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 ) ); + Quake4FaceTokenImporter(Face &face) : m_face(face) + { + } - m_face.getTexdef().m_projectionInitialised = true; - m_face.getTexdef().m_scaleApplied = true; + 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 true; -} + m_face.getTexdef().m_projectionInitialised = true; + m_face.getTexdef().m_scaleApplied = true; + + return true; + } }; -class Quake2FaceTokenImporter -{ -Face& m_face; +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; -} + 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; +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; -} + 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; +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; -} + 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; +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; -} + 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; +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; -} + 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 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 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 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_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 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 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 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_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() ); - } +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; +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(); -} + 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; +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(); -} + 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; +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(); -} + 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; +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(); -} + 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; +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(); -} + 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; +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(); -} + 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; +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(); -} + 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; +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; -} + 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; +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(); -} + 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(); + } }; diff --git a/radiant/brushxml.h b/radiant/brushxml.h index c1fac55b..42c732af 100644 --- a/radiant/brushxml.h +++ b/radiant/brushxml.h @@ -27,396 +27,407 @@ #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( atof( content.getToken() ) ); - texdef.m_projection.m_brushprimit_texdef.coords[0][1] = static_cast( atof( content.getToken() ) ); - texdef.m_projection.m_brushprimit_texdef.coords[0][2] = static_cast( atof( content.getToken() ) ); - texdef.m_projection.m_brushprimit_texdef.coords[1][0] = static_cast( atof( content.getToken() ) ); - texdef.m_projection.m_brushprimit_texdef.coords[1][1] = static_cast( atof( content.getToken() ) ); - texdef.m_projection.m_brushprimit_texdef.coords[1][2] = static_cast( atof( content.getToken() ) ); +inline void FaceTexdef_BP_importXML(FaceTexdef &texdef, const char *xmlContent) +{ + StringTokeniser content(xmlContent); + + texdef.m_projection.m_brushprimit_texdef.coords[0][0] = static_cast( atof(content.getToken())); + texdef.m_projection.m_brushprimit_texdef.coords[0][1] = static_cast( atof(content.getToken())); + texdef.m_projection.m_brushprimit_texdef.coords[0][2] = static_cast( atof(content.getToken())); + texdef.m_projection.m_brushprimit_texdef.coords[1][0] = static_cast( atof(content.getToken())); + texdef.m_projection.m_brushprimit_texdef.coords[1][1] = static_cast( atof(content.getToken())); + texdef.m_projection.m_brushprimit_texdef.coords[1][2] = static_cast( atof(content.getToken())); } -inline void FaceTexdef_importXML( FaceTexdef& texdef, const char* xmlContent ){ - StringTokeniser content( xmlContent ); - texdef.m_projection.m_texdef.shift[0] = static_cast( atof( content.getToken() ) ); - texdef.m_projection.m_texdef.shift[1] = static_cast( atof( content.getToken() ) ); - texdef.m_projection.m_texdef.rotate = static_cast( atof( content.getToken() ) ); - texdef.m_projection.m_texdef.scale[0] = static_cast( atof( content.getToken() ) ); - texdef.m_projection.m_texdef.scale[1] = static_cast( atof( content.getToken() ) ); +inline void FaceTexdef_importXML(FaceTexdef &texdef, const char *xmlContent) +{ + StringTokeniser content(xmlContent); - ASSERT_MESSAGE( texdef_sane( texdef.m_projection.m_texdef ), "FaceTexdef_importXML: bad texdef" ); -} + texdef.m_projection.m_texdef.shift[0] = static_cast( atof(content.getToken())); + texdef.m_projection.m_texdef.shift[1] = static_cast( atof(content.getToken())); + texdef.m_projection.m_texdef.rotate = static_cast( atof(content.getToken())); + texdef.m_projection.m_texdef.scale[0] = static_cast( atof(content.getToken())); + texdef.m_projection.m_texdef.scale[1] = static_cast( atof(content.getToken())); -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(); + ASSERT_MESSAGE(texdef_sane(texdef.m_projection.m_texdef), "FaceTexdef_importXML: bad texdef"); } - -class FaceXMLImporter -{ -struct xml_state_t +inline void FacePlane_importXML(FacePlane &facePlane, const char *xmlContent) { - 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 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(); + 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(); } -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 ); -} + +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 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 ); +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" ); + 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 << 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() ); + 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 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; - } +inline void FaceShader_ContentsFlagsValue_exportXML(const FaceShader &faceShader, XMLImporter &importer) +{ + StaticElement element("flags"); + importer.pushElement(element); - importer.popElement( element.name() ); + { + 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() ); +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()); } -inline void FacePolygon_exportXML( const Winding& w, const BasicVector3& normal, XMLImporter& importer ){ - DynamicElement element( "polygon" ); +inline void FacePolygon_exportXML(const Winding &w, const BasicVector3 &normal, XMLImporter &importer) +{ + DynamicElement element("polygon"); - char tmp[32]; + char tmp[32]; - sprintf( tmp, "%f", normal.x() ); - element.insertAttribute( "nx", tmp ); + sprintf(tmp, "%f", normal.x()); + element.insertAttribute("nx", tmp); - sprintf( tmp, "%f", normal.y() ); - element.insertAttribute( "ny", tmp ); + sprintf(tmp, "%f", normal.y()); + element.insertAttribute("ny", tmp); - sprintf( tmp, "%f", normal.z() ); - element.insertAttribute( "nz", tmp ); + sprintf(tmp, "%f", normal.z()); + element.insertAttribute("nz", tmp); - importer.pushElement( element ); + importer.pushElement(element); - for ( unsigned int i = 0; i < w.numpoints; ++i ) - { - DynamicElement c( "vertex" ); + for (unsigned int i = 0; i < w.numpoints; ++i) { + DynamicElement c("vertex"); - sprintf( tmp, "%f", w.points[i].vertex.x() ); - c.insertAttribute( "x", tmp ); + sprintf(tmp, "%f", w.points[i].vertex.x()); + c.insertAttribute("x", tmp); - sprintf( tmp, "%f", w.points[i].vertex.y() ); - c.insertAttribute( "y", tmp ); + sprintf(tmp, "%f", w.points[i].vertex.y()); + c.insertAttribute("y", tmp); - sprintf( tmp, "%f", w.points[i].vertex.z() ); - c.insertAttribute( "z", tmp ); + sprintf(tmp, "%f", w.points[i].vertex.z()); + c.insertAttribute("z", tmp); - sprintf( tmp, "%f", w.points[i].texcoord.x() ); - c.insertAttribute( "s", tmp ); + sprintf(tmp, "%f", w.points[i].texcoord.x()); + c.insertAttribute("s", tmp); - sprintf( tmp, "%f", w.points[i].texcoord.y() ); - c.insertAttribute( "t", tmp ); + sprintf(tmp, "%f", w.points[i].texcoord.y()); + c.insertAttribute("t", tmp); - importer.pushElement( c ); - importer.popElement( c.name() ); - } + importer.pushElement(c); + importer.popElement(c.name()); + } - importer.popElement( element.name() ); + importer.popElement(element.name()); } -class FaceXMLExporter -{ -const Face& m_face; +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() ); - } - - FacePolygon_exportXML( m_face.getWinding(), m_face.getPlane().plane3().normal(), importer ); - 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 ); -} + 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()); + } + + FacePolygon_exportXML(m_face.getWinding(), m_face.getPlane().plane3().normal(), importer); + 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, -}; +class BrushXMLImporter : public XMLImporter { + class xml_state_t { + public: + enum EState { + eDefault, + eBrush, + eFace, + }; -private: -EState m_state; + private: + EState m_state; -public: -xml_state_t( EState state ) - : m_state( state ){ -} -EState state() const { - return m_state; -} -}; + public: + xml_state_t(EState state) + : m_state(state) + { + } -std::vector m_xml_state; -char m_faceImporter[sizeof( FaceXMLImporter )]; -Brush& m_brush; + EState state() const + { + return m_state; + } + }; -FaceXMLImporter& faceImporter(){ - return *reinterpret_cast( m_faceImporter ); -} + std::vector m_xml_state; + char m_faceImporter[sizeof(FaceXMLImporter)]; + Brush &m_brush; + + FaceXMLImporter &faceImporter() + { + return *reinterpret_cast( 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; -} + 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; +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() ); -} + 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()); + } }; diff --git a/radiant/build.cpp b/radiant/build.cpp index 6462e382..4524a4e8 100644 --- a/radiant/build.cpp +++ b/radiant/build.cpp @@ -33,596 +33,660 @@ typedef std::map Variables; Variables g_build_variables; -void build_clear_variables(){ - g_build_variables.clear(); +void build_clear_variables() +{ + g_build_variables.clear(); } -void build_set_variable( const char* name, const char* value ){ - g_build_variables[name] = value; +void build_set_variable(const char *name, const char *value) +{ + g_build_variables[name] = value; } -const char* build_get_variable( const char* name ){ - Variables::iterator i = g_build_variables.find( name ); - if ( i != g_build_variables.end() ) { - return ( *i ).second.c_str(); - } - globalErrorStream() << "undefined build variable: " << makeQuoted( name ) << "\n"; - return ""; +const char *build_get_variable(const char *name) +{ + Variables::iterator i = g_build_variables.find(name); + if (i != g_build_variables.end()) { + return (*i).second.c_str(); + } + globalErrorStream() << "undefined build variable: " << makeQuoted(name) << "\n"; + return ""; } #include "xml/ixml.h" #include "xml/xmlelement.h" -class Evaluatable -{ +class Evaluatable { public: -virtual ~Evaluatable() = default; -virtual void evaluate( StringBuffer& output ) = 0; -virtual void exportXML( XMLImporter& importer ) = 0; + virtual ~Evaluatable() = default; + + virtual void evaluate(StringBuffer &output) = 0; + + virtual void exportXML(XMLImporter &importer) = 0; }; -class VariableString : public Evaluatable -{ -CopiedString m_string; +class VariableString : public Evaluatable { + CopiedString m_string; public: -VariableString() : m_string(){ -} -VariableString( const char* string ) : m_string( string ){ -} -const char* c_str() const { - return m_string.c_str(); -} -void setString( const char* string ){ - m_string = string; -} -void evaluate( StringBuffer& output ){ - StringBuffer variable; - bool in_variable = false; - for ( const char* i = m_string.c_str(); *i != '\0'; ++i ) - { - if ( !in_variable ) { - switch ( *i ) - { - case '[': - in_variable = true; - break; - default: - output.push_back( *i ); - break; - } - } - else - { - switch ( *i ) - { - case ']': - in_variable = false; - output.push_string( build_get_variable( variable.c_str() ) ); - variable.clear(); - break; - default: - variable.push_back( *i ); - break; - } - } - } -} -void exportXML( XMLImporter& importer ){ - importer << c_str(); -} + VariableString() : m_string() + { + } + + VariableString(const char *string) : m_string(string) + { + } + + const char *c_str() const + { + return m_string.c_str(); + } + + void setString(const char *string) + { + m_string = string; + } + + void evaluate(StringBuffer &output) + { + StringBuffer variable; + bool in_variable = false; + for (const char *i = m_string.c_str(); *i != '\0'; ++i) { + if (!in_variable) { + switch (*i) { + case '[': + in_variable = true; + break; + default: + output.push_back(*i); + break; + } + } else { + switch (*i) { + case ']': + in_variable = false; + output.push_string(build_get_variable(variable.c_str())); + variable.clear(); + break; + default: + variable.push_back(*i); + break; + } + } + } + } + + void exportXML(XMLImporter &importer) + { + importer << c_str(); + } }; -class Conditional : public Evaluatable -{ -VariableString* m_test; +class Conditional : public Evaluatable { + VariableString *m_test; public: -Evaluatable* m_result; -Conditional( VariableString* test ) : m_test( test ){ -} -~Conditional(){ - delete m_test; - delete m_result; -} -void evaluate( StringBuffer& output ){ - StringBuffer buffer; - m_test->evaluate( buffer ); - if ( !string_empty( buffer.c_str() ) ) { - m_result->evaluate( output ); - } -} -void exportXML( XMLImporter& importer ){ - StaticElement conditionElement( "cond" ); - conditionElement.insertAttribute( "value", m_test->c_str() ); - importer.pushElement( conditionElement ); - m_result->exportXML( importer ); - importer.popElement( conditionElement.name() ); -} + Evaluatable *m_result; + + Conditional(VariableString *test) : m_test(test) + { + } + + ~Conditional() + { + delete m_test; + delete m_result; + } + + void evaluate(StringBuffer &output) + { + StringBuffer buffer; + m_test->evaluate(buffer); + if (!string_empty(buffer.c_str())) { + m_result->evaluate(output); + } + } + + void exportXML(XMLImporter &importer) + { + StaticElement conditionElement("cond"); + conditionElement.insertAttribute("value", m_test->c_str()); + importer.pushElement(conditionElement); + m_result->exportXML(importer); + importer.popElement(conditionElement.name()); + } }; -typedef std::vector Evaluatables; +typedef std::vector Evaluatables; -class Tool : public Evaluatable -{ -Evaluatables m_evaluatables; +class Tool : public Evaluatable { + Evaluatables m_evaluatables; public: -~Tool(){ - for ( Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i ) - { - delete ( *i ); - } -} -void push_back( Evaluatable* evaluatable ){ - m_evaluatables.push_back( evaluatable ); -} -void evaluate( StringBuffer& output ){ - for ( Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i ) - { - ( *i )->evaluate( output ); - } -} -void exportXML( XMLImporter& importer ){ - for ( Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i ) - { - ( *i )->exportXML( importer ); - } -} + ~Tool() + { + for (Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i) { + delete (*i); + } + } + + void push_back(Evaluatable *evaluatable) + { + m_evaluatables.push_back(evaluatable); + } + + void evaluate(StringBuffer &output) + { + for (Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i) { + (*i)->evaluate(output); + } + } + + void exportXML(XMLImporter &importer) + { + for (Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i) { + (*i)->exportXML(importer); + } + } }; #include "xml/ixml.h" -class XMLElementParser : public TextOutputStream -{ +class XMLElementParser : public TextOutputStream { public: -virtual ~XMLElementParser() = default; -virtual XMLElementParser& pushElement( const XMLElement& element ) = 0; -virtual void popElement( const char* name ) = 0; + virtual ~XMLElementParser() = default; + + virtual XMLElementParser &pushElement(const XMLElement &element) = 0; + + virtual void popElement(const char *name) = 0; }; -class VariableStringXMLConstructor : public XMLElementParser -{ -StringBuffer m_buffer; -VariableString& m_variableString; +class VariableStringXMLConstructor : public XMLElementParser { + StringBuffer m_buffer; + VariableString &m_variableString; public: -VariableStringXMLConstructor( VariableString& variableString ) : m_variableString( variableString ){ -} -~VariableStringXMLConstructor(){ - m_variableString.setString( m_buffer.c_str() ); -} -std::size_t write( const char* buffer, std::size_t length ){ - m_buffer.push_range( buffer, buffer + length ); - return length; -} -XMLElementParser& pushElement( const XMLElement& element ){ - ERROR_MESSAGE( "parse error: invalid element \"" << element.name() << "\"" ); - return *this; -} -void popElement( const char* name ){ -} + VariableStringXMLConstructor(VariableString &variableString) : m_variableString(variableString) + { + } + + ~VariableStringXMLConstructor() + { + m_variableString.setString(m_buffer.c_str()); + } + + std::size_t write(const char *buffer, std::size_t length) + { + m_buffer.push_range(buffer, buffer + length); + return length; + } + + XMLElementParser &pushElement(const XMLElement &element) + { + ERROR_MESSAGE("parse error: invalid element \"" << element.name() << "\""); + return *this; + } + + void popElement(const char *name) + { + } }; -class ConditionalXMLConstructor : public XMLElementParser -{ -StringBuffer m_buffer; -Conditional& m_conditional; +class ConditionalXMLConstructor : public XMLElementParser { + StringBuffer m_buffer; + Conditional &m_conditional; public: -ConditionalXMLConstructor( Conditional& conditional ) : m_conditional( conditional ){ -} -~ConditionalXMLConstructor(){ - m_conditional.m_result = new VariableString( m_buffer.c_str() ); -} -std::size_t write( const char* buffer, std::size_t length ){ - m_buffer.push_range( buffer, buffer + length ); - return length; -} -XMLElementParser& pushElement( const XMLElement& element ){ - ERROR_MESSAGE( "parse error: invalid element \"" << element.name() << "\"" ); - return *this; -} -void popElement( const char* name ){ -} + ConditionalXMLConstructor(Conditional &conditional) : m_conditional(conditional) + { + } + + ~ConditionalXMLConstructor() + { + m_conditional.m_result = new VariableString(m_buffer.c_str()); + } + + std::size_t write(const char *buffer, std::size_t length) + { + m_buffer.push_range(buffer, buffer + length); + return length; + } + + XMLElementParser &pushElement(const XMLElement &element) + { + ERROR_MESSAGE("parse error: invalid element \"" << element.name() << "\""); + return *this; + } + + void popElement(const char *name) + { + } }; -class ToolXMLConstructor : public XMLElementParser -{ -StringBuffer m_buffer; -Tool& m_tool; -ConditionalXMLConstructor* m_conditional; +class ToolXMLConstructor : public XMLElementParser { + StringBuffer m_buffer; + Tool &m_tool; + ConditionalXMLConstructor *m_conditional; public: -ToolXMLConstructor( Tool& tool ) : m_tool( tool ){ -} -~ToolXMLConstructor(){ - flush(); -} -std::size_t write( const char* buffer, std::size_t length ){ - m_buffer.push_range( buffer, buffer + length ); - return length; -} -XMLElementParser& pushElement( const XMLElement& element ){ - if ( string_equal( element.name(), "cond" ) ) { - flush(); - Conditional* conditional = new Conditional( new VariableString( element.attribute( "value" ) ) ); - m_tool.push_back( conditional ); - m_conditional = new ConditionalXMLConstructor( *conditional ); - return *m_conditional; - } - else - { - ERROR_MESSAGE( "parse error: invalid element \"" << element.name() << "\"" ); - return *this; - } -} -void popElement( const char* name ){ - if ( string_equal( name, "cond" ) ) { - delete m_conditional; - } -} - -void flush(){ - if ( !m_buffer.empty() ) { - m_tool.push_back( new VariableString( m_buffer.c_str() ) ); - m_buffer.clear(); - } -} + ToolXMLConstructor(Tool &tool) : m_tool(tool) + { + } + + ~ToolXMLConstructor() + { + flush(); + } + + std::size_t write(const char *buffer, std::size_t length) + { + m_buffer.push_range(buffer, buffer + length); + return length; + } + + XMLElementParser &pushElement(const XMLElement &element) + { + if (string_equal(element.name(), "cond")) { + flush(); + Conditional *conditional = new Conditional(new VariableString(element.attribute("value"))); + m_tool.push_back(conditional); + m_conditional = new ConditionalXMLConstructor(*conditional); + return *m_conditional; + } else { + ERROR_MESSAGE("parse error: invalid element \"" << element.name() << "\""); + return *this; + } + } + + void popElement(const char *name) + { + if (string_equal(name, "cond")) { + delete m_conditional; + } + } + + void flush() + { + if (!m_buffer.empty()) { + m_tool.push_back(new VariableString(m_buffer.c_str())); + m_buffer.clear(); + } + } }; typedef VariableString BuildCommand; typedef std::list Build; -class BuildXMLConstructor : public XMLElementParser -{ -VariableStringXMLConstructor* m_variableString; -Build& m_build; +class BuildXMLConstructor : public XMLElementParser { + VariableStringXMLConstructor *m_variableString; + Build &m_build; public: -BuildXMLConstructor( Build& build ) : m_build( build ){ -} -std::size_t write( const char* buffer, std::size_t length ){ - return length; -} -XMLElementParser& pushElement( const XMLElement& element ){ - if ( string_equal( element.name(), "command" ) ) { - m_build.push_back( BuildCommand() ); - m_variableString = new VariableStringXMLConstructor( m_build.back() ); - return *m_variableString; - } - else - { - ERROR_MESSAGE( "parse error: invalid element" ); - return *this; - } -} -void popElement( const char* name ){ - delete m_variableString; -} + BuildXMLConstructor(Build &build) : m_build(build) + { + } + + std::size_t write(const char *buffer, std::size_t length) + { + return length; + } + + XMLElementParser &pushElement(const XMLElement &element) + { + if (string_equal(element.name(), "command")) { + m_build.push_back(BuildCommand()); + m_variableString = new VariableStringXMLConstructor(m_build.back()); + return *m_variableString; + } else { + ERROR_MESSAGE("parse error: invalid element"); + return *this; + } + } + + void popElement(const char *name) + { + delete m_variableString; + } }; typedef std::pair BuildPair; const char *SEPARATOR_STRING = "-"; -static bool is_separator( const BuildPair &p ){ - if ( !string_equal( p.first.c_str(), SEPARATOR_STRING ) ) { - return false; - } - for ( Build::const_iterator j = p.second.begin(); j != p.second.end(); ++j ) - { - if ( !string_equal( ( *j ).c_str(), "" ) ) { - return false; - } - } - return true; + +static bool is_separator(const BuildPair &p) +{ + if (!string_equal(p.first.c_str(), SEPARATOR_STRING)) { + return false; + } + for (Build::const_iterator j = p.second.begin(); j != p.second.end(); ++j) { + if (!string_equal((*j).c_str(), "")) { + return false; + } + } + return true; } typedef std::list Project; -Project::iterator Project_find( Project& project, const char* name ){ - return std::find_if(project.begin(), project.end(), [&](const BuildPair &self) { - return string_equal(self.first.c_str(), name); - }); +Project::iterator Project_find(Project &project, const char *name) +{ + return std::find_if(project.begin(), project.end(), [&](const BuildPair &self) { + return string_equal(self.first.c_str(), name); + }); } -Project::iterator Project_find( Project& project, std::size_t index ){ - Project::iterator i = project.begin(); - while ( index-- != 0 && i != project.end() ) - { - ++i; - } - return i; +Project::iterator Project_find(Project &project, std::size_t index) +{ + Project::iterator i = project.begin(); + while (index-- != 0 && i != project.end()) { + ++i; + } + return i; } -Build& project_find( Project& project, const char* build ){ - Project::iterator i = Project_find( project, build ); - ASSERT_MESSAGE( i != project.end(), "error finding build command" ); - return ( *i ).second; +Build &project_find(Project &project, const char *build) +{ + Project::iterator i = Project_find(project, build); + ASSERT_MESSAGE(i != project.end(), "error finding build command"); + return (*i).second; } -Build::iterator Build_find( Build& build, std::size_t index ){ - Build::iterator i = build.begin(); - while ( index-- != 0 && i != build.end() ) - { - ++i; - } - return i; +Build::iterator Build_find(Build &build, std::size_t index) +{ + Build::iterator i = build.begin(); + while (index-- != 0 && i != build.end()) { + ++i; + } + return i; } typedef std::map Tools; -class ProjectXMLConstructor : public XMLElementParser -{ -ToolXMLConstructor* m_tool; -BuildXMLConstructor* m_build; -Project& m_project; -Tools& m_tools; +class ProjectXMLConstructor : public XMLElementParser { + ToolXMLConstructor *m_tool; + BuildXMLConstructor *m_build; + Project &m_project; + Tools &m_tools; public: -ProjectXMLConstructor( Project& project, Tools& tools ) : m_project( project ), m_tools( tools ){ -} -std::size_t write( const char* buffer, std::size_t length ){ - return length; -} -XMLElementParser& pushElement( const XMLElement& element ){ - if ( string_equal( element.name(), "var" ) ) { - Tools::iterator i = m_tools.insert( Tools::value_type( element.attribute( "name" ), Tool() ) ).first; - m_tool = new ToolXMLConstructor( ( *i ).second ); - return *m_tool; - } - else if ( string_equal( element.name(), "build" ) ) { - m_project.push_back( Project::value_type( element.attribute( "name" ), Build() ) ); - m_build = new BuildXMLConstructor( m_project.back().second ); - return *m_build; - } - else if ( string_equal( element.name(), "separator" ) ) { - m_project.push_back( Project::value_type( SEPARATOR_STRING, Build() ) ); - return *this; - } - else - { - ERROR_MESSAGE( "parse error: invalid element" ); - return *this; - } -} -void popElement( const char* name ){ - if ( string_equal( name, "var" ) ) { - delete m_tool; - } - else if ( string_equal( name, "build" ) ) { - delete m_build; - } -} + ProjectXMLConstructor(Project &project, Tools &tools) : m_project(project), m_tools(tools) + { + } + + std::size_t write(const char *buffer, std::size_t length) + { + return length; + } + + XMLElementParser &pushElement(const XMLElement &element) + { + if (string_equal(element.name(), "var")) { + Tools::iterator i = m_tools.insert(Tools::value_type(element.attribute("name"), Tool())).first; + m_tool = new ToolXMLConstructor((*i).second); + return *m_tool; + } else if (string_equal(element.name(), "build")) { + m_project.push_back(Project::value_type(element.attribute("name"), Build())); + m_build = new BuildXMLConstructor(m_project.back().second); + return *m_build; + } else if (string_equal(element.name(), "separator")) { + m_project.push_back(Project::value_type(SEPARATOR_STRING, Build())); + return *this; + } else { + ERROR_MESSAGE("parse error: invalid element"); + return *this; + } + } + + void popElement(const char *name) + { + if (string_equal(name, "var")) { + delete m_tool; + } else if (string_equal(name, "build")) { + delete m_build; + } + } }; -class SkipAllParser : public XMLElementParser -{ +class SkipAllParser : public XMLElementParser { public: -std::size_t write( const char* buffer, std::size_t length ){ - return length; -} -XMLElementParser& pushElement( const XMLElement& element ){ - return *this; -} -void popElement( const char* name ){ -} + std::size_t write(const char *buffer, std::size_t length) + { + return length; + } + + XMLElementParser &pushElement(const XMLElement &element) + { + return *this; + } + + void popElement(const char *name) + { + } }; -class RootXMLConstructor : public XMLElementParser -{ -CopiedString m_elementName; -XMLElementParser& m_parser; -SkipAllParser m_skip; -Version m_version; -bool m_compatible; +class RootXMLConstructor : public XMLElementParser { + CopiedString m_elementName; + XMLElementParser &m_parser; + SkipAllParser m_skip; + Version m_version; + bool m_compatible; public: -RootXMLConstructor( const char* elementName, XMLElementParser& parser, const char* version ) : - m_elementName( elementName ), - m_parser( parser ), - m_version( version_parse( version ) ), - m_compatible( false ){ -} -std::size_t write( const char* buffer, std::size_t length ){ - return length; -} -XMLElementParser& pushElement( const XMLElement& element ){ - if ( string_equal( element.name(), m_elementName.c_str() ) ) { - Version dataVersion( version_parse( element.attribute( "version" ) ) ); - if ( version_compatible( m_version, dataVersion ) ) { - m_compatible = true; - return m_parser; - } - else - { - return m_skip; - } - } - else - { - //ERROR_MESSAGE("parse error: invalid element \"" << element.name() << "\""); - return *this; - } -} -void popElement( const char* name ){ -} - -bool versionCompatible() const { - return m_compatible; -} + RootXMLConstructor(const char *elementName, XMLElementParser &parser, const char *version) : + m_elementName(elementName), + m_parser(parser), + m_version(version_parse(version)), + m_compatible(false) + { + } + + std::size_t write(const char *buffer, std::size_t length) + { + return length; + } + + XMLElementParser &pushElement(const XMLElement &element) + { + if (string_equal(element.name(), m_elementName.c_str())) { + Version dataVersion(version_parse(element.attribute("version"))); + if (version_compatible(m_version, dataVersion)) { + m_compatible = true; + return m_parser; + } else { + return m_skip; + } + } else { + //ERROR_MESSAGE("parse error: invalid element \"" << element.name() << "\""); + return *this; + } + } + + void popElement(const char *name) + { + } + + bool versionCompatible() const + { + return m_compatible; + } }; -namespace -{ -Project g_build_project; -Tools g_build_tools; -bool g_build_changed = false; +namespace { + Project g_build_project; + Tools g_build_tools; + bool g_build_changed = false; } -void build_error_undefined_tool( const char* build, const char* tool ){ - globalErrorStream() << "build " << makeQuoted( build ) << " refers to undefined tool " << makeQuoted( tool ) << '\n'; +void build_error_undefined_tool(const char *build, const char *tool) +{ + globalErrorStream() << "build " << makeQuoted(build) << " refers to undefined tool " << makeQuoted(tool) << '\n'; } -void project_verify( Project& project, Tools& tools ){ +void project_verify(Project &project, Tools &tools) +{ #if 0 - for ( Project::iterator i = project.begin(); i != project.end(); ++i ) - { - Build& build = ( *i ).second; - for ( Build::iterator j = build.begin(); j != build.end(); ++j ) - { - Tools::iterator k = tools.find( ( *j ).first ); - if ( k == g_build_tools.end() ) { - build_error_undefined_tool( ( *i ).first.c_str(), ( *j ).first.c_str() ); - } - } - } + for ( Project::iterator i = project.begin(); i != project.end(); ++i ) + { + Build& build = ( *i ).second; + for ( Build::iterator j = build.begin(); j != build.end(); ++j ) + { + Tools::iterator k = tools.find( ( *j ).first ); + if ( k == g_build_tools.end() ) { + build_error_undefined_tool( ( *i ).first.c_str(), ( *j ).first.c_str() ); + } + } + } #endif } -void build_run( const char* name, CommandListener& listener ){ - for ( Tools::iterator i = g_build_tools.begin(); i != g_build_tools.end(); ++i ) - { - StringBuffer output; - ( *i ).second.evaluate( output ); - build_set_variable( ( *i ).first.c_str(), output.c_str() ); - } - - { - Project::iterator i = Project_find( g_build_project, name ); - if ( i != g_build_project.end() ) { - Build& build = ( *i ).second; - for ( Build::iterator j = build.begin(); j != build.end(); ++j ) - { - StringBuffer output; - ( *j ).evaluate( output ); - listener.execute( output.c_str() ); - } - } - else - { - globalErrorStream() << "build " << makeQuoted( name ) << " not defined"; - } - } -} - - -typedef std::vector XMLElementStack; - -class XMLParser : public XMLImporter +void build_run(const char *name, CommandListener &listener) { -XMLElementStack m_stack; + for (Tools::iterator i = g_build_tools.begin(); i != g_build_tools.end(); ++i) { + StringBuffer output; + (*i).second.evaluate(output); + build_set_variable((*i).first.c_str(), output.c_str()); + } + + { + Project::iterator i = Project_find(g_build_project, name); + if (i != g_build_project.end()) { + Build &build = (*i).second; + for (Build::iterator j = build.begin(); j != build.end(); ++j) { + StringBuffer output; + (*j).evaluate(output); + listener.execute(output.c_str()); + } + } else { + globalErrorStream() << "build " << makeQuoted(name) << " not defined"; + } + } +} + + +typedef std::vector XMLElementStack; + +class XMLParser : public XMLImporter { + XMLElementStack m_stack; public: -XMLParser( XMLElementParser& parser ){ - m_stack.push_back( &parser ); -} -std::size_t write( const char* buffer, std::size_t length ){ - return m_stack.back()->write( buffer, length ); -} -void pushElement( const XMLElement& element ){ - m_stack.push_back( &m_stack.back()->pushElement( element ) ); -} -void popElement( const char* name ){ - m_stack.pop_back(); - m_stack.back()->popElement( name ); -} + XMLParser(XMLElementParser &parser) + { + m_stack.push_back(&parser); + } + + std::size_t write(const char *buffer, std::size_t length) + { + return m_stack.back()->write(buffer, length); + } + + void pushElement(const XMLElement &element) + { + m_stack.push_back(&m_stack.back()->pushElement(element)); + } + + void popElement(const char *name) + { + m_stack.pop_back(); + m_stack.back()->popElement(name); + } }; #include "stream/textfilestream.h" #include "xml/xmlparser.h" -const char* const BUILDMENU_VERSION = "2.0"; - -bool build_commands_parse( const char* filename ){ - TextFileInputStream projectFile( filename ); - if ( !projectFile.failed() ) { - ProjectXMLConstructor projectConstructor( g_build_project, g_build_tools ); - RootXMLConstructor rootConstructor( "project", projectConstructor, BUILDMENU_VERSION ); - XMLParser importer( rootConstructor ); - XMLStreamParser parser( projectFile ); - parser.exportXML( importer ); - - if ( rootConstructor.versionCompatible() ) { - project_verify( g_build_project, g_build_tools ); - - return true; - } - globalErrorStream() << "failed to parse build menu: " << makeQuoted( filename ) << "\n"; - } - return false; -} +const char *const BUILDMENU_VERSION = "2.0"; -void build_commands_clear(){ - g_build_project.clear(); - g_build_tools.clear(); +bool build_commands_parse(const char *filename) +{ + TextFileInputStream projectFile(filename); + if (!projectFile.failed()) { + ProjectXMLConstructor projectConstructor(g_build_project, g_build_tools); + RootXMLConstructor rootConstructor("project", projectConstructor, BUILDMENU_VERSION); + XMLParser importer(rootConstructor); + XMLStreamParser parser(projectFile); + parser.exportXML(importer); + + if (rootConstructor.versionCompatible()) { + project_verify(g_build_project, g_build_tools); + + return true; + } + globalErrorStream() << "failed to parse build menu: " << makeQuoted(filename) << "\n"; + } + return false; } -class BuildXMLExporter +void build_commands_clear() { -Build& m_build; -public: -BuildXMLExporter( Build& build ) : m_build( build ){ -} -void exportXML( XMLImporter& importer ){ - importer << "\n"; - for ( Build::iterator i = m_build.begin(); i != m_build.end(); ++i ) - { - StaticElement commandElement( "command" ); - importer.pushElement( commandElement ); - ( *i ).exportXML( importer ); - importer.popElement( commandElement.name() ); - importer << "\n"; - } + g_build_project.clear(); + g_build_tools.clear(); } + +class BuildXMLExporter { + Build &m_build; +public: + BuildXMLExporter(Build &build) : m_build(build) + { + } + + void exportXML(XMLImporter &importer) + { + importer << "\n"; + for (Build::iterator i = m_build.begin(); i != m_build.end(); ++i) { + StaticElement commandElement("command"); + importer.pushElement(commandElement); + (*i).exportXML(importer); + importer.popElement(commandElement.name()); + importer << "\n"; + } + } }; -class ProjectXMLExporter -{ -Project& m_project; -Tools& m_tools; +class ProjectXMLExporter { + Project &m_project; + Tools &m_tools; public: -ProjectXMLExporter( Project& project, Tools& tools ) : m_project( project ), m_tools( tools ){ -} -void exportXML( XMLImporter& importer ){ - StaticElement projectElement( "project" ); - projectElement.insertAttribute( "version", BUILDMENU_VERSION ); - importer.pushElement( projectElement ); - importer << "\n"; - - for ( Tools::iterator i = m_tools.begin(); i != m_tools.end(); ++i ) - { - StaticElement toolElement( "var" ); - toolElement.insertAttribute( "name", ( *i ).first.c_str() ); - importer.pushElement( toolElement ); - ( *i ).second.exportXML( importer ); - importer.popElement( toolElement.name() ); - importer << "\n"; - } - for ( Project::iterator i = m_project.begin(); i != m_project.end(); ++i ) - { - if ( is_separator( *i ) ) { - StaticElement buildElement( "separator" ); - importer.pushElement( buildElement ); - importer.popElement( buildElement.name() ); - importer << "\n"; - } - else - { - StaticElement buildElement( "build" ); - buildElement.insertAttribute( "name", ( *i ).first.c_str() ); - importer.pushElement( buildElement ); - BuildXMLExporter buildExporter( ( *i ).second ); - buildExporter.exportXML( importer ); - importer.popElement( buildElement.name() ); - importer << "\n"; - } - } - importer.popElement( projectElement.name() ); -} + ProjectXMLExporter(Project &project, Tools &tools) : m_project(project), m_tools(tools) + { + } + + void exportXML(XMLImporter &importer) + { + StaticElement projectElement("project"); + projectElement.insertAttribute("version", BUILDMENU_VERSION); + importer.pushElement(projectElement); + importer << "\n"; + + for (Tools::iterator i = m_tools.begin(); i != m_tools.end(); ++i) { + StaticElement toolElement("var"); + toolElement.insertAttribute("name", (*i).first.c_str()); + importer.pushElement(toolElement); + (*i).second.exportXML(importer); + importer.popElement(toolElement.name()); + importer << "\n"; + } + for (Project::iterator i = m_project.begin(); i != m_project.end(); ++i) { + if (is_separator(*i)) { + StaticElement buildElement("separator"); + importer.pushElement(buildElement); + importer.popElement(buildElement.name()); + importer << "\n"; + } else { + StaticElement buildElement("build"); + buildElement.insertAttribute("name", (*i).first.c_str()); + importer.pushElement(buildElement); + BuildXMLExporter buildExporter((*i).second); + buildExporter.exportXML(importer); + importer.popElement(buildElement.name()); + importer << "\n"; + } + } + importer.popElement(projectElement.name()); + } }; #include "xml/xmlwriter.h" -void build_commands_write( const char* filename ){ - TextFileOutputStream projectFile( filename ); - if ( !projectFile.failed() ) { - XMLStreamWriter writer( projectFile ); - ProjectXMLExporter projectExporter( g_build_project, g_build_tools ); - writer << "\n"; - projectExporter.exportXML( writer ); - writer << "\n"; - } +void build_commands_write(const char *filename) +{ + TextFileOutputStream projectFile(filename); + if (!projectFile.failed()) { + XMLStreamWriter writer(projectFile); + ProjectXMLExporter projectExporter(g_build_project, g_build_tools); + writer << "\n"; + projectExporter.exportXML(writer); + writer << "\n"; + } } @@ -633,335 +697,336 @@ void build_commands_write( const char* filename ){ #include "gtkutil/window.h" #include "gtkdlgs.h" -void Build_refreshMenu( ui::Menu menu ); +void Build_refreshMenu(ui::Menu menu); -void BSPCommandList_Construct( ui::ListStore store, Project& project ){ - store.clear(); +void BSPCommandList_Construct(ui::ListStore store, Project &project) +{ + store.clear(); - for ( Project::iterator i = project.begin(); i != project.end(); ++i ) - { - store.append(0, (*i).first.c_str()); - } + for (Project::iterator i = project.begin(); i != project.end(); ++i) { + store.append(0, (*i).first.c_str()); + } - store.append(); + store.append(); } -class ProjectList -{ +class ProjectList { public: -Project& m_project; -ui::ListStore m_store{ui::null}; -bool m_changed; -ProjectList( Project& project ) : m_project( project ), m_changed( false ){ -} + Project &m_project; + ui::ListStore m_store{ui::null}; + bool m_changed; + + ProjectList(Project &project) : m_project(project), m_changed(false) + { + } }; -gboolean project_cell_edited(ui::CellRendererText cell, gchar* path_string, gchar* new_text, ProjectList* projectList ){ - Project& project = projectList->m_project; +gboolean project_cell_edited(ui::CellRendererText cell, gchar *path_string, gchar *new_text, ProjectList *projectList) +{ + Project &project = projectList->m_project; - auto path = ui::TreePath( path_string ); + auto path = ui::TreePath(path_string); - ASSERT_MESSAGE( gtk_tree_path_get_depth( path ) == 1, "invalid path length" ); + ASSERT_MESSAGE(gtk_tree_path_get_depth(path) == 1, "invalid path length"); - GtkTreeIter iter; - gtk_tree_model_get_iter(projectList->m_store, &iter, path ); + GtkTreeIter iter; + gtk_tree_model_get_iter(projectList->m_store, &iter, path); - Project::iterator i = Project_find( project, gtk_tree_path_get_indices( path )[0] ); - if ( i != project.end() ) { - projectList->m_changed = true; - if ( string_empty( new_text ) ) { - project.erase( i ); - gtk_list_store_remove( projectList->m_store, &iter ); - } - else - { - ( *i ).first = new_text; - gtk_list_store_set( projectList->m_store, &iter, 0, new_text, -1 ); - } - } - else if ( !string_empty( new_text ) ) { - projectList->m_changed = true; - project.push_back( Project::value_type( new_text, Build() ) ); + Project::iterator i = Project_find(project, gtk_tree_path_get_indices(path)[0]); + if (i != project.end()) { + projectList->m_changed = true; + if (string_empty(new_text)) { + project.erase(i); + gtk_list_store_remove(projectList->m_store, &iter); + } else { + (*i).first = new_text; + gtk_list_store_set(projectList->m_store, &iter, 0, new_text, -1); + } + } else if (!string_empty(new_text)) { + projectList->m_changed = true; + project.push_back(Project::value_type(new_text, Build())); - gtk_list_store_set( projectList->m_store, &iter, 0, new_text, -1 ); - projectList->m_store.append(); - } + gtk_list_store_set(projectList->m_store, &iter, 0, new_text, -1); + projectList->m_store.append(); + } - gtk_tree_path_free( path ); + gtk_tree_path_free(path); - Build_refreshMenu( g_bsp_menu ); + Build_refreshMenu(g_bsp_menu); - return FALSE; + return FALSE; } -gboolean project_key_press( ui::TreeView widget, GdkEventKey* event, ProjectList* projectList ){ - Project& project = projectList->m_project; - - if ( event->keyval == GDK_KEY_Delete ) { - auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(widget)); - GtkTreeIter iter; - GtkTreeModel* model; - if ( gtk_tree_selection_get_selected( selection, &model, &iter ) ) { - auto path = gtk_tree_model_get_path( model, &iter ); - Project::iterator x = Project_find( project, gtk_tree_path_get_indices( path )[0] ); - gtk_tree_path_free( path ); - - if ( x != project.end() ) { - projectList->m_changed = true; - project.erase( x ); - Build_refreshMenu( g_bsp_menu ); - - gtk_list_store_remove( projectList->m_store, &iter ); - } - } - } - return FALSE; +gboolean project_key_press(ui::TreeView widget, GdkEventKey *event, ProjectList *projectList) +{ + Project &project = projectList->m_project; + + if (event->keyval == GDK_KEY_Delete) { + auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(widget)); + GtkTreeIter iter; + GtkTreeModel *model; + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { + auto path = gtk_tree_model_get_path(model, &iter); + Project::iterator x = Project_find(project, gtk_tree_path_get_indices(path)[0]); + gtk_tree_path_free(path); + + if (x != project.end()) { + projectList->m_changed = true; + project.erase(x); + Build_refreshMenu(g_bsp_menu); + + gtk_list_store_remove(projectList->m_store, &iter); + } + } + } + return FALSE; } -Build* g_current_build = 0; - -gboolean project_selection_changed( ui::TreeSelection selection, ui::ListStore store ){ - Project& project = g_build_project; - - store.clear(); - - GtkTreeIter iter; - GtkTreeModel* model; - if ( gtk_tree_selection_get_selected( selection, &model, &iter ) ) { - auto path = gtk_tree_model_get_path( model, &iter ); - Project::iterator x = Project_find( project, gtk_tree_path_get_indices( path )[0] ); - gtk_tree_path_free( path ); - - if ( x != project.end() ) { - Build& build = ( *x ).second; - g_current_build = &build; - - for ( Build::iterator i = build.begin(); i != build.end(); ++i ) - { - store.append(0, (*i).c_str()); - } - store.append(); - } - else - { - g_current_build = 0; - } - } - else - { - g_current_build = 0; - } - - return FALSE; +Build *g_current_build = 0; + +gboolean project_selection_changed(ui::TreeSelection selection, ui::ListStore store) +{ + Project &project = g_build_project; + + store.clear(); + + GtkTreeIter iter; + GtkTreeModel *model; + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { + auto path = gtk_tree_model_get_path(model, &iter); + Project::iterator x = Project_find(project, gtk_tree_path_get_indices(path)[0]); + gtk_tree_path_free(path); + + if (x != project.end()) { + Build &build = (*x).second; + g_current_build = &build; + + for (Build::iterator i = build.begin(); i != build.end(); ++i) { + store.append(0, (*i).c_str()); + } + store.append(); + } else { + g_current_build = 0; + } + } else { + g_current_build = 0; + } + + return FALSE; } -gboolean commands_cell_edited(ui::CellRendererText cell, gchar* path_string, gchar* new_text, ui::ListStore store ){ - if ( g_current_build == 0 ) { - return FALSE; - } - Build& build = *g_current_build; +gboolean commands_cell_edited(ui::CellRendererText cell, gchar *path_string, gchar *new_text, ui::ListStore store) +{ + if (g_current_build == 0) { + return FALSE; + } + Build &build = *g_current_build; - auto path = ui::TreePath( path_string ); + auto path = ui::TreePath(path_string); - ASSERT_MESSAGE( gtk_tree_path_get_depth( path ) == 1, "invalid path length" ); + ASSERT_MESSAGE(gtk_tree_path_get_depth(path) == 1, "invalid path length"); - GtkTreeIter iter; - gtk_tree_model_get_iter(store, &iter, path ); + GtkTreeIter iter; + gtk_tree_model_get_iter(store, &iter, path); - Build::iterator i = Build_find( build, gtk_tree_path_get_indices( path )[0] ); - if ( i != build.end() ) { - g_build_changed = true; - ( *i ).setString( new_text ); + Build::iterator i = Build_find(build, gtk_tree_path_get_indices(path)[0]); + if (i != build.end()) { + g_build_changed = true; + (*i).setString(new_text); - gtk_list_store_set( store, &iter, 0, new_text, -1 ); - } - else if ( !string_empty( new_text ) ) { - g_build_changed = true; - build.push_back( Build::value_type( VariableString( new_text ) ) ); + gtk_list_store_set(store, &iter, 0, new_text, -1); + } else if (!string_empty(new_text)) { + g_build_changed = true; + build.push_back(Build::value_type(VariableString(new_text))); - gtk_list_store_set( store, &iter, 0, new_text, -1 ); + gtk_list_store_set(store, &iter, 0, new_text, -1); - store.append(); - } + store.append(); + } - gtk_tree_path_free( path ); + gtk_tree_path_free(path); - Build_refreshMenu( g_bsp_menu ); + Build_refreshMenu(g_bsp_menu); - return FALSE; + return FALSE; } -gboolean commands_key_press( ui::TreeView widget, GdkEventKey* event, ui::ListStore store ){ - if ( g_current_build == 0 ) { - return FALSE; - } - Build& build = *g_current_build; - - if ( event->keyval == GDK_KEY_Delete ) { - auto selection = gtk_tree_view_get_selection(widget ); - GtkTreeIter iter; - GtkTreeModel* model; - if ( gtk_tree_selection_get_selected( selection, &model, &iter ) ) { - auto path = gtk_tree_model_get_path( model, &iter ); - Build::iterator i = Build_find( build, gtk_tree_path_get_indices( path )[0] ); - gtk_tree_path_free( path ); - - if ( i != build.end() ) { - g_build_changed = true; - build.erase( i ); - - gtk_list_store_remove( store, &iter ); - } - } - } - return FALSE; -} +gboolean commands_key_press(ui::TreeView widget, GdkEventKey *event, ui::ListStore store) +{ + if (g_current_build == 0) { + return FALSE; + } + Build &build = *g_current_build; + if (event->keyval == GDK_KEY_Delete) { + auto selection = gtk_tree_view_get_selection(widget); + GtkTreeIter iter; + GtkTreeModel *model; + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { + auto path = gtk_tree_model_get_path(model, &iter); + Build::iterator i = Build_find(build, gtk_tree_path_get_indices(path)[0]); + gtk_tree_path_free(path); -ui::Window BuildMenuDialog_construct( ModalDialog& modal, ProjectList& projectList ){ - ui::Window window = MainFrame_getWindow().create_dialog_window("Build Menu", G_CALLBACK(dialog_delete_callback ), &modal, -1, 400 ); + if (i != build.end()) { + g_build_changed = true; + build.erase(i); - { - auto table1 = create_dialog_table( 2, 2, 4, 4, 4 ); - window.add(table1); - { - auto vbox = create_dialog_vbox( 4 ); + gtk_list_store_remove(store, &iter); + } + } + } + return FALSE; +} + + +ui::Window BuildMenuDialog_construct(ModalDialog &modal, ProjectList &projectList) +{ + ui::Window window = MainFrame_getWindow().create_dialog_window("Build Menu", G_CALLBACK(dialog_delete_callback), + &modal, -1, 400); + + { + auto table1 = create_dialog_table(2, 2, 4, 4, 4); + window.add(table1); + { + auto vbox = create_dialog_vbox(4); table1.attach(vbox, {1, 2, 0, 1}, {GTK_FILL, GTK_FILL}); - { - auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &modal ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - } - { - auto button = create_dialog_button( "Cancel", G_CALLBACK( dialog_button_cancel ), &modal ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - } - } - auto buildViewStore = ui::ListStore::from(gtk_list_store_new( 1, G_TYPE_STRING )); - auto buildView = ui::TreeView( ui::TreeModel::from( buildViewStore._handle )); - { - auto frame = create_dialog_frame( "Build menu" ); + { + auto button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &modal); + vbox.pack_start(button, FALSE, FALSE, 0); + } + { + auto button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &modal); + vbox.pack_start(button, FALSE, FALSE, 0); + } + } + auto buildViewStore = ui::ListStore::from(gtk_list_store_new(1, G_TYPE_STRING)); + auto buildView = ui::TreeView(ui::TreeModel::from(buildViewStore._handle)); + { + auto frame = create_dialog_frame("Build menu"); table1.attach(frame, {0, 1, 0, 1}); - { - auto scr = create_scrolled_window( ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4 ); - frame.add(scr); + { + auto scr = create_scrolled_window(ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4); + frame.add(scr); - { - auto view = buildView; - auto store = buildViewStore; - gtk_tree_view_set_headers_visible(view, FALSE ); + { + auto view = buildView; + auto store = buildViewStore; + gtk_tree_view_set_headers_visible(view, FALSE); - auto renderer = ui::CellRendererText(ui::New); - object_set_boolean_property( G_OBJECT( renderer ), "editable", TRUE ); - renderer.connect("edited", G_CALLBACK( project_cell_edited ), &projectList ); + auto renderer = ui::CellRendererText(ui::New); + object_set_boolean_property(G_OBJECT(renderer), "editable", TRUE); + renderer.connect("edited", G_CALLBACK(project_cell_edited), &projectList); - auto column = ui::TreeViewColumn( "", renderer, {{"text", 0}} ); - gtk_tree_view_append_column(view, column ); + auto column = ui::TreeViewColumn("", renderer, {{"text", 0}}); + gtk_tree_view_append_column(view, column); - auto selection = gtk_tree_view_get_selection(view ); - gtk_tree_selection_set_mode( selection, GTK_SELECTION_BROWSE ); + auto selection = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); - view.show(); + view.show(); - projectList.m_store = store; - scr.add(view); + projectList.m_store = store; + scr.add(view); - view.connect( "key_press_event", G_CALLBACK( project_key_press ), &projectList ); + view.connect("key_press_event", G_CALLBACK(project_key_press), &projectList); - store.unref(); - } - } - } - { - auto frame = create_dialog_frame( "Commandline" ); + store.unref(); + } + } + } + { + auto frame = create_dialog_frame("Commandline"); table1.attach(frame, {0, 1, 1, 2}); - { - auto scr = create_scrolled_window( ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4 ); - frame.add(scr); + { + auto scr = create_scrolled_window(ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4); + frame.add(scr); - { - auto store = ui::ListStore::from(gtk_list_store_new( 1, G_TYPE_STRING )); + { + auto store = ui::ListStore::from(gtk_list_store_new(1, G_TYPE_STRING)); - auto view = ui::TreeView(ui::TreeModel::from( store._handle )); - gtk_tree_view_set_headers_visible(view, FALSE ); + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_headers_visible(view, FALSE); - auto renderer = ui::CellRendererText(ui::New); - object_set_boolean_property( G_OBJECT( renderer ), "editable", TRUE ); - renderer.connect( "edited", G_CALLBACK( commands_cell_edited ), store ); + auto renderer = ui::CellRendererText(ui::New); + object_set_boolean_property(G_OBJECT(renderer), "editable", TRUE); + renderer.connect("edited", G_CALLBACK(commands_cell_edited), store); - auto column = ui::TreeViewColumn( "", renderer, {{"text", 0}} ); - gtk_tree_view_append_column(view, column ); + auto column = ui::TreeViewColumn("", renderer, {{"text", 0}}); + gtk_tree_view_append_column(view, column); - auto selection = gtk_tree_view_get_selection(view ); - gtk_tree_selection_set_mode( selection, GTK_SELECTION_BROWSE ); + auto selection = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); - view.show(); + view.show(); - scr.add(view); + scr.add(view); - store.unref(); + store.unref(); - view.connect( "key_press_event", G_CALLBACK( commands_key_press ), store ); + view.connect("key_press_event", G_CALLBACK(commands_key_press), store); - auto sel = ui::TreeSelection::from(gtk_tree_view_get_selection(buildView )); - sel.connect( "changed", G_CALLBACK( project_selection_changed ), store ); - } - } - } - } + auto sel = ui::TreeSelection::from(gtk_tree_view_get_selection(buildView)); + sel.connect("changed", G_CALLBACK(project_selection_changed), store); + } + } + } + } - BSPCommandList_Construct( projectList.m_store, g_build_project ); + BSPCommandList_Construct(projectList.m_store, g_build_project); - return window; + return window; } -namespace -{ -CopiedString g_buildMenu; +namespace { + CopiedString g_buildMenu; } void LoadBuildMenu(); -void DoBuildMenu(){ - ModalDialog modal; +void DoBuildMenu() +{ + ModalDialog modal; - ProjectList projectList( g_build_project ); + ProjectList projectList(g_build_project); - ui::Window window = BuildMenuDialog_construct( modal, projectList ); + ui::Window window = BuildMenuDialog_construct(modal, projectList); - if ( modal_dialog_show( window, modal ) == eIDCANCEL ) { - build_commands_clear(); - LoadBuildMenu(); + if (modal_dialog_show(window, modal) == eIDCANCEL) { + build_commands_clear(); + LoadBuildMenu(); - Build_refreshMenu( g_bsp_menu ); - } - else if ( projectList.m_changed ) { - g_build_changed = true; - } + Build_refreshMenu(g_bsp_menu); + } else if (projectList.m_changed) { + g_build_changed = true; + } - window.destroy(); + window.destroy(); } - #include "gtkutil/menu.h" #include "mainframe.h" #include "preferences.h" #include "qe3.h" -class BuildMenuItem -{ -const char* m_name; +class BuildMenuItem { + const char *m_name; public: -ui::MenuItem m_item; -BuildMenuItem( const char* name, ui::MenuItem item ) - : m_name( name ), m_item( item ){ -} -void run(){ - RunBSP( m_name ); -} -typedef MemberCaller RunCaller; + ui::MenuItem m_item; + + BuildMenuItem(const char *name, ui::MenuItem item) + : m_name(name), m_item(item) + { + } + + void run() + { + RunBSP(m_name); + } + + typedef MemberCaller RunCaller; }; typedef std::list BuildMenuItems; @@ -970,65 +1035,70 @@ BuildMenuItems g_BuildMenuItems; ui::Menu g_bsp_menu{ui::null}; -void Build_constructMenu( ui::Menu menu ){ - for ( Project::iterator i = g_build_project.begin(); i != g_build_project.end(); ++i ) - { - g_BuildMenuItems.push_back( BuildMenuItem( ( *i ).first.c_str(), ui::MenuItem(ui::null) ) ); - if ( is_separator( *i ) ) { - g_BuildMenuItems.back().m_item = menu_separator( menu ); - } - else - { - g_BuildMenuItems.back().m_item = create_menu_item_with_mnemonic( menu, ( *i ).first.c_str(), BuildMenuItem::RunCaller( g_BuildMenuItems.back() ) ); - } - } +void Build_constructMenu(ui::Menu menu) +{ + for (Project::iterator i = g_build_project.begin(); i != g_build_project.end(); ++i) { + g_BuildMenuItems.push_back(BuildMenuItem((*i).first.c_str(), ui::MenuItem(ui::null))); + if (is_separator(*i)) { + g_BuildMenuItems.back().m_item = menu_separator(menu); + } else { + g_BuildMenuItems.back().m_item = create_menu_item_with_mnemonic(menu, (*i).first.c_str(), + BuildMenuItem::RunCaller( + g_BuildMenuItems.back())); + } + } } -void Build_refreshMenu( ui::Menu menu ){ - for (auto i = g_BuildMenuItems.begin(); i != g_BuildMenuItems.end(); ++i ) - { - menu.remove(ui::MenuItem(i->m_item)); - } +void Build_refreshMenu(ui::Menu menu) +{ + for (auto i = g_BuildMenuItems.begin(); i != g_BuildMenuItems.end(); ++i) { + menu.remove(ui::MenuItem(i->m_item)); + } - g_BuildMenuItems.clear(); + g_BuildMenuItems.clear(); - Build_constructMenu( menu ); + Build_constructMenu(menu); } -void LoadBuildMenu(){ - if ( string_empty( g_buildMenu.c_str() ) || !build_commands_parse( g_buildMenu.c_str() ) ) { - { - StringOutputStream buffer( 256 ); - buffer << GameToolsPath_get() << "default_build_menu.xml"; +void LoadBuildMenu() +{ + if (string_empty(g_buildMenu.c_str()) || !build_commands_parse(g_buildMenu.c_str())) { + { + StringOutputStream buffer(256); + buffer << GameToolsPath_get() << "default_build_menu.xml"; - bool success = build_commands_parse( buffer.c_str() ); - ASSERT_MESSAGE( success, "failed to parse default build commands: " << buffer.c_str() ); - } - { - StringOutputStream buffer( 256 ); - buffer << SettingsPath_get() << g_pGameDescription->mGameFile.c_str() << "/build_menu.xml"; + bool success = build_commands_parse(buffer.c_str()); + ASSERT_MESSAGE(success, "failed to parse default build commands: " << buffer.c_str()); + } + { + StringOutputStream buffer(256); + buffer << SettingsPath_get() << g_pGameDescription->mGameFile.c_str() << "/build_menu.xml"; - g_buildMenu = buffer.c_str(); - } - } + g_buildMenu = buffer.c_str(); + } + } } -void SaveBuildMenu(){ - if ( g_build_changed ) { - g_build_changed = false; - build_commands_write( g_buildMenu.c_str() ); - } +void SaveBuildMenu() +{ + if (g_build_changed) { + g_build_changed = false; + build_commands_write(g_buildMenu.c_str()); + } } #include "preferencesystem.h" #include "stringio.h" -void BuildMenu_Construct(){ - GlobalPreferenceSystem().registerPreference( "BuildMenu", make_property_string( g_buildMenu ) ); - LoadBuildMenu(); +void BuildMenu_Construct() +{ + GlobalPreferenceSystem().registerPreference("BuildMenu", make_property_string(g_buildMenu)); + LoadBuildMenu(); } -void BuildMenu_Destroy(){ - SaveBuildMenu(); + +void BuildMenu_Destroy() +{ + SaveBuildMenu(); } diff --git a/radiant/build.h b/radiant/build.h index 4e494146..3419f0a7 100644 --- a/radiant/build.h +++ b/radiant/build.h @@ -23,22 +23,25 @@ #if !defined( INCLUDED_BUILD_H ) #define INCLUDED_BUILD_H -void build_set_variable( const char* name, const char* value ); +void build_set_variable(const char *name, const char *value); + void build_clear_variables(); -class CommandListener -{ +class CommandListener { public: -virtual void execute( const char* command ) = 0; + virtual void execute(const char *command) = 0; }; -void build_run( const char* name, CommandListener& listener ); + +void build_run(const char *name, CommandListener &listener); void DoBuildMenu(); void BuildMenu_Construct(); + void BuildMenu_Destroy(); -void Build_constructMenu( ui::Menu menu ); +void Build_constructMenu(ui::Menu menu); + extern ui::Menu g_bsp_menu; diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp index 04110ee7..a3ead2fd 100644 --- a/radiant/camwindow.cpp +++ b/radiant/camwindow.cpp @@ -65,36 +65,38 @@ Signal0 g_cameraMoved_callbacks; -void AddCameraMovedCallback( const SignalHandler& handler ){ - g_cameraMoved_callbacks.connectLast( handler ); -} - -void CameraMovedNotify(){ - g_cameraMoved_callbacks(); +void AddCameraMovedCallback(const SignalHandler &handler) +{ + g_cameraMoved_callbacks.connectLast(handler); } - -struct camwindow_globals_private_t +void CameraMovedNotify() { - int m_nMoveSpeed; - bool m_bCamLinkSpeed; - int m_nAngleSpeed; - bool m_bCamInverseMouse; - bool m_bCamDiscrete; - bool m_bCubicClipping; - bool m_showStats; - int m_nStrafeMode; - - camwindow_globals_private_t() : - m_nMoveSpeed( 100 ), - m_bCamLinkSpeed( true ), - m_nAngleSpeed( 3 ), - m_bCamInverseMouse( false ), - m_bCamDiscrete( true ), - m_bCubicClipping( true ), - m_showStats( true ), - m_nStrafeMode( 0 ){ - } + g_cameraMoved_callbacks(); +} + + +struct camwindow_globals_private_t { + int m_nMoveSpeed; + bool m_bCamLinkSpeed; + int m_nAngleSpeed; + bool m_bCamInverseMouse; + bool m_bCamDiscrete; + bool m_bCubicClipping; + bool m_showStats; + int m_nStrafeMode; + + camwindow_globals_private_t() : + m_nMoveSpeed(100), + m_bCamLinkSpeed(true), + m_nAngleSpeed(3), + m_bCamInverseMouse(false), + m_bCamDiscrete(true), + m_bCubicClipping(true), + m_showStats(true), + m_nStrafeMode(0) + { + } }; @@ -102,255 +104,264 @@ camwindow_globals_private_t g_camwindow_globals_private; const Matrix4 g_opengl2radiant( - 0, 0,-1, 0, - -1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 1 - ); + 0, 0, -1, 0, + -1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 1 +); const Matrix4 g_radiant2opengl( - 0,-1, 0, 0, - 0, 0, 1, 0, - -1, 0, 0, 0, - 0, 0, 0, 1 - ); + 0, -1, 0, 0, + 0, 0, 1, 0, + -1, 0, 0, 0, + 0, 0, 0, 1 +); struct camera_t; -void Camera_mouseMove( camera_t& camera, int x, int y ); -enum camera_draw_mode -{ - cd_wire, - cd_solid, - cd_texture, - cd_lighting +void Camera_mouseMove(camera_t &camera, int x, int y); + +enum camera_draw_mode { + cd_wire, + cd_solid, + cd_texture, + cd_lighting }; -struct camera_t -{ - int width, height; +struct camera_t { + int width, height; - bool timing; + bool timing; - Vector3 origin; - Vector3 angles; + Vector3 origin; + Vector3 angles; - Vector3 color; // background + Vector3 color; // background - Vector3 forward, right; // move matrix (TTimo: used to have up but it was not updated) - Vector3 vup, vpn, vright; // view matrix (taken from the modelview matrix) + Vector3 forward, right; // move matrix (TTimo: used to have up but it was not updated) + Vector3 vup, vpn, vright; // view matrix (taken from the modelview matrix) - Matrix4 projection; - Matrix4 modelview; + Matrix4 projection; + Matrix4 modelview; - bool m_strafe; // true when in strafemode toggled by the ctrl-key - bool m_strafe_forward; // true when in strafemode by ctrl-key and shift is pressed for forward strafing + bool m_strafe; // true when in strafemode toggled by the ctrl-key + bool m_strafe_forward; // true when in strafemode by ctrl-key and shift is pressed for forward strafing - unsigned int movementflags; // movement flags - Timer m_keycontrol_timer; - guint m_keymove_handler; + unsigned int movementflags; // movement flags + Timer m_keycontrol_timer; + guint m_keymove_handler; - float fieldOfView; + float fieldOfView; - DeferredMotionDelta m_mouseMove; + DeferredMotionDelta m_mouseMove; - static void motionDelta( int x, int y, void* data ){ - Camera_mouseMove( *reinterpret_cast( data ), x, y ); - } + static void motionDelta(int x, int y, void *data) + { + Camera_mouseMove(*reinterpret_cast( data ), x, y); + } - View* m_view; - Callback m_update; - - static camera_draw_mode draw_mode; - - camera_t( View* view, const Callback& update ) - : width( 0 ), - height( 0 ), - timing( false ), - origin( 0, 0, 0 ), - angles( 0, 0, 0 ), - color( 0, 0, 0 ), - movementflags( 0 ), - m_keymove_handler( 0 ), - fieldOfView( 90.0f ), - m_mouseMove( motionDelta, this ), - m_view( view ), - m_update( update ){ - } + View *m_view; + Callback m_update; + + static camera_draw_mode draw_mode; + + camera_t(View *view, const Callback &update) + : width(0), + height(0), + timing(false), + origin(0, 0, 0), + angles(0, 0, 0), + color(0, 0, 0), + movementflags(0), + m_keymove_handler(0), + fieldOfView(90.0f), + m_mouseMove(motionDelta, this), + m_view(view), + m_update(update) + { + } }; camera_draw_mode camera_t::draw_mode = cd_texture; -inline Matrix4 projection_for_camera( float near_z, float far_z, float fieldOfView, int width, int height ){ - const float half_width = static_cast( near_z * tan( degrees_to_radians( fieldOfView * 0.5 ) ) ); - const float half_height = half_width * ( static_cast( height ) / static_cast( width ) ); +inline Matrix4 projection_for_camera(float near_z, float far_z, float fieldOfView, int width, int height) +{ + const float half_width = static_cast( near_z * tan(degrees_to_radians(fieldOfView * 0.5))); + const float half_height = half_width * (static_cast( height ) / static_cast( width )); - return matrix4_frustum( - -half_width, - half_width, - -half_height, - half_height, - near_z, - far_z - ); + return matrix4_frustum( + -half_width, + half_width, + -half_height, + half_height, + near_z, + far_z + ); } -float Camera_getFarClipPlane( camera_t& camera ){ - return ( g_camwindow_globals_private.m_bCubicClipping ) ? pow( 2.0, ( g_camwindow_globals.m_nCubicScale + 7 ) / 2.0 ) : 32768.0f; +float Camera_getFarClipPlane(camera_t &camera) +{ + return (g_camwindow_globals_private.m_bCubicClipping) ? pow(2.0, (g_camwindow_globals.m_nCubicScale + 7) / 2.0) + : 32768.0f; } -void Camera_updateProjection( camera_t& camera ){ - float farClip = Camera_getFarClipPlane( camera ); - camera.projection = projection_for_camera( farClip / 4096.0f, farClip, camera.fieldOfView, camera.width, camera.height ); +void Camera_updateProjection(camera_t &camera) +{ + float farClip = Camera_getFarClipPlane(camera); + camera.projection = projection_for_camera(farClip / 4096.0f, farClip, camera.fieldOfView, camera.width, + camera.height); - camera.m_view->Construct( camera.projection, camera.modelview, camera.width, camera.height ); + camera.m_view->Construct(camera.projection, camera.modelview, camera.width, camera.height); } -void Camera_updateVectors( camera_t& camera ){ - for ( int i = 0 ; i < 3 ; i++ ) - { - camera.vright[i] = camera.modelview[( i << 2 ) + 0]; - camera.vup[i] = camera.modelview[( i << 2 ) + 1]; - camera.vpn[i] = camera.modelview[( i << 2 ) + 2]; - } +void Camera_updateVectors(camera_t &camera) +{ + for (int i = 0; i < 3; i++) { + camera.vright[i] = camera.modelview[(i << 2) + 0]; + camera.vup[i] = camera.modelview[(i << 2) + 1]; + camera.vpn[i] = camera.modelview[(i << 2) + 2]; + } } -void Camera_updateModelview( camera_t& camera ){ - camera.modelview = g_matrix4_identity; +void Camera_updateModelview(camera_t &camera) +{ + camera.modelview = g_matrix4_identity; - // roll, pitch, yaw - Vector3 radiant_eulerXYZ( 0, -camera.angles[CAMERA_PITCH], camera.angles[CAMERA_YAW] ); + // roll, pitch, yaw + Vector3 radiant_eulerXYZ(0, -camera.angles[CAMERA_PITCH], camera.angles[CAMERA_YAW]); - matrix4_translate_by_vec3( camera.modelview, camera.origin ); - matrix4_rotate_by_euler_xyz_degrees( camera.modelview, radiant_eulerXYZ ); - matrix4_multiply_by_matrix4( camera.modelview, g_radiant2opengl ); - matrix4_affine_invert( camera.modelview ); + matrix4_translate_by_vec3(camera.modelview, camera.origin); + matrix4_rotate_by_euler_xyz_degrees(camera.modelview, radiant_eulerXYZ); + matrix4_multiply_by_matrix4(camera.modelview, g_radiant2opengl); + matrix4_affine_invert(camera.modelview); - Camera_updateVectors( camera ); + Camera_updateVectors(camera); - camera.m_view->Construct( camera.projection, camera.modelview, camera.width, camera.height ); + camera.m_view->Construct(camera.projection, camera.modelview, camera.width, camera.height); } -void Camera_Move_updateAxes( camera_t& camera ){ - double ya = degrees_to_radians( camera.angles[CAMERA_YAW] ); +void Camera_Move_updateAxes(camera_t &camera) +{ + double ya = degrees_to_radians(camera.angles[CAMERA_YAW]); - // the movement matrix is kept 2d - camera.forward[0] = static_cast( cos( ya ) ); - camera.forward[1] = static_cast( sin( ya ) ); - camera.forward[2] = 0; - camera.right[0] = camera.forward[1]; - camera.right[1] = -camera.forward[0]; + // the movement matrix is kept 2d + camera.forward[0] = static_cast( cos(ya)); + camera.forward[1] = static_cast( sin(ya)); + camera.forward[2] = 0; + camera.right[0] = camera.forward[1]; + camera.right[1] = -camera.forward[0]; } -void Camera_Freemove_updateAxes( camera_t& camera ){ - camera.right = camera.vright; - camera.forward = vector3_negated( camera.vpn ); +void Camera_Freemove_updateAxes(camera_t &camera) +{ + camera.right = camera.vright; + camera.forward = vector3_negated(camera.vpn); } -const Vector3& Camera_getOrigin( camera_t& camera ){ - return camera.origin; +const Vector3 &Camera_getOrigin(camera_t &camera) +{ + return camera.origin; } -void Camera_setOrigin( camera_t& camera, const Vector3& origin ){ - camera.origin = origin; - Camera_updateModelview( camera ); - camera.m_update(); - CameraMovedNotify(); +void Camera_setOrigin(camera_t &camera, const Vector3 &origin) +{ + camera.origin = origin; + Camera_updateModelview(camera); + camera.m_update(); + CameraMovedNotify(); } -const Vector3& Camera_getAngles( camera_t& camera ){ - return camera.angles; +const Vector3 &Camera_getAngles(camera_t &camera) +{ + return camera.angles; } -void Camera_setAngles( camera_t& camera, const Vector3& angles ){ - camera.angles = angles; - Camera_updateModelview( camera ); - camera.m_update(); - CameraMovedNotify(); +void Camera_setAngles(camera_t &camera, const Vector3 &angles) +{ + camera.angles = angles; + Camera_updateModelview(camera); + camera.m_update(); + CameraMovedNotify(); } -void Camera_FreeMove( camera_t& camera, int dx, int dy ){ - // free strafe mode, toggled by the ctrl key with optional shift for forward movement - if ( camera.m_strafe ) { - float strafespeed = 0.65f; - - if ( g_camwindow_globals_private.m_bCamLinkSpeed ) { - strafespeed = (float)g_camwindow_globals_private.m_nMoveSpeed / 100; - } - - camera.origin -= camera.vright * strafespeed * dx; - if ( camera.m_strafe_forward ) { - camera.origin += camera.vpn * strafespeed * dy; - } - else{ - camera.origin += camera.vup * strafespeed * dy; - } - } - else // free rotation - { - const float dtime = 0.1f; - - if ( g_camwindow_globals_private.m_bCamInverseMouse ) { - camera.angles[CAMERA_PITCH] -= dy * dtime * g_camwindow_globals_private.m_nAngleSpeed; - } - else{ - camera.angles[CAMERA_PITCH] += dy * dtime * g_camwindow_globals_private.m_nAngleSpeed; - } - - camera.angles[CAMERA_YAW] += dx * dtime * g_camwindow_globals_private.m_nAngleSpeed; - - if ( camera.angles[CAMERA_PITCH] > 90 ) { - camera.angles[CAMERA_PITCH] = 90; - } - else if ( camera.angles[CAMERA_PITCH] < -90 ) { - camera.angles[CAMERA_PITCH] = -90; - } - - if ( camera.angles[CAMERA_YAW] >= 360 ) { - camera.angles[CAMERA_YAW] -= 360; - } - else if ( camera.angles[CAMERA_YAW] <= 0 ) { - camera.angles[CAMERA_YAW] += 360; - } - } - - Camera_updateModelview( camera ); - Camera_Freemove_updateAxes( camera ); -} - -void Cam_MouseControl( camera_t& camera, int x, int y ){ - float xf = (float)( x - camera.width / 2 ) / ( camera.width / 2 ); - float yf = (float)( y - camera.height / 2 ) / ( camera.height / 2 ); +void Camera_FreeMove(camera_t &camera, int dx, int dy) +{ + // free strafe mode, toggled by the ctrl key with optional shift for forward movement + if (camera.m_strafe) { + float strafespeed = 0.65f; + + if (g_camwindow_globals_private.m_bCamLinkSpeed) { + strafespeed = (float) g_camwindow_globals_private.m_nMoveSpeed / 100; + } + + camera.origin -= camera.vright * strafespeed * dx; + if (camera.m_strafe_forward) { + camera.origin += camera.vpn * strafespeed * dy; + } else { + camera.origin += camera.vup * strafespeed * dy; + } + } else // free rotation + { + const float dtime = 0.1f; + + if (g_camwindow_globals_private.m_bCamInverseMouse) { + camera.angles[CAMERA_PITCH] -= dy * dtime * g_camwindow_globals_private.m_nAngleSpeed; + } else { + camera.angles[CAMERA_PITCH] += dy * dtime * g_camwindow_globals_private.m_nAngleSpeed; + } + + camera.angles[CAMERA_YAW] += dx * dtime * g_camwindow_globals_private.m_nAngleSpeed; + + if (camera.angles[CAMERA_PITCH] > 90) { + camera.angles[CAMERA_PITCH] = 90; + } else if (camera.angles[CAMERA_PITCH] < -90) { + camera.angles[CAMERA_PITCH] = -90; + } + + if (camera.angles[CAMERA_YAW] >= 360) { + camera.angles[CAMERA_YAW] -= 360; + } else if (camera.angles[CAMERA_YAW] <= 0) { + camera.angles[CAMERA_YAW] += 360; + } + } + + Camera_updateModelview(camera); + Camera_Freemove_updateAxes(camera); +} + +void Cam_MouseControl(camera_t &camera, int x, int y) +{ + float xf = (float) (x - camera.width / 2) / (camera.width / 2); + float yf = (float) (y - camera.height / 2) / (camera.height / 2); - xf *= 1.0f - fabsf( yf ); - if ( xf < 0 ) { - xf += 0.1f; - if ( xf > 0 ) { - xf = 0; - } - } - else - { - xf -= 0.1f; - if ( xf < 0 ) { - xf = 0; - } - } + xf *= 1.0f - fabsf(yf); + if (xf < 0) { + xf += 0.1f; + if (xf > 0) { + xf = 0; + } + } else { + xf -= 0.1f; + if (xf < 0) { + xf = 0; + } + } - vector3_add( camera.origin, vector3_scaled( camera.forward, yf * 0.1f * g_camwindow_globals_private.m_nMoveSpeed ) ); - camera.angles[CAMERA_YAW] += xf * -0.1f * g_camwindow_globals_private.m_nAngleSpeed; + vector3_add(camera.origin, vector3_scaled(camera.forward, yf * 0.1f * g_camwindow_globals_private.m_nMoveSpeed)); + camera.angles[CAMERA_YAW] += xf * -0.1f * g_camwindow_globals_private.m_nAngleSpeed; - Camera_updateModelview( camera ); + Camera_updateModelview(camera); } -void Camera_mouseMove( camera_t& camera, int x, int y ){ - //globalOutputStream() << "mousemove... "; - Camera_FreeMove( camera, -x, -y ); - camera.m_update(); - CameraMovedNotify(); +void Camera_mouseMove(camera_t &camera, int x, int y) +{ + //globalOutputStream() << "mousemove... "; + Camera_FreeMove(camera, -x, -y); + camera.m_update(); + CameraMovedNotify(); } const unsigned int MOVE_NONE = 0; @@ -364,152 +375,195 @@ const unsigned int MOVE_UP = 1 << 6; const unsigned int MOVE_DOWN = 1 << 7; const unsigned int MOVE_PITCHUP = 1 << 8; const unsigned int MOVE_PITCHDOWN = 1 << 9; -const unsigned int MOVE_ALL = MOVE_FORWARD | MOVE_BACK | MOVE_ROTRIGHT | MOVE_ROTLEFT | MOVE_STRAFERIGHT | MOVE_STRAFELEFT | MOVE_UP | MOVE_DOWN | MOVE_PITCHUP | MOVE_PITCHDOWN; - -void Cam_KeyControl( camera_t& camera, float dtime ){ - // Update angles - if ( camera.movementflags & MOVE_ROTLEFT ) { - camera.angles[CAMERA_YAW] += 15 * dtime * g_camwindow_globals_private.m_nAngleSpeed; - } - if ( camera.movementflags & MOVE_ROTRIGHT ) { - camera.angles[CAMERA_YAW] -= 15 * dtime * g_camwindow_globals_private.m_nAngleSpeed; - } - if ( camera.movementflags & MOVE_PITCHUP ) { - camera.angles[CAMERA_PITCH] += 15 * dtime * g_camwindow_globals_private.m_nAngleSpeed; - if ( camera.angles[CAMERA_PITCH] > 90 ) { - camera.angles[CAMERA_PITCH] = 90; - } - } - if ( camera.movementflags & MOVE_PITCHDOWN ) { - camera.angles[CAMERA_PITCH] -= 15 * dtime * g_camwindow_globals_private.m_nAngleSpeed; - if ( camera.angles[CAMERA_PITCH] < -90 ) { - camera.angles[CAMERA_PITCH] = -90; - } - } +const unsigned int MOVE_ALL = + MOVE_FORWARD | MOVE_BACK | MOVE_ROTRIGHT | MOVE_ROTLEFT | MOVE_STRAFERIGHT | MOVE_STRAFELEFT | MOVE_UP | + MOVE_DOWN | MOVE_PITCHUP | MOVE_PITCHDOWN; - Camera_updateModelview( camera ); - Camera_Freemove_updateAxes( camera ); +void Cam_KeyControl(camera_t &camera, float dtime) +{ + // Update angles + if (camera.movementflags & MOVE_ROTLEFT) { + camera.angles[CAMERA_YAW] += 15 * dtime * g_camwindow_globals_private.m_nAngleSpeed; + } + if (camera.movementflags & MOVE_ROTRIGHT) { + camera.angles[CAMERA_YAW] -= 15 * dtime * g_camwindow_globals_private.m_nAngleSpeed; + } + if (camera.movementflags & MOVE_PITCHUP) { + camera.angles[CAMERA_PITCH] += 15 * dtime * g_camwindow_globals_private.m_nAngleSpeed; + if (camera.angles[CAMERA_PITCH] > 90) { + camera.angles[CAMERA_PITCH] = 90; + } + } + if (camera.movementflags & MOVE_PITCHDOWN) { + camera.angles[CAMERA_PITCH] -= 15 * dtime * g_camwindow_globals_private.m_nAngleSpeed; + if (camera.angles[CAMERA_PITCH] < -90) { + camera.angles[CAMERA_PITCH] = -90; + } + } + + Camera_updateModelview(camera); + Camera_Freemove_updateAxes(camera); + + // Update position + if (camera.movementflags & MOVE_FORWARD) { + vector3_add(camera.origin, vector3_scaled(camera.forward, dtime * g_camwindow_globals_private.m_nMoveSpeed)); + } + if (camera.movementflags & MOVE_BACK) { + vector3_add(camera.origin, vector3_scaled(camera.forward, -dtime * g_camwindow_globals_private.m_nMoveSpeed)); + } + if (camera.movementflags & MOVE_STRAFELEFT) { + vector3_add(camera.origin, vector3_scaled(camera.right, -dtime * g_camwindow_globals_private.m_nMoveSpeed)); + } + if (camera.movementflags & MOVE_STRAFERIGHT) { + vector3_add(camera.origin, vector3_scaled(camera.right, dtime * g_camwindow_globals_private.m_nMoveSpeed)); + } + if (camera.movementflags & MOVE_UP) { + vector3_add(camera.origin, vector3_scaled(g_vector3_axis_z, dtime * g_camwindow_globals_private.m_nMoveSpeed)); + } + if (camera.movementflags & MOVE_DOWN) { + vector3_add(camera.origin, vector3_scaled(g_vector3_axis_z, -dtime * g_camwindow_globals_private.m_nMoveSpeed)); + } + + Camera_updateModelview(camera); +} + +void Camera_keyMove(camera_t &camera) +{ + camera.m_mouseMove.flush(); - // Update position - if ( camera.movementflags & MOVE_FORWARD ) { - vector3_add( camera.origin, vector3_scaled( camera.forward, dtime * g_camwindow_globals_private.m_nMoveSpeed ) ); - } - if ( camera.movementflags & MOVE_BACK ) { - vector3_add( camera.origin, vector3_scaled( camera.forward, -dtime * g_camwindow_globals_private.m_nMoveSpeed ) ); - } - if ( camera.movementflags & MOVE_STRAFELEFT ) { - vector3_add( camera.origin, vector3_scaled( camera.right, -dtime * g_camwindow_globals_private.m_nMoveSpeed ) ); - } - if ( camera.movementflags & MOVE_STRAFERIGHT ) { - vector3_add( camera.origin, vector3_scaled( camera.right, dtime * g_camwindow_globals_private.m_nMoveSpeed ) ); - } - if ( camera.movementflags & MOVE_UP ) { - vector3_add( camera.origin, vector3_scaled( g_vector3_axis_z, dtime * g_camwindow_globals_private.m_nMoveSpeed ) ); - } - if ( camera.movementflags & MOVE_DOWN ) { - vector3_add( camera.origin, vector3_scaled( g_vector3_axis_z, -dtime * g_camwindow_globals_private.m_nMoveSpeed ) ); - } + //globalOutputStream() << "keymove... "; + float time_seconds = camera.m_keycontrol_timer.elapsed_msec() / static_cast( msec_per_sec ); + camera.m_keycontrol_timer.start(); + if (time_seconds > 0.05f) { + time_seconds = 0.05f; // 20fps + } + Cam_KeyControl(camera, time_seconds * 5.0f); - Camera_updateModelview( camera ); + camera.m_update(); + CameraMovedNotify(); } -void Camera_keyMove( camera_t& camera ){ - camera.m_mouseMove.flush(); - - //globalOutputStream() << "keymove... "; - float time_seconds = camera.m_keycontrol_timer.elapsed_msec() / static_cast( msec_per_sec ); - camera.m_keycontrol_timer.start(); - if ( time_seconds > 0.05f ) { - time_seconds = 0.05f; // 20fps - } - Cam_KeyControl( camera, time_seconds * 5.0f ); - - camera.m_update(); - CameraMovedNotify(); +gboolean camera_keymove(gpointer data) +{ + Camera_keyMove(*reinterpret_cast( data )); + return TRUE; } -gboolean camera_keymove( gpointer data ){ - Camera_keyMove( *reinterpret_cast( data ) ); - return TRUE; +void Camera_setMovementFlags(camera_t &camera, unsigned int mask) +{ + if ((~camera.movementflags & mask) != 0 && camera.movementflags == 0) { + camera.m_keymove_handler = g_idle_add(camera_keymove, &camera); + } + camera.movementflags |= mask; } -void Camera_setMovementFlags( camera_t& camera, unsigned int mask ){ - if ( ( ~camera.movementflags & mask ) != 0 && camera.movementflags == 0 ) { - camera.m_keymove_handler = g_idle_add( camera_keymove, &camera ); - } - camera.movementflags |= mask; -} -void Camera_clearMovementFlags( camera_t& camera, unsigned int mask ){ - if ( ( camera.movementflags & ~mask ) == 0 && camera.movementflags != 0 ) { - g_source_remove( camera.m_keymove_handler ); - camera.m_keymove_handler = 0; - } - camera.movementflags &= ~mask; +void Camera_clearMovementFlags(camera_t &camera, unsigned int mask) +{ + if ((camera.movementflags & ~mask) == 0 && camera.movementflags != 0) { + g_source_remove(camera.m_keymove_handler); + camera.m_keymove_handler = 0; + } + camera.movementflags &= ~mask; } -void Camera_MoveForward_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_FORWARD ); +void Camera_MoveForward_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_FORWARD); } -void Camera_MoveForward_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_FORWARD ); + +void Camera_MoveForward_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_FORWARD); } -void Camera_MoveBack_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_BACK ); + +void Camera_MoveBack_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_BACK); } -void Camera_MoveBack_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_BACK ); + +void Camera_MoveBack_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_BACK); } -void Camera_MoveLeft_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_STRAFELEFT ); +void Camera_MoveLeft_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_STRAFELEFT); } -void Camera_MoveLeft_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_STRAFELEFT ); + +void Camera_MoveLeft_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_STRAFELEFT); } -void Camera_MoveRight_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_STRAFERIGHT ); + +void Camera_MoveRight_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_STRAFERIGHT); } -void Camera_MoveRight_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_STRAFERIGHT ); + +void Camera_MoveRight_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_STRAFERIGHT); } -void Camera_MoveUp_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_UP ); +void Camera_MoveUp_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_UP); } -void Camera_MoveUp_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_UP ); + +void Camera_MoveUp_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_UP); } -void Camera_MoveDown_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_DOWN ); + +void Camera_MoveDown_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_DOWN); } -void Camera_MoveDown_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_DOWN ); + +void Camera_MoveDown_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_DOWN); } -void Camera_RotateLeft_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_ROTLEFT ); +void Camera_RotateLeft_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_ROTLEFT); } -void Camera_RotateLeft_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_ROTLEFT ); + +void Camera_RotateLeft_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_ROTLEFT); } -void Camera_RotateRight_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_ROTRIGHT ); + +void Camera_RotateRight_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_ROTRIGHT); } -void Camera_RotateRight_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_ROTRIGHT ); + +void Camera_RotateRight_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_ROTRIGHT); } -void Camera_PitchUp_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_PITCHUP ); +void Camera_PitchUp_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_PITCHUP); } -void Camera_PitchUp_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_PITCHUP ); + +void Camera_PitchUp_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_PITCHUP); } -void Camera_PitchDown_KeyDown( camera_t& camera ){ - Camera_setMovementFlags( camera, MOVE_PITCHDOWN ); + +void Camera_PitchDown_KeyDown(camera_t &camera) +{ + Camera_setMovementFlags(camera, MOVE_PITCHDOWN); } -void Camera_PitchDown_KeyUp( camera_t& camera ){ - Camera_clearMovementFlags( camera, MOVE_PITCHDOWN ); + +void Camera_PitchDown_KeyUp(camera_t &camera) +{ + Camera_clearMovementFlags(camera, MOVE_PITCHDOWN); } @@ -533,284 +587,332 @@ const float MIN_CAM_SPEED = 10; const float MAX_CAM_SPEED = 610; const float CAM_SPEED_STEP = 50; -void Camera_MoveForward_Discrete( camera_t& camera ){ - Camera_Move_updateAxes( camera ); - Camera_setOrigin( camera, vector3_added( Camera_getOrigin( camera ), vector3_scaled( camera.forward, SPEED_MOVE ) ) ); +void Camera_MoveForward_Discrete(camera_t &camera) +{ + Camera_Move_updateAxes(camera); + Camera_setOrigin(camera, vector3_added(Camera_getOrigin(camera), vector3_scaled(camera.forward, SPEED_MOVE))); } -void Camera_MoveBack_Discrete( camera_t& camera ){ - Camera_Move_updateAxes( camera ); - Camera_setOrigin( camera, vector3_added( Camera_getOrigin( camera ), vector3_scaled( camera.forward, -SPEED_MOVE ) ) ); + +void Camera_MoveBack_Discrete(camera_t &camera) +{ + Camera_Move_updateAxes(camera); + Camera_setOrigin(camera, vector3_added(Camera_getOrigin(camera), vector3_scaled(camera.forward, -SPEED_MOVE))); } -void Camera_MoveUp_Discrete( camera_t& camera ){ - Vector3 origin( Camera_getOrigin( camera ) ); - origin[2] += SPEED_MOVE; - Camera_setOrigin( camera, origin ); +void Camera_MoveUp_Discrete(camera_t &camera) +{ + Vector3 origin(Camera_getOrigin(camera)); + origin[2] += SPEED_MOVE; + Camera_setOrigin(camera, origin); } -void Camera_MoveDown_Discrete( camera_t& camera ){ - Vector3 origin( Camera_getOrigin( camera ) ); - origin[2] -= SPEED_MOVE; - Camera_setOrigin( camera, origin ); + +void Camera_MoveDown_Discrete(camera_t &camera) +{ + Vector3 origin(Camera_getOrigin(camera)); + origin[2] -= SPEED_MOVE; + Camera_setOrigin(camera, origin); } -void Camera_MoveLeft_Discrete( camera_t& camera ){ - Camera_Move_updateAxes( camera ); - Camera_setOrigin( camera, vector3_added( Camera_getOrigin( camera ), vector3_scaled( camera.right, -SPEED_MOVE ) ) ); +void Camera_MoveLeft_Discrete(camera_t &camera) +{ + Camera_Move_updateAxes(camera); + Camera_setOrigin(camera, vector3_added(Camera_getOrigin(camera), vector3_scaled(camera.right, -SPEED_MOVE))); } -void Camera_MoveRight_Discrete( camera_t& camera ){ - Camera_Move_updateAxes( camera ); - Camera_setOrigin( camera, vector3_added( Camera_getOrigin( camera ), vector3_scaled( camera.right, SPEED_MOVE ) ) ); + +void Camera_MoveRight_Discrete(camera_t &camera) +{ + Camera_Move_updateAxes(camera); + Camera_setOrigin(camera, vector3_added(Camera_getOrigin(camera), vector3_scaled(camera.right, SPEED_MOVE))); } -void Camera_RotateLeft_Discrete( camera_t& camera ){ - Vector3 angles( Camera_getAngles( camera ) ); - angles[CAMERA_YAW] += SPEED_TURN; - Camera_setAngles( camera, angles ); +void Camera_RotateLeft_Discrete(camera_t &camera) +{ + Vector3 angles(Camera_getAngles(camera)); + angles[CAMERA_YAW] += SPEED_TURN; + Camera_setAngles(camera, angles); } -void Camera_RotateRight_Discrete( camera_t& camera ){ - Vector3 angles( Camera_getAngles( camera ) ); - angles[CAMERA_YAW] -= SPEED_TURN; - Camera_setAngles( camera, angles ); + +void Camera_RotateRight_Discrete(camera_t &camera) +{ + Vector3 angles(Camera_getAngles(camera)); + angles[CAMERA_YAW] -= SPEED_TURN; + Camera_setAngles(camera, angles); } -void Camera_PitchUp_Discrete( camera_t& camera ){ - Vector3 angles( Camera_getAngles( camera ) ); - angles[CAMERA_PITCH] += SPEED_TURN; - if ( angles[CAMERA_PITCH] > 90 ) { - angles[CAMERA_PITCH] = 90; - } - Camera_setAngles( camera, angles ); +void Camera_PitchUp_Discrete(camera_t &camera) +{ + Vector3 angles(Camera_getAngles(camera)); + angles[CAMERA_PITCH] += SPEED_TURN; + if (angles[CAMERA_PITCH] > 90) { + angles[CAMERA_PITCH] = 90; + } + Camera_setAngles(camera, angles); } -void Camera_PitchDown_Discrete( camera_t& camera ){ - Vector3 angles( Camera_getAngles( camera ) ); - angles[CAMERA_PITCH] -= SPEED_TURN; - if ( angles[CAMERA_PITCH] < -90 ) { - angles[CAMERA_PITCH] = -90; - } - Camera_setAngles( camera, angles ); + +void Camera_PitchDown_Discrete(camera_t &camera) +{ + Vector3 angles(Camera_getAngles(camera)); + angles[CAMERA_PITCH] -= SPEED_TURN; + if (angles[CAMERA_PITCH] < -90) { + angles[CAMERA_PITCH] = -90; + } + Camera_setAngles(camera, angles); } -class RadiantCameraView : public CameraView -{ -camera_t& m_camera; -View* m_view; -Callback m_update; +class RadiantCameraView : public CameraView { + camera_t &m_camera; + View *m_view; + Callback m_update; public: -RadiantCameraView( camera_t& camera, View* view, const Callback& update ) : m_camera( camera ), m_view( view ), m_update( update ){ -} -void update(){ - m_view->Construct( m_camera.projection, m_camera.modelview, m_camera.width, m_camera.height ); - m_update(); -} -void setModelview( const Matrix4& modelview ){ - m_camera.modelview = modelview; - matrix4_multiply_by_matrix4( m_camera.modelview, g_radiant2opengl ); - matrix4_affine_invert( m_camera.modelview ); - Camera_updateVectors( m_camera ); - update(); -} -void setFieldOfView( float fieldOfView ){ - float farClip = Camera_getFarClipPlane( m_camera ); - m_camera.projection = projection_for_camera( farClip / 4096.0f, farClip, fieldOfView, m_camera.width, m_camera.height ); - update(); -} + RadiantCameraView(camera_t &camera, View *view, const Callback &update) : m_camera(camera), m_view(view), + m_update(update) + { + } + + void update() + { + m_view->Construct(m_camera.projection, m_camera.modelview, m_camera.width, m_camera.height); + m_update(); + } + + void setModelview(const Matrix4 &modelview) + { + m_camera.modelview = modelview; + matrix4_multiply_by_matrix4(m_camera.modelview, g_radiant2opengl); + matrix4_affine_invert(m_camera.modelview); + Camera_updateVectors(m_camera); + update(); + } + + void setFieldOfView(float fieldOfView) + { + float farClip = Camera_getFarClipPlane(m_camera); + m_camera.projection = projection_for_camera(farClip / 4096.0f, farClip, fieldOfView, m_camera.width, + m_camera.height); + update(); + } }; -void Camera_motionDelta( int x, int y, unsigned int state, void* data ){ - camera_t* cam = reinterpret_cast( data ); - - cam->m_mouseMove.motion_delta( x, y, state ); - - switch ( g_camwindow_globals_private.m_nStrafeMode ) - { - case 0: - cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0; - if ( cam->m_strafe ) { - cam->m_strafe_forward = ( state & GDK_SHIFT_MASK ) != 0; - } - else{ - cam->m_strafe_forward = false; - } - break; - case 1: - cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0 && ( state & GDK_SHIFT_MASK ) == 0; - cam->m_strafe_forward = false; - break; - case 2: - cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0 && ( state & GDK_SHIFT_MASK ) == 0; - cam->m_strafe_forward = cam->m_strafe; - break; - } -} - -class CamWnd +void Camera_motionDelta(int x, int y, unsigned int state, void *data) { -View m_view; -camera_t m_Camera; -RadiantCameraView m_cameraview; + camera_t *cam = reinterpret_cast( data ); + + cam->m_mouseMove.motion_delta(x, y, state); + + switch (g_camwindow_globals_private.m_nStrafeMode) { + case 0: + cam->m_strafe = (state & GDK_CONTROL_MASK) != 0; + if (cam->m_strafe) { + cam->m_strafe_forward = (state & GDK_SHIFT_MASK) != 0; + } else { + cam->m_strafe_forward = false; + } + break; + case 1: + cam->m_strafe = (state & GDK_CONTROL_MASK) != 0 && (state & GDK_SHIFT_MASK) == 0; + cam->m_strafe_forward = false; + break; + case 2: + cam->m_strafe = (state & GDK_CONTROL_MASK) != 0 && (state & GDK_SHIFT_MASK) == 0; + cam->m_strafe_forward = cam->m_strafe; + break; + } +} + +class CamWnd { + View m_view; + camera_t m_Camera; + RadiantCameraView m_cameraview; #if 0 -int m_PositionDragCursorX; + int m_PositionDragCursorX; int m_PositionDragCursorY; #endif -guint m_freemove_handle_focusout; + guint m_freemove_handle_focusout; -static Shader* m_state_select1; -static Shader* m_state_select2; + static Shader *m_state_select1; + static Shader *m_state_select2; -FreezePointer m_freezePointer; + FreezePointer m_freezePointer; public: -ui::GLArea m_gl_widget; -ui::Window m_parent{ui::null}; + ui::GLArea m_gl_widget; + ui::Window m_parent{ui::null}; -SelectionSystemWindowObserver* m_window_observer; -XORRectangle m_XORRectangle; + SelectionSystemWindowObserver *m_window_observer; + XORRectangle m_XORRectangle; -DeferredDraw m_deferredDraw; -DeferredMotion m_deferred_motion; + DeferredDraw m_deferredDraw; + DeferredMotion m_deferred_motion; -guint m_selection_button_press_handler; -guint m_selection_button_release_handler; -guint m_selection_motion_handler; + guint m_selection_button_press_handler; + guint m_selection_button_release_handler; + guint m_selection_motion_handler; -guint m_freelook_button_press_handler; + guint m_freelook_button_press_handler; -guint m_sizeHandler; -guint m_exposeHandler; + guint m_sizeHandler; + guint m_exposeHandler; -CamWnd(); -~CamWnd(); + CamWnd(); -bool m_drawing; -void queue_draw(){ - //ASSERT_MESSAGE(!m_drawing, "CamWnd::queue_draw(): called while draw is already in progress"); - if ( m_drawing ) { - return; - } - //globalOutputStream() << "queue... "; - m_deferredDraw.draw(); -} -void draw(); + ~CamWnd(); -static void captureStates(){ - m_state_select1 = GlobalShaderCache().capture( "$CAM_HIGHLIGHT" ); - m_state_select2 = GlobalShaderCache().capture( "$CAM_OVERLAY" ); -} -static void releaseStates(){ - GlobalShaderCache().release( "$CAM_HIGHLIGHT" ); - GlobalShaderCache().release( "$CAM_OVERLAY" ); -} + bool m_drawing; -camera_t& getCamera(){ - return m_Camera; -}; + void queue_draw() + { + //ASSERT_MESSAGE(!m_drawing, "CamWnd::queue_draw(): called while draw is already in progress"); + if (m_drawing) { + return; + } + //globalOutputStream() << "queue... "; + m_deferredDraw.draw(); + } -void BenchMark(); -void Cam_ChangeFloor( bool up ); + void draw(); -void DisableFreeMove(); -void EnableFreeMove(); -bool m_bFreeMove; + static void captureStates() + { + m_state_select1 = GlobalShaderCache().capture("$CAM_HIGHLIGHT"); + m_state_select2 = GlobalShaderCache().capture("$CAM_OVERLAY"); + } -CameraView& getCameraView(){ - return m_cameraview; -} + static void releaseStates() + { + GlobalShaderCache().release("$CAM_HIGHLIGHT"); + GlobalShaderCache().release("$CAM_OVERLAY"); + } + + camera_t &getCamera() + { + return m_Camera; + }; + + void BenchMark(); + + void Cam_ChangeFloor(bool up); + + void DisableFreeMove(); + + void EnableFreeMove(); + + bool m_bFreeMove; + + CameraView &getCameraView() + { + return m_cameraview; + } private: -void Cam_Draw(); + void Cam_Draw(); }; typedef MemberCaller CamWndQueueDraw; -Shader* CamWnd::m_state_select1 = 0; -Shader* CamWnd::m_state_select2 = 0; +Shader *CamWnd::m_state_select1 = 0; +Shader *CamWnd::m_state_select2 = 0; -CamWnd* NewCamWnd(){ - return new CamWnd; +CamWnd *NewCamWnd() +{ + return new CamWnd; } -void DeleteCamWnd( CamWnd* camwnd ){ - delete camwnd; + +void DeleteCamWnd(CamWnd *camwnd) +{ + delete camwnd; } -void CamWnd_constructStatic(){ - CamWnd::captureStates(); +void CamWnd_constructStatic() +{ + CamWnd::captureStates(); } -void CamWnd_destroyStatic(){ - CamWnd::releaseStates(); +void CamWnd_destroyStatic() +{ + CamWnd::releaseStates(); } -static CamWnd* g_camwnd = 0; +static CamWnd *g_camwnd = 0; -void GlobalCamera_setCamWnd( CamWnd& camwnd ){ - g_camwnd = &camwnd; +void GlobalCamera_setCamWnd(CamWnd &camwnd) +{ + g_camwnd = &camwnd; } -ui::GLArea CamWnd_getWidget( CamWnd& camwnd ){ - return camwnd.m_gl_widget; +ui::GLArea CamWnd_getWidget(CamWnd &camwnd) +{ + return camwnd.m_gl_widget; } -ui::Window CamWnd_getParent( CamWnd& camwnd ){ - return camwnd.m_parent; +ui::Window CamWnd_getParent(CamWnd &camwnd) +{ + return camwnd.m_parent; } -ToggleShown g_camera_shown( true ); +ToggleShown g_camera_shown(true); -void CamWnd_setParent( CamWnd& camwnd, ui::Window parent ){ - camwnd.m_parent = parent; - g_camera_shown.connect( camwnd.m_parent ); +void CamWnd_setParent(CamWnd &camwnd, ui::Window parent) +{ + camwnd.m_parent = parent; + g_camera_shown.connect(camwnd.m_parent); } -void CamWnd_Update( CamWnd& camwnd ){ - camwnd.queue_draw(); +void CamWnd_Update(CamWnd &camwnd) +{ + camwnd.queue_draw(); } - camwindow_globals_t g_camwindow_globals; -const Vector3& Camera_getOrigin( CamWnd& camwnd ){ - return Camera_getOrigin( camwnd.getCamera() ); +const Vector3 &Camera_getOrigin(CamWnd &camwnd) +{ + return Camera_getOrigin(camwnd.getCamera()); } -void Camera_setOrigin( CamWnd& camwnd, const Vector3& origin ){ - Camera_setOrigin( camwnd.getCamera(), origin ); +void Camera_setOrigin(CamWnd &camwnd, const Vector3 &origin) +{ + Camera_setOrigin(camwnd.getCamera(), origin); } -const Vector3& Camera_getAngles( CamWnd& camwnd ){ - return Camera_getAngles( camwnd.getCamera() ); +const Vector3 &Camera_getAngles(CamWnd &camwnd) +{ + return Camera_getAngles(camwnd.getCamera()); } -void Camera_setAngles( CamWnd& camwnd, const Vector3& angles ){ - Camera_setAngles( camwnd.getCamera(), angles ); +void Camera_setAngles(CamWnd &camwnd, const Vector3 &angles) +{ + Camera_setAngles(camwnd.getCamera(), angles); } // ============================================================================= // CamWnd class -gboolean enable_freelook_button_press( ui::Widget widget, GdkEventButton* event, CamWnd* camwnd ){ - if ( event->type == GDK_BUTTON_PRESS && event->button == 3 ) { - camwnd->EnableFreeMove(); - return TRUE; - } - return FALSE; +gboolean enable_freelook_button_press(ui::Widget widget, GdkEventButton *event, CamWnd *camwnd) +{ + if (event->type == GDK_BUTTON_PRESS && event->button == 3) { + camwnd->EnableFreeMove(); + return TRUE; + } + return FALSE; } -gboolean disable_freelook_button_press( ui::Widget widget, GdkEventButton* event, CamWnd* camwnd ){ - if ( event->type == GDK_BUTTON_PRESS && event->button == 3 ) { - camwnd->DisableFreeMove(); - return TRUE; - } - return FALSE; +gboolean disable_freelook_button_press(ui::Widget widget, GdkEventButton *event, CamWnd *camwnd) +{ + if (event->type == GDK_BUTTON_PRESS && event->button == 3) { + camwnd->DisableFreeMove(); + return TRUE; + } + return FALSE; } #if 0 -gboolean mousecontrol_button_press( ui::Widget widget, GdkEventButton* event, CamWnd* camwnd ){ + gboolean mousecontrol_button_press( ui::Widget widget, GdkEventButton* event, CamWnd* camwnd ){ if ( event->type == GDK_BUTTON_PRESS && event->button == 3 ) { Cam_MouseControl( camwnd->getCamera(), event->x, widget->allocation.height - 1 - event->y ); } @@ -818,428 +920,495 @@ gboolean mousecontrol_button_press( ui::Widget widget, GdkEventButton* event, Ca } #endif -void camwnd_update_xor_rectangle( CamWnd& self, rect_t area ){ - if ( self.m_gl_widget.visible() ) { - self.m_XORRectangle.set( rectangle_from_area( area.min, area.max, self.getCamera().width, self.getCamera().height ) ); - } +void camwnd_update_xor_rectangle(CamWnd &self, rect_t area) +{ + if (self.m_gl_widget.visible()) { + self.m_XORRectangle.set( + rectangle_from_area(area.min, area.max, self.getCamera().width, self.getCamera().height)); + } } -gboolean selection_button_press( ui::Widget widget, GdkEventButton* event, WindowObserver* observer ){ - if ( event->type == GDK_BUTTON_PRESS ) { - observer->onMouseDown( WindowVector_forDouble( event->x, event->y ), button_for_button( event->button ), modifiers_for_state( event->state ) ); - } - return FALSE; +gboolean selection_button_press(ui::Widget widget, GdkEventButton *event, WindowObserver *observer) +{ + if (event->type == GDK_BUTTON_PRESS) { + observer->onMouseDown(WindowVector_forDouble(event->x, event->y), button_for_button(event->button), + modifiers_for_state(event->state)); + } + return FALSE; } -gboolean selection_button_release( ui::Widget widget, GdkEventButton* event, WindowObserver* observer ){ - if ( event->type == GDK_BUTTON_RELEASE ) { - observer->onMouseUp( WindowVector_forDouble( event->x, event->y ), button_for_button( event->button ), modifiers_for_state( event->state ) ); - } - return FALSE; +gboolean selection_button_release(ui::Widget widget, GdkEventButton *event, WindowObserver *observer) +{ + if (event->type == GDK_BUTTON_RELEASE) { + observer->onMouseUp(WindowVector_forDouble(event->x, event->y), button_for_button(event->button), + modifiers_for_state(event->state)); + } + return FALSE; } -void selection_motion( gdouble x, gdouble y, guint state, void* data ){ - //globalOutputStream() << "motion... "; - reinterpret_cast( data )->onMouseMotion( WindowVector_forDouble( x, y ), modifiers_for_state( state ) ); +void selection_motion(gdouble x, gdouble y, guint state, void *data) +{ + //globalOutputStream() << "motion... "; + reinterpret_cast( data )->onMouseMotion(WindowVector_forDouble(x, y), modifiers_for_state(state)); } -inline WindowVector windowvector_for_widget_centre( ui::Widget widget ){ - auto allocation = widget.dimensions(); - return WindowVector( static_cast( allocation.width / 2 ), static_cast(allocation.height / 2 ) ); +inline WindowVector windowvector_for_widget_centre(ui::Widget widget) +{ + auto allocation = widget.dimensions(); + return WindowVector(static_cast( allocation.width / 2 ), static_cast(allocation.height / 2 )); } -gboolean selection_button_press_freemove( ui::Widget widget, GdkEventButton* event, WindowObserver* observer ){ - if ( event->type == GDK_BUTTON_PRESS ) { - observer->onMouseDown( windowvector_for_widget_centre( widget ), button_for_button( event->button ), modifiers_for_state( event->state ) ); - } - return FALSE; +gboolean selection_button_press_freemove(ui::Widget widget, GdkEventButton *event, WindowObserver *observer) +{ + if (event->type == GDK_BUTTON_PRESS) { + observer->onMouseDown(windowvector_for_widget_centre(widget), button_for_button(event->button), + modifiers_for_state(event->state)); + } + return FALSE; } -gboolean selection_button_release_freemove( ui::Widget widget, GdkEventButton* event, WindowObserver* observer ){ - if ( event->type == GDK_BUTTON_RELEASE ) { - observer->onMouseUp( windowvector_for_widget_centre( widget ), button_for_button( event->button ), modifiers_for_state( event->state ) ); - } - return FALSE; +gboolean selection_button_release_freemove(ui::Widget widget, GdkEventButton *event, WindowObserver *observer) +{ + if (event->type == GDK_BUTTON_RELEASE) { + observer->onMouseUp(windowvector_for_widget_centre(widget), button_for_button(event->button), + modifiers_for_state(event->state)); + } + return FALSE; } -gboolean selection_motion_freemove( ui::Widget widget, GdkEventMotion *event, WindowObserver* observer ){ - observer->onMouseMotion( windowvector_for_widget_centre( widget ), modifiers_for_state( event->state ) ); - return FALSE; +gboolean selection_motion_freemove(ui::Widget widget, GdkEventMotion *event, WindowObserver *observer) +{ + observer->onMouseMotion(windowvector_for_widget_centre(widget), modifiers_for_state(event->state)); + return FALSE; } -gboolean wheelmove_scroll( ui::Widget widget, GdkEventScroll* event, CamWnd* camwnd ){ - if ( event->direction == GDK_SCROLL_UP ) { - Camera_Freemove_updateAxes( camwnd->getCamera() ); - Camera_setOrigin( *camwnd, vector3_added( Camera_getOrigin( *camwnd ), vector3_scaled( camwnd->getCamera().forward, static_cast( g_camwindow_globals_private.m_nMoveSpeed ) ) ) ); - } - else if ( event->direction == GDK_SCROLL_DOWN ) { - Camera_Freemove_updateAxes( camwnd->getCamera() ); - Camera_setOrigin( *camwnd, vector3_added( Camera_getOrigin( *camwnd ), vector3_scaled( camwnd->getCamera().forward, -static_cast( g_camwindow_globals_private.m_nMoveSpeed ) ) ) ); - } +gboolean wheelmove_scroll(ui::Widget widget, GdkEventScroll *event, CamWnd *camwnd) +{ + if (event->direction == GDK_SCROLL_UP) { + Camera_Freemove_updateAxes(camwnd->getCamera()); + Camera_setOrigin(*camwnd, vector3_added(Camera_getOrigin(*camwnd), vector3_scaled(camwnd->getCamera().forward, + static_cast( g_camwindow_globals_private.m_nMoveSpeed )))); + } else if (event->direction == GDK_SCROLL_DOWN) { + Camera_Freemove_updateAxes(camwnd->getCamera()); + Camera_setOrigin(*camwnd, vector3_added(Camera_getOrigin(*camwnd), vector3_scaled(camwnd->getCamera().forward, + -static_cast( g_camwindow_globals_private.m_nMoveSpeed )))); + } - return FALSE; + return FALSE; } -gboolean camera_size_allocate( ui::Widget widget, GtkAllocation* allocation, CamWnd* camwnd ){ - camwnd->getCamera().width = allocation->width; - camwnd->getCamera().height = allocation->height; - Camera_updateProjection( camwnd->getCamera() ); - camwnd->m_window_observer->onSizeChanged( camwnd->getCamera().width, camwnd->getCamera().height ); - camwnd->queue_draw(); - return FALSE; +gboolean camera_size_allocate(ui::Widget widget, GtkAllocation *allocation, CamWnd *camwnd) +{ + camwnd->getCamera().width = allocation->width; + camwnd->getCamera().height = allocation->height; + Camera_updateProjection(camwnd->getCamera()); + camwnd->m_window_observer->onSizeChanged(camwnd->getCamera().width, camwnd->getCamera().height); + camwnd->queue_draw(); + return FALSE; } -gboolean camera_expose( ui::Widget widget, GdkEventExpose* event, gpointer data ){ - reinterpret_cast( data )->draw(); - return FALSE; +gboolean camera_expose(ui::Widget widget, GdkEventExpose *event, gpointer data) +{ + reinterpret_cast( data )->draw(); + return FALSE; } -void KeyEvent_connect( const char* name ){ - const KeyEvent& keyEvent = GlobalKeyEvents_find( name ); - keydown_accelerators_add( keyEvent.m_accelerator, keyEvent.m_keyDown ); - keyup_accelerators_add( keyEvent.m_accelerator, keyEvent.m_keyUp ); -} - -void KeyEvent_disconnect( const char* name ){ - const KeyEvent& keyEvent = GlobalKeyEvents_find( name ); - keydown_accelerators_remove( keyEvent.m_accelerator ); - keyup_accelerators_remove( keyEvent.m_accelerator ); -} - -void CamWnd_registerCommands( CamWnd& camwnd ){ - GlobalKeyEvents_insert( "CameraForward", Accelerator( GDK_KEY_Up ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraBack", Accelerator( GDK_KEY_Down ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraLeft", Accelerator( GDK_KEY_Left ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraRight", Accelerator( GDK_KEY_Right ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraStrafeRight", Accelerator( GDK_KEY_period ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraStrafeLeft", Accelerator( GDK_KEY_comma ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraUp", Accelerator( 'D' ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraDown", Accelerator( 'C' ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraAngleDown", Accelerator( 'A' ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraAngleUp", Accelerator( 'Z' ), - ReferenceCaller( camwnd.getCamera() ), - ReferenceCaller( camwnd.getCamera() ) - ); - - GlobalKeyEvents_insert( "CameraFreeMoveForward", Accelerator( GDK_KEY_Up ), - FreeMoveCameraMoveForwardKeyDownCaller( camwnd.getCamera() ), - FreeMoveCameraMoveForwardKeyUpCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraFreeMoveBack", Accelerator( GDK_KEY_Down ), - FreeMoveCameraMoveBackKeyDownCaller( camwnd.getCamera() ), - FreeMoveCameraMoveBackKeyUpCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraFreeMoveLeft", Accelerator( GDK_KEY_Left ), - FreeMoveCameraMoveLeftKeyDownCaller( camwnd.getCamera() ), - FreeMoveCameraMoveLeftKeyUpCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraFreeMoveRight", Accelerator( GDK_KEY_Right ), - FreeMoveCameraMoveRightKeyDownCaller( camwnd.getCamera() ), - FreeMoveCameraMoveRightKeyUpCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraFreeMoveUp", Accelerator( 'D' ), - FreeMoveCameraMoveUpKeyDownCaller( camwnd.getCamera() ), - FreeMoveCameraMoveUpKeyUpCaller( camwnd.getCamera() ) - ); - GlobalKeyEvents_insert( "CameraFreeMoveDown", Accelerator( 'C' ), - FreeMoveCameraMoveDownKeyDownCaller( camwnd.getCamera() ), - FreeMoveCameraMoveDownKeyUpCaller( camwnd.getCamera() ) - ); - - GlobalCommands_insert( "CameraForward", ReferenceCaller( camwnd.getCamera() ), Accelerator( GDK_KEY_Up ) ); - GlobalCommands_insert( "CameraBack", ReferenceCaller( camwnd.getCamera() ), Accelerator( GDK_KEY_Down ) ); - GlobalCommands_insert( "CameraLeft", ReferenceCaller( camwnd.getCamera() ), Accelerator( GDK_KEY_Left ) ); - GlobalCommands_insert( "CameraRight", ReferenceCaller( camwnd.getCamera() ), Accelerator( GDK_KEY_Right ) ); - GlobalCommands_insert( "CameraStrafeRight", ReferenceCaller( camwnd.getCamera() ), Accelerator( GDK_KEY_period ) ); - GlobalCommands_insert( "CameraStrafeLeft", ReferenceCaller( camwnd.getCamera() ), Accelerator( GDK_KEY_comma ) ); - - GlobalCommands_insert( "CameraUp", ReferenceCaller( camwnd.getCamera() ), Accelerator( 'D' ) ); - GlobalCommands_insert( "CameraDown", ReferenceCaller( camwnd.getCamera() ), Accelerator( 'C' ) ); - GlobalCommands_insert( "CameraAngleUp", ReferenceCaller( camwnd.getCamera() ), Accelerator( 'A' ) ); - GlobalCommands_insert( "CameraAngleDown", ReferenceCaller( camwnd.getCamera() ), Accelerator( 'Z' ) ); -} - -void CamWnd_Move_Enable( CamWnd& camwnd ){ - KeyEvent_connect( "CameraForward" ); - KeyEvent_connect( "CameraBack" ); - KeyEvent_connect( "CameraLeft" ); - KeyEvent_connect( "CameraRight" ); - KeyEvent_connect( "CameraStrafeRight" ); - KeyEvent_connect( "CameraStrafeLeft" ); - KeyEvent_connect( "CameraUp" ); - KeyEvent_connect( "CameraDown" ); - KeyEvent_connect( "CameraAngleUp" ); - KeyEvent_connect( "CameraAngleDown" ); -} - -void CamWnd_Move_Disable( CamWnd& camwnd ){ - KeyEvent_disconnect( "CameraForward" ); - KeyEvent_disconnect( "CameraBack" ); - KeyEvent_disconnect( "CameraLeft" ); - KeyEvent_disconnect( "CameraRight" ); - KeyEvent_disconnect( "CameraStrafeRight" ); - KeyEvent_disconnect( "CameraStrafeLeft" ); - KeyEvent_disconnect( "CameraUp" ); - KeyEvent_disconnect( "CameraDown" ); - KeyEvent_disconnect( "CameraAngleUp" ); - KeyEvent_disconnect( "CameraAngleDown" ); -} - -void CamWnd_Move_Discrete_Enable( CamWnd& camwnd ){ - command_connect_accelerator( "CameraForward" ); - command_connect_accelerator( "CameraBack" ); - command_connect_accelerator( "CameraLeft" ); - command_connect_accelerator( "CameraRight" ); - command_connect_accelerator( "CameraStrafeRight" ); - command_connect_accelerator( "CameraStrafeLeft" ); - command_connect_accelerator( "CameraUp" ); - command_connect_accelerator( "CameraDown" ); - command_connect_accelerator( "CameraAngleUp" ); - command_connect_accelerator( "CameraAngleDown" ); -} - -void CamWnd_Move_Discrete_Disable( CamWnd& camwnd ){ - command_disconnect_accelerator( "CameraForward" ); - command_disconnect_accelerator( "CameraBack" ); - command_disconnect_accelerator( "CameraLeft" ); - command_disconnect_accelerator( "CameraRight" ); - command_disconnect_accelerator( "CameraStrafeRight" ); - command_disconnect_accelerator( "CameraStrafeLeft" ); - command_disconnect_accelerator( "CameraUp" ); - command_disconnect_accelerator( "CameraDown" ); - command_disconnect_accelerator( "CameraAngleUp" ); - command_disconnect_accelerator( "CameraAngleDown" ); +void KeyEvent_connect(const char *name) +{ + const KeyEvent &keyEvent = GlobalKeyEvents_find(name); + keydown_accelerators_add(keyEvent.m_accelerator, keyEvent.m_keyDown); + keyup_accelerators_add(keyEvent.m_accelerator, keyEvent.m_keyUp); } -struct CamWnd_Move_Discrete { - static void Export(const Callback &returnz) { - returnz(g_camwindow_globals_private.m_bCamDiscrete); - } - - static void Import(bool value) { - if (g_camwnd) { - Import_(*g_camwnd, value); - } else { - g_camwindow_globals_private.m_bCamDiscrete = value; - } - } - - static void Import_(CamWnd &camwnd, bool value) { - if (g_camwindow_globals_private.m_bCamDiscrete) { - CamWnd_Move_Discrete_Disable(camwnd); - } else { - CamWnd_Move_Disable(camwnd); - } - - g_camwindow_globals_private.m_bCamDiscrete = value; - - if (g_camwindow_globals_private.m_bCamDiscrete) { - CamWnd_Move_Discrete_Enable(camwnd); - } else { - CamWnd_Move_Enable(camwnd); - } - } -}; - - -void CamWnd_Add_Handlers_Move( CamWnd& camwnd ){ - camwnd.m_selection_button_press_handler = camwnd.m_gl_widget.connect( "button_press_event", G_CALLBACK( selection_button_press ), camwnd.m_window_observer ); - camwnd.m_selection_button_release_handler = camwnd.m_gl_widget.connect( "button_release_event", G_CALLBACK( selection_button_release ), camwnd.m_window_observer ); - camwnd.m_selection_motion_handler = camwnd.m_gl_widget.connect( "motion_notify_event", G_CALLBACK( DeferredMotion::gtk_motion ), &camwnd.m_deferred_motion ); - - camwnd.m_freelook_button_press_handler = camwnd.m_gl_widget.connect( "button_press_event", G_CALLBACK( enable_freelook_button_press ), &camwnd ); - - if ( g_camwindow_globals_private.m_bCamDiscrete ) { - CamWnd_Move_Discrete_Enable( camwnd ); - } - else - { - CamWnd_Move_Enable( camwnd ); - } +void KeyEvent_disconnect(const char *name) +{ + const KeyEvent &keyEvent = GlobalKeyEvents_find(name); + keydown_accelerators_remove(keyEvent.m_accelerator); + keyup_accelerators_remove(keyEvent.m_accelerator); } -void CamWnd_Remove_Handlers_Move( CamWnd& camwnd ){ - g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_selection_button_press_handler ); - g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_selection_button_release_handler ); - g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_selection_motion_handler ); +void CamWnd_registerCommands(CamWnd &camwnd) +{ + GlobalKeyEvents_insert("CameraForward", Accelerator(GDK_KEY_Up), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraBack", Accelerator(GDK_KEY_Down), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraLeft", Accelerator(GDK_KEY_Left), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraRight", Accelerator(GDK_KEY_Right), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraStrafeRight", Accelerator(GDK_KEY_period), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraStrafeLeft", Accelerator(GDK_KEY_comma), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraUp", Accelerator('D'), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraDown", Accelerator('C'), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraAngleDown", Accelerator('A'), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraAngleUp", Accelerator('Z'), + ReferenceCaller(camwnd.getCamera()), + ReferenceCaller(camwnd.getCamera()) + ); + + GlobalKeyEvents_insert("CameraFreeMoveForward", Accelerator(GDK_KEY_Up), + FreeMoveCameraMoveForwardKeyDownCaller(camwnd.getCamera()), + FreeMoveCameraMoveForwardKeyUpCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraFreeMoveBack", Accelerator(GDK_KEY_Down), + FreeMoveCameraMoveBackKeyDownCaller(camwnd.getCamera()), + FreeMoveCameraMoveBackKeyUpCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraFreeMoveLeft", Accelerator(GDK_KEY_Left), + FreeMoveCameraMoveLeftKeyDownCaller(camwnd.getCamera()), + FreeMoveCameraMoveLeftKeyUpCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraFreeMoveRight", Accelerator(GDK_KEY_Right), + FreeMoveCameraMoveRightKeyDownCaller(camwnd.getCamera()), + FreeMoveCameraMoveRightKeyUpCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraFreeMoveUp", Accelerator('D'), + FreeMoveCameraMoveUpKeyDownCaller(camwnd.getCamera()), + FreeMoveCameraMoveUpKeyUpCaller(camwnd.getCamera()) + ); + GlobalKeyEvents_insert("CameraFreeMoveDown", Accelerator('C'), + FreeMoveCameraMoveDownKeyDownCaller(camwnd.getCamera()), + FreeMoveCameraMoveDownKeyUpCaller(camwnd.getCamera()) + ); + + GlobalCommands_insert("CameraForward", + ReferenceCaller(camwnd.getCamera()), + Accelerator(GDK_KEY_Up)); + GlobalCommands_insert("CameraBack", ReferenceCaller(camwnd.getCamera()), + Accelerator(GDK_KEY_Down)); + GlobalCommands_insert("CameraLeft", + ReferenceCaller(camwnd.getCamera()), + Accelerator(GDK_KEY_Left)); + GlobalCommands_insert("CameraRight", + ReferenceCaller(camwnd.getCamera()), + Accelerator(GDK_KEY_Right)); + GlobalCommands_insert("CameraStrafeRight", + ReferenceCaller(camwnd.getCamera()), + Accelerator(GDK_KEY_period)); + GlobalCommands_insert("CameraStrafeLeft", + ReferenceCaller(camwnd.getCamera()), + Accelerator(GDK_KEY_comma)); + + GlobalCommands_insert("CameraUp", ReferenceCaller(camwnd.getCamera()), + Accelerator('D')); + GlobalCommands_insert("CameraDown", ReferenceCaller(camwnd.getCamera()), + Accelerator('C')); + GlobalCommands_insert("CameraAngleUp", + ReferenceCaller(camwnd.getCamera()), + Accelerator('A')); + GlobalCommands_insert("CameraAngleDown", + ReferenceCaller(camwnd.getCamera()), + Accelerator('Z')); +} + +void CamWnd_Move_Enable(CamWnd &camwnd) +{ + KeyEvent_connect("CameraForward"); + KeyEvent_connect("CameraBack"); + KeyEvent_connect("CameraLeft"); + KeyEvent_connect("CameraRight"); + KeyEvent_connect("CameraStrafeRight"); + KeyEvent_connect("CameraStrafeLeft"); + KeyEvent_connect("CameraUp"); + KeyEvent_connect("CameraDown"); + KeyEvent_connect("CameraAngleUp"); + KeyEvent_connect("CameraAngleDown"); +} + +void CamWnd_Move_Disable(CamWnd &camwnd) +{ + KeyEvent_disconnect("CameraForward"); + KeyEvent_disconnect("CameraBack"); + KeyEvent_disconnect("CameraLeft"); + KeyEvent_disconnect("CameraRight"); + KeyEvent_disconnect("CameraStrafeRight"); + KeyEvent_disconnect("CameraStrafeLeft"); + KeyEvent_disconnect("CameraUp"); + KeyEvent_disconnect("CameraDown"); + KeyEvent_disconnect("CameraAngleUp"); + KeyEvent_disconnect("CameraAngleDown"); +} + +void CamWnd_Move_Discrete_Enable(CamWnd &camwnd) +{ + command_connect_accelerator("CameraForward"); + command_connect_accelerator("CameraBack"); + command_connect_accelerator("CameraLeft"); + command_connect_accelerator("CameraRight"); + command_connect_accelerator("CameraStrafeRight"); + command_connect_accelerator("CameraStrafeLeft"); + command_connect_accelerator("CameraUp"); + command_connect_accelerator("CameraDown"); + command_connect_accelerator("CameraAngleUp"); + command_connect_accelerator("CameraAngleDown"); +} + +void CamWnd_Move_Discrete_Disable(CamWnd &camwnd) +{ + command_disconnect_accelerator("CameraForward"); + command_disconnect_accelerator("CameraBack"); + command_disconnect_accelerator("CameraLeft"); + command_disconnect_accelerator("CameraRight"); + command_disconnect_accelerator("CameraStrafeRight"); + command_disconnect_accelerator("CameraStrafeLeft"); + command_disconnect_accelerator("CameraUp"); + command_disconnect_accelerator("CameraDown"); + command_disconnect_accelerator("CameraAngleUp"); + command_disconnect_accelerator("CameraAngleDown"); +} - g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_freelook_button_press_handler ); +struct CamWnd_Move_Discrete { + static void Export(const Callback &returnz) + { + returnz(g_camwindow_globals_private.m_bCamDiscrete); + } + + static void Import(bool value) + { + if (g_camwnd) { + Import_(*g_camwnd, value); + } else { + g_camwindow_globals_private.m_bCamDiscrete = value; + } + } + + static void Import_(CamWnd &camwnd, bool value) + { + if (g_camwindow_globals_private.m_bCamDiscrete) { + CamWnd_Move_Discrete_Disable(camwnd); + } else { + CamWnd_Move_Disable(camwnd); + } + + g_camwindow_globals_private.m_bCamDiscrete = value; + + if (g_camwindow_globals_private.m_bCamDiscrete) { + CamWnd_Move_Discrete_Enable(camwnd); + } else { + CamWnd_Move_Enable(camwnd); + } + } +}; - if ( g_camwindow_globals_private.m_bCamDiscrete ) { - CamWnd_Move_Discrete_Disable( camwnd ); - } - else - { - CamWnd_Move_Disable( camwnd ); - } -} -void CamWnd_Add_Handlers_FreeMove( CamWnd& camwnd ){ - camwnd.m_selection_button_press_handler = camwnd.m_gl_widget.connect( "button_press_event", G_CALLBACK( selection_button_press_freemove ), camwnd.m_window_observer ); - camwnd.m_selection_button_release_handler = camwnd.m_gl_widget.connect( "button_release_event", G_CALLBACK( selection_button_release_freemove ), camwnd.m_window_observer ); - camwnd.m_selection_motion_handler = camwnd.m_gl_widget.connect( "motion_notify_event", G_CALLBACK( selection_motion_freemove ), camwnd.m_window_observer ); +void CamWnd_Add_Handlers_Move(CamWnd &camwnd) +{ + camwnd.m_selection_button_press_handler = camwnd.m_gl_widget.connect("button_press_event", + G_CALLBACK(selection_button_press), + camwnd.m_window_observer); + camwnd.m_selection_button_release_handler = camwnd.m_gl_widget.connect("button_release_event", + G_CALLBACK(selection_button_release), + camwnd.m_window_observer); + camwnd.m_selection_motion_handler = camwnd.m_gl_widget.connect("motion_notify_event", + G_CALLBACK(DeferredMotion::gtk_motion), + &camwnd.m_deferred_motion); + + camwnd.m_freelook_button_press_handler = camwnd.m_gl_widget.connect("button_press_event", + G_CALLBACK(enable_freelook_button_press), + &camwnd); + + if (g_camwindow_globals_private.m_bCamDiscrete) { + CamWnd_Move_Discrete_Enable(camwnd); + } else { + CamWnd_Move_Enable(camwnd); + } +} + +void CamWnd_Remove_Handlers_Move(CamWnd &camwnd) +{ + g_signal_handler_disconnect(G_OBJECT(camwnd.m_gl_widget), camwnd.m_selection_button_press_handler); + g_signal_handler_disconnect(G_OBJECT(camwnd.m_gl_widget), camwnd.m_selection_button_release_handler); + g_signal_handler_disconnect(G_OBJECT(camwnd.m_gl_widget), camwnd.m_selection_motion_handler); - camwnd.m_freelook_button_press_handler = camwnd.m_gl_widget.connect( "button_press_event", G_CALLBACK( disable_freelook_button_press ), &camwnd ); + g_signal_handler_disconnect(G_OBJECT(camwnd.m_gl_widget), camwnd.m_freelook_button_press_handler); - KeyEvent_connect( "CameraFreeMoveForward" ); - KeyEvent_connect( "CameraFreeMoveBack" ); - KeyEvent_connect( "CameraFreeMoveLeft" ); - KeyEvent_connect( "CameraFreeMoveRight" ); - KeyEvent_connect( "CameraFreeMoveUp" ); - KeyEvent_connect( "CameraFreeMoveDown" ); + if (g_camwindow_globals_private.m_bCamDiscrete) { + CamWnd_Move_Discrete_Disable(camwnd); + } else { + CamWnd_Move_Disable(camwnd); + } } -void CamWnd_Remove_Handlers_FreeMove( CamWnd& camwnd ){ - KeyEvent_disconnect( "CameraFreeMoveForward" ); - KeyEvent_disconnect( "CameraFreeMoveBack" ); - KeyEvent_disconnect( "CameraFreeMoveLeft" ); - KeyEvent_disconnect( "CameraFreeMoveRight" ); - KeyEvent_disconnect( "CameraFreeMoveUp" ); - KeyEvent_disconnect( "CameraFreeMoveDown" ); +void CamWnd_Add_Handlers_FreeMove(CamWnd &camwnd) +{ + camwnd.m_selection_button_press_handler = camwnd.m_gl_widget.connect("button_press_event", + G_CALLBACK(selection_button_press_freemove), + camwnd.m_window_observer); + camwnd.m_selection_button_release_handler = camwnd.m_gl_widget.connect("button_release_event", G_CALLBACK( + selection_button_release_freemove), camwnd.m_window_observer); + camwnd.m_selection_motion_handler = camwnd.m_gl_widget.connect("motion_notify_event", + G_CALLBACK(selection_motion_freemove), + camwnd.m_window_observer); + + camwnd.m_freelook_button_press_handler = camwnd.m_gl_widget.connect("button_press_event", + G_CALLBACK(disable_freelook_button_press), + &camwnd); + + KeyEvent_connect("CameraFreeMoveForward"); + KeyEvent_connect("CameraFreeMoveBack"); + KeyEvent_connect("CameraFreeMoveLeft"); + KeyEvent_connect("CameraFreeMoveRight"); + KeyEvent_connect("CameraFreeMoveUp"); + KeyEvent_connect("CameraFreeMoveDown"); +} + +void CamWnd_Remove_Handlers_FreeMove(CamWnd &camwnd) +{ + KeyEvent_disconnect("CameraFreeMoveForward"); + KeyEvent_disconnect("CameraFreeMoveBack"); + KeyEvent_disconnect("CameraFreeMoveLeft"); + KeyEvent_disconnect("CameraFreeMoveRight"); + KeyEvent_disconnect("CameraFreeMoveUp"); + KeyEvent_disconnect("CameraFreeMoveDown"); - g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_selection_button_press_handler ); - g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_selection_button_release_handler ); - g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_selection_motion_handler ); + g_signal_handler_disconnect(G_OBJECT(camwnd.m_gl_widget), camwnd.m_selection_button_press_handler); + g_signal_handler_disconnect(G_OBJECT(camwnd.m_gl_widget), camwnd.m_selection_button_release_handler); + g_signal_handler_disconnect(G_OBJECT(camwnd.m_gl_widget), camwnd.m_selection_motion_handler); - g_signal_handler_disconnect( G_OBJECT( camwnd.m_gl_widget ), camwnd.m_freelook_button_press_handler ); + g_signal_handler_disconnect(G_OBJECT(camwnd.m_gl_widget), camwnd.m_freelook_button_press_handler); } CamWnd::CamWnd() : - m_view( true ), - m_Camera( &m_view, CamWndQueueDraw( *this ) ), - m_cameraview( m_Camera, &m_view, ReferenceCaller( *this ) ), - m_gl_widget( glwidget_new( TRUE ) ), - m_window_observer( NewWindowObserver() ), - m_XORRectangle( m_gl_widget ), - m_deferredDraw( WidgetQueueDrawCaller( m_gl_widget ) ), - m_deferred_motion( selection_motion, m_window_observer ), - m_selection_button_press_handler( 0 ), - m_selection_button_release_handler( 0 ), - m_selection_motion_handler( 0 ), - m_freelook_button_press_handler( 0 ), - m_drawing( false ){ - m_bFreeMove = false; + m_view(true), + m_Camera(&m_view, CamWndQueueDraw(*this)), + m_cameraview(m_Camera, &m_view, ReferenceCaller(*this)), + m_gl_widget(glwidget_new(TRUE)), + m_window_observer(NewWindowObserver()), + m_XORRectangle(m_gl_widget), + m_deferredDraw(WidgetQueueDrawCaller(m_gl_widget)), + m_deferred_motion(selection_motion, m_window_observer), + m_selection_button_press_handler(0), + m_selection_button_release_handler(0), + m_selection_motion_handler(0), + m_freelook_button_press_handler(0), + m_drawing(false) +{ + m_bFreeMove = false; - GlobalWindowObservers_add( m_window_observer ); - GlobalWindowObservers_connectWidget( m_gl_widget ); + GlobalWindowObservers_add(m_window_observer); + GlobalWindowObservers_connectWidget(m_gl_widget); - m_window_observer->setRectangleDrawCallback( ReferenceCaller( *this ) ); - m_window_observer->setView( m_view ); + m_window_observer->setRectangleDrawCallback( + ReferenceCaller(*this)); + m_window_observer->setView(m_view); - g_object_ref( m_gl_widget._handle ); + g_object_ref(m_gl_widget._handle); - gtk_widget_set_events( m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK ); - gtk_widget_set_can_focus( m_gl_widget, true ); + gtk_widget_set_events(m_gl_widget, + GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK); + gtk_widget_set_can_focus(m_gl_widget, true); - m_sizeHandler = m_gl_widget.connect( "size_allocate", G_CALLBACK( camera_size_allocate ), this ); - m_exposeHandler = m_gl_widget.on_render( G_CALLBACK( camera_expose ), this ); + m_sizeHandler = m_gl_widget.connect("size_allocate", G_CALLBACK(camera_size_allocate), this); + m_exposeHandler = m_gl_widget.on_render(G_CALLBACK(camera_expose), this); - Map_addValidCallback( g_map, DeferredDrawOnMapValidChangedCaller( m_deferredDraw ) ); + Map_addValidCallback(g_map, DeferredDrawOnMapValidChangedCaller(m_deferredDraw)); - CamWnd_registerCommands( *this ); + CamWnd_registerCommands(*this); - CamWnd_Add_Handlers_Move( *this ); + CamWnd_Add_Handlers_Move(*this); - m_gl_widget.connect( "scroll_event", G_CALLBACK( wheelmove_scroll ), this ); + m_gl_widget.connect("scroll_event", G_CALLBACK(wheelmove_scroll), this); - AddSceneChangeCallback( ReferenceCaller( *this ) ); + AddSceneChangeCallback(ReferenceCaller(*this)); - PressedButtons_connect( g_pressedButtons, m_gl_widget ); + PressedButtons_connect(g_pressedButtons, m_gl_widget); } -CamWnd::~CamWnd(){ - if ( m_bFreeMove ) { - DisableFreeMove(); - } +CamWnd::~CamWnd() +{ + if (m_bFreeMove) { + DisableFreeMove(); + } - CamWnd_Remove_Handlers_Move( *this ); + CamWnd_Remove_Handlers_Move(*this); - g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_sizeHandler ); - g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_exposeHandler ); + g_signal_handler_disconnect(G_OBJECT(m_gl_widget), m_sizeHandler); + g_signal_handler_disconnect(G_OBJECT(m_gl_widget), m_exposeHandler); - m_gl_widget.unref(); + m_gl_widget.unref(); - m_window_observer->release(); + m_window_observer->release(); } -class FloorHeightWalker : public scene::Graph::Walker -{ -float m_current; -float& m_bestUp; -float& m_bestDown; +class FloorHeightWalker : public scene::Graph::Walker { + float m_current; + float &m_bestUp; + float &m_bestDown; public: -FloorHeightWalker( float current, float& bestUp, float& bestDown ) : - m_current( current ), m_bestUp( bestUp ), m_bestDown( bestDown ){ - bestUp = g_MaxWorldCoord; - bestDown = -g_MaxWorldCoord; -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() - && Node_isBrush( path.top() ) ) { // this node is a floor - const AABB& aabb = instance.worldAABB(); - float floorHeight = aabb.origin.z() + aabb.extents.z(); - if ( floorHeight > m_current && floorHeight < m_bestUp ) { - m_bestUp = floorHeight; - } - if ( floorHeight < m_current && floorHeight > m_bestDown ) { - m_bestDown = floorHeight; - } - } - return true; -} + FloorHeightWalker(float current, float &bestUp, float &bestDown) : + m_current(current), m_bestUp(bestUp), m_bestDown(bestDown) + { + bestUp = g_MaxWorldCoord; + bestDown = -g_MaxWorldCoord; + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible() + && Node_isBrush(path.top())) { // this node is a floor + const AABB &aabb = instance.worldAABB(); + float floorHeight = aabb.origin.z() + aabb.extents.z(); + if (floorHeight > m_current && floorHeight < m_bestUp) { + m_bestUp = floorHeight; + } + if (floorHeight < m_current && floorHeight > m_bestDown) { + m_bestDown = floorHeight; + } + } + return true; + } }; -void CamWnd::Cam_ChangeFloor( bool up ){ - float current = m_Camera.origin[2] - 48; - float bestUp; - float bestDown; - GlobalSceneGraph().traverse( FloorHeightWalker( current, bestUp, bestDown ) ); +void CamWnd::Cam_ChangeFloor(bool up) +{ + float current = m_Camera.origin[2] - 48; + float bestUp; + float bestDown; + GlobalSceneGraph().traverse(FloorHeightWalker(current, bestUp, bestDown)); - if ( up && bestUp != g_MaxWorldCoord ) { - current = bestUp; - } - if ( !up && bestDown != -g_MaxWorldCoord ) { - current = bestDown; - } + if (up && bestUp != g_MaxWorldCoord) { + current = bestUp; + } + if (!up && bestDown != -g_MaxWorldCoord) { + current = bestDown; + } - m_Camera.origin[2] = current + 48; - Camera_updateModelview( getCamera() ); - CamWnd_Update( *this ); - CameraMovedNotify(); + m_Camera.origin[2] = current + 48; + Camera_updateModelview(getCamera()); + CamWnd_Update(*this); + CameraMovedNotify(); } #if 0 -// button_press + // button_press Sys_GetCursorPos( &m_PositionDragCursorX, &m_PositionDragCursorY ); // motion @@ -1272,113 +1441,131 @@ void CamWnd::Cam_PositionDrag(){ // NOTE TTimo if there's an OS-level focus out of the application // then we can release the camera cursor grab -static gboolean camwindow_freemove_focusout( ui::Widget widget, GdkEventFocus* event, gpointer data ){ - reinterpret_cast( data )->DisableFreeMove(); - return FALSE; +static gboolean camwindow_freemove_focusout(ui::Widget widget, GdkEventFocus *event, gpointer data) +{ + reinterpret_cast( data )->DisableFreeMove(); + return FALSE; } -void CamWnd::EnableFreeMove(){ - //globalOutputStream() << "EnableFreeMove\n"; +void CamWnd::EnableFreeMove() +{ + //globalOutputStream() << "EnableFreeMove\n"; - ASSERT_MESSAGE( !m_bFreeMove, "EnableFreeMove: free-move was already enabled" ); - m_bFreeMove = true; - Camera_clearMovementFlags( getCamera(), MOVE_ALL ); + ASSERT_MESSAGE(!m_bFreeMove, "EnableFreeMove: free-move was already enabled"); + m_bFreeMove = true; + Camera_clearMovementFlags(getCamera(), MOVE_ALL); - CamWnd_Remove_Handlers_Move( *this ); - CamWnd_Add_Handlers_FreeMove( *this ); + CamWnd_Remove_Handlers_Move(*this); + CamWnd_Add_Handlers_FreeMove(*this); - gtk_window_set_focus( m_parent, m_gl_widget ); - m_freemove_handle_focusout = m_gl_widget.connect( "focus_out_event", G_CALLBACK( camwindow_freemove_focusout ), this ); - m_freezePointer.freeze_pointer( m_parent, Camera_motionDelta, &m_Camera ); + gtk_window_set_focus(m_parent, m_gl_widget); + m_freemove_handle_focusout = m_gl_widget.connect("focus_out_event", G_CALLBACK(camwindow_freemove_focusout), this); + m_freezePointer.freeze_pointer(m_parent, Camera_motionDelta, &m_Camera); - CamWnd_Update( *this ); + CamWnd_Update(*this); } -void CamWnd::DisableFreeMove(){ - //globalOutputStream() << "DisableFreeMove\n"; +void CamWnd::DisableFreeMove() +{ + //globalOutputStream() << "DisableFreeMove\n"; - ASSERT_MESSAGE( m_bFreeMove, "DisableFreeMove: free-move was not enabled" ); - m_bFreeMove = false; - Camera_clearMovementFlags( getCamera(), MOVE_ALL ); + ASSERT_MESSAGE(m_bFreeMove, "DisableFreeMove: free-move was not enabled"); + m_bFreeMove = false; + Camera_clearMovementFlags(getCamera(), MOVE_ALL); - CamWnd_Remove_Handlers_FreeMove( *this ); - CamWnd_Add_Handlers_Move( *this ); + CamWnd_Remove_Handlers_FreeMove(*this); + CamWnd_Add_Handlers_Move(*this); - m_freezePointer.unfreeze_pointer( m_parent ); - g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_freemove_handle_focusout ); + m_freezePointer.unfreeze_pointer(m_parent); + g_signal_handler_disconnect(G_OBJECT(m_gl_widget), m_freemove_handle_focusout); - CamWnd_Update( *this ); + CamWnd_Update(*this); } #include "renderer.h" -class CamRenderer : public Renderer -{ -struct state_type -{ - state_type() : m_highlight( 0 ), m_state( 0 ), m_lights( 0 ){ - } - unsigned int m_highlight; - Shader* m_state; - const LightList* m_lights; -}; - -std::vector m_state_stack; -RenderStateFlags m_globalstate; -Shader* m_state_select0; -Shader* m_state_select1; -const Vector3& m_viewer; +class CamRenderer : public Renderer { + struct state_type { + state_type() : m_highlight(0), m_state(0), m_lights(0) + { + } -public: -CamRenderer( RenderStateFlags globalstate, Shader* select0, Shader* select1, const Vector3& viewer ) : - m_globalstate( globalstate ), - m_state_select0( select0 ), - m_state_select1( select1 ), - m_viewer( viewer ){ - ASSERT_NOTNULL( select0 ); - ASSERT_NOTNULL( select1 ); - m_state_stack.push_back( state_type() ); -} - -void SetState( Shader* state, EStyle style ){ - ASSERT_NOTNULL( state ); - if ( style == eFullMaterials ) { - m_state_stack.back().m_state = state; - } -} -EStyle getStyle() const { - return eFullMaterials; -} -void PushState(){ - m_state_stack.push_back( m_state_stack.back() ); -} -void PopState(){ - ASSERT_MESSAGE( !m_state_stack.empty(), "popping empty stack" ); - m_state_stack.pop_back(); -} -void Highlight( EHighlightMode mode, bool bEnable = true ){ - ( bEnable ) - ? m_state_stack.back().m_highlight |= mode - : m_state_stack.back().m_highlight &= ~mode; -} -void setLights( const LightList& lights ){ - m_state_stack.back().m_lights = &lights; -} -void addRenderable( const OpenGLRenderable& renderable, const Matrix4& world ){ - if ( m_state_stack.back().m_highlight & ePrimitive ) { - m_state_select0->addRenderable( renderable, world, m_state_stack.back().m_lights ); - } - if ( m_state_stack.back().m_highlight & eFace ) { - m_state_select1->addRenderable( renderable, world, m_state_stack.back().m_lights ); - } + unsigned int m_highlight; + Shader *m_state; + const LightList *m_lights; + }; - m_state_stack.back().m_state->addRenderable( renderable, world, m_state_stack.back().m_lights ); -} + std::vector m_state_stack; + RenderStateFlags m_globalstate; + Shader *m_state_select0; + Shader *m_state_select1; + const Vector3 &m_viewer; -void render( const Matrix4& modelview, const Matrix4& projection ){ - GlobalShaderCache().render( m_globalstate, modelview, projection, m_viewer ); -} +public: + CamRenderer(RenderStateFlags globalstate, Shader *select0, Shader *select1, const Vector3 &viewer) : + m_globalstate(globalstate), + m_state_select0(select0), + m_state_select1(select1), + m_viewer(viewer) + { + ASSERT_NOTNULL(select0); + ASSERT_NOTNULL(select1); + m_state_stack.push_back(state_type()); + } + + void SetState(Shader *state, EStyle style) + { + ASSERT_NOTNULL(state); + if (style == eFullMaterials) { + m_state_stack.back().m_state = state; + } + } + + EStyle getStyle() const + { + return eFullMaterials; + } + + void PushState() + { + m_state_stack.push_back(m_state_stack.back()); + } + + void PopState() + { + ASSERT_MESSAGE(!m_state_stack.empty(), "popping empty stack"); + m_state_stack.pop_back(); + } + + void Highlight(EHighlightMode mode, bool bEnable = true) + { + (bEnable) + ? m_state_stack.back().m_highlight |= mode + : m_state_stack.back().m_highlight &= ~mode; + } + + void setLights(const LightList &lights) + { + m_state_stack.back().m_lights = &lights; + } + + void addRenderable(const OpenGLRenderable &renderable, const Matrix4 &world) + { + if (m_state_stack.back().m_highlight & ePrimitive) { + m_state_select0->addRenderable(renderable, world, m_state_stack.back().m_lights); + } + if (m_state_stack.back().m_highlight & eFace) { + m_state_select1->addRenderable(renderable, world, m_state_stack.back().m_lights); + } + + m_state_stack.back().m_state->addRenderable(renderable, world, m_state_stack.back().m_lights); + } + + void render(const Matrix4 &modelview, const Matrix4 &projection) + { + GlobalShaderCache().render(m_globalstate, modelview, projection, m_viewer); + } }; /* @@ -1387,541 +1574,602 @@ void render( const Matrix4& modelview, const Matrix4& projection ){ ============== */ -void ShowStatsToggle(){ - g_camwindow_globals_private.m_showStats ^= 1; +void ShowStatsToggle() +{ + g_camwindow_globals_private.m_showStats ^= 1; } -void ShowStatsExport( const Callback &importer ){ - importer( g_camwindow_globals_private.m_showStats ); +void ShowStatsExport(const Callback &importer) +{ + importer(g_camwindow_globals_private.m_showStats); } -FreeCaller&), ShowStatsExport> g_show_stats_caller; -Callback &)> g_show_stats_callback( g_show_stats_caller ); -ToggleItem g_show_stats( g_show_stats_callback ); +FreeCaller &), ShowStatsExport> g_show_stats_caller; +Callback &)> g_show_stats_callback(g_show_stats_caller); +ToggleItem g_show_stats(g_show_stats_callback); -void CamWnd::Cam_Draw(){ - glViewport( 0, 0, m_Camera.width, m_Camera.height ); +void CamWnd::Cam_Draw() +{ + glViewport(0, 0, m_Camera.width, m_Camera.height); #if 0 - GLint viewprt[4]; + GLint viewprt[4]; glGetIntegerv( GL_VIEWPORT, viewprt ); #endif - // enable depth buffer writes - glDepthMask( GL_TRUE ); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - - Vector3 clearColour( 0, 0, 0 ); - if ( m_Camera.draw_mode != cd_lighting ) { - clearColour = g_camwindow_globals.color_cameraback; - } - - glClearColor( clearColour[0], clearColour[1], clearColour[2], 0 ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - extern void Renderer_ResetStats(); - Renderer_ResetStats(); - extern void Cull_ResetStats(); - Cull_ResetStats(); - - glMatrixMode( GL_PROJECTION ); - glLoadMatrixf( reinterpret_cast( &m_Camera.projection ) ); - - glMatrixMode( GL_MODELVIEW ); - glLoadMatrixf( reinterpret_cast( &m_Camera.modelview ) ); - - - // one directional light source directly behind the viewer - { - GLfloat inverse_cam_dir[4], ambient[4], diffuse[4]; //, material[4]; - - ambient[0] = ambient[1] = ambient[2] = 0.4f; - ambient[3] = 1.0f; - diffuse[0] = diffuse[1] = diffuse[2] = 0.4f; - diffuse[3] = 1.0f; - //material[0] = material[1] = material[2] = 0.8f; - //material[3] = 1.0f; - - inverse_cam_dir[0] = m_Camera.vpn[0]; - inverse_cam_dir[1] = m_Camera.vpn[1]; - inverse_cam_dir[2] = m_Camera.vpn[2]; - inverse_cam_dir[3] = 0; - - glLightfv( GL_LIGHT0, GL_POSITION, inverse_cam_dir ); - - glLightfv( GL_LIGHT0, GL_AMBIENT, ambient ); - glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse ); - - glEnable( GL_LIGHT0 ); - } - - - unsigned int globalstate = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_ALPHATEST | RENDER_BLEND | RENDER_CULLFACE | RENDER_COLOURARRAY | RENDER_OFFSETLINE | RENDER_POLYGONSMOOTH | RENDER_LINESMOOTH | RENDER_FOG | RENDER_COLOURCHANGE; - switch ( m_Camera.draw_mode ) - { - case cd_wire: - break; - case cd_solid: - globalstate |= RENDER_FILL - | RENDER_LIGHTING - | RENDER_SMOOTH - | RENDER_SCALED; - break; - case cd_texture: - globalstate |= RENDER_FILL - | RENDER_LIGHTING - | RENDER_TEXTURE - | RENDER_SMOOTH - | RENDER_SCALED; - break; - case cd_lighting: - globalstate |= RENDER_FILL - | RENDER_LIGHTING - | RENDER_TEXTURE - | RENDER_SMOOTH - | RENDER_SCALED - | RENDER_BUMP - | RENDER_PROGRAM - | RENDER_SCREEN; - break; - default: - globalstate = 0; - break; - } - - if ( !g_xywindow_globals.m_bNoStipple ) { - globalstate |= RENDER_LINESTIPPLE | RENDER_POLYGONSTIPPLE; - } - - { - CamRenderer renderer( globalstate, m_state_select2, m_state_select1, m_view.getViewer() ); - - Scene_Render( renderer, m_view ); - - renderer.render( m_Camera.modelview, m_Camera.projection ); - } - - // prepare for 2d stuff - glColor4f( 1, 1, 1, 1 ); - glDisable( GL_BLEND ); - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( 0, (float)m_Camera.width, 0, (float)m_Camera.height, -100, 100 ); - glScalef( 1, -1, 1 ); - glTranslatef( 0, -(float)m_Camera.height, 0 ); - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - if ( GlobalOpenGL().GL_1_3() ) { - glClientActiveTexture( GL_TEXTURE0 ); - glActiveTexture( GL_TEXTURE0 ); - } - - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - glDisableClientState( GL_NORMAL_ARRAY ); - glDisableClientState( GL_COLOR_ARRAY ); - - glDisable( GL_TEXTURE_2D ); - glDisable( GL_LIGHTING ); - glDisable( GL_COLOR_MATERIAL ); - glDisable( GL_DEPTH_TEST ); - glColor3f( 1.f, 1.f, 1.f ); - glLineWidth( 1 ); - - // draw the crosshair - if ( m_bFreeMove ) { - glBegin( GL_LINES ); - glVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f + 6 ); - glVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f + 2 ); - glVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f - 6 ); - glVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f - 2 ); - glVertex2f( (float)m_Camera.width / 2.f + 6, (float)m_Camera.height / 2.f ); - glVertex2f( (float)m_Camera.width / 2.f + 2, (float)m_Camera.height / 2.f ); - glVertex2f( (float)m_Camera.width / 2.f - 6, (float)m_Camera.height / 2.f ); - glVertex2f( (float)m_Camera.width / 2.f - 2, (float)m_Camera.height / 2.f ); - glEnd(); - } - - if ( g_camwindow_globals_private.m_showStats ) { - glRasterPos3f( 1.0f, static_cast( m_Camera.height ) - GlobalOpenGL().m_font->getPixelDescent(), 0.0f ); - extern const char* Renderer_GetStats(); - GlobalOpenGL().drawString( Renderer_GetStats() ); - - glRasterPos3f( 1.0f, static_cast( m_Camera.height ) - GlobalOpenGL().m_font->getPixelDescent() - GlobalOpenGL().m_font->getPixelHeight(), 0.0f ); - extern const char* Cull_GetStats(); - GlobalOpenGL().drawString( Cull_GetStats() ); - } - - // bind back to the default texture so that we don't have problems - // elsewhere using/modifying texture maps between contexts - glBindTexture( GL_TEXTURE_2D, 0 ); -} - -void CamWnd::draw(){ - m_drawing = true; + // enable depth buffer writes + glDepthMask(GL_TRUE); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + Vector3 clearColour(0, 0, 0); + if (m_Camera.draw_mode != cd_lighting) { + clearColour = g_camwindow_globals.color_cameraback; + } + + glClearColor(clearColour[0], clearColour[1], clearColour[2], 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + extern void Renderer_ResetStats(); + Renderer_ResetStats(); + extern void Cull_ResetStats(); + Cull_ResetStats(); + + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(reinterpret_cast( &m_Camera.projection )); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(reinterpret_cast( &m_Camera.modelview )); + + + // one directional light source directly behind the viewer + { + GLfloat inverse_cam_dir[4], ambient[4], diffuse[4]; //, material[4]; + + ambient[0] = ambient[1] = ambient[2] = 0.4f; + ambient[3] = 1.0f; + diffuse[0] = diffuse[1] = diffuse[2] = 0.4f; + diffuse[3] = 1.0f; + //material[0] = material[1] = material[2] = 0.8f; + //material[3] = 1.0f; + + inverse_cam_dir[0] = m_Camera.vpn[0]; + inverse_cam_dir[1] = m_Camera.vpn[1]; + inverse_cam_dir[2] = m_Camera.vpn[2]; + inverse_cam_dir[3] = 0; + + glLightfv(GL_LIGHT0, GL_POSITION, inverse_cam_dir); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + + glEnable(GL_LIGHT0); + } + + + unsigned int globalstate = + RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_ALPHATEST | RENDER_BLEND | + RENDER_CULLFACE | RENDER_COLOURARRAY | RENDER_OFFSETLINE | RENDER_POLYGONSMOOTH | RENDER_LINESMOOTH | + RENDER_FOG | RENDER_COLOURCHANGE; + switch (m_Camera.draw_mode) { + case cd_wire: + break; + case cd_solid: + globalstate |= RENDER_FILL + | RENDER_LIGHTING + | RENDER_SMOOTH + | RENDER_SCALED; + break; + case cd_texture: + globalstate |= RENDER_FILL + | RENDER_LIGHTING + | RENDER_TEXTURE + | RENDER_SMOOTH + | RENDER_SCALED; + break; + case cd_lighting: + globalstate |= RENDER_FILL + | RENDER_LIGHTING + | RENDER_TEXTURE + | RENDER_SMOOTH + | RENDER_SCALED + | RENDER_BUMP + | RENDER_PROGRAM + | RENDER_SCREEN; + break; + default: + globalstate = 0; + break; + } + + if (!g_xywindow_globals.m_bNoStipple) { + globalstate |= RENDER_LINESTIPPLE | RENDER_POLYGONSTIPPLE; + } + + { + CamRenderer renderer(globalstate, m_state_select2, m_state_select1, m_view.getViewer()); + + Scene_Render(renderer, m_view); + + renderer.render(m_Camera.modelview, m_Camera.projection); + } + + // prepare for 2d stuff + glColor4f(1, 1, 1, 1); + glDisable(GL_BLEND); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, (float) m_Camera.width, 0, (float) m_Camera.height, -100, 100); + glScalef(1, -1, 1); + glTranslatef(0, -(float) m_Camera.height, 0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (GlobalOpenGL().GL_1_3()) { + glClientActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); + } + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_DEPTH_TEST); + glColor3f(1.f, 1.f, 1.f); + glLineWidth(1); + + // draw the crosshair + if (m_bFreeMove) { + glBegin(GL_LINES); + glVertex2f((float) m_Camera.width / 2.f, (float) m_Camera.height / 2.f + 6); + glVertex2f((float) m_Camera.width / 2.f, (float) m_Camera.height / 2.f + 2); + glVertex2f((float) m_Camera.width / 2.f, (float) m_Camera.height / 2.f - 6); + glVertex2f((float) m_Camera.width / 2.f, (float) m_Camera.height / 2.f - 2); + glVertex2f((float) m_Camera.width / 2.f + 6, (float) m_Camera.height / 2.f); + glVertex2f((float) m_Camera.width / 2.f + 2, (float) m_Camera.height / 2.f); + glVertex2f((float) m_Camera.width / 2.f - 6, (float) m_Camera.height / 2.f); + glVertex2f((float) m_Camera.width / 2.f - 2, (float) m_Camera.height / 2.f); + glEnd(); + } + + if (g_camwindow_globals_private.m_showStats) { + glRasterPos3f(1.0f, static_cast( m_Camera.height ) - GlobalOpenGL().m_font->getPixelDescent(), 0.0f); + extern const char *Renderer_GetStats(); + GlobalOpenGL().drawString(Renderer_GetStats()); + + glRasterPos3f(1.0f, static_cast( m_Camera.height ) - GlobalOpenGL().m_font->getPixelDescent() - + GlobalOpenGL().m_font->getPixelHeight(), 0.0f); + extern const char *Cull_GetStats(); + GlobalOpenGL().drawString(Cull_GetStats()); + } + + // bind back to the default texture so that we don't have problems + // elsewhere using/modifying texture maps between contexts + glBindTexture(GL_TEXTURE_2D, 0); +} + +void CamWnd::draw() +{ + m_drawing = true; - //globalOutputStream() << "draw...\n"; - if ( glwidget_make_current( m_gl_widget ) != FALSE ) { - if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) { - GlobalOpenGL_debugAssertNoErrors(); - Cam_Draw(); - GlobalOpenGL_debugAssertNoErrors(); - //qglFinish(); + //globalOutputStream() << "draw...\n"; + if (glwidget_make_current(m_gl_widget) != FALSE) { + if (Map_Valid(g_map) && ScreenUpdates_Enabled()) { + GlobalOpenGL_debugAssertNoErrors(); + Cam_Draw(); + GlobalOpenGL_debugAssertNoErrors(); + //qglFinish(); - m_XORRectangle.set( rectangle_t() ); - } + m_XORRectangle.set(rectangle_t()); + } - glwidget_swap_buffers( m_gl_widget ); - } + glwidget_swap_buffers(m_gl_widget); + } - m_drawing = false; + m_drawing = false; } -void CamWnd::BenchMark(){ - double dStart = Sys_DoubleTime(); - for ( int i = 0 ; i < 100 ; i++ ) - { - Vector3 angles; - angles[CAMERA_ROLL] = 0; - angles[CAMERA_PITCH] = 0; - angles[CAMERA_YAW] = static_cast( i * ( 360.0 / 100.0 ) ); - Camera_setAngles( *this, angles ); - } - double dEnd = Sys_DoubleTime(); - globalOutputStream() << FloatFormat( dEnd - dStart, 5, 2 ) << " seconds\n"; +void CamWnd::BenchMark() +{ + double dStart = Sys_DoubleTime(); + for (int i = 0; i < 100; i++) { + Vector3 angles; + angles[CAMERA_ROLL] = 0; + angles[CAMERA_PITCH] = 0; + angles[CAMERA_YAW] = static_cast( i * (360.0 / 100.0)); + Camera_setAngles(*this, angles); + } + double dEnd = Sys_DoubleTime(); + globalOutputStream() << FloatFormat(dEnd - dStart, 5, 2) << " seconds\n"; } -void fill_view_camera_menu( ui::Menu menu ){ - create_check_menu_item_with_mnemonic( menu, "Camera View", "ToggleCamera" ); +void fill_view_camera_menu(ui::Menu menu) +{ + create_check_menu_item_with_mnemonic(menu, "Camera View", "ToggleCamera"); } -void GlobalCamera_ResetAngles(){ - CamWnd& camwnd = *g_camwnd; - Vector3 angles; - angles[CAMERA_ROLL] = angles[CAMERA_PITCH] = 0; - angles[CAMERA_YAW] = static_cast( 22.5 * floor( ( Camera_getAngles( camwnd )[CAMERA_YAW] + 11 ) / 22.5 ) ); - Camera_setAngles( camwnd, angles ); +void GlobalCamera_ResetAngles() +{ + CamWnd &camwnd = *g_camwnd; + Vector3 angles; + angles[CAMERA_ROLL] = angles[CAMERA_PITCH] = 0; + angles[CAMERA_YAW] = static_cast( 22.5 * floor((Camera_getAngles(camwnd)[CAMERA_YAW] + 11) / 22.5)); + Camera_setAngles(camwnd, angles); } -void Camera_ChangeFloorUp(){ - CamWnd& camwnd = *g_camwnd; - camwnd.Cam_ChangeFloor( true ); +void Camera_ChangeFloorUp() +{ + CamWnd &camwnd = *g_camwnd; + camwnd.Cam_ChangeFloor(true); } -void Camera_ChangeFloorDown(){ - CamWnd& camwnd = *g_camwnd; - camwnd.Cam_ChangeFloor( false ); +void Camera_ChangeFloorDown() +{ + CamWnd &camwnd = *g_camwnd; + camwnd.Cam_ChangeFloor(false); } -void Camera_CubeIn(){ - CamWnd& camwnd = *g_camwnd; - g_camwindow_globals.m_nCubicScale--; - if ( g_camwindow_globals.m_nCubicScale < 1 ) { - g_camwindow_globals.m_nCubicScale = 1; - } - Camera_updateProjection( camwnd.getCamera() ); - CamWnd_Update( camwnd ); - g_pParentWnd->SetGridStatus(); +void Camera_CubeIn() +{ + CamWnd &camwnd = *g_camwnd; + g_camwindow_globals.m_nCubicScale--; + if (g_camwindow_globals.m_nCubicScale < 1) { + g_camwindow_globals.m_nCubicScale = 1; + } + Camera_updateProjection(camwnd.getCamera()); + CamWnd_Update(camwnd); + g_pParentWnd->SetGridStatus(); } -void Camera_CubeOut(){ - CamWnd& camwnd = *g_camwnd; - g_camwindow_globals.m_nCubicScale++; - if ( g_camwindow_globals.m_nCubicScale > 23 ) { - g_camwindow_globals.m_nCubicScale = 23; - } - Camera_updateProjection( camwnd.getCamera() ); - CamWnd_Update( camwnd ); - g_pParentWnd->SetGridStatus(); +void Camera_CubeOut() +{ + CamWnd &camwnd = *g_camwnd; + g_camwindow_globals.m_nCubicScale++; + if (g_camwindow_globals.m_nCubicScale > 23) { + g_camwindow_globals.m_nCubicScale = 23; + } + Camera_updateProjection(camwnd.getCamera()); + CamWnd_Update(camwnd); + g_pParentWnd->SetGridStatus(); } -bool Camera_GetFarClip(){ - return g_camwindow_globals_private.m_bCubicClipping; +bool Camera_GetFarClip() +{ + return g_camwindow_globals_private.m_bCubicClipping; } -ConstReferenceCaller &), PropertyImpl::Export> g_getfarclip_caller( g_camwindow_globals_private.m_bCubicClipping ); -ToggleItem g_getfarclip_item( g_getfarclip_caller ); +ConstReferenceCaller &), PropertyImpl::Export> g_getfarclip_caller( + g_camwindow_globals_private.m_bCubicClipping); +ToggleItem g_getfarclip_item(g_getfarclip_caller); -void Camera_SetFarClip( bool value ){ - CamWnd& camwnd = *g_camwnd; - g_camwindow_globals_private.m_bCubicClipping = value; - g_getfarclip_item.update(); - Camera_updateProjection( camwnd.getCamera() ); - CamWnd_Update( camwnd ); +void Camera_SetFarClip(bool value) +{ + CamWnd &camwnd = *g_camwnd; + g_camwindow_globals_private.m_bCubicClipping = value; + g_getfarclip_item.update(); + Camera_updateProjection(camwnd.getCamera()); + CamWnd_Update(camwnd); } struct Camera_FarClip { - static void Export(const Callback &returnz) { - returnz(g_camwindow_globals_private.m_bCubicClipping); - } - - static void Import(bool value) { - Camera_SetFarClip(value); - } + static void Export(const Callback &returnz) + { + returnz(g_camwindow_globals_private.m_bCubicClipping); + } + + static void Import(bool value) + { + Camera_SetFarClip(value); + } }; -void Camera_ToggleFarClip(){ - Camera_SetFarClip( !Camera_GetFarClip() ); +void Camera_ToggleFarClip() +{ + Camera_SetFarClip(!Camera_GetFarClip()); } -void CamWnd_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_toggle_button( toolbar, "Cubic clip the camera view (\\)", "view_cubicclipping.png", "ToggleCubicClip" ); +void CamWnd_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_toggle_button(toolbar, "Cubic clip the camera view (\\)", "view_cubicclipping.png", + "ToggleCubicClip"); } -void CamWnd_registerShortcuts(){ - toggle_add_accelerator( "ToggleCubicClip" ); +void CamWnd_registerShortcuts() +{ + toggle_add_accelerator("ToggleCubicClip"); - if ( g_pGameDescription->mGameType == "doom3" ) { - command_connect_accelerator( "TogglePreview" ); - } + if (g_pGameDescription->mGameType == "doom3") { + command_connect_accelerator("TogglePreview"); + } - command_connect_accelerator( "CameraSpeedInc" ); - command_connect_accelerator( "CameraSpeedDec" ); + command_connect_accelerator("CameraSpeedInc"); + command_connect_accelerator("CameraSpeedDec"); } -void GlobalCamera_Benchmark(){ - CamWnd& camwnd = *g_camwnd; - camwnd.BenchMark(); +void GlobalCamera_Benchmark() +{ + CamWnd &camwnd = *g_camwnd; + camwnd.BenchMark(); } -void GlobalCamera_Update(){ - CamWnd& camwnd = *g_camwnd; - CamWnd_Update( camwnd ); +void GlobalCamera_Update() +{ + CamWnd &camwnd = *g_camwnd; + CamWnd_Update(camwnd); } -camera_draw_mode CamWnd_GetMode(){ - return camera_t::draw_mode; +camera_draw_mode CamWnd_GetMode() +{ + return camera_t::draw_mode; } -void CamWnd_SetMode( camera_draw_mode mode ){ - ShaderCache_setBumpEnabled( mode == cd_lighting ); - camera_t::draw_mode = mode; - if ( g_camwnd != 0 ) { - CamWnd_Update( *g_camwnd ); - } + +void CamWnd_SetMode(camera_draw_mode mode) +{ + ShaderCache_setBumpEnabled(mode == cd_lighting); + camera_t::draw_mode = mode; + if (g_camwnd != 0) { + CamWnd_Update(*g_camwnd); + } } -void CamWnd_TogglePreview( void ){ - // gametype must be doom3 for this function to work - // if the gametype is not doom3 something is wrong with the - // global command list or somebody else calls this function. - ASSERT_MESSAGE( g_pGameDescription->mGameType == "doom3", "CamWnd_TogglePreview called although mGameType is not doom3 compatible" ); +void CamWnd_TogglePreview(void) +{ + // gametype must be doom3 for this function to work + // if the gametype is not doom3 something is wrong with the + // global command list or somebody else calls this function. + ASSERT_MESSAGE(g_pGameDescription->mGameType == "doom3", + "CamWnd_TogglePreview called although mGameType is not doom3 compatible"); - // switch between textured and lighting mode - CamWnd_SetMode( ( CamWnd_GetMode() == cd_lighting ) ? cd_texture : cd_lighting ); + // switch between textured and lighting mode + CamWnd_SetMode((CamWnd_GetMode() == cd_lighting) ? cd_texture : cd_lighting); } -CameraModel* g_camera_model = 0; +CameraModel *g_camera_model = 0; -void CamWnd_LookThroughCamera( CamWnd& camwnd ){ - if ( g_camera_model != 0 ) { - CamWnd_Add_Handlers_Move( camwnd ); - g_camera_model->setCameraView( 0, Callback() ); - g_camera_model = 0; - Camera_updateModelview( camwnd.getCamera() ); - Camera_updateProjection( camwnd.getCamera() ); - CamWnd_Update( camwnd ); - } -} - -inline CameraModel* Instance_getCameraModel( scene::Instance& instance ){ - return InstanceTypeCast::cast( instance ); +void CamWnd_LookThroughCamera(CamWnd &camwnd) +{ + if (g_camera_model != 0) { + CamWnd_Add_Handlers_Move(camwnd); + g_camera_model->setCameraView(0, Callback()); + g_camera_model = 0; + Camera_updateModelview(camwnd.getCamera()); + Camera_updateProjection(camwnd.getCamera()); + CamWnd_Update(camwnd); + } } -void CamWnd_LookThroughSelected( CamWnd& camwnd ){ - if ( g_camera_model != 0 ) { - CamWnd_LookThroughCamera( camwnd ); - } - - if ( GlobalSelectionSystem().countSelected() != 0 ) { - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); - CameraModel* cameraModel = Instance_getCameraModel( instance ); - if ( cameraModel != 0 ) { - CamWnd_Remove_Handlers_Move( camwnd ); - g_camera_model = cameraModel; - g_camera_model->setCameraView( &camwnd.getCameraView(), ReferenceCaller( camwnd ) ); - } - } +inline CameraModel *Instance_getCameraModel(scene::Instance &instance) +{ + return InstanceTypeCast::cast(instance); } -void GlobalCamera_LookThroughSelected(){ - CamWnd_LookThroughSelected( *g_camwnd ); +void CamWnd_LookThroughSelected(CamWnd &camwnd) +{ + if (g_camera_model != 0) { + CamWnd_LookThroughCamera(camwnd); + } + + if (GlobalSelectionSystem().countSelected() != 0) { + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); + CameraModel *cameraModel = Instance_getCameraModel(instance); + if (cameraModel != 0) { + CamWnd_Remove_Handlers_Move(camwnd); + g_camera_model = cameraModel; + g_camera_model->setCameraView(&camwnd.getCameraView(), + ReferenceCaller(camwnd)); + } + } +} + +void GlobalCamera_LookThroughSelected() +{ + CamWnd_LookThroughSelected(*g_camwnd); } -void GlobalCamera_LookThroughCamera(){ - CamWnd_LookThroughCamera( *g_camwnd ); +void GlobalCamera_LookThroughCamera() +{ + CamWnd_LookThroughCamera(*g_camwnd); } struct RenderMode { - static void Export(const Callback &returnz) { - switch (CamWnd_GetMode()) { - case cd_wire: - returnz(0); - break; - case cd_solid: - returnz(1); - break; - case cd_texture: - returnz(2); - break; - case cd_lighting: - returnz(3); - break; - } - } - - static void Import(int value) { - switch (value) { - case 0: - CamWnd_SetMode(cd_wire); - break; - case 1: - CamWnd_SetMode(cd_solid); - break; - case 2: - CamWnd_SetMode(cd_texture); - break; - case 3: - CamWnd_SetMode(cd_lighting); - break; - default: - CamWnd_SetMode(cd_texture); - } - } + static void Export(const Callback &returnz) + { + switch (CamWnd_GetMode()) { + case cd_wire: + returnz(0); + break; + case cd_solid: + returnz(1); + break; + case cd_texture: + returnz(2); + break; + case cd_lighting: + returnz(3); + break; + } + } + + static void Import(int value) + { + switch (value) { + case 0: + CamWnd_SetMode(cd_wire); + break; + case 1: + CamWnd_SetMode(cd_solid); + break; + case 2: + CamWnd_SetMode(cd_texture); + break; + case 3: + CamWnd_SetMode(cd_lighting); + break; + default: + CamWnd_SetMode(cd_texture); + } + } }; -void Camera_constructPreferences( PreferencesPage& page ){ - page.appendSlider( "Movement Speed", g_camwindow_globals_private.m_nMoveSpeed, TRUE, 0, 0, 100, MIN_CAM_SPEED, MAX_CAM_SPEED, 1, 10 ); - page.appendCheckBox( "", "Link strafe speed to movement speed", g_camwindow_globals_private.m_bCamLinkSpeed ); - page.appendSlider( "Rotation Speed", g_camwindow_globals_private.m_nAngleSpeed, TRUE, 0, 0, 3, 1, 180, 1, 10 ); - page.appendCheckBox( "", "Invert mouse vertical axis", g_camwindow_globals_private.m_bCamInverseMouse ); - page.appendCheckBox( - "", "Discrete movement", - make_property() - ); - page.appendCheckBox( - "", "Enable far-clip plane", - make_property() - ); - - if ( g_pGameDescription->mGameType == "doom3" ) { - const char* render_mode[] = { "Wireframe", "Flatshade", "Textured", "Lighting" }; - - page.appendCombo( - "Render Mode", - STRING_ARRAY_RANGE( render_mode ), - make_property() - ); - } - else - { - const char* render_mode[] = { "Wireframe", "Flatshade", "Textured" }; - - page.appendCombo( - "Render Mode", - STRING_ARRAY_RANGE( render_mode ), - make_property() - ); - } - - const char* strafe_mode[] = { "Both", "Forward", "Up" }; - - page.appendCombo( - "Strafe Mode", - g_camwindow_globals_private.m_nStrafeMode, - STRING_ARRAY_RANGE( strafe_mode ) - ); -} -void Camera_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Camera", "Camera View Preferences" ) ); - Camera_constructPreferences( page ); +void Camera_constructPreferences(PreferencesPage &page) +{ + page.appendSlider("Movement Speed", g_camwindow_globals_private.m_nMoveSpeed, TRUE, 0, 0, 100, MIN_CAM_SPEED, + MAX_CAM_SPEED, 1, 10); + page.appendCheckBox("", "Link strafe speed to movement speed", g_camwindow_globals_private.m_bCamLinkSpeed); + page.appendSlider("Rotation Speed", g_camwindow_globals_private.m_nAngleSpeed, TRUE, 0, 0, 3, 1, 180, 1, 10); + page.appendCheckBox("", "Invert mouse vertical axis", g_camwindow_globals_private.m_bCamInverseMouse); + page.appendCheckBox( + "", "Discrete movement", + make_property() + ); + page.appendCheckBox( + "", "Enable far-clip plane", + make_property() + ); + + if (g_pGameDescription->mGameType == "doom3") { + const char *render_mode[] = {"Wireframe", "Flatshade", "Textured", "Lighting"}; + + page.appendCombo( + "Render Mode", + STRING_ARRAY_RANGE(render_mode), + make_property() + ); + } else { + const char *render_mode[] = {"Wireframe", "Flatshade", "Textured"}; + + page.appendCombo( + "Render Mode", + STRING_ARRAY_RANGE(render_mode), + make_property() + ); + } + + const char *strafe_mode[] = {"Both", "Forward", "Up"}; + + page.appendCombo( + "Strafe Mode", + g_camwindow_globals_private.m_nStrafeMode, + STRING_ARRAY_RANGE(strafe_mode) + ); +} + +void Camera_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Camera", "Camera View Preferences")); + Camera_constructPreferences(page); } -void Camera_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage( makeCallbackF(Camera_constructPage) ); + +void Camera_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(Camera_constructPage)); } #include "preferencesystem.h" #include "stringio.h" #include "dialog.h" -void CameraSpeed_increase(){ - if ( g_camwindow_globals_private.m_nMoveSpeed <= ( MAX_CAM_SPEED - CAM_SPEED_STEP - 10 ) ) { - g_camwindow_globals_private.m_nMoveSpeed += CAM_SPEED_STEP; - } - else { - g_camwindow_globals_private.m_nMoveSpeed = MAX_CAM_SPEED - 10; - } +void CameraSpeed_increase() +{ + if (g_camwindow_globals_private.m_nMoveSpeed <= (MAX_CAM_SPEED - CAM_SPEED_STEP - 10)) { + g_camwindow_globals_private.m_nMoveSpeed += CAM_SPEED_STEP; + } else { + g_camwindow_globals_private.m_nMoveSpeed = MAX_CAM_SPEED - 10; + } } -void CameraSpeed_decrease(){ - if ( g_camwindow_globals_private.m_nMoveSpeed >= ( MIN_CAM_SPEED + CAM_SPEED_STEP ) ) { - g_camwindow_globals_private.m_nMoveSpeed -= CAM_SPEED_STEP; - } - else { - g_camwindow_globals_private.m_nMoveSpeed = MIN_CAM_SPEED; - } +void CameraSpeed_decrease() +{ + if (g_camwindow_globals_private.m_nMoveSpeed >= (MIN_CAM_SPEED + CAM_SPEED_STEP)) { + g_camwindow_globals_private.m_nMoveSpeed -= CAM_SPEED_STEP; + } else { + g_camwindow_globals_private.m_nMoveSpeed = MIN_CAM_SPEED; + } } /// \brief Initialisation for things that have the same lifespan as this module. -void CamWnd_Construct(){ - GlobalCommands_insert( "CenterView", makeCallbackF(GlobalCamera_ResetAngles), Accelerator( GDK_KEY_End ) ); - - GlobalToggles_insert( "ToggleCubicClip", makeCallbackF(Camera_ToggleFarClip), ToggleItem::AddCallbackCaller( g_getfarclip_item ), Accelerator( '\\', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "CubicClipZoomIn", makeCallbackF(Camera_CubeIn), Accelerator( '[', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "CubicClipZoomOut", makeCallbackF(Camera_CubeOut), Accelerator( ']', (GdkModifierType)GDK_CONTROL_MASK ) ); - - GlobalCommands_insert( "UpFloor", makeCallbackF(Camera_ChangeFloorUp), Accelerator( GDK_KEY_Prior ) ); - GlobalCommands_insert( "DownFloor", makeCallbackF(Camera_ChangeFloorDown), Accelerator( GDK_KEY_Next ) ); - - GlobalToggles_insert( "ToggleCamera", ToggleShown::ToggleCaller( g_camera_shown ), ToggleItem::AddCallbackCaller( g_camera_shown.m_item ), Accelerator( 'C', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "LookThroughSelected", makeCallbackF(GlobalCamera_LookThroughSelected) ); - GlobalCommands_insert( "LookThroughCamera", makeCallbackF(GlobalCamera_LookThroughCamera) ); - - if ( g_pGameDescription->mGameType == "doom3" ) { - GlobalCommands_insert( "TogglePreview", makeCallbackF(CamWnd_TogglePreview), Accelerator( GDK_KEY_F3 ) ); - } - - GlobalCommands_insert( "CameraSpeedInc", makeCallbackF(CameraSpeed_increase), Accelerator( GDK_KEY_KP_Add, (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "CameraSpeedDec", makeCallbackF(CameraSpeed_decrease), Accelerator( GDK_KEY_KP_Subtract, (GdkModifierType)GDK_SHIFT_MASK ) ); - - GlobalShortcuts_insert( "CameraForward", Accelerator( GDK_KEY_Up ) ); - GlobalShortcuts_insert( "CameraBack", Accelerator( GDK_KEY_Down ) ); - GlobalShortcuts_insert( "CameraLeft", Accelerator( GDK_KEY_Left ) ); - GlobalShortcuts_insert( "CameraRight", Accelerator( GDK_KEY_Right ) ); - GlobalShortcuts_insert( "CameraStrafeRight", Accelerator( GDK_KEY_period ) ); - GlobalShortcuts_insert( "CameraStrafeLeft", Accelerator( GDK_KEY_comma ) ); - - GlobalShortcuts_insert( "CameraUp", Accelerator( 'D' ) ); - GlobalShortcuts_insert( "CameraDown", Accelerator( 'C' ) ); - GlobalShortcuts_insert( "CameraAngleUp", Accelerator( 'A' ) ); - GlobalShortcuts_insert( "CameraAngleDown", Accelerator( 'Z' ) ); - - GlobalShortcuts_insert( "CameraFreeMoveForward", Accelerator( GDK_KEY_Up ) ); - GlobalShortcuts_insert( "CameraFreeMoveBack", Accelerator( GDK_KEY_Down ) ); - GlobalShortcuts_insert( "CameraFreeMoveLeft", Accelerator( GDK_KEY_Left ) ); - GlobalShortcuts_insert( "CameraFreeMoveRight", Accelerator( GDK_KEY_Right ) ); - - GlobalToggles_insert( "ShowStats", makeCallbackF(ShowStatsToggle), ToggleItem::AddCallbackCaller( g_show_stats ) ); - - GlobalPreferenceSystem().registerPreference( "ShowStats", make_property_string( g_camwindow_globals_private.m_showStats ) ); - GlobalPreferenceSystem().registerPreference( "MoveSpeed", make_property_string( g_camwindow_globals_private.m_nMoveSpeed ) ); - GlobalPreferenceSystem().registerPreference( "CamLinkSpeed", make_property_string( g_camwindow_globals_private.m_bCamLinkSpeed ) ); - GlobalPreferenceSystem().registerPreference( "AngleSpeed", make_property_string( g_camwindow_globals_private.m_nAngleSpeed ) ); - GlobalPreferenceSystem().registerPreference( "CamInverseMouse", make_property_string( g_camwindow_globals_private.m_bCamInverseMouse ) ); - GlobalPreferenceSystem().registerPreference( "CamDiscrete", make_property_string()); - GlobalPreferenceSystem().registerPreference( "CubicClipping", make_property_string( g_camwindow_globals_private.m_bCubicClipping ) ); - GlobalPreferenceSystem().registerPreference( "CubicScale", make_property_string( g_camwindow_globals.m_nCubicScale ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors4", make_property_string( g_camwindow_globals.color_cameraback ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors12", make_property_string( g_camwindow_globals.color_selbrushes3d ) ); - GlobalPreferenceSystem().registerPreference( "CameraRenderMode", make_property_string() ); - GlobalPreferenceSystem().registerPreference( "StrafeMode", make_property_string( g_camwindow_globals_private.m_nStrafeMode ) ); - - CamWnd_constructStatic(); - - Camera_registerPreferencesPage(); -} -void CamWnd_Destroy(){ - CamWnd_destroyStatic(); +void CamWnd_Construct() +{ + GlobalCommands_insert("CenterView", makeCallbackF(GlobalCamera_ResetAngles), Accelerator(GDK_KEY_End)); + + GlobalToggles_insert("ToggleCubicClip", makeCallbackF(Camera_ToggleFarClip), + ToggleItem::AddCallbackCaller(g_getfarclip_item), + Accelerator('\\', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("CubicClipZoomIn", makeCallbackF(Camera_CubeIn), + Accelerator('[', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("CubicClipZoomOut", makeCallbackF(Camera_CubeOut), + Accelerator(']', (GdkModifierType) GDK_CONTROL_MASK)); + + GlobalCommands_insert("UpFloor", makeCallbackF(Camera_ChangeFloorUp), Accelerator(GDK_KEY_Prior)); + GlobalCommands_insert("DownFloor", makeCallbackF(Camera_ChangeFloorDown), Accelerator(GDK_KEY_Next)); + + GlobalToggles_insert("ToggleCamera", ToggleShown::ToggleCaller(g_camera_shown), + ToggleItem::AddCallbackCaller(g_camera_shown.m_item), + Accelerator('C', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("LookThroughSelected", makeCallbackF(GlobalCamera_LookThroughSelected)); + GlobalCommands_insert("LookThroughCamera", makeCallbackF(GlobalCamera_LookThroughCamera)); + + if (g_pGameDescription->mGameType == "doom3") { + GlobalCommands_insert("TogglePreview", makeCallbackF(CamWnd_TogglePreview), Accelerator(GDK_KEY_F3)); + } + + GlobalCommands_insert("CameraSpeedInc", makeCallbackF(CameraSpeed_increase), + Accelerator(GDK_KEY_KP_Add, (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("CameraSpeedDec", makeCallbackF(CameraSpeed_decrease), + Accelerator(GDK_KEY_KP_Subtract, (GdkModifierType) GDK_SHIFT_MASK)); + + GlobalShortcuts_insert("CameraForward", Accelerator(GDK_KEY_Up)); + GlobalShortcuts_insert("CameraBack", Accelerator(GDK_KEY_Down)); + GlobalShortcuts_insert("CameraLeft", Accelerator(GDK_KEY_Left)); + GlobalShortcuts_insert("CameraRight", Accelerator(GDK_KEY_Right)); + GlobalShortcuts_insert("CameraStrafeRight", Accelerator(GDK_KEY_period)); + GlobalShortcuts_insert("CameraStrafeLeft", Accelerator(GDK_KEY_comma)); + + GlobalShortcuts_insert("CameraUp", Accelerator('D')); + GlobalShortcuts_insert("CameraDown", Accelerator('C')); + GlobalShortcuts_insert("CameraAngleUp", Accelerator('A')); + GlobalShortcuts_insert("CameraAngleDown", Accelerator('Z')); + + GlobalShortcuts_insert("CameraFreeMoveForward", Accelerator(GDK_KEY_Up)); + GlobalShortcuts_insert("CameraFreeMoveBack", Accelerator(GDK_KEY_Down)); + GlobalShortcuts_insert("CameraFreeMoveLeft", Accelerator(GDK_KEY_Left)); + GlobalShortcuts_insert("CameraFreeMoveRight", Accelerator(GDK_KEY_Right)); + + GlobalToggles_insert("ShowStats", makeCallbackF(ShowStatsToggle), ToggleItem::AddCallbackCaller(g_show_stats)); + + GlobalPreferenceSystem().registerPreference("ShowStats", + make_property_string(g_camwindow_globals_private.m_showStats)); + GlobalPreferenceSystem().registerPreference("MoveSpeed", + make_property_string(g_camwindow_globals_private.m_nMoveSpeed)); + GlobalPreferenceSystem().registerPreference("CamLinkSpeed", + make_property_string(g_camwindow_globals_private.m_bCamLinkSpeed)); + GlobalPreferenceSystem().registerPreference("AngleSpeed", + make_property_string(g_camwindow_globals_private.m_nAngleSpeed)); + GlobalPreferenceSystem().registerPreference("CamInverseMouse", + make_property_string(g_camwindow_globals_private.m_bCamInverseMouse)); + GlobalPreferenceSystem().registerPreference("CamDiscrete", make_property_string()); + GlobalPreferenceSystem().registerPreference("CubicClipping", + make_property_string(g_camwindow_globals_private.m_bCubicClipping)); + GlobalPreferenceSystem().registerPreference("CubicScale", make_property_string(g_camwindow_globals.m_nCubicScale)); + GlobalPreferenceSystem().registerPreference("SI_Colors4", + make_property_string(g_camwindow_globals.color_cameraback)); + GlobalPreferenceSystem().registerPreference("SI_Colors12", + make_property_string(g_camwindow_globals.color_selbrushes3d)); + GlobalPreferenceSystem().registerPreference("CameraRenderMode", make_property_string()); + GlobalPreferenceSystem().registerPreference("StrafeMode", + make_property_string(g_camwindow_globals_private.m_nStrafeMode)); + + CamWnd_constructStatic(); + + Camera_registerPreferencesPage(); +} + +void CamWnd_Destroy() +{ + CamWnd_destroyStatic(); } diff --git a/radiant/camwindow.h b/radiant/camwindow.h index d0722a79..02f1b3bb 100644 --- a/radiant/camwindow.h +++ b/radiant/camwindow.h @@ -27,56 +27,63 @@ #include "signal/signalfwd.h" class CamWnd; -CamWnd* NewCamWnd(); -void DeleteCamWnd( CamWnd* camwnd ); -void AddCameraMovedCallback( const SignalHandler& handler ); +CamWnd *NewCamWnd(); -void CamWnd_Update( CamWnd& camwnd ); +void DeleteCamWnd(CamWnd *camwnd); -ui::GLArea CamWnd_getWidget( CamWnd& camwnd ); -void CamWnd_setParent( CamWnd& camwnd, ui::Window parent ); +void AddCameraMovedCallback(const SignalHandler &handler); -void GlobalCamera_setCamWnd( CamWnd& camwnd ); +void CamWnd_Update(CamWnd &camwnd); + +ui::GLArea CamWnd_getWidget(CamWnd &camwnd); + +void CamWnd_setParent(CamWnd &camwnd, ui::Window parent); + +void GlobalCamera_setCamWnd(CamWnd &camwnd); + +void fill_view_camera_menu(ui::Menu menu); + +void CamWnd_constructToolbar(ui::Toolbar toolbar); -void fill_view_camera_menu( ui::Menu menu ); -void CamWnd_constructToolbar( ui::Toolbar toolbar ); void CamWnd_registerShortcuts(); void GlobalCamera_Benchmark(); -const Vector3& Camera_getOrigin( CamWnd& camwnd ); -void Camera_setOrigin( CamWnd& camwnd, const Vector3& origin ); +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 +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 ); +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; +struct camwindow_globals_t { + Vector3 color_cameraback; + Vector3 color_selbrushes3d; - camwindow_globals_t() : - color_cameraback( 0.25f, 0.25f, 0.25f ), - color_selbrushes3d( 1.0f, 0.f, 0.f ), - m_nCubicScale( 13 ){ - } + 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 diff --git a/radiant/commands.cpp b/radiant/commands.cpp index 9c1b7682..e5448bcd 100644 --- a/radiant/commands.cpp +++ b/radiant/commands.cpp @@ -34,52 +34,58 @@ typedef std::pair ShortcutValue; // accelerator, isRegistered typedef std::map 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 ); - } +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; +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_foreach(CommandVisitor &visitor) +{ + Shortcuts_foreach(g_shortcuts, visitor); } -void GlobalShortcuts_register( const char* name, int type ){ - Shortcuts::iterator i = g_shortcuts.find( name ); - if ( i != g_shortcuts.end() ) { - ( *i ).second.second = type; - } +void GlobalShortcuts_register(const char *name, int type) +{ + Shortcuts::iterator i = g_shortcuts.find(name); + if (i != g_shortcuts.end()) { + (*i).second.second = type; + } } -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"; - } - } +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 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 ) ); +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; +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 Toggles; @@ -87,14 +93,20 @@ typedef std::map Toggles; Toggles g_toggles; -void GlobalToggles_insert( const char* name, const Callback& callback, const Callback &)>& 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 ) ); +void GlobalToggles_insert(const char *name, const Callback &callback, + const Callback &)> &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; + +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 KeyEvents; @@ -102,49 +114,54 @@ typedef std::map 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 ) ); +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; + +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; } -void disconnect_accelerator( const char *name ){ - Shortcuts::iterator i = g_shortcuts.find( name ); - if ( i != g_shortcuts.end() ) { - switch ( ( *i ).second.second ) - { - case 1: - // command - command_disconnect_accelerator( name ); - break; - case 2: - // toggle - toggle_remove_accelerator( name ); - break; - } - } +void disconnect_accelerator(const char *name) +{ + Shortcuts::iterator i = g_shortcuts.find(name); + if (i != g_shortcuts.end()) { + switch ((*i).second.second) { + case 1: + // command + command_disconnect_accelerator(name); + break; + case 2: + // toggle + toggle_remove_accelerator(name); + break; + } + } } -void connect_accelerator( const char *name ){ - Shortcuts::iterator i = g_shortcuts.find( name ); - if ( i != g_shortcuts.end() ) { - switch ( ( *i ).second.second ) - { - case 1: - // command - command_connect_accelerator( name ); - break; - case 2: - // toggle - toggle_add_accelerator( name ); - break; - } - } +void connect_accelerator(const char *name) +{ + Shortcuts::iterator i = g_shortcuts.find(name); + if (i != g_shortcuts.end()) { + switch ((*i).second.second) { + case 1: + // command + command_connect_accelerator(name); + break; + case 2: + // toggle + toggle_add_accelerator(name); + break; + } + } } @@ -158,211 +175,217 @@ void connect_accelerator( const char *name ){ #include "stream/stringstream.h" -struct command_list_dialog_t : public ModalDialog -{ - command_list_dialog_t() - : m_close_button( *this, eIDCANCEL ), m_list( ui::null ), m_command_iter(), m_model( ui::null ), m_waiting_for_key( false ){ - } - ModalDialogButton m_close_button; - - ui::TreeView m_list; - GtkTreeIter m_command_iter; - ui::TreeModel m_model; - bool m_waiting_for_key; +struct command_list_dialog_t : public ModalDialog { + command_list_dialog_t() + : m_close_button(*this, eIDCANCEL), m_list(ui::null), m_command_iter(), m_model(ui::null), + m_waiting_for_key(false) + { + } + + ModalDialogButton m_close_button; + + ui::TreeView m_list; + GtkTreeIter m_command_iter; + ui::TreeModel m_model; + bool m_waiting_for_key; }; -void accelerator_clear_button_clicked( ui::Button btn, gpointer dialogptr ){ - command_list_dialog_t &dialog = *(command_list_dialog_t *) dialogptr; - - if ( dialog.m_waiting_for_key ) { - // just unhighlight, user wanted to cancel - dialog.m_waiting_for_key = false; - gtk_list_store_set( ui::ListStore::from( dialog.m_model ), &dialog.m_command_iter, 2, false, -1 ); - gtk_widget_set_sensitive( dialog.m_list , true ); - dialog.m_model = ui::TreeModel(ui::null); - return; - } - - auto sel = gtk_tree_view_get_selection( dialog.m_list ); - GtkTreeModel *model; - GtkTreeIter iter; - if ( !gtk_tree_selection_get_selected( sel, &model, &iter ) ) { - return; - } - - GValue val; - memset( &val, 0, sizeof( val ) ); - gtk_tree_model_get_value(model, &iter, 0, &val ); - const char *commandName = g_value_get_string( &val );; - - // clear the ACTUAL accelerator too! - disconnect_accelerator( commandName ); - - Shortcuts::iterator thisShortcutIterator = g_shortcuts.find( commandName ); - if ( thisShortcutIterator == g_shortcuts.end() ) { - return; - } - thisShortcutIterator->second.first = accelerator_null(); - - gtk_list_store_set( ui::ListStore::from( model ), &iter, 1, "", -1 ); - - g_value_unset( &val ); -} +void accelerator_clear_button_clicked(ui::Button btn, gpointer dialogptr) +{ + command_list_dialog_t &dialog = *(command_list_dialog_t *) dialogptr; + + if (dialog.m_waiting_for_key) { + // just unhighlight, user wanted to cancel + dialog.m_waiting_for_key = false; + gtk_list_store_set(ui::ListStore::from(dialog.m_model), &dialog.m_command_iter, 2, false, -1); + gtk_widget_set_sensitive(dialog.m_list, true); + dialog.m_model = ui::TreeModel(ui::null); + return; + } + + auto sel = gtk_tree_view_get_selection(dialog.m_list); + GtkTreeModel *model; + GtkTreeIter iter; + if (!gtk_tree_selection_get_selected(sel, &model, &iter)) { + return; + } -void accelerator_edit_button_clicked( ui::Button btn, gpointer dialogptr ){ - command_list_dialog_t &dialog = *(command_list_dialog_t *) dialogptr; + GValue val; + memset(&val, 0, sizeof(val)); + gtk_tree_model_get_value(model, &iter, 0, &val); + const char *commandName = g_value_get_string(&val);; - // 1. find selected row - auto sel = gtk_tree_view_get_selection( dialog.m_list ); - GtkTreeModel *model; - GtkTreeIter iter; - if ( !gtk_tree_selection_get_selected( sel, &model, &iter ) ) { - return; - } - dialog.m_command_iter = iter; - dialog.m_model = ui::TreeModel::from(model); + // clear the ACTUAL accelerator too! + disconnect_accelerator(commandName); - // 2. disallow changing the row - //gtk_widget_set_sensitive(dialog.m_list, false); + Shortcuts::iterator thisShortcutIterator = g_shortcuts.find(commandName); + if (thisShortcutIterator == g_shortcuts.end()) { + return; + } + thisShortcutIterator->second.first = accelerator_null(); - // 3. highlight the row - gtk_list_store_set( ui::ListStore::from( model ), &iter, 2, true, -1 ); + gtk_list_store_set(ui::ListStore::from(model), &iter, 1, "", -1); - // 4. grab keyboard focus - dialog.m_waiting_for_key = true; + g_value_unset(&val); } -bool accelerator_window_key_press( ui::Window widget, GdkEventKey *event, gpointer dialogptr ){ - command_list_dialog_t &dialog = *(command_list_dialog_t *) dialogptr; +void accelerator_edit_button_clicked(ui::Button btn, gpointer dialogptr) +{ + command_list_dialog_t &dialog = *(command_list_dialog_t *) dialogptr; + + // 1. find selected row + auto sel = gtk_tree_view_get_selection(dialog.m_list); + GtkTreeModel *model; + GtkTreeIter iter; + if (!gtk_tree_selection_get_selected(sel, &model, &iter)) { + return; + } + dialog.m_command_iter = iter; + dialog.m_model = ui::TreeModel::from(model); + + // 2. disallow changing the row + //gtk_widget_set_sensitive(dialog.m_list, false); + + // 3. highlight the row + gtk_list_store_set(ui::ListStore::from(model), &iter, 2, true, -1); - if ( !dialog.m_waiting_for_key ) { - return false; - } + // 4. grab keyboard focus + dialog.m_waiting_for_key = true; +} + +bool accelerator_window_key_press(ui::Window widget, GdkEventKey *event, gpointer dialogptr) +{ + command_list_dialog_t &dialog = *(command_list_dialog_t *) dialogptr; + + if (!dialog.m_waiting_for_key) { + return false; + } #if 0 - if ( event->is_modifier ) { - return false; - } + if ( event->is_modifier ) { + return false; + } #else - switch ( event->keyval ) - { - case GDK_KEY_Shift_L: - case GDK_KEY_Shift_R: - case GDK_KEY_Control_L: - case GDK_KEY_Control_R: - case GDK_KEY_Caps_Lock: - case GDK_KEY_Shift_Lock: - case GDK_KEY_Meta_L: - case GDK_KEY_Meta_R: - case GDK_KEY_Alt_L: - case GDK_KEY_Alt_R: - case GDK_KEY_Super_L: - case GDK_KEY_Super_R: - case GDK_KEY_Hyper_L: - case GDK_KEY_Hyper_R: - return false; - } + switch (event->keyval) { + case GDK_KEY_Shift_L: + case GDK_KEY_Shift_R: + case GDK_KEY_Control_L: + case GDK_KEY_Control_R: + case GDK_KEY_Caps_Lock: + case GDK_KEY_Shift_Lock: + case GDK_KEY_Meta_L: + case GDK_KEY_Meta_R: + case GDK_KEY_Alt_L: + case GDK_KEY_Alt_R: + case GDK_KEY_Super_L: + case GDK_KEY_Super_R: + case GDK_KEY_Hyper_L: + case GDK_KEY_Hyper_R: + return false; + } #endif - dialog.m_waiting_for_key = false; - - // 7. find the name of the accelerator - GValue val; - memset( &val, 0, sizeof( val ) ); - gtk_tree_model_get_value(dialog.m_model, &dialog.m_command_iter, 0, &val ); - const char *commandName = g_value_get_string( &val );; - Shortcuts::iterator thisShortcutIterator = g_shortcuts.find( commandName ); - if ( thisShortcutIterator == g_shortcuts.end() ) { - gtk_list_store_set( ui::ListStore::from( dialog.m_model ), &dialog.m_command_iter, 2, false, -1 ); - gtk_widget_set_sensitive( dialog.m_list , true ); - return true; - } - - // 8. build an Accelerator - Accelerator newAccel( event->keyval, (GdkModifierType) event->state ); - - // 8. verify the key is still free, show a dialog to ask what to do if not - class VerifyAcceleratorNotTaken : public CommandVisitor - { - const char *commandName; - const Accelerator &newAccel; - ui::Widget widget; - ui::TreeModel model; -public: - bool allow; - VerifyAcceleratorNotTaken( const char *name, const Accelerator &accelerator, ui::Widget w, ui::TreeModel m ) : commandName( name ), newAccel( accelerator ), widget( w ), model( m ), allow( true ){ - } - void visit( const char* name, Accelerator& accelerator ){ - if ( !strcmp( name, commandName ) ) { - return; - } - if ( !allow ) { - return; - } - if ( accelerator.key == 0 ) { - return; - } - if ( accelerator == newAccel ) { - StringOutputStream msg; - msg << "The command " << name << " is already assigned to the key " << accelerator << ".\n\n" - << "Do you want to unassign " << name << " first?"; - auto r = ui::alert( widget.window(), msg.c_str(), "Key already used", ui::alert_type::YESNOCANCEL ); - if ( r == ui::alert_response::YES ) { - // clear the ACTUAL accelerator too! - disconnect_accelerator( name ); - // delete the modifier - accelerator = accelerator_null(); - // empty the cell of the key binds dialog - GtkTreeIter i; - if ( gtk_tree_model_get_iter_first(model, &i ) ) { - for (;; ) - { - GValue val; - memset( &val, 0, sizeof( val ) ); - gtk_tree_model_get_value(model, &i, 0, &val ); - const char *thisName = g_value_get_string( &val );; - if ( !strcmp( thisName, name ) ) { - gtk_list_store_set( ui::ListStore::from( model ), &i, 1, "", -1 ); - } - g_value_unset( &val ); - if ( !gtk_tree_model_iter_next(model, &i ) ) { - break; - } - } - } - } - else if ( r == ui::alert_response::CANCEL ) { - // aborted - allow = false; - } - } - } - } verify_visitor( commandName, newAccel, widget, dialog.m_model ); - GlobalShortcuts_foreach( verify_visitor ); - - gtk_list_store_set( ui::ListStore::from( dialog.m_model ), &dialog.m_command_iter, 2, false, -1 ); - gtk_widget_set_sensitive( dialog.m_list , true ); - - if ( verify_visitor.allow ) { - // clear the ACTUAL accelerator first - disconnect_accelerator( commandName ); - - thisShortcutIterator->second.first = newAccel; - - // write into the cell - StringOutputStream modifiers; - modifiers << newAccel; - gtk_list_store_set( ui::ListStore::from( dialog.m_model ), &dialog.m_command_iter, 1, modifiers.c_str(), -1 ); - - // set the ACTUAL accelerator too! - connect_accelerator( commandName ); - } - - g_value_unset( &val ); - - dialog.m_model = ui::TreeModel(ui::null); - - return true; + dialog.m_waiting_for_key = false; + + // 7. find the name of the accelerator + GValue val; + memset(&val, 0, sizeof(val)); + gtk_tree_model_get_value(dialog.m_model, &dialog.m_command_iter, 0, &val); + const char *commandName = g_value_get_string(&val);; + Shortcuts::iterator thisShortcutIterator = g_shortcuts.find(commandName); + if (thisShortcutIterator == g_shortcuts.end()) { + gtk_list_store_set(ui::ListStore::from(dialog.m_model), &dialog.m_command_iter, 2, false, -1); + gtk_widget_set_sensitive(dialog.m_list, true); + return true; + } + + // 8. build an Accelerator + Accelerator newAccel(event->keyval, (GdkModifierType) event->state); + + // 8. verify the key is still free, show a dialog to ask what to do if not + class VerifyAcceleratorNotTaken : public CommandVisitor { + const char *commandName; + const Accelerator &newAccel; + ui::Widget widget; + ui::TreeModel model; + public: + bool allow; + + VerifyAcceleratorNotTaken(const char *name, const Accelerator &accelerator, ui::Widget w, ui::TreeModel m) + : commandName(name), newAccel(accelerator), widget(w), model(m), allow(true) + { + } + + void visit(const char *name, Accelerator &accelerator) + { + if (!strcmp(name, commandName)) { + return; + } + if (!allow) { + return; + } + if (accelerator.key == 0) { + return; + } + if (accelerator == newAccel) { + StringOutputStream msg; + msg << "The command " << name << " is already assigned to the key " << accelerator << ".\n\n" + << "Do you want to unassign " << name << " first?"; + auto r = ui::alert(widget.window(), msg.c_str(), "Key already used", ui::alert_type::YESNOCANCEL); + if (r == ui::alert_response::YES) { + // clear the ACTUAL accelerator too! + disconnect_accelerator(name); + // delete the modifier + accelerator = accelerator_null(); + // empty the cell of the key binds dialog + GtkTreeIter i; + if (gtk_tree_model_get_iter_first(model, &i)) { + for (;;) { + GValue val; + memset(&val, 0, sizeof(val)); + gtk_tree_model_get_value(model, &i, 0, &val); + const char *thisName = g_value_get_string(&val);; + if (!strcmp(thisName, name)) { + gtk_list_store_set(ui::ListStore::from(model), &i, 1, "", -1); + } + g_value_unset(&val); + if (!gtk_tree_model_iter_next(model, &i)) { + break; + } + } + } + } else if (r == ui::alert_response::CANCEL) { + // aborted + allow = false; + } + } + } + } verify_visitor(commandName, newAccel, widget, dialog.m_model); + GlobalShortcuts_foreach(verify_visitor); + + gtk_list_store_set(ui::ListStore::from(dialog.m_model), &dialog.m_command_iter, 2, false, -1); + gtk_widget_set_sensitive(dialog.m_list, true); + + if (verify_visitor.allow) { + // clear the ACTUAL accelerator first + disconnect_accelerator(commandName); + + thisShortcutIterator->second.first = newAccel; + + // write into the cell + StringOutputStream modifiers; + modifiers << newAccel; + gtk_list_store_set(ui::ListStore::from(dialog.m_model), &dialog.m_command_iter, 1, modifiers.c_str(), -1); + + // set the ACTUAL accelerator too! + connect_accelerator(commandName); + } + + g_value_unset(&val); + + dialog.m_model = ui::TreeModel(ui::null); + + return true; } /* @@ -384,212 +407,228 @@ public: }; */ -void DoCommandListDlg(){ - command_list_dialog_t dialog; - - ui::Window window = MainFrame_getWindow().create_modal_dialog_window("Mapped Commands", dialog, -1, 400); - window.on_key_press([](ui::Widget widget, GdkEventKey *event, gpointer dialogptr) { - return accelerator_window_key_press(ui::Window::from(widget), event, dialogptr); - }, &dialog); - - auto accel = ui::AccelGroup(ui::New); - window.add_accel_group( accel ); - - auto hbox = create_dialog_hbox( 4, 4 ); - window.add(hbox); - - { - auto scr = create_scrolled_window( ui::Policy::NEVER, ui::Policy::AUTOMATIC ); - hbox.pack_start( scr, TRUE, TRUE, 0 ); - - { - auto store = ui::ListStore::from(gtk_list_store_new( 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT )); +void DoCommandListDlg() +{ + command_list_dialog_t dialog; - auto view = ui::TreeView(ui::TreeModel::from(store._handle)); - dialog.m_list = view; + ui::Window window = MainFrame_getWindow().create_modal_dialog_window("Mapped Commands", dialog, -1, 400); + window.on_key_press([](ui::Widget widget, GdkEventKey *event, gpointer dialogptr) { + return accelerator_window_key_press(ui::Window::from(widget), event, dialogptr); + }, &dialog); - gtk_tree_view_set_enable_search(view, false ); // annoying + auto accel = ui::AccelGroup(ui::New); + window.add_accel_group(accel); - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn( "Command", renderer, {{"text", 0}, {"weight-set", 2}, {"weight", 3}} ); - gtk_tree_view_append_column(view, column ); - } + auto hbox = create_dialog_hbox(4, 4); + window.add(hbox); - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn( "Key", renderer, {{"text", 1}, {"weight-set", 2}, {"weight", 3}} ); - gtk_tree_view_append_column(view, column ); - } + { + auto scr = create_scrolled_window(ui::Policy::NEVER, ui::Policy::AUTOMATIC); + hbox.pack_start(scr, TRUE, TRUE, 0); + + { + auto store = ui::ListStore::from( + gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT)); + + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + dialog.m_list = view; + + gtk_tree_view_set_enable_search(view, false); // annoying + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("Command", renderer, {{"text", 0}, + {"weight-set", 2}, + {"weight", 3}}); + gtk_tree_view_append_column(view, column); + } + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("Key", renderer, {{"text", 1}, + {"weight-set", 2}, + {"weight", 3}}); + gtk_tree_view_append_column(view, column); + } + + view.show(); + scr.add(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; + ui::ListStore m_store; + public: + BuildCommandList(const char *filename, ui::ListStore store) : m_commandList(filename), + m_store(store) + { + } + + void visit(const char *name, Accelerator &accelerator) + { + StringOutputStream modifiers; + modifiers << accelerator; + + m_store.append(0, name, 1, modifiers.c_str(), 2, false, 3, 800); + + if (!m_commandList.failed()) { + int l = strlen(name); + m_commandList << name; + while (l++ < 25) { + m_commandList << ' '; + } + m_commandList << modifiers.c_str() << '\n'; + } + } + } visitor(path.c_str(), store); + + GlobalShortcuts_foreach(visitor); + } + + store.unref(); + } + } - view.show(); - scr.add(view); + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, TRUE, TRUE, 0); + { + auto editbutton = create_dialog_button("Edit", (GCallback) accelerator_edit_button_clicked, &dialog); + vbox.pack_start(editbutton, FALSE, FALSE, 0); + + auto clearbutton = create_dialog_button("Clear", (GCallback) accelerator_clear_button_clicked, &dialog); + vbox.pack_start(clearbutton, FALSE, FALSE, 0); + + ui::Widget spacer = ui::Image(ui::New); + spacer.show(); + vbox.pack_start(spacer, TRUE, TRUE, 0); + + auto button = create_modal_dialog_button("Close", dialog.m_close_button); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_grab_default(button); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, (GtkAccelFlags) 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, (GtkAccelFlags) 0); + } - { - // 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; - ui::ListStore m_store; -public: - BuildCommandList( const char* filename, ui::ListStore store ) : m_commandList( filename ), m_store( store ){ - } - void visit( const char* name, Accelerator& accelerator ){ - StringOutputStream modifiers; - modifiers << accelerator; - - m_store.append(0, name, 1, modifiers.c_str(), 2, false, 3, 800); - - if ( !m_commandList.failed() ) { - int l = strlen( name ); - m_commandList << name; - while ( l++ < 25 ) - m_commandList << ' '; - m_commandList << modifiers.c_str() << '\n'; - } - } - } visitor( path.c_str(), store ); - - GlobalShortcuts_foreach( visitor ); - } - - store.unref(); - } - } - - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, TRUE, TRUE, 0 ); - { - auto editbutton = create_dialog_button( "Edit", (GCallback) accelerator_edit_button_clicked, &dialog ); - vbox.pack_start( editbutton, FALSE, FALSE, 0 ); - - auto clearbutton = create_dialog_button( "Clear", (GCallback) accelerator_clear_button_clicked, &dialog ); - vbox.pack_start( clearbutton, FALSE, FALSE, 0 ); - - ui::Widget spacer = ui::Image(ui::New); - spacer.show(); - vbox.pack_start( spacer, TRUE, TRUE, 0 ); - - auto button = create_modal_dialog_button( "Close", dialog.m_close_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_grab_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - - modal_dialog_show( window, dialog ); - window.destroy(); + modal_dialog_show(window, dialog); + window.destroy(); } #include "profile/profile.h" -const char* const COMMANDS_VERSION = "1.0-gtk-accelnames"; - -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 = gtk_accelerator_name( accelerator.key, accelerator.modifiers ); - m_file << key; - m_file << "\n"; - } - } visitor( file ); - GlobalShortcuts_foreach( visitor ); - } -} +const char *const COMMANDS_VERSION = "1.0-gtk-accelnames"; -const char* stringrange_find( const char* first, const char* last, char c ){ - const char* p = strchr( first, '+' ); - if ( p == 0 ) { - return last; - } - return p; +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 = gtk_accelerator_name(accelerator.key, accelerator.modifiers); + m_file << key; + m_file << "\n"; + } + } visitor(file); + GlobalShortcuts_foreach(visitor); + } } -class ReadCommandMap : public CommandVisitor +const char *stringrange_find(const char *first, const char *last, char c) { -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; - } - - gtk_accelerator_parse( value, &accelerator.key, &accelerator.modifiers ); - accelerator = accelerator; // fix modifiers - - if ( accelerator.key != 0 ) { - ++m_count; - } - else - { - globalOutputStream() << "WARNING: failed to parse user command " << makeQuoted( name ) << ": unknown key " << makeQuoted( value ) << "\n"; - } - } -} -std::size_t count() const { - return m_count; + 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; + } + + gtk_accelerator_parse(value, &accelerator.key, &accelerator.modifiers); + accelerator = accelerator; // fix modifiers + + if (accelerator.key != 0) { + ++m_count; + } else { + globalOutputStream() << "WARNING: failed to parse user command " << makeQuoted(name) << ": unknown key " + << makeQuoted(value) << "\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"; - } +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"; + } } diff --git a/radiant/commands.h b/radiant/commands.h index 8c6b9f19..5f264d23 100644 --- a/radiant/commands.h +++ b/radiant/commands.h @@ -25,30 +25,38 @@ #include "gtkutil/accelerator.h" -const Accelerator& GlobalShortcuts_insert( const char* name, const Accelerator& accelerator ); -void GlobalShortcuts_register( const char* name, int type ); // 1 = command, 2 = toggle +const Accelerator &GlobalShortcuts_insert(const char *name, const Accelerator &accelerator); + +void GlobalShortcuts_register(const char *name, int type); // 1 = command, 2 = toggle void GlobalShortcuts_reportUnregistered(); -class CommandVisitor -{ +class CommandVisitor { public: -virtual void visit( const char* name, Accelerator& accelerator ) = 0; + 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 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 Callback &)> &exportCallback, + const Accelerator &accelerator = accelerator_null()); -void GlobalToggles_insert( const char* name, const Callback& callback, const Callback &)>& exportCallback, const Accelerator& accelerator = accelerator_null() ); -const Toggle& GlobalToggles_find( const char* name ); +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 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 ); +void LoadCommandMap(const char *path); + +void SaveCommandMap(const char *path); #endif diff --git a/radiant/console.cpp b/radiant/console.cpp index 82b08e3c..d2495bb7 100644 --- a/radiant/console.cpp +++ b/radiant/console.cpp @@ -39,210 +39,216 @@ #include "mainframe.h" // handle to the console log file -namespace -{ -FILE* g_hLogFile; +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 - if ( !SettingsPath_get()[0] ) { - return; // cannot open a log file yet - } - // 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 NetRadiant '" RADIANT_VERSION "' compiled " __DATE__ "\n" RADIANT_ABOUTMSG "\n"; - } - else{ - ui::alert( ui::root, "Failed to create log file, check write permissions in Radiant directory.\n", - "Console logging", ui::alert_type::OK, ui::alert_icon::Error ); - } - } - 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; - } +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 + if (!SettingsPath_get()[0]) { + return; // cannot open a log file yet + } + // 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 NetRadiant '" RADIANT_VERSION "' compiled " __DATE__ "\n" RADIANT_ABOUTMSG "\n"; + } else { + ui::alert(ui::root, "Failed to create log file, check write permissions in Radiant directory.\n", + "Console logging", ui::alert_type::OK, ui::alert_icon::Error); + } + } 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; + } } ui::TextView g_console{ui::null}; -void console_clear(){ - g_console.text(""); +void console_clear() +{ + g_console.text(""); } -void console_populate_popup( ui::TextView textview, ui::Menu menu, gpointer user_data ){ - menu_separator( menu ); +void console_populate_popup(ui::TextView textview, ui::Menu menu, gpointer user_data) +{ + menu_separator(menu); - ui::Widget item(ui::MenuItem( "Clear" )); - item.connect( "activate", G_CALLBACK( console_clear ), 0 ); - item.show(); - menu.add(item); + ui::Widget item(ui::MenuItem("Clear")); + item.connect("activate", G_CALLBACK(console_clear), 0); + item.show(); + menu.add(item); } -gboolean destroy_set_null( ui::Window widget, ui::Widget* p ){ - *p = ui::Widget{ui::null}; - return FALSE; +gboolean destroy_set_null(ui::Window widget, ui::Widget *p) +{ + *p = ui::Widget{ui::null}; + return FALSE; } -WidgetFocusPrinter g_consoleWidgetFocusPrinter( "console" ); +WidgetFocusPrinter g_consoleWidgetFocusPrinter("console"); -ui::Widget Console_constructWindow( ui::Window toplevel ){ - auto scr = ui::ScrolledWindow(ui::New); - scr.overflow(ui::Policy::AUTOMATIC, ui::Policy::AUTOMATIC); - gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scr ), GTK_SHADOW_IN ); - scr.show(); +ui::Widget Console_constructWindow(ui::Window toplevel) +{ + auto scr = ui::ScrolledWindow(ui::New); + scr.overflow(ui::Policy::AUTOMATIC, ui::Policy::AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN); + scr.show(); - { - auto text = ui::TextView(ui::New); - text.dimensions(0, -1); // allow shrinking - gtk_text_view_set_wrap_mode( text, GTK_WRAP_WORD ); - gtk_text_view_set_editable( text, FALSE ); - scr.add(text); - text.show(); - g_console = text; + { + auto text = ui::TextView(ui::New); + text.dimensions(0, -1); // allow shrinking + gtk_text_view_set_wrap_mode(text, GTK_WRAP_WORD); + gtk_text_view_set_editable(text, FALSE); + scr.add(text); + text.show(); + g_console = text; - //globalExtendedASCIICharacterSet().print(); + //globalExtendedASCIICharacterSet().print(); - widget_connect_escape_clear_focus_widget( g_console ); + widget_connect_escape_clear_focus_widget(g_console); - //g_consoleWidgetFocusPrinter.connect(g_console); + //g_consoleWidgetFocusPrinter.connect(g_console); - g_console.connect( "populate-popup", G_CALLBACK( console_populate_popup ), 0 ); - g_console.connect( "destroy", G_CALLBACK( destroy_set_null ), &g_console ); - } + g_console.connect("populate-popup", G_CALLBACK(console_populate_popup), 0); + g_console.connect("destroy", G_CALLBACK(destroy_set_null), &g_console); + } - gtk_container_set_focus_chain( GTK_CONTAINER( scr ), NULL ); + gtk_container_set_focus_chain(GTK_CONTAINER(scr), NULL); - return scr; + return scr; } -class GtkTextBufferOutputStream : public TextOutputStream -{ -GtkTextBuffer* textBuffer; -GtkTextIter* iter; -GtkTextTag* tag; +class GtkTextBufferOutputStream : public TextOutputStream { + GtkTextBuffer *textBuffer; + GtkTextIter *iter; + GtkTextTag *tag; public: -GtkTextBufferOutputStream( GtkTextBuffer* textBuffer, GtkTextIter* iter, GtkTextTag* tag ) : textBuffer( textBuffer ), iter( iter ), tag( tag ){ -} -std::size_t write( const char* buffer, std::size_t length ){ - gtk_text_buffer_insert_with_tags( textBuffer, iter, buffer, gint( length ), tag, NULL ); - return length; -} + GtkTextBufferOutputStream(GtkTextBuffer *textBuffer, GtkTextIter *iter, GtkTextTag *tag) : textBuffer(textBuffer), + iter(iter), tag(tag) + { + } + + std::size_t write(const char *buffer, std::size_t length) + { + gtk_text_buffer_insert_with_tags(textBuffer, iter, buffer, gint(length), tag, NULL); + return length; + } }; -std::size_t Sys_Print( int level, const char* buf, std::size_t length ){ - bool contains_newline = std::find( buf, buf + length, '\n' ) != buf + length; - - 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 ) { - auto buffer = gtk_text_view_get_buffer( g_console ); - - GtkTextIter iter; - gtk_text_buffer_get_end_iter( buffer, &iter ); - - static auto end = gtk_text_buffer_create_mark( buffer, "end", &iter, FALSE ); - - const GdkColor yellow = { 0, 0xb0ff, 0xb0ff, 0x0000 }; - const GdkColor red = { 0, 0xffff, 0x0000, 0x0000 }; - - static auto error_tag = gtk_text_buffer_create_tag( buffer, "red_foreground", "foreground-gdk", &red, NULL ); - static auto warning_tag = gtk_text_buffer_create_tag( buffer, "yellow_foreground", "foreground-gdk", &yellow, NULL ); - static auto standard_tag = gtk_text_buffer_create_tag( buffer, "black_foreground", NULL ); - 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; - } - - - { - GtkTextBufferOutputStream textBuffer( buffer, &iter, tag ); - if ( !globalCharacterSet().isUTF8() ) { - BufferedTextOutputStream buffered( textBuffer ); - buffered << StringRange( buf, buf + length ); - } - else - { - textBuffer << StringRange( buf, buf + length ); - } - } - - // update console widget immediatly if we're doing something time-consuming - if ( contains_newline ) { - gtk_text_view_scroll_mark_onscreen( g_console, end ); - - if ( !ScreenUpdates_Enabled() && gtk_widget_get_realized( g_console ) ) { - ScreenUpdates_process(); - } - } - } - } - return length; +std::size_t Sys_Print(int level, const char *buf, std::size_t length) +{ + bool contains_newline = std::find(buf, buf + length, '\n') != buf + length; + + 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) { + auto buffer = gtk_text_view_get_buffer(g_console); + + GtkTextIter iter; + gtk_text_buffer_get_end_iter(buffer, &iter); + + static auto end = gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE); + + const GdkColor yellow = {0, 0xb0ff, 0xb0ff, 0x0000}; + const GdkColor red = {0, 0xffff, 0x0000, 0x0000}; + + static auto error_tag = gtk_text_buffer_create_tag(buffer, "red_foreground", "foreground-gdk", &red, NULL); + static auto warning_tag = gtk_text_buffer_create_tag(buffer, "yellow_foreground", "foreground-gdk", &yellow, + NULL); + static auto standard_tag = gtk_text_buffer_create_tag(buffer, "black_foreground", NULL); + 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; + } + + + { + GtkTextBufferOutputStream textBuffer(buffer, &iter, tag); + if (!globalCharacterSet().isUTF8()) { + BufferedTextOutputStream buffered(textBuffer); + buffered << StringRange(buf, buf + length); + } else { + textBuffer << StringRange(buf, buf + length); + } + } + + // update console widget immediatly if we're doing something time-consuming + if (contains_newline) { + gtk_text_view_scroll_mark_onscreen(g_console, end); + + if (!ScreenUpdates_Enabled() && gtk_widget_get_realized(g_console)) { + ScreenUpdates_process(); + } + } + } + } + return length; } -class SysPrintOutputStream : public TextOutputStream -{ +class SysPrintOutputStream : public TextOutputStream { public: -std::size_t write( const char* buffer, std::size_t length ){ - return Sys_Print( SYS_STD, buffer, length ); -} + std::size_t write(const char *buffer, std::size_t length) + { + return Sys_Print(SYS_STD, buffer, length); + } }; -class SysPrintErrorStream : public TextOutputStream -{ +class SysPrintErrorStream : public TextOutputStream { public: -std::size_t write( const char* buffer, std::size_t length ){ - return Sys_Print( SYS_ERR, buffer, length ); -} + 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; +TextOutputStream &getSysPrintOutputStream() +{ + return g_outputStream; } SysPrintErrorStream g_errorStream; -TextOutputStream& getSysPrintErrorStream(){ - return g_errorStream; +TextOutputStream &getSysPrintErrorStream() +{ + return g_errorStream; } diff --git a/radiant/console.h b/radiant/console.h index 8bbe71e1..551b696d 100644 --- a/radiant/console.h +++ b/radiant/console.h @@ -31,15 +31,19 @@ #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 ); +std::size_t Sys_Print(int level, const char *buf, std::size_t length); + class TextOutputStream; -TextOutputStream& getSysPrintOutputStream(); -TextOutputStream& getSysPrintErrorStream(); -ui::Widget Console_constructWindow( ui::Window toplevel ); +TextOutputStream &getSysPrintOutputStream(); + +TextOutputStream &getSysPrintErrorStream(); + +ui::Widget Console_constructWindow(ui::Window toplevel); // will open/close the log file based on the parameter -void Sys_LogFile( bool enable ); +void Sys_LogFile(bool enable); + extern bool g_Console_enableLogging; diff --git a/radiant/csg.cpp b/radiant/csg.cpp index 2abfb1b3..c294642c 100644 --- a/radiant/csg.cpp +++ b/radiant/csg.cpp @@ -30,95 +30,103 @@ #include "brushnode.h" #include "grid.h" -void Face_makeBrush( Face& face, const Brush& brush, brush_vector_t& out, float offset ){ - if ( face.contributes() ) { - out.push_back( new Brush( brush ) ); - Face* newFace = out.back()->addFace( face ); - if ( newFace != 0 ) { - newFace->flipWinding(); - newFace->getPlane().offset( offset ); - newFace->planeChanged(); - } - } -} - -void Brush_makeHollow( const Brush& brush, brush_vector_t& out, float offset ){ - Brush_forEachFace(brush, [&](Face &face) { - Face_makeBrush(face, brush, out, offset); - }); +void Face_makeBrush(Face &face, const Brush &brush, brush_vector_t &out, float offset) +{ + if (face.contributes()) { + out.push_back(new Brush(brush)); + Face *newFace = out.back()->addFace(face); + if (newFace != 0) { + newFace->flipWinding(); + newFace->getPlane().offset(offset); + newFace->planeChanged(); + } + } +} + +void Brush_makeHollow(const Brush &brush, brush_vector_t &out, float offset) +{ + Brush_forEachFace(brush, [&](Face &face) { + Face_makeBrush(face, brush, out, offset); + }); } -class BrushHollowSelectedWalker : public scene::Graph::Walker -{ -float m_offset; +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 ) - { - ( *i )->removeEmptyFaces(); - NodeSmartReference node( ( new BrushNode() )->node() ); - Node_getBrush( node )->copy( *( *i ) ); - delete ( *i ); - Node_getTraversable( path.parent() )->insert( node ); - } - } - } - return true; -} + 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) { + (*i)->removeEmptyFaces(); + NodeSmartReference node((new BrushNode())->node()); + Node_getBrush(node)->copy(*(*i)); + delete (*i); + Node_getTraversable(path.parent())->insert(node); + } + } + } + return true; + } }; -typedef std::list brushlist_t; +typedef std::list brushlist_t; -class BrushGatherSelected : public scene::Graph::Walker -{ -brush_vector_t& m_brushlist; +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; -} + 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 -{ +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 ); - } - } -} + 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() ); +void Scene_BrushMakeHollow_Selected(scene::Graph &graph) +{ + GlobalSceneGraph().traverse(BrushHollowSelectedWalker(GetGridSize())); + GlobalSceneGraph().traverse(BrushDeleteSelected()); } /* @@ -127,346 +135,359 @@ void Scene_BrushMakeHollow_Selected( scene::Graph& graph ){ ============= */ -void CSG_MakeHollow( void ){ - UndoableCommand undo( "brushHollow" ); +void CSG_MakeHollow(void) +{ + UndoableCommand undo("brushHollow"); - Scene_BrushMakeHollow_Selected( GlobalSceneGraph() ); + Scene_BrushMakeHollow_Selected(GlobalSceneGraph()); - SceneChangeNotify(); + SceneChangeNotify(); } template -class RemoveReference -{ +class RemoveReference { public: -typedef Type type; + typedef Type type; }; template -class RemoveReference -{ +class RemoveReference { public: -typedef Type type; + typedef Type type; }; template -class Dereference -{ -const Functor& functor; +class Dereference { + const Functor &functor; public: -Dereference( const Functor& functor ) : functor( functor ){ -} -get_result_type operator()( typename RemoveReference>::type *firstArgument ) const { - return functor( *firstArgument ); -} + Dereference(const Functor &functor) : functor(functor) + { + } + + get_result_type operator()(typename RemoveReference>::type *firstArgument) const + { + return functor(*firstArgument); + } }; template -inline Dereference makeDereference( const Functor& functor ){ - return Dereference( functor ); +inline Dereference makeDereference(const Functor &functor) +{ + return Dereference(functor); } -typedef Face* FacePointer; +typedef Face *FacePointer; const FacePointer c_nullFacePointer = 0; template -Face* Brush_findIf( const Brush& brush, const Predicate& predicate ){ - Brush::const_iterator i = std::find_if( brush.begin(), brush.end(), makeDereference( predicate ) ); - return i == brush.end() ? c_nullFacePointer : *i; // uses c_nullFacePointer instead of 0 because otherwise gcc 4.1 attempts conversion to int +Face *Brush_findIf(const Brush &brush, const Predicate &predicate) +{ + Brush::const_iterator i = std::find_if(brush.begin(), brush.end(), makeDereference(predicate)); + return i == brush.end() ? c_nullFacePointer + : *i; // uses c_nullFacePointer instead of 0 because otherwise gcc 4.1 attempts conversion to int } template -class BindArguments1 -{ -typedef get_argument FirstBound; -FirstBound firstBound; +class BindArguments1 { + typedef get_argument FirstBound; + FirstBound firstBound; public: -BindArguments1( FirstBound firstBound ) - : firstBound( firstBound ){ -} -get_result_type operator()( get_argument firstArgument ) const { - return Caller::call( firstArgument, firstBound ); -} + BindArguments1(FirstBound firstBound) + : firstBound(firstBound) + { + } + + get_result_type operator()(get_argument firstArgument) const + { + return Caller::call(firstArgument, firstBound); + } }; template -class BindArguments2 -{ -typedef get_argument FirstBound; -typedef get_argument SecondBound; -FirstBound firstBound; -SecondBound secondBound; +class BindArguments2 { + typedef get_argument FirstBound; + typedef get_argument SecondBound; + FirstBound firstBound; + SecondBound secondBound; public: -BindArguments2( FirstBound firstBound, SecondBound secondBound ) - : firstBound( firstBound ), secondBound( secondBound ){ -} -get_result_type operator()( get_argument firstArgument ) const { - return Caller::call( firstArgument, firstBound, secondBound ); -} + BindArguments2(FirstBound firstBound, SecondBound secondBound) + : firstBound(firstBound), secondBound(secondBound) + { + } + + get_result_type operator()(get_argument firstArgument) const + { + return Caller::call(firstArgument, firstBound, secondBound); + } }; template -BindArguments2 bindArguments( const Caller& caller, FirstBound firstBound, SecondBound secondBound ){ - return BindArguments2( firstBound, secondBound ); +BindArguments2 bindArguments(const Caller &caller, FirstBound firstBound, SecondBound secondBound) +{ + return BindArguments2(firstBound, secondBound); } -inline bool Face_testPlane( const Face& face, const Plane3& plane, bool flipped ){ - return face.contributes() && !Winding_TestPlane( face.getWinding(), plane, flipped ); +inline bool Face_testPlane(const Face &face, const Plane3 &plane, bool flipped) +{ + return face.contributes() && !Winding_TestPlane(face.getWinding(), plane, flipped); } -typedef Function FaceTestPlane; +typedef Function FaceTestPlane; /// \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(); +bool Brush_testPlane(const Brush &brush, const Plane3 &plane, bool flipped) +{ + brush.evaluateBRep(); #if 1 - for ( Brush::const_iterator i( brush.begin() ); i != brush.end(); ++i ) - { - if ( Face_testPlane( *( *i ), plane, flipped ) ) { - return false; - } - } - return true; + for (Brush::const_iterator i(brush.begin()); i != brush.end(); ++i) { + if (Face_testPlane(*(*i), plane, flipped)) { + return false; + } + } + return true; #else - return Brush_findIf( brush, bindArguments( FaceTestPlane(), makeReference( plane ), flipped ) ) == 0; + return Brush_findIf( brush, bindArguments( FaceTestPlane(), makeReference( plane ), flipped ) ) == 0; #endif } -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; +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; } -class SubtractBrushesFromUnselected : public scene::Graph::Walker +bool Brush_subtract(const Brush &brush, const Brush &other, brush_vector_t &ret_fragments) { -const brush_vector_t& m_brushlist; -std::size_t& m_before; -std::size_t& m_after; + 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( 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( swap )].begin() ); j != buffer[static_cast( swap )].end(); ++j ) - { - if ( Brush_subtract( *( *j ), *( *i ), buffer[static_cast( !swap )] ) ) { - delete ( *j ); - } - else - { - buffer[static_cast( !swap )].push_back( ( *j ) ); - } - } - buffer[static_cast( swap )].clear(); - swap = !swap; - } - } - - brush_vector_t& out = buffer[static_cast( 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; - ( *i )->removeEmptyFaces(); - if ( !( *i )->empty() ) { - NodeSmartReference node( ( new BrushNode() )->node() ); - Node_getBrush( node )->copy( *( *i ) ); - delete ( *i ); - Node_getTraversable( path.parent() )->insert( node ); - } - else{ - delete ( *i ); - } - } - Path_deleteTop( path ); - } - } - } -} + 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( 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( swap )].begin()); + j != buffer[static_cast( swap )].end(); ++j) { + if (Brush_subtract(*(*j), *(*i), buffer[static_cast( !swap )])) { + delete (*j); + } else { + buffer[static_cast( !swap )].push_back((*j)); + } + } + buffer[static_cast( swap )].clear(); + swap = !swap; + } + } + + brush_vector_t &out = buffer[static_cast( 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; + (*i)->removeEmptyFaces(); + if (!(*i)->empty()) { + NodeSmartReference node((new BrushNode())->node()); + Node_getBrush(node)->copy(*(*i)); + delete (*i); + Node_getTraversable(path.parent())->insert(node); + } else { + delete (*i); + } + } + 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 +void CSG_Subtract() { -const Vector3& m_p0; -const Vector3& m_p1; -const Vector3& m_p2; -const char* m_shader; -const TextureProjection& m_projection; -EBrushSplit m_split; + 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 ); - } - } - } - } -} + 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(); +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; +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; -} + 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 ) ); +void Scene_BrushSetClipPlane(scene::Graph &graph, const Plane3 &plane) +{ + graph.traverse(BrushInstanceSetClipPlane(plane)); } /* @@ -474,127 +495,121 @@ void Scene_BrushSetClipPlane( scene::Graph& graph, const Plane3& plane ){ CSG_Merge ============= */ -bool Brush_merge( Brush& brush, const brush_vector_t& in, bool onlyshape ){ - // gather potential outer faces - - { - typedef std::vector 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; +bool Brush_merge(Brush &brush, const brush_vector_t &in, bool onlyshape) +{ + // gather potential outer faces + + { + typedef std::vector 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 ) ); + // remove selected + GlobalSceneGraph().traverse(BrushGatherSelected(selected_brushes)); - if ( selected_brushes.empty() ) { - globalOutputStream() << "CSG Merge: No brushes selected.\n"; - return; - } + 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; - } + 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"; + globalOutputStream() << "CSG Merge: Merging " << Unsigned(selected_brushes.size()) << " brushes.\n"; - UndoableCommand undo( "brushMerge" ); + UndoableCommand undo("brushMerge"); - scene::Path merged_path = GlobalSelectionSystem().ultimateSelected().path(); + 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" ); + 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() ); + // free the original brushes + GlobalSceneGraph().traverse(BrushDeleteSelected()); - merged_path.pop(); - Node_getTraversable( merged_path.top() )->insert( node ); - merged_path.push( makeReference( node.get() ) ); + merged_path.pop(); + Node_getTraversable(merged_path.top())->insert(node); + merged_path.push(makeReference(node.get())); - selectPath( merged_path, true ); + selectPath(merged_path, true); - globalOutputStream() << "CSG Merge: Succeeded.\n"; - SceneChangeNotify(); - } + globalOutputStream() << "CSG Merge: Succeeded.\n"; + SceneChangeNotify(); + } } diff --git a/radiant/csg.h b/radiant/csg.h index 189ae72c..c2765341 100644 --- a/radiant/csg.h +++ b/radiant/csg.h @@ -22,25 +22,31 @@ #if !defined( INCLUDED_CSG_H ) #define INCLUDED_CSG_H -void CSG_MakeHollow( void ); -void CSG_Subtract( void ); -void CSG_Merge( void ); +void CSG_MakeHollow(void); -namespace scene -{ -class Graph; +void CSG_Subtract(void); + +void CSG_Merge(void); + +namespace scene { + class Graph; } -template class BasicVector3; +template +class BasicVector3; + typedef BasicVector3 Vector3; + class Plane3; -void Scene_BrushSetClipPlane( scene::Graph& graph, const Plane3& plane ); -enum EBrushSplit -{ - eFront, - eBack, - eFrontAndBack, +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 ); + +void Scene_BrushSplitByPlane(scene::Graph &graph, const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, + const char *shader, EBrushSplit split); #endif diff --git a/radiant/dialog.cpp b/radiant/dialog.cpp index 1c628ff1..3b59f6ab 100644 --- a/radiant/dialog.cpp +++ b/radiant/dialog.cpp @@ -47,231 +47,262 @@ #include "gtkmisc.h" -ui::Entry DialogEntry_new(){ - auto entry = ui::Entry(ui::New); - entry.show(); - entry.dimensions(64, -1); - return entry; +ui::Entry DialogEntry_new() +{ + auto entry = ui::Entry(ui::New); + entry.show(); + entry.dimensions(64, -1); + return entry; } -class DialogEntryRow -{ +class DialogEntryRow { public: -DialogEntryRow( ui::Widget row, ui::Entry entry ) : m_row( row ), m_entry( entry ){ -} -ui::Widget m_row; -ui::Entry m_entry; + DialogEntryRow(ui::Widget row, ui::Entry entry) : m_row(row), m_entry(entry) + { + } + + ui::Widget m_row; + ui::Entry m_entry; }; -DialogEntryRow DialogEntryRow_new( const char* name ){ - auto alignment = ui::Alignment( 0.0, 0.5, 0.0, 0.0 ); - alignment.show(); +DialogEntryRow DialogEntryRow_new(const char *name) +{ + auto alignment = ui::Alignment(0.0, 0.5, 0.0, 0.0); + alignment.show(); - auto entry = DialogEntry_new(); - alignment.add(entry); + auto entry = DialogEntry_new(); + alignment.add(entry); - return DialogEntryRow( ui::Widget(DialogRow_new( name, alignment )), entry ); + return DialogEntryRow(ui::Widget(DialogRow_new(name, alignment)), entry); } -ui::SpinButton 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; - } - auto spin = ui::SpinButton( ui::Adjustment( value, lower, upper, step, 10, 0 ), step, digits ); - spin.show(); - spin.dimensions(64, -1); - return spin; -} - -class DialogSpinnerRow +ui::SpinButton 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; + } + auto spin = ui::SpinButton(ui::Adjustment(value, lower, upper, step, 10, 0), step, digits); + spin.show(); + spin.dimensions(64, -1); + return spin; +} + +class DialogSpinnerRow { public: -DialogSpinnerRow( ui::Widget row, ui::SpinButton spin ) : m_row( row ), m_spin( spin ){ -} -ui::Widget m_row; -ui::SpinButton m_spin; + DialogSpinnerRow(ui::Widget row, ui::SpinButton spin) : m_row(row), m_spin(spin) + { + } + + ui::Widget m_row; + ui::SpinButton m_spin; }; -DialogSpinnerRow DialogSpinnerRow_new( const char* name, double value, double lower, double upper, int fraction ){ - auto alignment = ui::Alignment( 0.0, 0.5, 0.0, 0.0 ); - alignment.show(); +DialogSpinnerRow DialogSpinnerRow_new(const char *name, double value, double lower, double upper, int fraction) +{ + auto alignment = ui::Alignment(0.0, 0.5, 0.0, 0.0); + alignment.show(); - auto spin = DialogSpinner_new( value, lower, upper, fraction ); - alignment.add(spin); + auto spin = DialogSpinner_new(value, lower, upper, fraction); + alignment.add(spin); - return DialogSpinnerRow( ui::Widget(DialogRow_new( name, alignment )), spin ); + return DialogSpinnerRow(ui::Widget(DialogRow_new(name, alignment)), spin); } struct BoolToggle { - static void Export(const ui::ToggleButton &self, const Callback &returnz) { - returnz(self.active()); - } - - static void Import(ui::ToggleButton &self, bool value) { - self.active(value); - } + static void Export(const ui::ToggleButton &self, const Callback &returnz) + { + returnz(self.active()); + } + + static void Import(ui::ToggleButton &self, bool value) + { + self.active(value); + } }; using BoolToggleImportExport = PropertyAdaptor; struct IntEntry { - static void Export(const ui::Entry &self, const Callback &returnz) { - returnz(atoi(gtk_entry_get_text(self))); - } - - static void Import(ui::Entry &self, int value) { - entry_set_int(self, value); - } + static void Export(const ui::Entry &self, const Callback &returnz) + { + returnz(atoi(gtk_entry_get_text(self))); + } + + static void Import(ui::Entry &self, int value) + { + entry_set_int(self, value); + } }; using IntEntryImportExport = PropertyAdaptor; struct IntRadio { - static void Export(const ui::RadioButton &self, const Callback &returnz) { - returnz(radio_button_get_active(self)); - } - - static void Import(ui::RadioButton &self, int value) { - radio_button_set_active(self, value); - } + static void Export(const ui::RadioButton &self, const Callback &returnz) + { + returnz(radio_button_get_active(self)); + } + + static void Import(ui::RadioButton &self, int value) + { + radio_button_set_active(self, value); + } }; using IntRadioImportExport = PropertyAdaptor; struct IntCombo { - static void Export(const ui::ComboBox &self, const Callback &returnz) { - returnz(gtk_combo_box_get_active(self)); - } - - static void Import(ui::ComboBox &self, int value) { - gtk_combo_box_set_active(self, value); - } + static void Export(const ui::ComboBox &self, const Callback &returnz) + { + returnz(gtk_combo_box_get_active(self)); + } + + static void Import(ui::ComboBox &self, int value) + { + gtk_combo_box_set_active(self, value); + } }; using IntComboImportExport = PropertyAdaptor; struct IntAdjustment { - static void Export(const ui::Adjustment &self, const Callback &returnz) { - returnz(int(gtk_adjustment_get_value(self))); - } - - static void Import(ui::Adjustment &self, int value) { - gtk_adjustment_set_value(self, value); - } + static void Export(const ui::Adjustment &self, const Callback &returnz) + { + returnz(int(gtk_adjustment_get_value(self))); + } + + static void Import(ui::Adjustment &self, int value) + { + gtk_adjustment_set_value(self, value); + } }; using IntAdjustmentImportExport = PropertyAdaptor; struct IntSpinner { - static void Export(const ui::SpinButton &self, const Callback &returnz) { - returnz(gtk_spin_button_get_value_as_int(self)); - } - - static void Import(ui::SpinButton &self, int value) { - gtk_spin_button_set_value(self, value); - } + static void Export(const ui::SpinButton &self, const Callback &returnz) + { + returnz(gtk_spin_button_get_value_as_int(self)); + } + + static void Import(ui::SpinButton &self, int value) + { + gtk_spin_button_set_value(self, value); + } }; using IntSpinnerImportExport = PropertyAdaptor; struct TextEntry { - static void Export(const ui::Entry &self, const Callback &returnz) { - returnz(gtk_entry_get_text(self)); - } - - static void Import(ui::Entry &self, const char *value) { - self.text(value); - } + static void Export(const ui::Entry &self, const Callback &returnz) + { + returnz(gtk_entry_get_text(self)); + } + + static void Import(ui::Entry &self, const char *value) + { + self.text(value); + } }; using TextEntryImportExport = PropertyAdaptor; struct SizeEntry { - static void Export(const ui::Entry &self, const Callback &returnz) { - int value = atoi(gtk_entry_get_text(self)); - if (value < 0) { - value = 0; - } - returnz(value); - } - - static void Import(ui::Entry &self, std::size_t value) { - entry_set_int(self, int(value)); - } + static void Export(const ui::Entry &self, const Callback &returnz) + { + int value = atoi(gtk_entry_get_text(self)); + if (value < 0) { + value = 0; + } + returnz(value); + } + + static void Import(ui::Entry &self, std::size_t value) + { + entry_set_int(self, int(value)); + } }; using SizeEntryImportExport = PropertyAdaptor; struct FloatEntry { - static void Export(const ui::Entry &self, const Callback &returnz) { - returnz(float(atof(gtk_entry_get_text(self)))); - } - - static void Import(ui::Entry &self, float value) { - entry_set_float(self, value); - } + static void Export(const ui::Entry &self, const Callback &returnz) + { + returnz(float(atof(gtk_entry_get_text(self)))); + } + + static void Import(ui::Entry &self, float value) + { + entry_set_float(self, value); + } }; using FloatEntryImportExport = PropertyAdaptor; struct FloatSpinner { - static void Export(const ui::SpinButton &self, const Callback &returnz) { - returnz(float(gtk_spin_button_get_value(self))); - } - - static void Import(ui::SpinButton &self, float value) { - gtk_spin_button_set_value(self, value); - } + static void Export(const ui::SpinButton &self, const Callback &returnz) + { + returnz(float(gtk_spin_button_get_value(self))); + } + + static void Import(ui::SpinButton &self, float value) + { + gtk_spin_button_set_value(self, value); + } }; using FloatSpinnerImportExport = PropertyAdaptor; - template class CallbackDialogData : public DLG_DATA { - Property m_pWidget; - Property m_pData; + Property m_pWidget; + Property m_pData; public: - CallbackDialogData(const Property &pWidget, const Property &pData) - : m_pWidget(pWidget), m_pData(pData) { - } - - void release() { - delete this; - } - - void importData() const { - m_pData.get(m_pWidget.set); - } - - void exportData() const { - m_pWidget.get(m_pData.set); - } + CallbackDialogData(const Property &pWidget, const Property &pData) + : m_pWidget(pWidget), m_pData(pData) + { + } + + void release() + { + delete this; + } + + void importData() const + { + m_pData.get(m_pWidget.set); + } + + void exportData() const + { + m_pWidget.get(m_pData.set); + } }; template -void AddDataCustom(DialogDataList &self, typename Widget::Type widget, Property const &property) { +void AddDataCustom(DialogDataList &self, typename Widget::Type widget, Property const &property) +{ using Self = typename Widget::Type; using T = typename Widget::Other; using native = typename std::remove_pointer::type; struct Wrapper { - static void Export(const native &self, const Callback &returnz) { - native *p = &const_cast(self); - auto widget = Self::from(p); - Widget::Get::thunk_(widget, returnz); + static void Export(const native &self, const Callback &returnz) + { + native *p = &const_cast(self); + auto widget = Self::from(p); + Widget::Get::thunk_(widget, returnz); } - static void Import(native &self, T value) { - native *p = &self; - auto widget = Self::from(p); - Widget::Set::thunk_(widget, value); + static void Import(native &self, T value) + { + native *p = &self; + auto widget = Self::from(p); + Widget::Set::thunk_(widget, value); } }; self.push_back(new CallbackDialogData( @@ -281,345 +312,405 @@ void AddDataCustom(DialogDataList &self, typename Widget::Type widget, Property< } template -void AddData(DialogDataList &self, typename Widget::Type widget, D &data) { +void AddData(DialogDataList &self, typename Widget::Type widget, D &data) +{ AddDataCustom(self, widget, make_property>(data)); } // ============================================================================= // Dialog class -Dialog::Dialog() : m_window( ui::null ), m_parent( ui::null ){ +Dialog::Dialog() : m_window(ui::null), m_parent(ui::null) +{ } -Dialog::~Dialog(){ - for ( DialogDataList::iterator i = m_data.begin(); i != m_data.end(); ++i ) - { - ( *i )->release(); - } +Dialog::~Dialog() +{ + for (DialogDataList::iterator i = m_data.begin(); i != m_data.end(); ++i) { + (*i)->release(); + } - ASSERT_MESSAGE( !m_window, "dialog window not destroyed" ); + ASSERT_MESSAGE(!m_window, "dialog window not destroyed"); } -void Dialog::ShowDlg(){ - ASSERT_MESSAGE( m_window, "dialog was not constructed" ); - importData(); - m_window.show(); +void Dialog::ShowDlg() +{ + ASSERT_MESSAGE(m_window, "dialog was not constructed"); + importData(); + m_window.show(); } -void Dialog::HideDlg(){ - ASSERT_MESSAGE( m_window, "dialog was not constructed" ); - exportData(); - m_window.hide(); +void Dialog::HideDlg() +{ + ASSERT_MESSAGE(m_window, "dialog was not constructed"); + exportData(); + m_window.hide(); } -static gint delete_event_callback( ui::Widget widget, GdkEvent* event, gpointer data ){ - reinterpret_cast( data )->HideDlg(); - reinterpret_cast( data )->EndModal( eIDCANCEL ); - return TRUE; +static gint delete_event_callback(ui::Widget widget, GdkEvent *event, gpointer data) +{ + reinterpret_cast( data )->HideDlg(); + reinterpret_cast( data )->EndModal(eIDCANCEL); + return TRUE; } -void Dialog::Create(){ - ASSERT_MESSAGE( !m_window, "dialog cannot be constructed" ); +void Dialog::Create() +{ + ASSERT_MESSAGE(!m_window, "dialog cannot be constructed"); - m_window = BuildDialog(); - m_window.connect( "delete_event", G_CALLBACK( delete_event_callback ), this ); + m_window = BuildDialog(); + m_window.connect("delete_event", G_CALLBACK(delete_event_callback), this); } -void Dialog::Destroy(){ - ASSERT_MESSAGE( m_window, "dialog cannot be destroyed" ); +void Dialog::Destroy() +{ + ASSERT_MESSAGE(m_window, "dialog cannot be destroyed"); - m_window.destroy(); - m_window = ui::Window{ui::null}; + m_window.destroy(); + m_window = ui::Window{ui::null}; } -void Dialog::AddBoolToggleData( ui::ToggleButton widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddBoolToggleData(ui::ToggleButton widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddIntRadioData( ui::RadioButton widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddIntRadioData(ui::RadioButton widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddTextEntryData( ui::Entry widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddTextEntryData(ui::Entry widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddIntEntryData( ui::Entry widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddIntEntryData(ui::Entry widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddSizeEntryData( ui::Entry widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddSizeEntryData(ui::Entry widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddFloatEntryData( ui::Entry widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddFloatEntryData(ui::Entry widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddFloatSpinnerData( ui::SpinButton widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddFloatSpinnerData(ui::SpinButton widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddIntSpinnerData( ui::SpinButton widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddIntSpinnerData(ui::SpinButton widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddIntAdjustmentData( ui::Adjustment widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddIntAdjustmentData(ui::Adjustment widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddIntComboData( ui::ComboBox widget, Property const &cb ){ - AddDataCustom( m_data, widget, cb ); +void Dialog::AddIntComboData(ui::ComboBox widget, Property const &cb) +{ + AddDataCustom(m_data, widget, cb); } -void Dialog::AddDialogData( ui::ToggleButton widget, bool& data ){ - AddData( m_data, widget, data ); +void Dialog::AddDialogData(ui::ToggleButton widget, bool &data) +{ + AddData(m_data, widget, data); } -void Dialog::AddDialogData( ui::RadioButton widget, int& data ){ - AddData( m_data, widget, data ); + +void Dialog::AddDialogData(ui::RadioButton widget, int &data) +{ + AddData(m_data, widget, data); } -void Dialog::AddDialogData( ui::Entry widget, CopiedString& data ){ - AddData( m_data, widget, data ); + +void Dialog::AddDialogData(ui::Entry widget, CopiedString &data) +{ + AddData(m_data, widget, data); } -void Dialog::AddDialogData( ui::Entry widget, int& data ){ - AddData( m_data, widget, data ); + +void Dialog::AddDialogData(ui::Entry widget, int &data) +{ + AddData(m_data, widget, data); } -void Dialog::AddDialogData( ui::Entry widget, std::size_t& data ){ - AddData( m_data, widget, data ); + +void Dialog::AddDialogData(ui::Entry widget, std::size_t &data) +{ + AddData(m_data, widget, data); } -void Dialog::AddDialogData( ui::Entry widget, float& data ){ - AddData( m_data, widget, data ); + +void Dialog::AddDialogData(ui::Entry widget, float &data) +{ + AddData(m_data, widget, data); } -void Dialog::AddDialogData( ui::SpinButton widget, float& data ){ - AddData( m_data, widget, data ); + +void Dialog::AddDialogData(ui::SpinButton widget, float &data) +{ + AddData(m_data, widget, data); } -void Dialog::AddDialogData( ui::SpinButton widget, int& data ){ - AddData( m_data, widget, data ); + +void Dialog::AddDialogData(ui::SpinButton widget, int &data) +{ + AddData(m_data, widget, data); } -void Dialog::AddDialogData( ui::Adjustment widget, int& data ){ - AddData( m_data, widget, data ); + +void Dialog::AddDialogData(ui::Adjustment widget, int &data) +{ + AddData(m_data, widget, data); } -void Dialog::AddDialogData( ui::ComboBox widget, int& data ){ - AddData( m_data, widget, data ); + +void Dialog::AddDialogData(ui::ComboBox widget, int &data) +{ + AddData(m_data, widget, data); } -void Dialog::exportData(){ - for ( DialogDataList::iterator i = m_data.begin(); i != m_data.end(); ++i ) - { - ( *i )->exportData(); - } +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::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; +void Dialog::EndModal(EMessageBoxReturn code) +{ + m_modal.loop = 0; + m_modal.ret = code; } -EMessageBoxReturn Dialog::DoModal(){ - importData(); +EMessageBoxReturn Dialog::DoModal() +{ + importData(); - PreModal(); + PreModal(); - EMessageBoxReturn ret = modal_dialog_show( m_window, m_modal ); - ASSERT_TRUE( (bool) m_window ); - if ( ret == eIDOK ) { - exportData(); - } + EMessageBoxReturn ret = modal_dialog_show(m_window, m_modal); + ASSERT_TRUE((bool) m_window); + if (ret == eIDOK) { + exportData(); + } - m_window.hide(); + m_window.hide(); - PostModal( m_modal.ret ); + PostModal(m_modal.ret); - return m_modal.ret; + return m_modal.ret; } -ui::CheckButton Dialog::addCheckBox( ui::VBox vbox, const char* name, const char* flag, Property const &cb ){ - auto check = ui::CheckButton( flag ); - check.show(); - AddBoolToggleData( check, cb ); +ui::CheckButton Dialog::addCheckBox(ui::VBox vbox, const char *name, const char *flag, Property const &cb) +{ + auto check = ui::CheckButton(flag); + check.show(); + AddBoolToggleData(check, cb); - DialogVBox_packRow( vbox, ui::Widget(DialogRow_new( name, check ) )); - return check; + DialogVBox_packRow(vbox, ui::Widget(DialogRow_new(name, check))); + return check; } -ui::CheckButton Dialog::addCheckBox( ui::VBox vbox, const char* name, const char* flag, bool& data ){ - return addCheckBox(vbox, name, flag, make_property(data)); +ui::CheckButton Dialog::addCheckBox(ui::VBox vbox, const char *name, const char *flag, bool &data) +{ + return addCheckBox(vbox, name, flag, make_property(data)); } -void Dialog::addCombo( ui::VBox vbox, const char* name, StringArrayRange values, Property const &cb ){ - auto alignment = ui::Alignment( 0.0, 0.5, 0.0, 0.0 ); - alignment.show(); - { - auto combo = ui::ComboBoxText(ui::New); +void Dialog::addCombo(ui::VBox vbox, const char *name, StringArrayRange values, Property const &cb) +{ + auto alignment = ui::Alignment(0.0, 0.5, 0.0, 0.0); + alignment.show(); + { + auto combo = ui::ComboBoxText(ui::New); - for ( StringArrayRange::Iterator i = values.first; i != values.last; ++i ) - { - gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), *i ); - } + for (StringArrayRange::Iterator i = values.first; i != values.last; ++i) { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), *i); + } - AddIntComboData( combo, cb ); + AddIntComboData(combo, cb); - combo.show(); - alignment.add(combo); - } + combo.show(); + alignment.add(combo); + } - auto row = DialogRow_new( name, alignment ); - DialogVBox_packRow( vbox, row ); + auto row = DialogRow_new(name, alignment); + DialogVBox_packRow(vbox, row); } -void Dialog::addCombo( ui::VBox vbox, const char* name, int& data, StringArrayRange values ){ - addCombo(vbox, name, values, make_property(data)); +void Dialog::addCombo(ui::VBox vbox, const char *name, int &data, StringArrayRange values) +{ + addCombo(vbox, name, values, make_property(data)); } -void Dialog::addSlider( ui::VBox 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 ){ +void +Dialog::addSlider(ui::VBox 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) +{ #if 0 - if ( draw_value == FALSE ) { - auto hbox2 = ui::HBox( FALSE, 0 ); - hbox2.show(); - vbox.pack_start( hbox2 , FALSE, FALSE, 0 ); - { - ui::Widget label = ui::Label( low ); - label.show(); - hbox2.pack_start( label, FALSE, FALSE, 0 ); - } - { - ui::Widget label = ui::Label( high ); - label.show(); - hbox2.pack_end(label, FALSE, FALSE, 0); - } - } + if ( draw_value == FALSE ) { + auto hbox2 = ui::HBox( FALSE, 0 ); + hbox2.show(); + vbox.pack_start( hbox2 , FALSE, FALSE, 0 ); + { + ui::Widget label = ui::Label( low ); + label.show(); + hbox2.pack_start( label, FALSE, FALSE, 0 ); + } + { + ui::Widget label = ui::Label( high ); + label.show(); + hbox2.pack_end(label, FALSE, FALSE, 0); + } + } #endif - // adjustment - auto adj = ui::Adjustment( value, lower, upper, step_increment, page_increment, 0 ); - AddIntAdjustmentData(adj, make_property(data)); + // adjustment + auto adj = ui::Adjustment(value, lower, upper, step_increment, page_increment, 0); + AddIntAdjustmentData(adj, make_property(data)); - // scale - auto alignment = ui::Alignment( 0.0, 0.5, 1.0, 0.0 ); - alignment.show(); + // scale + auto alignment = ui::Alignment(0.0, 0.5, 1.0, 0.0); + alignment.show(); - ui::Widget scale = ui::HScale( adj ); - gtk_scale_set_value_pos( GTK_SCALE( scale ), GTK_POS_LEFT ); - scale.show(); - alignment.add(scale); + ui::Widget scale = ui::HScale(adj); + gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_LEFT); + scale.show(); + alignment.add(scale); - gtk_scale_set_draw_value( GTK_SCALE( scale ), draw_value ); - gtk_scale_set_digits( GTK_SCALE( scale ), 0 ); + gtk_scale_set_draw_value(GTK_SCALE(scale), draw_value); + gtk_scale_set_digits(GTK_SCALE(scale), 0); - auto row = DialogRow_new( name, alignment ); - DialogVBox_packRow( vbox, row ); + auto row = DialogRow_new(name, alignment); + DialogVBox_packRow(vbox, row); } -void Dialog::addRadio( ui::VBox vbox, const char* name, StringArrayRange names, Property const &cb ){ - auto alignment = ui::Alignment( 0.0, 0.5, 0.0, 0.0 ); - alignment.show();; - { - RadioHBox radioBox = RadioHBox_new( names ); - alignment.add(radioBox.m_hbox); - AddIntRadioData( radioBox.m_radio, cb ); - } +void Dialog::addRadio(ui::VBox vbox, const char *name, StringArrayRange names, Property const &cb) +{ + auto alignment = ui::Alignment(0.0, 0.5, 0.0, 0.0); + alignment.show();; + { + RadioHBox radioBox = RadioHBox_new(names); + alignment.add(radioBox.m_hbox); + AddIntRadioData(radioBox.m_radio, cb); + } - auto row = DialogRow_new( name, alignment ); - DialogVBox_packRow( vbox, row ); + auto row = DialogRow_new(name, alignment); + DialogVBox_packRow(vbox, row); } -void Dialog::addRadio( ui::VBox vbox, const char* name, int& data, StringArrayRange names ){ - addRadio(vbox, name, names, make_property(data)); +void Dialog::addRadio(ui::VBox vbox, const char *name, int &data, StringArrayRange names) +{ + addRadio(vbox, name, names, make_property(data)); } -void Dialog::addRadioIcons( ui::VBox vbox, const char* name, StringArrayRange icons, Property const &cb ){ +void Dialog::addRadioIcons(ui::VBox vbox, const char *name, StringArrayRange icons, Property const &cb) +{ auto table = ui::Table(2, icons.last - icons.first, FALSE); table.show(); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - GSList* group = 0; - ui::RadioButton radio{ui::null}; - for ( StringArrayRange::Iterator icon = icons.first; icon != icons.last; ++icon ) - { - guint pos = static_cast( icon - icons.first ); - auto image = new_local_image( *icon ); - image.show(); + GSList *group = 0; + ui::RadioButton radio{ui::null}; + for (StringArrayRange::Iterator icon = icons.first; icon != icons.last; ++icon) { + guint pos = static_cast( icon - icons.first ); + auto image = new_local_image(*icon); + image.show(); table.attach(image, {pos, pos + 1, 0, 1}, {0, 0}); - radio = ui::RadioButton::from(gtk_radio_button_new( group )); - radio.show(); + radio = ui::RadioButton::from(gtk_radio_button_new(group)); + radio.show(); table.attach(radio, {pos, pos + 1, 1, 2}, {0, 0}); - group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radio ) ); - } + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); + } - AddIntRadioData( radio, cb ); + AddIntRadioData(radio, cb); - DialogVBox_packRow( vbox, DialogRow_new( name, table ) ); + DialogVBox_packRow(vbox, DialogRow_new(name, table)); } -void Dialog::addRadioIcons( ui::VBox vbox, const char* name, int& data, StringArrayRange icons ){ - addRadioIcons(vbox, name, icons, make_property(data)); +void Dialog::addRadioIcons(ui::VBox vbox, const char *name, int &data, StringArrayRange icons) +{ + addRadioIcons(vbox, name, icons, make_property(data)); } -ui::Widget Dialog::addIntEntry( ui::VBox vbox, const char* name, Property const &cb ){ - DialogEntryRow row( DialogEntryRow_new( name ) ); - AddIntEntryData( row.m_entry, cb ); - DialogVBox_packRow( vbox, row.m_row ); - return row.m_row; +ui::Widget Dialog::addIntEntry(ui::VBox vbox, const char *name, Property const &cb) +{ + DialogEntryRow row(DialogEntryRow_new(name)); + AddIntEntryData(row.m_entry, cb); + DialogVBox_packRow(vbox, row.m_row); + return row.m_row; } -ui::Widget Dialog::addSizeEntry( ui::VBox vbox, const char* name, Property const &cb ){ - DialogEntryRow row( DialogEntryRow_new( name ) ); - AddSizeEntryData( row.m_entry, cb ); - DialogVBox_packRow( vbox, row.m_row ); - return row.m_row; +ui::Widget Dialog::addSizeEntry(ui::VBox vbox, const char *name, Property const &cb) +{ + DialogEntryRow row(DialogEntryRow_new(name)); + AddSizeEntryData(row.m_entry, cb); + DialogVBox_packRow(vbox, row.m_row); + return row.m_row; } -ui::Widget Dialog::addFloatEntry( ui::VBox vbox, const char* name, Property const &cb ){ - DialogEntryRow row( DialogEntryRow_new( name ) ); - AddFloatEntryData( row.m_entry, cb ); - DialogVBox_packRow( vbox, row.m_row ); - return row.m_row; +ui::Widget Dialog::addFloatEntry(ui::VBox vbox, const char *name, Property const &cb) +{ + DialogEntryRow row(DialogEntryRow_new(name)); + AddFloatEntryData(row.m_entry, cb); + DialogVBox_packRow(vbox, row.m_row); + return row.m_row; } -ui::Widget Dialog::addPathEntry( ui::VBox vbox, const char* name, bool browse_directory, Property const &cb ){ - PathEntry pathEntry = PathEntry_new(); - pathEntry.m_button.connect( "clicked", G_CALLBACK( browse_directory ? button_clicked_entry_browse_directory : button_clicked_entry_browse_file ), pathEntry.m_entry ); +ui::Widget +Dialog::addPathEntry(ui::VBox vbox, const char *name, bool browse_directory, Property const &cb) +{ + PathEntry pathEntry = PathEntry_new(); + pathEntry.m_button.connect("clicked", G_CALLBACK( + browse_directory ? button_clicked_entry_browse_directory : button_clicked_entry_browse_file), + pathEntry.m_entry); - AddTextEntryData( pathEntry.m_entry, cb ); + AddTextEntryData(pathEntry.m_entry, cb); - auto row = DialogRow_new( name, ui::Widget(pathEntry.m_frame ) ); - DialogVBox_packRow( vbox, row ); + auto row = DialogRow_new(name, ui::Widget(pathEntry.m_frame)); + DialogVBox_packRow(vbox, row); - return row; + return row; } -ui::Widget Dialog::addPathEntry( ui::VBox vbox, const char* name, CopiedString& data, bool browse_directory ){ +ui::Widget Dialog::addPathEntry(ui::VBox vbox, const char *name, CopiedString &data, bool browse_directory) +{ return addPathEntry(vbox, name, browse_directory, make_property(data)); } -ui::SpinButton Dialog::addSpinner( ui::VBox vbox, const char* name, double value, double lower, double upper, Property const &cb ){ - DialogSpinnerRow row( DialogSpinnerRow_new( name, value, lower, upper, 1 ) ); - AddIntSpinnerData( row.m_spin, cb ); - DialogVBox_packRow( vbox, row.m_row ); - return row.m_spin; +ui::SpinButton +Dialog::addSpinner(ui::VBox vbox, const char *name, double value, double lower, double upper, Property const &cb) +{ + DialogSpinnerRow row(DialogSpinnerRow_new(name, value, lower, upper, 1)); + AddIntSpinnerData(row.m_spin, cb); + DialogVBox_packRow(vbox, row.m_row); + return row.m_spin; } -ui::SpinButton Dialog::addSpinner( ui::VBox vbox, const char* name, int& data, double value, double lower, double upper ){ - return addSpinner(vbox, name, value, lower, upper, make_property(data)); +ui::SpinButton Dialog::addSpinner(ui::VBox vbox, const char *name, int &data, double value, double lower, double upper) +{ + return addSpinner(vbox, name, value, lower, upper, make_property(data)); } -ui::SpinButton Dialog::addSpinner( ui::VBox vbox, const char* name, double value, double lower, double upper, Property const &cb ){ - DialogSpinnerRow row( DialogSpinnerRow_new( name, value, lower, upper, 10 ) ); - AddFloatSpinnerData( row.m_spin, cb ); - DialogVBox_packRow( vbox, row.m_row ); - return row.m_spin; +ui::SpinButton +Dialog::addSpinner(ui::VBox vbox, const char *name, double value, double lower, double upper, Property const &cb) +{ + DialogSpinnerRow row(DialogSpinnerRow_new(name, value, lower, upper, 10)); + AddFloatSpinnerData(row.m_spin, cb); + DialogVBox_packRow(vbox, row.m_row); + return row.m_spin; } diff --git a/radiant/dialog.h b/radiant/dialog.h index 78efa830..d4b26d59 100644 --- a/radiant/dialog.h +++ b/radiant/dialog.h @@ -31,155 +31,164 @@ #include "generic/callback.h" #include "string/string.h" -struct DLG_DATA -{ - virtual ~DLG_DATA() = default; - virtual void release() = 0; - virtual void importData() const = 0; - virtual void exportData() const = 0; +struct DLG_DATA { + virtual ~DLG_DATA() = default; + + virtual void release() = 0; + + virtual void importData() const = 0; + + virtual void exportData() const = 0; }; template class CallbackDialogData; -typedef std::list DialogDataList; +typedef std::list DialogDataList; class Dialog { - ui::Window m_window; - DialogDataList m_data; + ui::Window m_window; + DialogDataList m_data; public: - ModalDialog m_modal; - ui::Window m_parent; + ModalDialog m_modal; + ui::Window m_parent; - Dialog(); + Dialog(); - virtual ~Dialog(); + virtual ~Dialog(); /*! start modal dialog box you need to use AddModalButton to select eIDOK eIDCANCEL buttons */ - EMessageBoxReturn DoModal(); + EMessageBoxReturn DoModal(); - void EndModal(EMessageBoxReturn code); + void EndModal(EMessageBoxReturn code); - virtual ui::Window BuildDialog() = 0; + virtual ui::Window BuildDialog() = 0; - virtual void exportData(); + virtual void exportData(); - virtual void importData(); + virtual void importData(); - virtual void PreModal() {}; + virtual void PreModal() + {}; - virtual void PostModal(EMessageBoxReturn code) {}; + virtual void PostModal(EMessageBoxReturn code) + {}; - virtual void ShowDlg(); + virtual void ShowDlg(); - virtual void HideDlg(); + virtual void HideDlg(); - void Create(); + void Create(); - void Destroy(); + void Destroy(); - ui::Window GetWidget() { - return m_window; - } + ui::Window GetWidget() + { + return m_window; + } - const ui::Window GetWidget() const { - return m_window; - } + const ui::Window GetWidget() const + { + return m_window; + } - ui::CheckButton addCheckBox(ui::VBox vbox, const char *name, const char *flag, Property const &cb); + ui::CheckButton addCheckBox(ui::VBox vbox, const char *name, const char *flag, Property const &cb); - ui::CheckButton addCheckBox(ui::VBox vbox, const char *name, const char *flag, bool &data); + ui::CheckButton addCheckBox(ui::VBox vbox, const char *name, const char *flag, bool &data); - void addCombo(ui::VBox vbox, const char *name, StringArrayRange values, Property const &cb); + void addCombo(ui::VBox vbox, const char *name, StringArrayRange values, Property const &cb); - void addCombo(ui::VBox vbox, const char *name, int &data, StringArrayRange values); + void addCombo(ui::VBox vbox, const char *name, int &data, StringArrayRange values); - void addSlider(ui::VBox 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); + void addSlider(ui::VBox 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); - void addRadio(ui::VBox vbox, const char *name, StringArrayRange names, Property const &cb); + void addRadio(ui::VBox vbox, const char *name, StringArrayRange names, Property const &cb); - void addRadio(ui::VBox vbox, const char *name, int &data, StringArrayRange names); + void addRadio(ui::VBox vbox, const char *name, int &data, StringArrayRange names); - void addRadioIcons(ui::VBox vbox, const char *name, StringArrayRange icons, Property const &cb); + void addRadioIcons(ui::VBox vbox, const char *name, StringArrayRange icons, Property const &cb); - void addRadioIcons(ui::VBox vbox, const char *name, int &data, StringArrayRange icons); + void addRadioIcons(ui::VBox vbox, const char *name, int &data, StringArrayRange icons); - ui::Widget addIntEntry(ui::VBox vbox, const char *name, Property const &cb); + ui::Widget addIntEntry(ui::VBox vbox, const char *name, Property const &cb); - ui::Widget addEntry(ui::VBox vbox, const char *name, int &data) { - return addIntEntry(vbox, name, make_property(data)); - } + ui::Widget addEntry(ui::VBox vbox, const char *name, int &data) + { + return addIntEntry(vbox, name, make_property(data)); + } - ui::Widget addSizeEntry(ui::VBox vbox, const char *name, Property const &cb); + ui::Widget addSizeEntry(ui::VBox vbox, const char *name, Property const &cb); - ui::Widget addEntry(ui::VBox vbox, const char *name, std::size_t &data) { - return addSizeEntry(vbox, name, make_property(data)); - } + ui::Widget addEntry(ui::VBox vbox, const char *name, std::size_t &data) + { + return addSizeEntry(vbox, name, make_property(data)); + } - ui::Widget addFloatEntry(ui::VBox vbox, const char *name, Property const &cb); + ui::Widget addFloatEntry(ui::VBox vbox, const char *name, Property const &cb); - ui::Widget addEntry(ui::VBox vbox, const char *name, float &data) { - return addFloatEntry(vbox, name, make_property(data)); - } + ui::Widget addEntry(ui::VBox vbox, const char *name, float &data) + { + return addFloatEntry(vbox, name, make_property(data)); + } - ui::Widget addPathEntry(ui::VBox vbox, const char *name, bool browse_directory, Property const &cb); + ui::Widget addPathEntry(ui::VBox vbox, const char *name, bool browse_directory, Property const &cb); - ui::Widget addPathEntry(ui::VBox vbox, const char *name, CopiedString &data, bool directory); + ui::Widget addPathEntry(ui::VBox vbox, const char *name, CopiedString &data, bool directory); - ui::SpinButton addSpinner(ui::VBox vbox, const char *name, int &data, double value, double lower, double upper); + ui::SpinButton addSpinner(ui::VBox vbox, const char *name, int &data, double value, double lower, double upper); - ui::SpinButton - addSpinner(ui::VBox vbox, const char *name, double value, double lower, double upper, Property const &cb); + ui::SpinButton + addSpinner(ui::VBox vbox, const char *name, double value, double lower, double upper, Property const &cb); - ui::SpinButton - addSpinner(ui::VBox vbox, const char *name, double value, double lower, double upper, Property const &cb); + ui::SpinButton + addSpinner(ui::VBox vbox, const char *name, double value, double lower, double upper, Property const &cb); protected: - void AddBoolToggleData(ui::ToggleButton object, Property const &cb); + void AddBoolToggleData(ui::ToggleButton object, Property const &cb); - void AddIntRadioData(ui::RadioButton object, Property const &cb); + void AddIntRadioData(ui::RadioButton object, Property const &cb); - void AddTextEntryData(ui::Entry object, Property const &cb); + void AddTextEntryData(ui::Entry object, Property const &cb); - void AddIntEntryData(ui::Entry object, Property const &cb); + void AddIntEntryData(ui::Entry object, Property const &cb); - void AddSizeEntryData(ui::Entry object, Property const &cb); + void AddSizeEntryData(ui::Entry object, Property const &cb); - void AddFloatEntryData(ui::Entry object, Property const &cb); + void AddFloatEntryData(ui::Entry object, Property const &cb); - void AddFloatSpinnerData(ui::SpinButton object, Property const &cb); + void AddFloatSpinnerData(ui::SpinButton object, Property const &cb); - void AddIntSpinnerData(ui::SpinButton object, Property const &cb); + void AddIntSpinnerData(ui::SpinButton object, Property const &cb); - void AddIntAdjustmentData(ui::Adjustment object, Property const &cb); + void AddIntAdjustmentData(ui::Adjustment object, Property const &cb); - void AddIntComboData(ui::ComboBox object, Property const &cb); + void AddIntComboData(ui::ComboBox object, Property const &cb); - void AddDialogData(ui::ToggleButton object, bool &data); + void AddDialogData(ui::ToggleButton object, bool &data); - void AddDialogData(ui::RadioButton object, int &data); + void AddDialogData(ui::RadioButton object, int &data); - void AddDialogData(ui::Entry object, CopiedString &data); + void AddDialogData(ui::Entry object, CopiedString &data); - void AddDialogData(ui::Entry object, int &data); + void AddDialogData(ui::Entry object, int &data); - void AddDialogData(ui::Entry object, std::size_t &data); + void AddDialogData(ui::Entry object, std::size_t &data); - void AddDialogData(ui::Entry object, float &data); + void AddDialogData(ui::Entry object, float &data); - void AddDialogData(ui::SpinButton object, float &data); + void AddDialogData(ui::SpinButton object, float &data); - void AddDialogData(ui::SpinButton object, int &data); + void AddDialogData(ui::SpinButton object, int &data); - void AddDialogData(ui::Adjustment object, int &data); + void AddDialogData(ui::Adjustment object, int &data); - void AddDialogData(ui::ComboBox object, int &data); + void AddDialogData(ui::ComboBox object, int &data); }; #endif diff --git a/radiant/eclass.cpp b/radiant/eclass.cpp index 90c8a11b..95b1a2cf 100644 --- a/radiant/eclass.cpp +++ b/radiant/eclass.cpp @@ -40,305 +40,340 @@ #include "mainframe.h" -namespace -{ -typedef std::map EntityClasses; -EntityClasses g_entityClasses; -EntityClass *eclass_bad = 0; -char eclass_directory[1024]; -typedef std::map ListAttributeTypes; -ListAttributeTypes g_listTypes; +namespace { + typedef std::map EntityClasses; + EntityClasses g_entityClasses; + EntityClass *eclass_bad = 0; + char eclass_directory[1024]; + typedef std::map ListAttributeTypes; + ListAttributeTypes g_listTypes; } -EClassModules& EntityClassManager_getEClassModules(); +EClassModules &EntityClassManager_getEClassModules(); /*! 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 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(); +void Eclass_Clear() +{ + CleanEntityList(g_entityClasses); + g_listTypes.clear(); } -EntityClass* EClass_InsertSortedList( EntityClasses& entityClasses, EntityClass *entityClass ){ - std::pair result = entityClasses.insert( EntityClasses::value_type( entityClass->name(), entityClass ) ); - if ( !result.second ) { - entityClass->free( entityClass ); - } - return ( *result.first ).second; +EntityClass *EClass_InsertSortedList(EntityClasses &entityClasses, EntityClass *entityClass) +{ + std::pair 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 ); +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 ); - } +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 -{ +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 ) ); -} + 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; +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 -{ +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_"; - } -} + 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 EntityClassScanner& scanner; -const char* m_directory; +class EntityClassesLoadFile { + const EntityClassScanner &scanner; + const char *m_directory; public: -EntityClassesLoadFile( const EntityClassScanner& scanner, const char* directory ) : scanner( scanner ), 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; - - scanner.scanFile( g_collector, relPath.c_str() ); -} + EntityClassesLoadFile(const EntityClassScanner &scanner, const char *directory) : scanner(scanner), + 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; + + scanner.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() ); - } +struct PathLess { + bool operator()(const CopiedString &path, const CopiedString &other) const + { + return path_less(path.c_str(), other.c_str()); + } }; -typedef std::map Paths; +typedef std::map Paths; -void EntityClassQuake3_constructDirectory( const char* directory, const char* extension, Paths& paths ){ - globalOutputStream() << "EntityClass: searching " << makeQuoted( directory ) << " for *." << extension << '\n'; - Directory_forEach(directory, matchFileExtension(extension, [&](const char *name) { - paths.insert(Paths::value_type(name, directory)); - })); +void EntityClassQuake3_constructDirectory(const char *directory, const char *extension, Paths &paths) +{ + globalOutputStream() << "EntityClass: searching " << makeQuoted(directory) << " for *." << extension << '\n'; + Directory_forEach(directory, matchFileExtension(extension, [&](const char *name) { + paths.insert(Paths::value_type(name, directory)); + })); } -void EntityClassQuake3_Construct(){ - 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 << '/'; - - class LoadEntityDefinitionsVisitor : public EClassModules::Visitor - { - const char* baseDirectory; - const char* gameDirectory; -public: - LoadEntityDefinitionsVisitor( const char* baseDirectory, const char* gameDirectory ) - : baseDirectory( baseDirectory ), gameDirectory( gameDirectory ){ - } - void visit( const char* name, const EntityClassScanner& table ) const { - Paths paths; - EntityClassQuake3_constructDirectory( baseDirectory, table.getExtension(), paths ); - if ( !string_equal( baseDirectory, gameDirectory ) ) { - EntityClassQuake3_constructDirectory( gameDirectory, table.getExtension(), paths ); - } - - for ( Paths::iterator i = paths.begin(); i != paths.end(); ++i ) - { - EntityClassesLoadFile( table, ( *i ).second ) ( ( *i ).first.c_str() ); - } - } - }; - - EntityClassManager_getEClassModules().foreachModule( LoadEntityDefinitionsVisitor( baseDirectory.c_str(), gameDirectory.c_str() ) ); -} - -EntityClass *Eclass_ForName( const char *name, bool has_brushes ){ - ASSERT_NOTNULL( name ); +void EntityClassQuake3_Construct() +{ + 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 << '/'; + + class LoadEntityDefinitionsVisitor : public EClassModules::Visitor { + const char *baseDirectory; + const char *gameDirectory; + public: + LoadEntityDefinitionsVisitor(const char *baseDirectory, const char *gameDirectory) + : baseDirectory(baseDirectory), gameDirectory(gameDirectory) + { + } + + void visit(const char *name, const EntityClassScanner &table) const + { + Paths paths; + EntityClassQuake3_constructDirectory(baseDirectory, table.getExtension(), paths); + if (!string_equal(baseDirectory, gameDirectory)) { + EntityClassQuake3_constructDirectory(gameDirectory, table.getExtension(), paths); + } + + for (Paths::iterator i = paths.begin(); i != paths.end(); ++i) { + EntityClassesLoadFile(table, (*i).second)((*i).first.c_str()); + } + } + }; + + EntityClassManager_getEClassModules().foreachModule( + LoadEntityDefinitionsVisitor(baseDirectory.c_str(), gameDirectory.c_str())); +} + +EntityClass *Eclass_ForName(const char *name, bool has_brushes) +{ + ASSERT_NOTNULL(name); - if ( string_empty( name ) ) { - return eclass_bad; - } + 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; - } + 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 ); + EntityClass *e = EntityClass_Create_Default(name, has_brushes); + return Eclass_InsertAlphabetized(e); } -class EntityClassQuake3 : public ModuleObserver -{ -std::size_t m_unrealised; -ModuleObservers m_observers; +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() : 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_attach(ModuleObserver &observer) +{ + g_EntityClassQuake3.attach(observer); } -void EntityClass_detach( ModuleObserver& observer ){ - g_EntityClassQuake3.detach( observer ); + +void EntityClass_detach(ModuleObserver &observer) +{ + g_EntityClassQuake3.detach(observer); } -void EntityClass_realise(){ - g_EntityClassQuake3.realise(); +void EntityClass_realise() +{ + g_EntityClassQuake3.realise(); } -void EntityClass_unrealise(){ - g_EntityClassQuake3.unrealise(); + +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 ), "" ); +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(); + EntityClass_realise(); } -void EntityClassQuake3_destroy(){ - EntityClass_unrealise(); +void EntityClassQuake3_destroy() +{ + EntityClass_unrealise(); - eclass_bad->free( eclass_bad ); + eclass_bad->free(eclass_bad); } #include "modulesystem/modulesmap.h" class EntityClassQuake3Dependencies : - public GlobalRadiantModuleRef, - public GlobalFileSystemModuleRef, - public GlobalShaderCacheModuleRef -{ -EClassModulesRef m_eclass_modules; + public GlobalRadiantModuleRef, + public GlobalFileSystemModuleRef, + public GlobalShaderCacheModuleRef { + EClassModulesRef m_eclass_modules; public: -EntityClassQuake3Dependencies() : - m_eclass_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entityclasstype" ) ){ -} -EClassModules& getEClassModules(){ - return m_eclass_modules.get(); -} + EntityClassQuake3Dependencies() : + m_eclass_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclasstype")) + { + } + + EClassModules &getEClassModules() + { + return m_eclass_modules.get(); + } }; -class EclassManagerAPI -{ -EntityClassManager m_eclassmanager; +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; - - Radiant_attachGameToolsPathObserver( g_EntityClassQuake3 ); - Radiant_attachGameModeObserver( g_EntityClassQuake3 ); - Radiant_attachGameNameObserver( g_EntityClassQuake3 ); -} -~EclassManagerAPI(){ - Radiant_detachGameNameObserver( g_EntityClassQuake3 ); - Radiant_detachGameModeObserver( g_EntityClassQuake3 ); - Radiant_detachGameToolsPathObserver( g_EntityClassQuake3 ); - - EntityClassQuake3_destroy(); -} -EntityClassManager* getTable(){ - return &m_eclassmanager; -} + 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; + + Radiant_attachGameToolsPathObserver(g_EntityClassQuake3); + Radiant_attachGameModeObserver(g_EntityClassQuake3); + Radiant_attachGameNameObserver(g_EntityClassQuake3); + } + + ~EclassManagerAPI() + { + Radiant_detachGameNameObserver(g_EntityClassQuake3); + Radiant_detachGameModeObserver(g_EntityClassQuake3); + Radiant_detachGameToolsPathObserver(g_EntityClassQuake3); + + EntityClassQuake3_destroy(); + } + + EntityClassManager *getTable() + { + return &m_eclassmanager; + } }; #include "modulesystem/singletonmodule.h" @@ -346,8 +381,9 @@ EntityClassManager* getTable(){ typedef SingletonModule EclassManagerModule; typedef Static StaticEclassManagerModule; -StaticRegisterModule staticRegisterEclassManager( StaticEclassManagerModule::instance() ); +StaticRegisterModule staticRegisterEclassManager(StaticEclassManagerModule::instance()); -EClassModules& EntityClassManager_getEClassModules(){ - return StaticEclassManagerModule::instance().getDependencies().getEClassModules(); +EClassModules &EntityClassManager_getEClassModules() +{ + return StaticEclassManagerModule::instance().getDependencies().getEClassModules(); } diff --git a/radiant/eclass_def.cpp b/radiant/eclass_def.cpp index 8637b480..daa0e706 100644 --- a/radiant/eclass_def.cpp +++ b/radiant/eclass_def.cpp @@ -31,37 +31,41 @@ #include "modulesystem/moduleregistry.h" #include "os/path.h" -const char* EClass_GetExtension(){ - return "def"; +const char *EClass_GetExtension() +{ + return "def"; } -void Eclass_ScanFile( EntityClassCollector& collector, const char *filename ); + +void Eclass_ScanFile(EntityClassCollector &collector, const char *filename); #include "modulesystem/singletonmodule.h" -class EntityClassDefDependencies : public GlobalShaderCacheModuleRef, public GlobalScripLibModuleRef -{ +class EntityClassDefDependencies : public GlobalShaderCacheModuleRef, public GlobalScripLibModuleRef { }; -class EclassDefAPI -{ -EntityClassScanner m_eclassdef; +class EclassDefAPI { + EntityClassScanner m_eclassdef; public: -typedef EntityClassScanner Type; -STRING_CONSTANT( Name, "def" ); + typedef EntityClassScanner Type; -EclassDefAPI(){ - m_eclassdef.scanFile = &Eclass_ScanFile; - m_eclassdef.getExtension = &EClass_GetExtension; -} -EntityClassScanner* getTable(){ - return &m_eclassdef; -} + STRING_CONSTANT(Name, "def"); + + EclassDefAPI() + { + m_eclassdef.scanFile = &Eclass_ScanFile; + m_eclassdef.getExtension = &EClass_GetExtension; + } + + EntityClassScanner *getTable() + { + return &m_eclassdef; + } }; typedef SingletonModule EclassDefModule; typedef Static StaticEclassDefModule; -StaticRegisterModule staticRegisterEclassDef( StaticEclassDefModule::instance() ); +StaticRegisterModule staticRegisterEclassDef(StaticEclassDefModule::instance()); #include "string/string.h" @@ -79,107 +83,106 @@ bool com_eof; Parse a token out of a string ============== */ -const char *COM_Parse( const char *data ){ - int c; - int len; +const char *COM_Parse(const char *data) +{ + int c; + int len; - len = 0; - com_token[0] = 0; + len = 0; + com_token[0] = 0; - if ( !data ) { - return 0; - } + if (!data) { + return 0; + } // skip whitespace -skipwhite: - while ( ( c = *data ) <= ' ' ) - { - if ( c == 0 ) { - com_eof = true; - return 0; // end of file; - } - data++; - } + 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; - } + 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 ); - } + 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; - } + 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; + 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 *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. - - const char *pText = 0; - const char *where = 0; - - where = strstr( e->comments(),pWhat ); - if ( !where ) { - return; - } - - pText = where + strlen( pWhat ); - if ( *pText == '\"' ) { - pText++; - } - - where = strchr( pText,'\"' ); - if ( where ) { - p = StringRange( pText, where ); - } - else - { - p = pText; - } +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. + + const char *pText = 0; + const char *where = 0; + + where = strstr(e->comments(), pWhat); + if (!where) { + return; + } + + pText = where + strlen(pWhat); + if (*pText == '\"') { + pText++; + } + + where = strchr(pText, '\"'); + if (where) { + p = StringRange(pText, where); + } else { + p = pText; + } } #include "eclasslib.h" @@ -198,192 +201,178 @@ void setSpecialLoad( EntityClass *e, const char* pWhat, CopiedString& p ){ */ -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; +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 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; - } - } +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 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; + } + } } diff --git a/radiant/eclass_doom3.cpp b/radiant/eclass_doom3.cpp index 4c7525ea..247c160b 100644 --- a/radiant/eclass_doom3.cpp +++ b/radiant/eclass_doom3.cpp @@ -39,778 +39,784 @@ #include "moduleobservers.h" #include "stringio.h" -class RawString -{ -const char* m_value; +class RawString { + const char *m_value; public: -RawString( const char* value ) : m_value( value ){ -} -const char* c_str() const { - return m_value; -} + 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() ); +inline bool operator<(const RawString &self, const RawString &other) +{ + return string_less_nocase(self.c_str(), other.c_str()); } -typedef std::map EntityClasses; +typedef std::map 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(); +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; +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_forEach(EntityClassVisitor &visitor) +{ + for (EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i) { + visitor.visit((*i).second); + } } -inline void printParseError( const char* message ){ - globalErrorStream() << message; +inline void printParseError(const char *message) +{ + globalErrorStream() << message; } #define PARSE_RETURN_FALSE_IF_FAIL(expression) do { if (!( expression)) { printParseError(FILE_LINE "\nparse failed: " #expression "\n"); return false; } } while (0) -bool EntityClassDoom3_parseToken( Tokeniser& tokeniser ){ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); - return true; +bool EntityClassDoom3_parseToken(Tokeniser &tokeniser) +{ + const char *token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL(token != 0); + return true; } -bool EntityClassDoom3_parseToken( Tokeniser& tokeniser, const char* string ){ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); - return string_equal( token, string ); +bool EntityClassDoom3_parseToken(Tokeniser &tokeniser, const char *string) +{ + const char *token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL(token != 0); + return string_equal(token, string); } -bool EntityClassDoom3_parseString( Tokeniser& tokeniser, const char*& s ){ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); - s = token; - return true; +bool EntityClassDoom3_parseString(Tokeniser &tokeniser, const char *&s) +{ + const char *token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL(token != 0); + s = token; + return true; } -bool EntityClassDoom3_parseString( Tokeniser& tokeniser, CopiedString& s ){ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); - s = token; - return true; +bool EntityClassDoom3_parseString(Tokeniser &tokeniser, CopiedString &s) +{ + const char *token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL(token != 0); + s = token; + return true; } -bool EntityClassDoom3_parseString( Tokeniser& tokeniser, StringOutputStream& s ){ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); - s << token; - return true; +bool EntityClassDoom3_parseString(Tokeniser &tokeniser, StringOutputStream &s) +{ + const char *token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL(token != 0); + s << token; + return true; } -bool EntityClassDoom3_parseUnknown( Tokeniser& tokeniser ){ - //const char* name = - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); +bool EntityClassDoom3_parseUnknown(Tokeniser &tokeniser) +{ + //const char* name = + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - //globalOutputStream() << "parsing unknown block " << makeQuoted(name) << "\n"; + //globalOutputStream() << "parsing unknown block " << makeQuoted(name) << "\n"; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "{")); + tokeniser.nextLine(); - std::size_t depth = 1; - for (;; ) - { - const char* token; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); - if ( string_equal( token, "}" ) ) { - if ( --depth == 0 ) { - tokeniser.nextLine(); - break; - } - } - else if ( string_equal( token, "{" ) ) { - ++depth; - } - tokeniser.nextLine(); - } - return true; + std::size_t depth = 1; + for (;;) { + const char *token; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); + if (string_equal(token, "}")) { + if (--depth == 0) { + tokeniser.nextLine(); + break; + } + } else if (string_equal(token, "{")) { + ++depth; + } + tokeniser.nextLine(); + } + return true; } -class Model -{ +class Model { public: -bool m_resolved; -CopiedString m_mesh; -CopiedString m_skin; -CopiedString m_parent; -typedef std::map Anims; -Anims m_anims; -Model() : m_resolved( false ){ -} + bool m_resolved; + CopiedString m_mesh; + CopiedString m_skin; + CopiedString m_parent; + typedef std::map Anims; + Anims m_anims; + + Model() : m_resolved(false) + { + } }; typedef std::map 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; - } - } - } -} - -bool EntityClassDoom3_parseModel( Tokeniser& tokeniser ){ - const char* name; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, name ) ); - - Model& model = g_models[name]; - - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); - - for (;; ) - { - const char* parameter; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, parameter ) ); - if ( string_equal( parameter, "}" ) ) { - tokeniser.nextLine(); - break; - } - else if ( string_equal( parameter, "inherit" ) ) { - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, model.m_parent ) ); - tokeniser.nextLine(); - } - else if ( string_equal( parameter, "remove" ) ) { - //const char* remove = - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - tokeniser.nextLine(); - } - else if ( string_equal( parameter, "mesh" ) ) { - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, model.m_mesh ) ); - tokeniser.nextLine(); - } - else if ( string_equal( parameter, "skin" ) ) { - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, model.m_skin ) ); - tokeniser.nextLine(); - } - else if ( string_equal( parameter, "offset" ) ) { - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "(" ) ); - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, ")" ) ); - tokeniser.nextLine(); - } - else if ( string_equal( parameter, "channel" ) ) { - //const char* channelName = - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "(" ) ); - for (;; ) - { - const char* end; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, end ) ); - if ( string_equal( end, ")" ) ) { - tokeniser.nextLine(); - break; - } - } - } - else if ( string_equal( parameter, "anim" ) ) { - CopiedString animName; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, animName ) ); - const char* animFile; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, animFile ) ); - model.m_anims.insert( Model::Anims::value_type( animName, animFile ) ); - - const char* token; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); - - while ( string_equal( token, "," ) ) - { - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, animFile ) ); - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); - } - - if ( string_equal( token, "{" ) ) { - for (;; ) - { - const char* end; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, end ) ); - if ( string_equal( end, "}" ) ) { - tokeniser.nextLine(); - break; - } - tokeniser.nextLine(); - } - } - else - { - tokeniser.ungetToken(); - } - } - else - { - globalErrorStream() << "unknown model parameter: " << makeQuoted( parameter ) << "\n"; - return false; - } - tokeniser.nextLine(); - } - return true; -} - -inline bool char_isSpaceOrTab( char c ){ - return c == ' ' || c == '\t'; -} - -inline bool char_isNotSpaceOrTab( char c ){ - return !char_isSpaceOrTab( c ); +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; + } + } + } +} + +bool EntityClassDoom3_parseModel(Tokeniser &tokeniser) +{ + const char *name; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, name)); + + Model &model = g_models[name]; + + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "{")); + tokeniser.nextLine(); + + for (;;) { + const char *parameter; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, parameter)); + if (string_equal(parameter, "}")) { + tokeniser.nextLine(); + break; + } else if (string_equal(parameter, "inherit")) { + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, model.m_parent)); + tokeniser.nextLine(); + } else if (string_equal(parameter, "remove")) { + //const char* remove = + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + tokeniser.nextLine(); + } else if (string_equal(parameter, "mesh")) { + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, model.m_mesh)); + tokeniser.nextLine(); + } else if (string_equal(parameter, "skin")) { + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, model.m_skin)); + tokeniser.nextLine(); + } else if (string_equal(parameter, "offset")) { + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "(")); + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, ")")); + tokeniser.nextLine(); + } else if (string_equal(parameter, "channel")) { + //const char* channelName = + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "(")); + for (;;) { + const char *end; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, end)); + if (string_equal(end, ")")) { + tokeniser.nextLine(); + break; + } + } + } else if (string_equal(parameter, "anim")) { + CopiedString animName; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, animName)); + const char *animFile; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, animFile)); + model.m_anims.insert(Model::Anims::value_type(animName, animFile)); + + const char *token; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); + + while (string_equal(token, ",")) { + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, animFile)); + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); + } + + if (string_equal(token, "{")) { + for (;;) { + const char *end; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, end)); + if (string_equal(end, "}")) { + tokeniser.nextLine(); + break; + } + tokeniser.nextLine(); + } + } else { + tokeniser.ungetToken(); + } + } else { + globalErrorStream() << "unknown model parameter: " << makeQuoted(parameter) << "\n"; + return false; + } + tokeniser.nextLine(); + } + return true; +} + +inline bool char_isSpaceOrTab(char c) +{ + return c == ' ' || c == '\t'; } -template -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 ); -} - - -static bool EntityClass_parse( EntityClass& entityClass, Tokeniser& tokeniser ){ - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, entityClass.m_name ) ); - - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "{" ) ); - tokeniser.nextLine(); - - StringOutputStream usage( 256 ); - StringOutputStream description( 256 ); - CopiedString* currentDescription = 0; - StringOutputStream* currentString = 0; - - for (;; ) - { - const char* key; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, key ) ); - - const char* last = string_findFirstSpaceOrTab( key ); - CopiedString first( StringRange( key, last ) ); - - if ( !string_empty( last ) ) { - last = string_findFirstNonSpaceOrTab( last ); - } - - if ( currentString != 0 && string_equal( key, "\\" ) ) { - tokeniser.nextLine(); - *currentString << " "; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, *currentString ) ); - 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" ) ) { - const char* token; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); - entityClass.fixedsize = true; - StringOutputStream buffer( 256 ); - buffer << PathCleaned( token ); - entityClass.m_modelpath = buffer.c_str(); - } - else if ( string_equal( key, "editor_color" ) ) { - const char* value; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - } - else if ( string_equal( key, "editor_mins" ) ) { - entityClass.sizeSpecified = true; - const char* value; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); - 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" ) ) { - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, usage ) ); - currentString = &usage; - } - else if ( string_equal_n( key, "editor_usage", 12 ) ) { - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, usage ) ); - currentString = &usage; - } - else if ( string_equal( key, "editor_rotatable" ) - || string_equal( key, "editor_showangle" ) - || string_equal( key, "editor_showangles" ) // typo? in prey movables.def - || 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 ) ) { - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - } - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); - } - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); - } - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); - } - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); - } - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); - } - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); - } - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); - } - 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; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); - } - else if ( string_equal( key, "inherit" ) ) { - entityClass.inheritanceResolved = false; - ASSERT_MESSAGE( entityClass.m_parent.empty(), "only one 'inherit' supported per entityDef" ); - const char* token; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); - entityClass.m_parent.push_back( token ); - } - // begin quake4-specific keys - else if ( string_equal( key, "editor_targetonsel" ) ) { - //const char* value = - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - } - else if ( string_equal( key, "editor_menu" ) ) { - //const char* value = - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - } - else if ( string_equal( key, "editor_ignore" ) ) { - //const char* value = - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - } - // end quake4-specific keys - // begin ignore prey (unknown/unused?) entity keys - else if ( string_equal( key, "editor_light" ) - || string_equal( key, "editor_def def_debrisspawner" ) - || string_equal( key, "editor_def def_drop" ) - || string_equal( key, "editor_def def_guihand" ) - || string_equal( key, "editor_def def_mine" ) ) { - //const char* value = - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); - } - // end ignore prey entity keys - else - { - CopiedString tmp( key ); - if ( string_equal_n( key, "editor_", 7 ) ) { - globalErrorStream() << "unsupported editor key " << makeQuoted( key ) ; - } - EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, key ).second; - attribute.m_type = "string"; - const char* value; - PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); - if ( string_equal( value, "}" ) ) { // hack for quake4 powerups.def bug - globalErrorStream() << "entityDef " << makeQuoted( entityClass.m_name.c_str() ) << " key " << makeQuoted( tmp.c_str() ) << " has no value\n"; - break; - } - else - { - attribute.m_value = value; - } - } - 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"; - } - } - - return true; -} - -bool EntityClassDoom3_parseEntityDef( Tokeniser& tokeniser ){ - EntityClass* entityClass = Eclass_Alloc(); - entityClass->free = &Eclass_Free; - - if ( !EntityClass_parse( *entityClass, tokeniser ) ) { - eclass_capture_state( entityClass ); // finish constructing the entity so that it can be destroyed cleanly. - entityClass->free( entityClass ); - return false; - } - - 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 ); - } - return true; -} - -bool EntityClassDoom3_parseBlock( Tokeniser& tokeniser, const char* blockType ){ - if ( string_equal( blockType, "entityDef" ) ) { - return EntityClassDoom3_parseEntityDef( tokeniser ); - } - else if ( string_equal( blockType, "model" ) ) { - return EntityClassDoom3_parseModel( tokeniser ); - } - else - { - return EntityClassDoom3_parseUnknown( tokeniser ); - } -} - -bool EntityClassDoom3_parse( TextInputStream& inputStream, const char* filename ){ - Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser( inputStream ); - - tokeniser.nextLine(); - - for (;; ) - { - const char* blockType = tokeniser.getToken(); - if ( blockType == 0 ) { - return true; - } - CopiedString tmp( blockType ); - if ( !EntityClassDoom3_parseBlock( tokeniser, tmp.c_str() ) ) { - globalErrorStream() << GlobalFileSystem().findFile( filename ) << filename << ":" << (unsigned int)tokeniser.getLine() << ": " << tmp.c_str() << " parse failed, skipping rest of file\n"; - return false; - } - } - - 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(), fullname.c_str() ); - 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", makeCallbackF(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 << "-------- NOTES --------\n"; - - if ( !string_empty( ( *i ).second->m_comments.c_str() ) ) { - usage << ( *i ).second->m_comments.c_str() << "\n"; - } - - usage << "\n-------- 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 ); +inline bool char_isNotSpaceOrTab(char c) +{ + return !char_isSpaceOrTab(c); } -}; -EntityClassDoom3 g_EntityClassDoom3; +template +inline const char *string_find_if(const char *string, Predicate predicate) +{ + for (; *string != 0; ++string) { + if (predicate(*string)) { + return string; + } + } + return string; +} -void EntityClassDoom3_attach( ModuleObserver& observer ){ - g_EntityClassDoom3.attach( observer ); +inline const char *string_findFirstSpaceOrTab(const char *string) +{ + return string_find_if(string, char_isSpaceOrTab); } -void EntityClassDoom3_detach( ModuleObserver& observer ){ - g_EntityClassDoom3.detach( observer ); + +inline const char *string_findFirstNonSpaceOrTab(const char *string) +{ + return string_find_if(string, char_isNotSpaceOrTab); } -void EntityClassDoom3_realise(){ - g_EntityClassDoom3.realise(); + +static bool EntityClass_parse(EntityClass &entityClass, Tokeniser &tokeniser) +{ + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, entityClass.m_name)); + + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "{")); + tokeniser.nextLine(); + + StringOutputStream usage(256); + StringOutputStream description(256); + CopiedString *currentDescription = 0; + StringOutputStream *currentString = 0; + + for (;;) { + const char *key; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, key)); + + const char *last = string_findFirstSpaceOrTab(key); + CopiedString first(StringRange(key, last)); + + if (!string_empty(last)) { + last = string_findFirstNonSpaceOrTab(last); + } + + if (currentString != 0 && string_equal(key, "\\")) { + tokeniser.nextLine(); + *currentString << " "; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, *currentString)); + 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")) { + const char *token; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); + entityClass.fixedsize = true; + StringOutputStream buffer(256); + buffer << PathCleaned(token); + entityClass.m_modelpath = buffer.c_str(); + } else if (string_equal(key, "editor_color")) { + const char *value; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, value)); + 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + } else if (string_equal(key, "editor_mins")) { + entityClass.sizeSpecified = true; + const char *value; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, value)); + 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, value)); + 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")) { + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, usage)); + currentString = &usage; + } else if (string_equal_n(key, "editor_usage", 12)) { + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, usage)); + currentString = &usage; + } else if (string_equal(key, "editor_rotatable") + || string_equal(key, "editor_showangle") + || string_equal(key, "editor_showangles") // typo? in prey movables.def + || 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)) { + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + } 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); + } 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); + } 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); + } 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); + } 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); + } 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); + } 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); + } 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; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); + } else if (string_equal(key, "inherit")) { + entityClass.inheritanceResolved = false; + ASSERT_MESSAGE(entityClass.m_parent.empty(), "only one 'inherit' supported per entityDef"); + const char *token; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); + entityClass.m_parent.push_back(token); + } + // begin quake4-specific keys + else if (string_equal(key, "editor_targetonsel")) { + //const char* value = + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + } else if (string_equal(key, "editor_menu")) { + //const char* value = + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + } else if (string_equal(key, "editor_ignore")) { + //const char* value = + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + } + // end quake4-specific keys + // begin ignore prey (unknown/unused?) entity keys + else if (string_equal(key, "editor_light") + || string_equal(key, "editor_def def_debrisspawner") + || string_equal(key, "editor_def def_drop") + || string_equal(key, "editor_def def_guihand") + || string_equal(key, "editor_def def_mine")) { + //const char* value = + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); + } + // end ignore prey entity keys + else { + CopiedString tmp(key); + if (string_equal_n(key, "editor_", 7)) { + globalErrorStream() << "unsupported editor key " << makeQuoted(key); + } + EntityClassAttribute &attribute = EntityClass_insertAttribute(entityClass, key).second; + attribute.m_type = "string"; + const char *value; + PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, value)); + if (string_equal(value, "}")) { // hack for quake4 powerups.def bug + globalErrorStream() << "entityDef " << makeQuoted(entityClass.m_name.c_str()) << " key " + << makeQuoted(tmp.c_str()) << " has no value\n"; + break; + } else { + attribute.m_value = value; + } + } + 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"; + } + } + + return true; +} + +bool EntityClassDoom3_parseEntityDef(Tokeniser &tokeniser) +{ + EntityClass *entityClass = Eclass_Alloc(); + entityClass->free = &Eclass_Free; + + if (!EntityClass_parse(*entityClass, tokeniser)) { + eclass_capture_state(entityClass); // finish constructing the entity so that it can be destroyed cleanly. + entityClass->free(entityClass); + return false; + } + + 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); + } + return true; +} + +bool EntityClassDoom3_parseBlock(Tokeniser &tokeniser, const char *blockType) +{ + if (string_equal(blockType, "entityDef")) { + return EntityClassDoom3_parseEntityDef(tokeniser); + } else if (string_equal(blockType, "model")) { + return EntityClassDoom3_parseModel(tokeniser); + } else { + return EntityClassDoom3_parseUnknown(tokeniser); + } } -void EntityClassDoom3_unrealise(){ - g_EntityClassDoom3.unrealise(); + +bool EntityClassDoom3_parse(TextInputStream &inputStream, const char *filename) +{ + Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser(inputStream); + + tokeniser.nextLine(); + + for (;;) { + const char *blockType = tokeniser.getToken(); + if (blockType == 0) { + return true; + } + CopiedString tmp(blockType); + if (!EntityClassDoom3_parseBlock(tokeniser, tmp.c_str())) { + globalErrorStream() << GlobalFileSystem().findFile(filename) << filename << ":" + << (unsigned int) tokeniser.getLine() << ": " << tmp.c_str() + << " parse failed, skipping rest of file\n"; + return false; + } + } + + tokeniser.release(); } -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 ), "" ); +void EntityClassDoom3_loadFile(const char *filename) +{ + globalOutputStream() << "parsing entity classes from " << makeQuoted(filename) << "\n"; - EntityClassDoom3_realise(); + StringOutputStream fullname(256); + fullname << "def/" << filename; + + ArchiveTextFile *file = GlobalFileSystem().openTextFile(fullname.c_str()); + if (file != 0) { + EntityClassDoom3_parse(file->getInputStream(), fullname.c_str()); + file->release(); + } } -void EntityClassDoom3_destroy(){ - EntityClassDoom3_unrealise(); +EntityClass *EntityClassDoom3_findOrInsert(const char *name, bool has_brushes) +{ + ASSERT_NOTNULL(name); + + if (string_empty(name)) { + return g_EntityClassDoom3_bad; + } - g_EntityClassDoom3_bad->free( 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; + } - GlobalFileSystem().detach( g_EntityClassDoom3 ); + EntityClass *e = EntityClass_Create_Default(name, has_brushes); + EntityClass *inserted = EntityClassDoom3_insertUnique(e); + ASSERT_MESSAGE(inserted == e, ""); + return inserted; } -class EntityClassDoom3Dependencies : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef +const ListAttributeType *EntityClassDoom3_findListType(const char *name) { -}; + return 0; +} + -class EntityClassDoom3API +void EntityClass_resolveInheritance(EntityClass *derivedClass) { -EntityClassManager m_eclassmanager; + 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: -typedef EntityClassManager Type; -STRING_CONSTANT( Name, "doom3" ); + EntityClassDoom3() : m_unrealised(2) + { + } + + void realise() + { + if (--m_unrealised == 0) { + globalOutputStream() << "searching vfs directory " << makeQuoted("def") << " for *.def\n"; + GlobalFileSystem().forEachFile("def/", "def", makeCallbackF(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 << "-------- NOTES --------\n"; + + if (!string_empty((*i).second->m_comments.c_str())) { + usage << (*i).second->m_comments.c_str() << "\n"; + } + + usage << "\n-------- 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); + } +}; -EntityClassDoom3API(){ - EntityClassDoom3_construct(); +EntityClassDoom3 g_EntityClassDoom3; - 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; +void EntityClassDoom3_attach(ModuleObserver &observer) +{ + g_EntityClassDoom3.attach(observer); } -~EntityClassDoom3API(){ - EntityClassDoom3_destroy(); + +void EntityClassDoom3_detach(ModuleObserver &observer) +{ + g_EntityClassDoom3.detach(observer); } -EntityClassManager* getTable(){ - return &m_eclassmanager; + +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" @@ -818,4 +824,4 @@ EntityClassManager* getTable(){ typedef SingletonModule EntityClassDoom3Module; typedef Static StaticEntityClassDoom3Module; -StaticRegisterModule staticRegisterEntityClassDoom3( StaticEntityClassDoom3Module::instance() ); +StaticRegisterModule staticRegisterEntityClassDoom3(StaticEntityClassDoom3Module::instance()); diff --git a/radiant/eclass_fgd.cpp b/radiant/eclass_fgd.cpp index b92afbfc..7ef05b55 100644 --- a/radiant/eclass_fgd.cpp +++ b/radiant/eclass_fgd.cpp @@ -39,679 +39,654 @@ #include "stringio.h" #include "stream/textfilestream.h" -namespace -{ -typedef std::map EntityClasses; -EntityClasses g_EntityClassFGD_classes; -typedef std::map BaseClasses; -BaseClasses g_EntityClassFGD_bases; -EntityClass *g_EntityClassFGD_bad = 0; -typedef std::map ListAttributeTypes; -ListAttributeTypes g_listTypesFGD; +namespace { + typedef std::map EntityClasses; + EntityClasses g_EntityClassFGD_classes; + typedef std::map BaseClasses; + BaseClasses g_EntityClassFGD_bases; + EntityClass *g_EntityClassFGD_bad = 0; + typedef std::map 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(); +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 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_insertUniqueBase(EntityClass *entityClass) +{ + std::pair 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 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; +EntityClass *EntityClassFGD_insertUnique(EntityClass *entityClass) +{ + EntityClassFGD_insertUniqueBase(entityClass); + std::pair 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 ); - } +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 ); +inline bool EntityClassFGD_parseToken(Tokeniser &tokeniser, const char *token) +{ + return string_equal(tokeniser.getToken(), token); } const char *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_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_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); + +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"; +void EntityClassFGD_loadFile(const char *filename) +{ + TextFileInputStream file(filename); + if (!file.failed()) { + globalOutputStream() << "parsing entity classes from " << makeQuoted(filename) << "\n"; - EntityClassFGD_parse( file, filename ); - } + EntityClassFGD_parse(file, filename); + } } -EntityClass* EntityClassFGD_findOrInsert( const char *name, bool has_brushes ){ - ASSERT_NOTNULL( name ); +EntityClass *EntityClassFGD_findOrInsert(const char *name, bool has_brushes) +{ + ASSERT_NOTNULL(name); - if ( string_empty( name ) ) { - return g_EntityClassFGD_bad; - } + 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; - } + 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 ); + 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; +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 ); - } - } - } - } +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; +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() : 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_attach(ModuleObserver &observer) +{ + g_EntityClassFGD.attach(observer); } -void EntityClassFGD_detach( ModuleObserver& observer ){ - g_EntityClassFGD.detach( observer ); + +void EntityClassFGD_detach(ModuleObserver &observer) +{ + g_EntityClassFGD.detach(observer); } -void EntityClassFGD_realise(){ - g_EntityClassFGD.realise(); +void EntityClassFGD_realise() +{ + g_EntityClassFGD.realise(); } -void EntityClassFGD_unrealise(){ - g_EntityClassFGD.unrealise(); + +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 ), "" ); +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(); + EntityClassFGD_realise(); } -void EntityClassFGD_destroy(){ - EntityClassFGD_unrealise(); +void EntityClassFGD_destroy() +{ + EntityClassFGD_unrealise(); - g_EntityClassFGD_bad->free( g_EntityClassFGD_bad ); + g_EntityClassFGD_bad->free(g_EntityClassFGD_bad); } -class EntityClassFGDDependencies : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef, public GlobalRadiantModuleRef -{ +class EntityClassFGDDependencies + : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef, public GlobalRadiantModuleRef { }; -class EntityClassFGDAPI -{ -EntityClassManager m_eclassmanager; +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; - - Radiant_attachGameToolsPathObserver( g_EntityClassFGD ); - Radiant_attachGameNameObserver( g_EntityClassFGD ); -} -~EntityClassFGDAPI(){ - Radiant_detachGameNameObserver( g_EntityClassFGD ); - Radiant_detachGameToolsPathObserver( g_EntityClassFGD ); - - EntityClassFGD_destroy(); -} -EntityClassManager* getTable(){ - return &m_eclassmanager; -} + 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; + + Radiant_attachGameToolsPathObserver(g_EntityClassFGD); + Radiant_attachGameNameObserver(g_EntityClassFGD); + } + + ~EntityClassFGDAPI() + { + Radiant_detachGameNameObserver(g_EntityClassFGD); + Radiant_detachGameToolsPathObserver(g_EntityClassFGD); + + EntityClassFGD_destroy(); + } + + EntityClassManager *getTable() + { + return &m_eclassmanager; + } }; #include "modulesystem/singletonmodule.h" @@ -719,4 +694,4 @@ EntityClassManager* getTable(){ typedef SingletonModule EntityClassFGDModule; typedef Static StaticEntityClassFGDModule; -StaticRegisterModule staticRegisterEntityClassFGD( StaticEntityClassFGDModule::instance() ); +StaticRegisterModule staticRegisterEntityClassFGD(StaticEntityClassFGDModule::instance()); diff --git a/radiant/eclass_xml.cpp b/radiant/eclass_xml.cpp index 687d4adf..5d9d317c 100644 --- a/radiant/eclass_xml.cpp +++ b/radiant/eclass_xml.cpp @@ -122,423 +122,477 @@ #include "modulesystem/moduleregistry.h" #include "stringio.h" -#define PARSE_ERROR( elementName, name ) makeQuoted( elementName ) << " is not a valid child of " << makeQuoted( name ) +#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 -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 -class Storage -{ -char m_storage[sizeof( Type )]; -public: -Type& get(){ - return *reinterpret_cast( m_storage ); -} -const Type& get() const { - return *reinterpret_cast( m_storage ); -} -}; - -class BreakImporter : public TreeXMLImporter -{ +class IgnoreBreaks { 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; -} -}; + const char *m_first; + const char *m_last; -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 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 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; -} + IgnoreBreaks(const char *first, const char *last) : m_first(first), m_last(last) + { + } }; -bool isItem( const char* name ){ - return string_equal( name, "item" ); -} - -class ListAttributeImporter : public TreeXMLImporter +template +TextOutputStreamType &ostream_write(TextOutputStreamType &ostream, const IgnoreBreaks &ignoreBreaks) { -ListAttributeType* m_listType; -Storage 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; -} -}; + 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 + class Storage { + char m_storage[sizeof(Type)]; + public: + Type &get() + { + return *reinterpret_cast( m_storage ); + } + + const Type &get() const + { + return *reinterpret_cast( 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 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 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 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 m_class; + Storage 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 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 > 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); + } + } -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 m_class; -Storage m_list; -ListAttributeTypes m_listTypes; +#include "modulesystem/singletonmodule.h" -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 EntityClassXMLDependencies : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef { }; -class EclassXMLImporter : public TreeXMLImporter -{ -EntityClassCollector& m_collector; -Storage m_classes; - +class EclassXMLAPI { + EntityClassScanner m_eclassxml; 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 > 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 ); -} -}; + typedef EntityClassScanner Type; + STRING_CONSTANT(Name, "xml"); + EclassXMLAPI() + { + m_eclassxml.scanFile = &ScanFile; + m_eclassxml.getExtension = &GetExtension; + } -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; -} + EntityClassScanner *getTable() + { + return &m_eclassxml; + } }; typedef SingletonModule EclassXMLModule; typedef Static StaticEclassXMLModule; -StaticRegisterModule staticRegisterEclassXML( StaticEclassXMLModule::instance() ); +StaticRegisterModule staticRegisterEclassXML(StaticEclassXMLModule::instance()); diff --git a/radiant/entity.cpp b/radiant/entity.cpp index 2952684d..797927d0 100644 --- a/radiant/entity.cpp +++ b/radiant/entity.cpp @@ -47,554 +47,582 @@ #include "uilib/uilib.h" -struct entity_globals_t -{ - Vector3 color_entity; +struct entity_globals_t { + Vector3 color_entity; - entity_globals_t() : - color_entity( 0.0f, 0.0f, 0.0f ){ - } + 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; +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 ); - } -} + 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; +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 ); - } -} + 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_EntitySetKeyValue_Selected(const char *key, const char *value) +{ + GlobalSceneGraph().traverse(EntitySetKeyValueSelected(key, value)); } -void Scene_EntitySetClassname_Selected( const char* classname ){ - GlobalSceneGraph().traverse( EntitySetClassnameSelected( classname ) ); +void Scene_EntitySetClassname_Selected(const char *classname) +{ + GlobalSceneGraph().traverse(EntitySetClassnameSelected(classname)); } -void Entity_ungroupSelected(){ - if ( GlobalSelectionSystem().countSelected() < 1 ) { - return; - } +void Entity_ungroupSelected() +{ + if (GlobalSelectionSystem().countSelected() < 1) { + return; + } - UndoableCommand undo( "ungroupSelectedEntities" ); + UndoableCommand undo("ungroupSelectedEntities"); - scene::Path world_path( makeReference( GlobalSceneGraph().root() ) ); - world_path.push( makeReference( Map_FindOrInsertWorldspawn( g_map ) ) ); + scene::Path world_path(makeReference(GlobalSceneGraph().root())); + world_path.push(makeReference(Map_FindOrInsertWorldspawn(g_map))); - scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); - scene::Path path = instance.path(); + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); + scene::Path path = instance.path(); - if ( !Node_isEntity( path.top() ) ) { - path.pop(); - } + if (!Node_isEntity(path.top())) { + path.pop(); + } - if ( Node_getEntity( path.top() ) != 0 - && node_is_group( path.top() ) ) { - if ( world_path.top().get_pointer() != path.top().get_pointer() ) { - parentBrushes( path.top(), world_path.top() ); - Path_deleteTop( path ); - } - } + if (Node_getEntity(path.top()) != 0 + && node_is_group(path.top())) { + if (world_path.top().get_pointer() != path.top().get_pointer()) { + parentBrushes(path.top(), world_path.top()); + Path_deleteTop(path); + } + } } -class EntityFindSelected : public scene::Graph::Walker -{ +class EntityFindSelected : public scene::Graph::Walker { public: -mutable const scene::Path *groupPath; -mutable scene::Instance *groupInstance; -EntityFindSelected() : groupPath( 0 ), groupInstance( 0 ){ -} -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_getSelectable( instance )->isSelected() - && node_is_group( path.top() ) - && !groupPath ) { - groupPath = &path; - groupInstance = &instance; - } -} + mutable const scene::Path *groupPath; + mutable scene::Instance *groupInstance; + + EntityFindSelected() : groupPath(0), groupInstance(0) + { + } + + 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_getSelectable(instance)->isSelected() + && node_is_group(path.top()) + && !groupPath) { + groupPath = &path; + groupInstance = &instance; + } + } }; -class EntityGroupSelected : public scene::Graph::Walker -{ -NodeSmartReference group, worldspawn; +class EntityGroupSelected : public scene::Graph::Walker { + NodeSmartReference group, worldspawn; //typedef std::pair DeletionPair; //Stack deleteme; public: -EntityGroupSelected( const scene::Path &p ) : group( p.top().get() ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - return true; -} -void post( const scene::Path& path, scene::Instance& instance ) const { - Selectable *selectable = Instance_getSelectable( instance ); - if ( selectable && selectable->isSelected() ) { - Entity* entity = Node_getEntity( path.top() ); - if ( entity == 0 && Node_isPrimitive( path.top() ) ) { - NodeSmartReference child( path.top().get() ); - NodeSmartReference parent( path.parent().get() ); - - if ( path.size() >= 3 && parent != worldspawn ) { - NodeSmartReference parentparent( path[path.size() - 3].get() ); - - Node_getTraversable( parent )->erase( child ); - Node_getTraversable( group )->insert( child ); - - if ( Node_getTraversable( parent )->empty() ) { - //deleteme.push(DeletionPair(parentparent, parent)); - Node_getTraversable( parentparent )->erase( parent ); - } - } - else - { - Node_getTraversable( parent )->erase( child ); - Node_getTraversable( group )->insert( child ); - } - } - } -} + EntityGroupSelected(const scene::Path &p) : group(p.top().get()), worldspawn(Map_FindOrInsertWorldspawn(g_map)) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + return true; + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable && selectable->isSelected()) { + Entity *entity = Node_getEntity(path.top()); + if (entity == 0 && Node_isPrimitive(path.top())) { + NodeSmartReference child(path.top().get()); + NodeSmartReference parent(path.parent().get()); + + if (path.size() >= 3 && parent != worldspawn) { + NodeSmartReference parentparent(path[path.size() - 3].get()); + + Node_getTraversable(parent)->erase(child); + Node_getTraversable(group)->insert(child); + + if (Node_getTraversable(parent)->empty()) { + //deleteme.push(DeletionPair(parentparent, parent)); + Node_getTraversable(parentparent)->erase(parent); + } + } else { + Node_getTraversable(parent)->erase(child); + Node_getTraversable(group)->insert(child); + } + } + } + } }; -void Entity_groupSelected(){ - if ( GlobalSelectionSystem().countSelected() < 1 ) { - return; - } - - UndoableCommand undo( "groupSelectedEntities" ); - - scene::Path world_path( makeReference( GlobalSceneGraph().root() ) ); - world_path.push( makeReference( Map_FindOrInsertWorldspawn( g_map ) ) ); - - EntityFindSelected fse; - GlobalSceneGraph().traverse( fse ); - if ( fse.groupPath ) { - GlobalSceneGraph().traverse( EntityGroupSelected( *fse.groupPath ) ); - } - else - { - GlobalSceneGraph().traverse( EntityGroupSelected( world_path ) ); - } +void Entity_groupSelected() +{ + if (GlobalSelectionSystem().countSelected() < 1) { + return; + } + + UndoableCommand undo("groupSelectedEntities"); + + scene::Path world_path(makeReference(GlobalSceneGraph().root())); + world_path.push(makeReference(Map_FindOrInsertWorldspawn(g_map))); + + EntityFindSelected fse; + GlobalSceneGraph().traverse(fse); + if (fse.groupPath) { + GlobalSceneGraph().traverse(EntityGroupSelected(*fse.groupPath)); + } else { + GlobalSceneGraph().traverse(EntityGroupSelected(world_path)); + } } - -void Entity_connectSelected(){ - if ( GlobalSelectionSystem().countSelected() == 2 ) { - GlobalEntityCreator().connectEntities( - GlobalSelectionSystem().penultimateSelected().path(), - GlobalSelectionSystem().ultimateSelected().path(), - 0 - ); - } - else - { - globalErrorStream() << "entityConnectSelected: exactly two instances must be selected\n"; - } +void Entity_connectSelected() +{ + if (GlobalSelectionSystem().countSelected() == 2) { + GlobalEntityCreator().connectEntities( + GlobalSelectionSystem().penultimateSelected().path(), + GlobalSelectionSystem().ultimateSelected().path(), + 0 + ); + } else { + globalErrorStream() << "entityConnectSelected: exactly two instances must be selected\n"; + } } -void Entity_killconnectSelected(){ - if ( GlobalSelectionSystem().countSelected() == 2 ) { - GlobalEntityCreator().connectEntities( - GlobalSelectionSystem().penultimateSelected().path(), - GlobalSelectionSystem().ultimateSelected().path(), - 1 - ); - } - else - { - globalErrorStream() << "entityKillConnectSelected: exactly two instances must be selected\n"; - } +void Entity_killconnectSelected() +{ + if (GlobalSelectionSystem().countSelected() == 2) { + GlobalEntityCreator().connectEntities( + GlobalSelectionSystem().penultimateSelected().path(), + GlobalSelectionSystem().ultimateSelected().path(), + 1 + ); + } else { + globalErrorStream() << "entityKillConnectSelected: exactly two instances must be selected\n"; + } } -AABB Doom3Light_getBounds( const AABB& workzone ){ - AABB aabb( workzone ); - - Vector3 defaultRadius( 300, 300, 300 ); - if ( !string_parse_vector3( EntityClass_valueForKey( *GlobalEntityClassManager().findOrInsert( "light", false ), "light_radius" ), defaultRadius ) ) { - globalErrorStream() << "Doom3Light_getBounds: failed to parse default light radius\n"; - } - - if ( aabb.extents[0] == 0 ) { - aabb.extents[0] = defaultRadius[0]; - } - if ( aabb.extents[1] == 0 ) { - aabb.extents[1] = defaultRadius[1]; - } - if ( aabb.extents[2] == 0 ) { - aabb.extents[2] = defaultRadius[2]; - } - - if ( aabb_valid( aabb ) ) { - return aabb; - } - return AABB( Vector3( 0, 0, 0 ), Vector3( 64, 64, 64 ) ); +AABB Doom3Light_getBounds(const AABB &workzone) +{ + AABB aabb(workzone); + + Vector3 defaultRadius(300, 300, 300); + if (!string_parse_vector3( + EntityClass_valueForKey(*GlobalEntityClassManager().findOrInsert("light", false), "light_radius"), + defaultRadius)) { + globalErrorStream() << "Doom3Light_getBounds: failed to parse default light radius\n"; + } + + if (aabb.extents[0] == 0) { + aabb.extents[0] = defaultRadius[0]; + } + if (aabb.extents[1] == 0) { + aabb.extents[1] = defaultRadius[1]; + } + if (aabb.extents[2] == 0) { + aabb.extents[2] = defaultRadius[2]; + } + + if (aabb_valid(aabb)) { + return aabb; + } + return AABB(Vector3(0, 0, 0), Vector3(64, 64, 64)); } int g_iLastLightIntensity; -void Entity_createFromSelection( const char* name, const Vector3& origin ){ +void Entity_createFromSelection(const char *name, const Vector3 &origin) +{ #if 0 - if ( string_equal_nocase( name, "worldspawn" ) ) { - ui::alert( MainFrame_getWindow( ), "Can't create an entity with worldspawn.", "info" ); - return; - } + if ( string_equal_nocase( name, "worldspawn" ) ) { + ui::alert( MainFrame_getWindow( ), "Can't create an entity with worldspawn.", "info" ); + return; + } #endif - EntityClass* entityClass = GlobalEntityClassManager().findOrInsert( name, true ); - - bool isModel = ( string_compare_nocase_n( name, "misc_", 5 ) == 0 && string_equal_nocase( name + string_length( name ) - 5, "model" ) ) // misc_*model (also misc_model) - || string_equal_nocase( name, "model_static" ) - || ( GlobalSelectionSystem().countSelected() == 0 && string_equal_nocase( name, "func_static" ) ); - - bool brushesSelected = Scene_countSelectedBrushes( GlobalSceneGraph() ) != 0; - - if ( !( entityClass->fixedsize || isModel ) && !brushesSelected ) { - globalErrorStream() << "failed to create a group entity - no brushes are selected\n"; - return; - } - - AABB workzone( aabb_for_minmax( Select_getWorkZone().d_work_min, Select_getWorkZone().d_work_max ) ); - - - 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 || ( isModel && !brushesSelected ) ) { - 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 - { - if ( g_pGameDescription->mGameType == "doom3" ) { - Node_getEntity( node )->setKeyValue( "model", Node_getEntity( node )->getKeyValue( "name" ) ); - } - - 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 ( string_equal_nocase( name, "light" ) ) { - if ( g_pGameDescription->mGameType != "doom3" ) { - int intensity = g_iLastLightIntensity; - - if ( DoLightIntensityDlg( &intensity ) == eIDOK ) { - g_iLastLightIntensity = intensity; - char buf[10]; - sprintf( buf, "%d", intensity ); - Node_getEntity( node )->setKeyValue( "light", buf ); - } - } - else if ( brushesSelected ) { // use workzone to set light position/size for doom3 lights, if there are brushes selected - AABB bounds( Doom3Light_getBounds( workzone ) ); - StringOutputStream key( 64 ); - key << bounds.origin[0] << " " << bounds.origin[1] << " " << bounds.origin[2]; - Node_getEntity( node )->setKeyValue( "origin", key.c_str() ); - key.clear(); - key << bounds.extents[0] << " " << bounds.extents[1] << " " << bounds.extents[2]; - Node_getEntity( node )->setKeyValue( "light_radius", key.c_str() ); - } - } - - if ( isModel ) { - const char* model = misc_model_dialog(MainFrame_getWindow()); - if ( model != 0 ) { - Node_getEntity( node )->setKeyValue( "model", model ); - } - } + EntityClass *entityClass = GlobalEntityClassManager().findOrInsert(name, true); + + bool isModel = (string_compare_nocase_n(name, "misc_", 5) == 0 && + string_equal_nocase(name + string_length(name) - 5, "model")) // misc_*model (also misc_model) + || string_equal_nocase(name, "model_static") + || (GlobalSelectionSystem().countSelected() == 0 && string_equal_nocase(name, "func_static")); + + bool brushesSelected = Scene_countSelectedBrushes(GlobalSceneGraph()) != 0; + + if (!(entityClass->fixedsize || isModel) && !brushesSelected) { + globalErrorStream() << "failed to create a group entity - no brushes are selected\n"; + return; + } + + AABB workzone(aabb_for_minmax(Select_getWorkZone().d_work_min, Select_getWorkZone().d_work_max)); + + + 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 || (isModel && !brushesSelected)) { + 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 { + if (g_pGameDescription->mGameType == "doom3") { + Node_getEntity(node)->setKeyValue("model", Node_getEntity(node)->getKeyValue("name")); + } + + 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 (string_equal_nocase(name, "light")) { + if (g_pGameDescription->mGameType != "doom3") { + int intensity = g_iLastLightIntensity; + + if (DoLightIntensityDlg(&intensity) == eIDOK) { + g_iLastLightIntensity = intensity; + char buf[10]; + sprintf(buf, "%d", intensity); + Node_getEntity(node)->setKeyValue("light", buf); + } + } else if (brushesSelected) { // use workzone to set light position/size for doom3 lights, if there are brushes selected + AABB bounds(Doom3Light_getBounds(workzone)); + StringOutputStream key(64); + key << bounds.origin[0] << " " << bounds.origin[1] << " " << bounds.origin[2]; + Node_getEntity(node)->setKeyValue("origin", key.c_str()); + key.clear(); + key << bounds.extents[0] << " " << bounds.extents[1] << " " << bounds.extents[2]; + Node_getEntity(node)->setKeyValue("light_radius", key.c_str()); + } + } + + if (isModel) { + const char *model = misc_model_dialog(MainFrame_getWindow()); + if (model != 0) { + Node_getEntity(node)->setKeyValue("model", model); + } + } } #if 0 bool DoNormalisedColor( Vector3& color ){ - if ( !color_dialog( 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; + if ( !color_dialog( 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; } #endif -void NormalizeColor( Vector3& color ){ - // 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; - } +void NormalizeColor(Vector3 &color) +{ + // 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; + } } -void Entity_normalizeColor(){ - 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; - NormalizeColor( 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 ); - } - } - } - } +void Entity_normalizeColor() +{ + 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; + NormalizeColor(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); + } + } + } + } } -void Entity_setColour(){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - bool normalize = false; - 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" ) { - normalize = false; - } - - if ( color_dialog( MainFrame_getWindow(), g_entity_globals.color_entity ) ) { - if ( normalize ) { - NormalizeColor( 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 ); - } - } - } +void Entity_setColour() +{ + if (GlobalSelectionSystem().countSelected() != 0) { + bool normalize = false; + 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") { + normalize = false; + } + + if (color_dialog(MainFrame_getWindow(), g_entity_globals.color_entity)) { + if (normalize) { + NormalizeColor(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( ui::Widget 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 = parent.file_dialog( 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; +const char *misc_model_dialog(ui::Widget 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 = parent.file_dialog(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; } struct LightRadii { - static void Export(const EntityCreator &self, const Callback &returnz) { - returnz(self.getLightRadii()); - } - - static void Import(EntityCreator &self, bool value) { - self.setLightRadii(value); - } + static void Export(const EntityCreator &self, const Callback &returnz) + { + returnz(self.getLightRadii()); + } + + static void Import(EntityCreator &self, bool value) + { + self.setLightRadii(value); + } }; -void Entity_constructPreferences( PreferencesPage& page ){ - page.appendCheckBox( - "Show", "Light Radii", - make_property(GlobalEntityCreator()) - ); -} -void Entity_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Entities", "Entity Display Preferences" ) ); - Entity_constructPreferences( page ); +void Entity_constructPreferences(PreferencesPage &page) +{ + page.appendCheckBox( + "Show", "Light Radii", + make_property(GlobalEntityCreator()) + ); } -void Entity_registerPreferencesPage(){ - PreferencesDialog_addDisplayPage( makeCallbackF(Entity_constructPage) ); + +void Entity_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Entities", "Entity Display Preferences")); + Entity_constructPreferences(page); } +void Entity_registerPreferencesPage() +{ + PreferencesDialog_addDisplayPage(makeCallbackF(Entity_constructPage)); +} -void Entity_constructMenu( ui::Menu menu ){ - create_menu_item_with_mnemonic( menu, "_Regroup", "GroupSelection" ); - create_menu_item_with_mnemonic( menu, "_Ungroup", "UngroupSelection" ); - create_menu_item_with_mnemonic( menu, "_Connect", "ConnectSelection" ); - create_menu_item_with_mnemonic( menu, "_KillConnect", "KillConnectSelection" ); - create_menu_item_with_mnemonic( menu, "_Select Color...", "EntityColor" ); - create_menu_item_with_mnemonic( menu, "_Normalize Color...", "NormalizeColor" ); +void Entity_constructMenu(ui::Menu menu) +{ + create_menu_item_with_mnemonic(menu, "_Regroup", "GroupSelection"); + create_menu_item_with_mnemonic(menu, "_Ungroup", "UngroupSelection"); + create_menu_item_with_mnemonic(menu, "_Connect", "ConnectSelection"); + create_menu_item_with_mnemonic(menu, "_KillConnect", "KillConnectSelection"); + create_menu_item_with_mnemonic(menu, "_Select Color...", "EntityColor"); + create_menu_item_with_mnemonic(menu, "_Normalize Color...", "NormalizeColor"); } - #include "preferencesystem.h" #include "stringio.h" -void Entity_Construct(){ - GlobalCommands_insert( "EntityColor", makeCallbackF(Entity_setColour), Accelerator( 'K' ) ); - GlobalCommands_insert( "NormalizeColor", makeCallbackF(Entity_normalizeColor) ); - GlobalCommands_insert( "ConnectSelection", makeCallbackF(Entity_connectSelected), Accelerator( 'K', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "KillConnectSelection", makeCallbackF(Entity_killconnectSelected), Accelerator( 'K', (GdkModifierType)( GDK_SHIFT_MASK ) ) ); - GlobalCommands_insert( "GroupSelection", makeCallbackF(Entity_groupSelected) ); - GlobalCommands_insert( "UngroupSelection", makeCallbackF(Entity_ungroupSelected) ); - - GlobalPreferenceSystem().registerPreference( "SI_Colors5", make_property_string( g_entity_globals.color_entity ) ); - GlobalPreferenceSystem().registerPreference( "LastLightIntensity", make_property_string( g_iLastLightIntensity ) ); - - Entity_registerPreferencesPage(); +void Entity_Construct() +{ + GlobalCommands_insert("EntityColor", makeCallbackF(Entity_setColour), Accelerator('K')); + GlobalCommands_insert("NormalizeColor", makeCallbackF(Entity_normalizeColor)); + GlobalCommands_insert("ConnectSelection", makeCallbackF(Entity_connectSelected), + Accelerator('K', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("KillConnectSelection", makeCallbackF(Entity_killconnectSelected), + Accelerator('K', (GdkModifierType) (GDK_SHIFT_MASK))); + GlobalCommands_insert("GroupSelection", makeCallbackF(Entity_groupSelected)); + GlobalCommands_insert("UngroupSelection", makeCallbackF(Entity_ungroupSelected)); + + GlobalPreferenceSystem().registerPreference("SI_Colors5", make_property_string(g_entity_globals.color_entity)); + GlobalPreferenceSystem().registerPreference("LastLightIntensity", make_property_string(g_iLastLightIntensity)); + + Entity_registerPreferencesPage(); } -void Entity_Destroy(){ +void Entity_Destroy() +{ } diff --git a/radiant/entity.h b/radiant/entity.h index fca38f92..a2a9f752 100644 --- a/radiant/entity.h +++ b/radiant/entity.h @@ -24,19 +24,24 @@ #include -template class BasicVector3; +template +class BasicVector3; + typedef BasicVector3 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 ); +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); -const char* misc_model_dialog( ui::Widget parent ); -void Entity_constructMenu( ui::Menu menu ); +const char *misc_model_dialog(ui::Widget parent); + +void Entity_constructMenu(ui::Menu menu); void Entity_Construct(); + void Entity_Destroy(); #endif diff --git a/radiant/entityinspector.cpp b/radiant/entityinspector.cpp index e74dd3f0..c5aeaa8b 100644 --- a/radiant/entityinspector.cpp +++ b/radiant/entityinspector.cpp @@ -64,1506 +64,1625 @@ #include "textureentry.h" #include "groupdialog.h" -ui::Entry numeric_entry_new(){ - auto entry = ui::Entry(ui::New); - entry.show(); - entry.dimensions(64, -1); - return entry; -} - -namespace +ui::Entry numeric_entry_new() { -typedef std::map KeyValues; -KeyValues g_selectedKeyValues; -KeyValues g_selectedDefaultKeyValues; + auto entry = ui::Entry(ui::New); + entry.show(); + entry.dimensions(64, -1); + return entry; } -const char* SelectedEntity_getValueForKey( const char* key ){ - { - KeyValues::const_iterator i = g_selectedKeyValues.find( key ); - if ( i != g_selectedKeyValues.end() ) { - return ( *i ).second.c_str(); - } - } - { - KeyValues::const_iterator i = g_selectedDefaultKeyValues.find( key ); - if ( i != g_selectedDefaultKeyValues.end() ) { - return ( *i ).second.c_str(); - } - } - return ""; +namespace { + typedef std::map KeyValues; + KeyValues g_selectedKeyValues; + KeyValues g_selectedDefaultKeyValues; } -void Scene_EntitySetKeyValue_Selected_Undoable( const char* key, const char* value ){ - StringOutputStream command( 256 ); - command << "entitySetKeyValue -key " << makeQuoted( key ) << " -value " << makeQuoted( value ); - UndoableCommand undo( command.c_str() ); - Scene_EntitySetKeyValue_Selected( key, value ); -} - -class EntityAttribute +const char *SelectedEntity_getValueForKey(const char *key) { -public: -virtual ~EntityAttribute() = default; -virtual ui::Widget getWidget() const = 0; -virtual void update() = 0; -virtual void release() = 0; -}; - -class BooleanAttribute : public EntityAttribute + { + KeyValues::const_iterator i = g_selectedKeyValues.find(key); + if (i != g_selectedKeyValues.end()) { + return (*i).second.c_str(); + } + } + { + KeyValues::const_iterator i = g_selectedDefaultKeyValues.find(key); + if (i != g_selectedDefaultKeyValues.end()) { + return (*i).second.c_str(); + } + } + return ""; +} + +void Scene_EntitySetKeyValue_Selected_Undoable(const char *key, const char *value) { -CopiedString m_key; -ui::CheckButton m_check; - -static gboolean toggled( ui::Widget widget, BooleanAttribute* self ){ - self->apply(); - return FALSE; + StringOutputStream command(256); + command << "entitySetKeyValue -key " << makeQuoted(key) << " -value " << makeQuoted(value); + UndoableCommand undo(command.c_str()); + Scene_EntitySetKeyValue_Selected(key, value); } + +class EntityAttribute { public: -BooleanAttribute( const char* key ) : - m_key( key ), - m_check( ui::null ){ - auto check = ui::CheckButton(ui::New); - check.show(); + virtual ~EntityAttribute() = default; - m_check = check; + virtual ui::Widget getWidget() const = 0; - guint handler = check.connect( "toggled", G_CALLBACK( toggled ), this ); - g_object_set_data( G_OBJECT( check ), "handler", gint_to_pointer( handler ) ); + virtual void update() = 0; - update(); -} -ui::Widget getWidget() const { - return m_check; -} -void release(){ - delete this; -} -void apply(){ - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), m_check.active() ? "1" : "0" ); -} -typedef MemberCaller ApplyCaller; - -void update(){ - const char* value = SelectedEntity_getValueForKey( m_key.c_str() ); - if ( !string_empty( value ) ) { - toggle_button_set_active_no_signal( m_check, atoi( value ) != 0 ); - } - else - { - toggle_button_set_active_no_signal( m_check, false ); - } -} -typedef MemberCaller UpdateCaller; + virtual void release() = 0; }; +class BooleanAttribute : public EntityAttribute { + CopiedString m_key; + ui::CheckButton m_check; + + static gboolean toggled(ui::Widget widget, BooleanAttribute *self) + { + self->apply(); + return FALSE; + } -class StringAttribute : public EntityAttribute -{ -CopiedString m_key; -ui::Entry m_entry; -NonModalEntry m_nonModal; public: -StringAttribute( const char* key ) : - m_key( key ), - m_entry( ui::null ), - m_nonModal( ApplyCaller( *this ), UpdateCaller( *this ) ){ - auto entry = ui::Entry(ui::New); - entry.show(); - entry.dimensions(50, -1); - - m_entry = entry; - m_nonModal.connect( m_entry ); -} -ui::Widget getWidget() const { - return m_entry; -} -ui::Entry getEntry() const { - return m_entry; -} + BooleanAttribute(const char *key) : + m_key(key), + m_check(ui::null) + { + auto check = ui::CheckButton(ui::New); + check.show(); + + m_check = check; + + guint handler = check.connect("toggled", G_CALLBACK(toggled), this); + g_object_set_data(G_OBJECT(check), "handler", gint_to_pointer(handler)); + + update(); + } + + ui::Widget getWidget() const + { + return m_check; + } + + void release() + { + delete this; + } + + void apply() + { + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), m_check.active() ? "1" : "0"); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + toggle_button_set_active_no_signal(m_check, atoi(value) != 0); + } else { + toggle_button_set_active_no_signal(m_check, false); + } + } + + typedef MemberCaller UpdateCaller; +}; -void release(){ - delete this; -} -void apply(){ - StringOutputStream value( 64 ); - value << m_entry.text(); - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), value.c_str() ); -} -typedef MemberCaller ApplyCaller; -void update(){ - StringOutputStream value( 64 ); - value << SelectedEntity_getValueForKey( m_key.c_str() ); - m_entry.text(value.c_str()); -} -typedef MemberCaller UpdateCaller; +class StringAttribute : public EntityAttribute { + CopiedString m_key; + ui::Entry m_entry; + NonModalEntry m_nonModal; +public: + StringAttribute(const char *key) : + m_key(key), + m_entry(ui::null), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + auto entry = ui::Entry(ui::New); + entry.show(); + entry.dimensions(50, -1); + + m_entry = entry; + m_nonModal.connect(m_entry); + } + + ui::Widget getWidget() const + { + return m_entry; + } + + ui::Entry getEntry() const + { + return m_entry; + } + + void release() + { + delete this; + } + + void apply() + { + StringOutputStream value(64); + value << m_entry.text(); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), value.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream value(64); + value << SelectedEntity_getValueForKey(m_key.c_str()); + m_entry.text(value.c_str()); + } + + typedef MemberCaller UpdateCaller; }; -class ShaderAttribute : public StringAttribute -{ +class ShaderAttribute : public StringAttribute { public: -ShaderAttribute( const char* key ) : StringAttribute( key ){ - GlobalShaderEntryCompletion::instance().connect( StringAttribute::getEntry() ); -} + ShaderAttribute(const char *key) : StringAttribute(key) + { + GlobalShaderEntryCompletion::instance().connect(StringAttribute::getEntry()); + } }; -class ModelAttribute : public EntityAttribute -{ -CopiedString m_key; -BrowsedPathEntry m_entry; -NonModalEntry m_nonModal; +class ModelAttribute : public EntityAttribute { + CopiedString m_key; + BrowsedPathEntry m_entry; + NonModalEntry m_nonModal; public: -ModelAttribute( const char* key ) : - m_key( key ), - m_entry( BrowseCaller( *this ) ), - m_nonModal( ApplyCaller( *this ), UpdateCaller( *this ) ){ - m_nonModal.connect( m_entry.m_entry.m_entry ); -} -void release(){ - delete this; -} -ui::Widget getWidget() const { - return m_entry.m_entry.m_frame; -} -void apply(){ - StringOutputStream value( 64 ); - value << m_entry.m_entry.m_entry.text(); - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), value.c_str() ); -} -typedef MemberCaller ApplyCaller; -void update(){ - StringOutputStream value( 64 ); - value << SelectedEntity_getValueForKey( m_key.c_str() ); - m_entry.m_entry.m_entry.text(value.c_str()); -} -typedef MemberCaller UpdateCaller; -void browse( const BrowsedPathEntry::SetPathCallback& setPath ){ - const char *filename = misc_model_dialog( m_entry.m_entry.m_frame.window() ); - - if ( filename != 0 ) { - setPath( filename ); - apply(); - } -} -typedef MemberCaller BrowseCaller; + ModelAttribute(const char *key) : + m_key(key), + m_entry(BrowseCaller(*this)), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + m_nonModal.connect(m_entry.m_entry.m_entry); + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return m_entry.m_entry.m_frame; + } + + void apply() + { + StringOutputStream value(64); + value << m_entry.m_entry.m_entry.text(); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), value.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream value(64); + value << SelectedEntity_getValueForKey(m_key.c_str()); + m_entry.m_entry.m_entry.text(value.c_str()); + } + + typedef MemberCaller UpdateCaller; + + void browse(const BrowsedPathEntry::SetPathCallback &setPath) + { + const char *filename = misc_model_dialog(m_entry.m_entry.m_frame.window()); + + if (filename != 0) { + setPath(filename); + apply(); + } + } + + typedef MemberCaller BrowseCaller; }; -const char* browse_sound( ui::Widget parent ){ - StringOutputStream buffer( 1024 ); - - buffer << g_qeglobals.m_userGamePath.c_str() << "sound/"; - - if ( !file_readable( buffer.c_str() ) ) { - // just go to fsmain - buffer.clear(); - buffer << g_qeglobals.m_userGamePath.c_str() << "/"; - } - - const char* filename = parent.file_dialog(TRUE, "Open Wav File", buffer.c_str(), "sound" ); - if ( filename != 0 ) { - 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 filename; -} - -class SoundAttribute : public EntityAttribute +const char *browse_sound(ui::Widget parent) { -CopiedString m_key; -BrowsedPathEntry m_entry; -NonModalEntry m_nonModal; + StringOutputStream buffer(1024); + + buffer << g_qeglobals.m_userGamePath.c_str() << "sound/"; + + if (!file_readable(buffer.c_str())) { + // just go to fsmain + buffer.clear(); + buffer << g_qeglobals.m_userGamePath.c_str() << "/"; + } + + const char *filename = parent.file_dialog(TRUE, "Open Wav File", buffer.c_str(), "sound"); + if (filename != 0) { + 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 filename; +} + +class SoundAttribute : public EntityAttribute { + CopiedString m_key; + BrowsedPathEntry m_entry; + NonModalEntry m_nonModal; public: -SoundAttribute( const char* key ) : - m_key( key ), - m_entry( BrowseCaller( *this ) ), - m_nonModal( ApplyCaller( *this ), UpdateCaller( *this ) ){ - m_nonModal.connect( m_entry.m_entry.m_entry ); -} -void release(){ - delete this; -} -ui::Widget getWidget() const { - return ui::Widget(m_entry.m_entry.m_frame ); -} -void apply(){ - StringOutputStream value( 64 ); - value << m_entry.m_entry.m_entry.text(); - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), value.c_str() ); -} -typedef MemberCaller ApplyCaller; -void update(){ - StringOutputStream value( 64 ); - value << SelectedEntity_getValueForKey( m_key.c_str() ); - m_entry.m_entry.m_entry.text(value.c_str()); -} -typedef MemberCaller UpdateCaller; -void browse( const BrowsedPathEntry::SetPathCallback& setPath ){ - const char *filename = browse_sound( m_entry.m_entry.m_frame.window() ); - - if ( filename != 0 ) { - setPath( filename ); - apply(); - } -} -typedef MemberCaller BrowseCaller; + SoundAttribute(const char *key) : + m_key(key), + m_entry(BrowseCaller(*this)), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + m_nonModal.connect(m_entry.m_entry.m_entry); + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_entry.m_entry.m_frame); + } + + void apply() + { + StringOutputStream value(64); + value << m_entry.m_entry.m_entry.text(); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), value.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream value(64); + value << SelectedEntity_getValueForKey(m_key.c_str()); + m_entry.m_entry.m_entry.text(value.c_str()); + } + + typedef MemberCaller UpdateCaller; + + void browse(const BrowsedPathEntry::SetPathCallback &setPath) + { + const char *filename = browse_sound(m_entry.m_entry.m_frame.window()); + + if (filename != 0) { + setPath(filename); + apply(); + } + } + + typedef MemberCaller BrowseCaller; }; -inline double angle_normalised( double angle ){ - return float_mod( angle, 360.0 ); +inline double angle_normalised(double angle) +{ + return float_mod(angle, 360.0); } -class AngleAttribute : public EntityAttribute -{ -CopiedString m_key; -ui::Entry m_entry; -NonModalEntry m_nonModal; +class AngleAttribute : public EntityAttribute { + CopiedString m_key; + ui::Entry m_entry; + NonModalEntry m_nonModal; public: -AngleAttribute( const char* key ) : - m_key( key ), - m_entry( ui::null ), - m_nonModal( ApplyCaller( *this ), UpdateCaller( *this ) ){ - auto entry = numeric_entry_new(); - m_entry = entry; - m_nonModal.connect( m_entry ); -} -void release(){ - delete this; -} -ui::Widget getWidget() const { - return ui::Widget(m_entry ); -} -void apply(){ - StringOutputStream angle( 32 ); - angle << angle_normalised( entry_get_float( m_entry ) ); - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), angle.c_str() ); -} -typedef MemberCaller ApplyCaller; - -void update(){ - const char* value = SelectedEntity_getValueForKey( m_key.c_str() ); - if ( !string_empty( value ) ) { - StringOutputStream angle( 32 ); - angle << angle_normalised( atof( value ) ); - m_entry.text(angle.c_str()); - } - else - { - m_entry.text("0"); - } -} -typedef MemberCaller UpdateCaller; + AngleAttribute(const char *key) : + m_key(key), + m_entry(ui::null), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + auto entry = numeric_entry_new(); + m_entry = entry; + m_nonModal.connect(m_entry); + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_entry); + } + + void apply() + { + StringOutputStream angle(32); + angle << angle_normalised(entry_get_float(m_entry)); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), angle.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + StringOutputStream angle(32); + angle << angle_normalised(atof(value)); + m_entry.text(angle.c_str()); + } else { + m_entry.text("0"); + } + } + + typedef MemberCaller UpdateCaller; }; -namespace -{ -typedef const char* String; -const String buttons[] = { "up", "down", "z-axis" }; +namespace { + typedef const char *String; + const String buttons[] = {"up", "down", "z-axis"}; } -class DirectionAttribute : public EntityAttribute -{ -CopiedString m_key; -ui::Entry m_entry; -NonModalEntry m_nonModal; -RadioHBox m_radio; -NonModalRadio m_nonModalRadio; -ui::HBox m_hbox{ui::null}; +class DirectionAttribute : public EntityAttribute { + CopiedString m_key; + ui::Entry m_entry; + NonModalEntry m_nonModal; + RadioHBox m_radio; + NonModalRadio m_nonModalRadio; + ui::HBox m_hbox{ui::null}; public: -DirectionAttribute( const char* key ) : - m_key( key ), - m_entry( ui::null ), - m_nonModal( ApplyCaller( *this ), UpdateCaller( *this ) ), - m_radio( RadioHBox_new( STRING_ARRAY_RANGE( buttons ) ) ), - m_nonModalRadio( ApplyRadioCaller( *this ) ){ - auto entry = numeric_entry_new(); - m_entry = entry; - m_nonModal.connect( m_entry ); - - m_nonModalRadio.connect( m_radio.m_radio ); - - m_hbox = ui::HBox( FALSE, 4 ); - m_hbox.show(); - - m_hbox.pack_start( m_radio.m_hbox, TRUE, TRUE, 0 ); - m_hbox.pack_start( m_entry, TRUE, TRUE, 0 ); -} -void release(){ - delete this; -} -ui::Widget getWidget() const { - return ui::Widget(m_hbox ); -} -void apply(){ - StringOutputStream angle( 32 ); - angle << angle_normalised( entry_get_float( m_entry ) ); - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), angle.c_str() ); -} -typedef MemberCaller ApplyCaller; - -void update(){ - const char* value = SelectedEntity_getValueForKey( m_key.c_str() ); - if ( !string_empty( value ) ) { - float f = float(atof( value ) ); - if ( f == -1 ) { - gtk_widget_set_sensitive( m_entry , FALSE ); - radio_button_set_active_no_signal( m_radio.m_radio, 0 ); - m_entry.text(""); - } - else if ( f == -2 ) { - gtk_widget_set_sensitive( m_entry , FALSE ); - radio_button_set_active_no_signal( m_radio.m_radio, 1 ); - m_entry.text(""); - } - else - { - gtk_widget_set_sensitive( m_entry , TRUE ); - radio_button_set_active_no_signal( m_radio.m_radio, 2 ); - StringOutputStream angle( 32 ); - angle << angle_normalised( f ); - m_entry.text(angle.c_str()); - } - } - else - { - m_entry.text("0"); - } -} -typedef MemberCaller UpdateCaller; - -void applyRadio(){ - int index = radio_button_get_active( m_radio.m_radio ); - if ( index == 0 ) { - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), "-1" ); - } - else if ( index == 1 ) { - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), "-2" ); - } - else if ( index == 2 ) { - apply(); - } -} -typedef MemberCaller ApplyRadioCaller; + DirectionAttribute(const char *key) : + m_key(key), + m_entry(ui::null), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)), + m_radio(RadioHBox_new(STRING_ARRAY_RANGE(buttons))), + m_nonModalRadio(ApplyRadioCaller(*this)) + { + auto entry = numeric_entry_new(); + m_entry = entry; + m_nonModal.connect(m_entry); + + m_nonModalRadio.connect(m_radio.m_radio); + + m_hbox = ui::HBox(FALSE, 4); + m_hbox.show(); + + m_hbox.pack_start(m_radio.m_hbox, TRUE, TRUE, 0); + m_hbox.pack_start(m_entry, TRUE, TRUE, 0); + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_hbox); + } + + void apply() + { + StringOutputStream angle(32); + angle << angle_normalised(entry_get_float(m_entry)); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), angle.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + float f = float(atof(value)); + if (f == -1) { + gtk_widget_set_sensitive(m_entry, FALSE); + radio_button_set_active_no_signal(m_radio.m_radio, 0); + m_entry.text(""); + } else if (f == -2) { + gtk_widget_set_sensitive(m_entry, FALSE); + radio_button_set_active_no_signal(m_radio.m_radio, 1); + m_entry.text(""); + } else { + gtk_widget_set_sensitive(m_entry, TRUE); + radio_button_set_active_no_signal(m_radio.m_radio, 2); + StringOutputStream angle(32); + angle << angle_normalised(f); + m_entry.text(angle.c_str()); + } + } else { + m_entry.text("0"); + } + } + + typedef MemberCaller UpdateCaller; + + void applyRadio() + { + int index = radio_button_get_active(m_radio.m_radio); + if (index == 0) { + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), "-1"); + } else if (index == 1) { + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), "-2"); + } else if (index == 2) { + apply(); + } + } + + typedef MemberCaller ApplyRadioCaller; }; -class AnglesEntry -{ +class AnglesEntry { public: -ui::Entry m_roll; -ui::Entry m_pitch; -ui::Entry m_yaw; -AnglesEntry() : m_roll( ui::null ), m_pitch( ui::null ), m_yaw( ui::null ){ -} + ui::Entry m_roll; + ui::Entry m_pitch; + ui::Entry m_yaw; + + AnglesEntry() : m_roll(ui::null), m_pitch(ui::null), m_yaw(ui::null) + { + } }; typedef BasicVector3 DoubleVector3; -class AnglesAttribute : public EntityAttribute -{ -CopiedString m_key; -AnglesEntry m_angles; -NonModalEntry m_nonModal; -ui::HBox m_hbox; +class AnglesAttribute : public EntityAttribute { + CopiedString m_key; + AnglesEntry m_angles; + NonModalEntry m_nonModal; + ui::HBox m_hbox; public: -AnglesAttribute( const char* key ) : - m_key( key ), - m_nonModal( ApplyCaller( *this ), UpdateCaller( *this ) ), - m_hbox(ui::HBox( TRUE, 4 )) -{ - m_hbox.show(); - { - auto entry = numeric_entry_new(); - m_hbox.pack_start( entry, TRUE, TRUE, 0 ); - m_angles.m_pitch = entry; - m_nonModal.connect( m_angles.m_pitch ); - } - { - auto entry = numeric_entry_new(); - m_hbox.pack_start( entry, TRUE, TRUE, 0 ); - m_angles.m_yaw = entry; - m_nonModal.connect( m_angles.m_yaw ); - } - { - auto entry = numeric_entry_new(); - m_hbox.pack_start( entry, TRUE, TRUE, 0 ); - m_angles.m_roll = entry; - m_nonModal.connect( m_angles.m_roll ); - } -} -void release(){ - delete this; -} -ui::Widget getWidget() const { - return ui::Widget(m_hbox ); -} -void apply(){ - StringOutputStream angles( 64 ); - angles << angle_normalised( entry_get_float( m_angles.m_pitch ) ) - << " " << angle_normalised( entry_get_float( m_angles.m_yaw ) ) - << " " << angle_normalised( entry_get_float( m_angles.m_roll ) ); - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), angles.c_str() ); -} -typedef MemberCaller ApplyCaller; - -void update(){ - StringOutputStream angle( 32 ); - const char* value = SelectedEntity_getValueForKey( m_key.c_str() ); - if ( !string_empty( value ) ) { - DoubleVector3 pitch_yaw_roll; - if ( !string_parse_vector3( value, pitch_yaw_roll ) ) { - pitch_yaw_roll = DoubleVector3( 0, 0, 0 ); - } - - angle << angle_normalised( pitch_yaw_roll.x() ); - m_angles.m_pitch.text(angle.c_str()); - angle.clear(); - - angle << angle_normalised( pitch_yaw_roll.y() ); - m_angles.m_yaw.text(angle.c_str()); - angle.clear(); - - angle << angle_normalised( pitch_yaw_roll.z() ); - m_angles.m_roll.text(angle.c_str()); - angle.clear(); - } - else - { - m_angles.m_pitch.text("0"); - m_angles.m_yaw.text("0"); - m_angles.m_roll.text("0"); - } -} -typedef MemberCaller UpdateCaller; + AnglesAttribute(const char *key) : + m_key(key), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)), + m_hbox(ui::HBox(TRUE, 4)) + { + m_hbox.show(); + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_angles.m_pitch = entry; + m_nonModal.connect(m_angles.m_pitch); + } + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_angles.m_yaw = entry; + m_nonModal.connect(m_angles.m_yaw); + } + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_angles.m_roll = entry; + m_nonModal.connect(m_angles.m_roll); + } + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_hbox); + } + + void apply() + { + StringOutputStream angles(64); + angles << angle_normalised(entry_get_float(m_angles.m_pitch)) + << " " << angle_normalised(entry_get_float(m_angles.m_yaw)) + << " " << angle_normalised(entry_get_float(m_angles.m_roll)); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), angles.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream angle(32); + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + DoubleVector3 pitch_yaw_roll; + if (!string_parse_vector3(value, pitch_yaw_roll)) { + pitch_yaw_roll = DoubleVector3(0, 0, 0); + } + + angle << angle_normalised(pitch_yaw_roll.x()); + m_angles.m_pitch.text(angle.c_str()); + angle.clear(); + + angle << angle_normalised(pitch_yaw_roll.y()); + m_angles.m_yaw.text(angle.c_str()); + angle.clear(); + + angle << angle_normalised(pitch_yaw_roll.z()); + m_angles.m_roll.text(angle.c_str()); + angle.clear(); + } else { + m_angles.m_pitch.text("0"); + m_angles.m_yaw.text("0"); + m_angles.m_roll.text("0"); + } + } + + typedef MemberCaller UpdateCaller; }; -class Vector3Entry -{ +class Vector3Entry { public: -ui::Entry m_x; -ui::Entry m_y; -ui::Entry m_z; -Vector3Entry() : m_x( ui::null ), m_y( ui::null ), m_z( ui::null ){ -} + ui::Entry m_x; + ui::Entry m_y; + ui::Entry m_z; + + Vector3Entry() : m_x(ui::null), m_y(ui::null), m_z(ui::null) + { + } }; -class Vector3Attribute : public EntityAttribute -{ -CopiedString m_key; -Vector3Entry m_vector3; -NonModalEntry m_nonModal; -ui::Box m_hbox{ui::null}; +class Vector3Attribute : public EntityAttribute { + CopiedString m_key; + Vector3Entry m_vector3; + NonModalEntry m_nonModal; + ui::Box m_hbox{ui::null}; public: -Vector3Attribute( const char* key ) : - m_key( key ), - m_nonModal( ApplyCaller( *this ), UpdateCaller( *this ) ){ - m_hbox = ui::HBox( TRUE, 4 ); - m_hbox.show(); - { - auto entry = numeric_entry_new(); - m_hbox.pack_start( entry, TRUE, TRUE, 0 ); - m_vector3.m_x = entry; - m_nonModal.connect( m_vector3.m_x ); - } - { - auto entry = numeric_entry_new(); - m_hbox.pack_start( entry, TRUE, TRUE, 0 ); - m_vector3.m_y = entry; - m_nonModal.connect( m_vector3.m_y ); - } - { - auto entry = numeric_entry_new(); - m_hbox.pack_start( entry, TRUE, TRUE, 0 ); - m_vector3.m_z = entry; - m_nonModal.connect( m_vector3.m_z ); - } -} -void release(){ - delete this; -} -ui::Widget getWidget() const { - return ui::Widget(m_hbox ); -} -void apply(){ - StringOutputStream vector3( 64 ); - vector3 << entry_get_float( m_vector3.m_x ) - << " " << entry_get_float( m_vector3.m_y ) - << " " << entry_get_float( m_vector3.m_z ); - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), vector3.c_str() ); -} -typedef MemberCaller ApplyCaller; - -void update(){ - StringOutputStream buffer( 32 ); - const char* value = SelectedEntity_getValueForKey( m_key.c_str() ); - if ( !string_empty( value ) ) { - DoubleVector3 x_y_z; - if ( !string_parse_vector3( value, x_y_z ) ) { - x_y_z = DoubleVector3( 0, 0, 0 ); - } - - buffer << x_y_z.x(); - m_vector3.m_x.text(buffer.c_str()); - buffer.clear(); - - buffer << x_y_z.y(); - m_vector3.m_y.text(buffer.c_str()); - buffer.clear(); - - buffer << x_y_z.z(); - m_vector3.m_z.text(buffer.c_str()); - buffer.clear(); - } - else - { - m_vector3.m_x.text("0"); - m_vector3.m_y.text("0"); - m_vector3.m_z.text("0"); - } -} -typedef MemberCaller UpdateCaller; + Vector3Attribute(const char *key) : + m_key(key), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + m_hbox = ui::HBox(TRUE, 4); + m_hbox.show(); + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_vector3.m_x = entry; + m_nonModal.connect(m_vector3.m_x); + } + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_vector3.m_y = entry; + m_nonModal.connect(m_vector3.m_y); + } + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_vector3.m_z = entry; + m_nonModal.connect(m_vector3.m_z); + } + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_hbox); + } + + void apply() + { + StringOutputStream vector3(64); + vector3 << entry_get_float(m_vector3.m_x) + << " " << entry_get_float(m_vector3.m_y) + << " " << entry_get_float(m_vector3.m_z); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), vector3.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream buffer(32); + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + DoubleVector3 x_y_z; + if (!string_parse_vector3(value, x_y_z)) { + x_y_z = DoubleVector3(0, 0, 0); + } + + buffer << x_y_z.x(); + m_vector3.m_x.text(buffer.c_str()); + buffer.clear(); + + buffer << x_y_z.y(); + m_vector3.m_y.text(buffer.c_str()); + buffer.clear(); + + buffer << x_y_z.z(); + m_vector3.m_z.text(buffer.c_str()); + buffer.clear(); + } else { + m_vector3.m_x.text("0"); + m_vector3.m_y.text("0"); + m_vector3.m_z.text("0"); + } + } + + typedef MemberCaller UpdateCaller; }; -class NonModalComboBox -{ -Callback m_changed; -guint m_changedHandler; +class NonModalComboBox { + Callback m_changed; + guint m_changedHandler; -static gboolean changed( ui::ComboBox widget, NonModalComboBox* self ){ - self->m_changed(); - return FALSE; -} + static gboolean changed(ui::ComboBox widget, NonModalComboBox *self) + { + self->m_changed(); + return FALSE; + } public: -NonModalComboBox( const Callback& changed ) : m_changed( changed ), m_changedHandler( 0 ){ -} -void connect( ui::ComboBox combo ){ - m_changedHandler = combo.connect( "changed", G_CALLBACK( changed ), this ); -} -void setActive( ui::ComboBox combo, int value ){ - g_signal_handler_disconnect( G_OBJECT( combo ), m_changedHandler ); - gtk_combo_box_set_active( combo, value ); - connect( combo ); -} + NonModalComboBox(const Callback &changed) : m_changed(changed), m_changedHandler(0) + { + } + + void connect(ui::ComboBox combo) + { + m_changedHandler = combo.connect("changed", G_CALLBACK(changed), this); + } + + void setActive(ui::ComboBox combo, int value) + { + g_signal_handler_disconnect(G_OBJECT(combo), m_changedHandler); + gtk_combo_box_set_active(combo, value); + connect(combo); + } }; -class ListAttribute : public EntityAttribute -{ -CopiedString m_key; -ui::ComboBox m_combo; -NonModalComboBox m_nonModal; -const ListAttributeType& m_type; +class ListAttribute : public EntityAttribute { + CopiedString m_key; + ui::ComboBox m_combo; + NonModalComboBox m_nonModal; + const ListAttributeType &m_type; public: -ListAttribute( const char* key, const ListAttributeType& type ) : - m_key( key ), - m_combo( ui::null ), - m_nonModal( ApplyCaller( *this ) ), - m_type( type ){ - auto combo = ui::ComboBoxText(ui::New); - - for ( ListAttributeType::const_iterator i = type.begin(); i != type.end(); ++i ) - { - gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), ( *i ).first.c_str() ); - } - - combo.show(); - m_nonModal.connect( combo ); - - m_combo = combo; -} -void release(){ - delete this; -} -ui::Widget getWidget() const { - return ui::Widget(m_combo ); -} -void apply(){ - Scene_EntitySetKeyValue_Selected_Undoable( m_key.c_str(), m_type[gtk_combo_box_get_active( m_combo )].second.c_str() ); -} -typedef MemberCaller ApplyCaller; - -void update(){ - const char* value = SelectedEntity_getValueForKey( m_key.c_str() ); - ListAttributeType::const_iterator i = m_type.findValue( value ); - if ( i != m_type.end() ) { - m_nonModal.setActive( m_combo, static_cast( std::distance( m_type.begin(), i ) ) ); - } - else - { - m_nonModal.setActive( m_combo, 0 ); - } -} -typedef MemberCaller UpdateCaller; + ListAttribute(const char *key, const ListAttributeType &type) : + m_key(key), + m_combo(ui::null), + m_nonModal(ApplyCaller(*this)), + m_type(type) + { + auto combo = ui::ComboBoxText(ui::New); + + for (ListAttributeType::const_iterator i = type.begin(); i != type.end(); ++i) { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), (*i).first.c_str()); + } + + combo.show(); + m_nonModal.connect(combo); + + m_combo = combo; + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_combo); + } + + void apply() + { + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), + m_type[gtk_combo_box_get_active(m_combo)].second.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + ListAttributeType::const_iterator i = m_type.findValue(value); + if (i != m_type.end()) { + m_nonModal.setActive(m_combo, static_cast( std::distance(m_type.begin(), i))); + } else { + m_nonModal.setActive(m_combo, 0); + } + } + + typedef MemberCaller UpdateCaller; }; -namespace -{ -ui::Widget g_entity_split1{ui::null}; -ui::Widget g_entity_split2{ui::null}; -int g_entitysplit1_position; -int g_entitysplit2_position; +namespace { + ui::Widget g_entity_split1{ui::null}; + ui::Widget g_entity_split2{ui::null}; + int g_entitysplit1_position; + int g_entitysplit2_position; -bool g_entityInspector_windowConstructed = false; + bool g_entityInspector_windowConstructed = false; -ui::TreeView g_entityClassList{ui::null}; -ui::TextView g_entityClassComment{ui::null}; + ui::TreeView g_entityClassList{ui::null}; + ui::TextView g_entityClassComment{ui::null}; -GtkCheckButton* g_entitySpawnflagsCheck[MAX_FLAGS]; + GtkCheckButton *g_entitySpawnflagsCheck[MAX_FLAGS]; -ui::Entry g_entityKeyEntry{ui::null}; -ui::Entry g_entityValueEntry{ui::null}; + ui::Entry g_entityKeyEntry{ui::null}; + ui::Entry g_entityValueEntry{ui::null}; -ui::ListStore g_entlist_store{ui::null}; -ui::ListStore g_entprops_store{ui::null}; -const EntityClass* g_current_flags = 0; -const EntityClass* g_current_comment = 0; -const EntityClass* g_current_attributes = 0; + ui::ListStore g_entlist_store{ui::null}; + ui::ListStore g_entprops_store{ui::null}; + const EntityClass *g_current_flags = 0; + const EntityClass *g_current_comment = 0; + const EntityClass *g_current_attributes = 0; // the number of active spawnflags -int g_spawnflag_count; + int g_spawnflag_count; // table: index, match spawnflag item to the spawnflag index (i.e. which bit) -int spawn_table[MAX_FLAGS]; + int spawn_table[MAX_FLAGS]; // we change the layout depending on how many spawn flags we need to display // the table is a 4x4 in which we need to put the comment box g_entityClassComment and the spawn flags.. -ui::Table g_spawnflagsTable{ui::null}; + ui::Table g_spawnflagsTable{ui::null}; -ui::VBox g_attributeBox{ui::null}; -typedef std::vector EntityAttributes; -EntityAttributes g_entityAttributes; + ui::VBox g_attributeBox{ui::null}; + typedef std::vector EntityAttributes; + EntityAttributes g_entityAttributes; } -void GlobalEntityAttributes_clear(){ - for ( EntityAttributes::iterator i = g_entityAttributes.begin(); i != g_entityAttributes.end(); ++i ) - { - ( *i )->release(); - } - g_entityAttributes.clear(); +void GlobalEntityAttributes_clear() +{ + for (EntityAttributes::iterator i = g_entityAttributes.begin(); i != g_entityAttributes.end(); ++i) { + (*i)->release(); + } + g_entityAttributes.clear(); } -class GetKeyValueVisitor : public Entity::Visitor -{ -KeyValues& m_keyvalues; +class GetKeyValueVisitor : public Entity::Visitor { + KeyValues &m_keyvalues; public: -GetKeyValueVisitor( KeyValues& keyvalues ) - : m_keyvalues( keyvalues ){ -} + GetKeyValueVisitor(KeyValues &keyvalues) + : m_keyvalues(keyvalues) + { + } -void visit( const char* key, const char* value ){ - m_keyvalues.insert( KeyValues::value_type( CopiedString( key ), CopiedString( value ) ) ); -} + void visit(const char *key, const char *value) + { + m_keyvalues.insert(KeyValues::value_type(CopiedString(key), CopiedString(value))); + } }; -void Entity_GetKeyValues( const Entity& entity, KeyValues& keyvalues, KeyValues& defaultValues ){ - GetKeyValueVisitor visitor( keyvalues ); - - entity.forEachKeyValue( visitor ); +void Entity_GetKeyValues(const Entity &entity, KeyValues &keyvalues, KeyValues &defaultValues) +{ + GetKeyValueVisitor visitor(keyvalues); - const EntityClassAttributes& attributes = entity.getEntityClass().m_attributes; + entity.forEachKeyValue(visitor); - for ( EntityClassAttributes::const_iterator i = attributes.begin(); i != attributes.end(); ++i ) - { - defaultValues.insert( KeyValues::value_type( ( *i ).first, ( *i ).second.m_value ) ); - } -} + const EntityClassAttributes &attributes = entity.getEntityClass().m_attributes; -void Entity_GetKeyValues_Selected( KeyValues& keyvalues, KeyValues& defaultValues ){ - class EntityGetKeyValues : public SelectionSystem::Visitor - { - KeyValues& m_keyvalues; - KeyValues& m_defaultValues; - mutable std::set m_visited; -public: - EntityGetKeyValues( KeyValues& keyvalues, KeyValues& defaultValues ) - : m_keyvalues( keyvalues ), m_defaultValues( defaultValues ){ - } - void visit( scene::Instance& instance ) const { - Entity* entity = Node_getEntity( instance.path().top() ); - if ( entity == 0 && instance.path().size() != 1 ) { - entity = Node_getEntity( instance.path().parent() ); - } - if ( entity != 0 && m_visited.insert( entity ).second ) { - Entity_GetKeyValues( *entity, m_keyvalues, m_defaultValues ); - } - } - } visitor( keyvalues, defaultValues ); - GlobalSelectionSystem().foreachSelected( visitor ); + for (EntityClassAttributes::const_iterator i = attributes.begin(); i != attributes.end(); ++i) { + defaultValues.insert(KeyValues::value_type((*i).first, (*i).second.m_value)); + } } -const char* keyvalues_valueforkey( KeyValues& keyvalues, const char* key ){ - KeyValues::iterator i = keyvalues.find( CopiedString( key ) ); - if ( i != keyvalues.end() ) { - return ( *i ).second.c_str(); - } - return ""; +void Entity_GetKeyValues_Selected(KeyValues &keyvalues, KeyValues &defaultValues) +{ + class EntityGetKeyValues : public SelectionSystem::Visitor { + KeyValues &m_keyvalues; + KeyValues &m_defaultValues; + mutable std::set m_visited; + public: + EntityGetKeyValues(KeyValues &keyvalues, KeyValues &defaultValues) + : m_keyvalues(keyvalues), m_defaultValues(defaultValues) + { + } + + void visit(scene::Instance &instance) const + { + Entity *entity = Node_getEntity(instance.path().top()); + if (entity == 0 && instance.path().size() != 1) { + entity = Node_getEntity(instance.path().parent()); + } + if (entity != 0 && m_visited.insert(entity).second) { + Entity_GetKeyValues(*entity, m_keyvalues, m_defaultValues); + } + } + } visitor(keyvalues, defaultValues); + GlobalSelectionSystem().foreachSelected(visitor); +} + +const char *keyvalues_valueforkey(KeyValues &keyvalues, const char *key) +{ + KeyValues::iterator i = keyvalues.find(CopiedString(key)); + if (i != keyvalues.end()) { + return (*i).second.c_str(); + } + return ""; } -class EntityClassListStoreAppend : public EntityClassVisitor -{ -ui::ListStore store; +class EntityClassListStoreAppend : public EntityClassVisitor { + ui::ListStore store; public: -EntityClassListStoreAppend( ui::ListStore store_ ) : store( store_ ){ -} -void visit( EntityClass* e ){ - store.append(0, e->name(), 1, e); -} + EntityClassListStoreAppend(ui::ListStore store_) : store(store_) + { + } + + void visit(EntityClass *e) + { + store.append(0, e->name(), 1, e); + } }; -void EntityClassList_fill(){ - EntityClassListStoreAppend append( g_entlist_store ); - GlobalEntityClassManager().forEach( append ); +void EntityClassList_fill() +{ + EntityClassListStoreAppend append(g_entlist_store); + GlobalEntityClassManager().forEach(append); } -void EntityClassList_clear(){ - g_entlist_store.clear(); +void EntityClassList_clear() +{ + g_entlist_store.clear(); } -void SetComment( EntityClass* eclass ){ - if ( eclass == g_current_comment ) { - return; - } - - g_current_comment = eclass; - - g_entityClassComment.text(eclass->comments()); -} +void SetComment(EntityClass *eclass) +{ + if (eclass == g_current_comment) { + return; + } -void SurfaceFlags_setEntityClass( EntityClass* eclass ){ - if ( eclass == g_current_flags ) { - return; - } - - g_current_flags = eclass; - - unsigned int spawnflag_count = 0; - - { - // do a first pass to count the spawn flags, don't touch the widgets, we don't know in what state they are - for ( int i = 0 ; i < MAX_FLAGS ; i++ ) - { - if ( eclass->flagnames[i] && eclass->flagnames[i][0] != 0 && strcmp( eclass->flagnames[i],"-" ) ) { - spawn_table[spawnflag_count] = i; - spawnflag_count++; - } - } - } - - // disable all remaining boxes - // NOTE: these boxes might not even be on display - { - for ( int i = 0; i < g_spawnflag_count; ++i ) - { - auto widget = ui::CheckButton::from(g_entitySpawnflagsCheck[i]); - auto label = ui::Label::from(gtk_bin_get_child(GTK_BIN(widget))); - label.text(" "); - widget.hide(); - widget.ref(); - g_spawnflagsTable.remove(widget); - } - } - - g_spawnflag_count = spawnflag_count; - - { - for (unsigned int i = 0; (int) i < g_spawnflag_count; ++i) - { - auto widget = ui::CheckButton::from(g_entitySpawnflagsCheck[i] ); - widget.show(); - - StringOutputStream str( 16 ); - str << LowerCase( eclass->flagnames[spawn_table[i]] ); - - g_spawnflagsTable.attach(widget, {i % 4, i % 4 + 1, i / 4, i / 4 + 1}, {GTK_FILL, GTK_FILL}); - widget.unref(); - - auto label = ui::Label::from(gtk_bin_get_child(GTK_BIN(widget)) ); - label.text(str.c_str()); - } - } -} + g_current_comment = eclass; -void EntityClassList_selectEntityClass( EntityClass* eclass ){ - auto model = g_entlist_store; - GtkTreeIter iter; - for ( gboolean good = gtk_tree_model_get_iter_first( model, &iter ); good != FALSE; good = gtk_tree_model_iter_next( model, &iter ) ) - { - char* text; - gtk_tree_model_get( model, &iter, 0, &text, -1 ); - if ( strcmp( text, eclass->name() ) == 0 ) { - auto view = ui::TreeView(g_entityClassList); - auto path = gtk_tree_model_get_path( model, &iter ); - gtk_tree_selection_select_path( gtk_tree_view_get_selection( view ), path ); - if ( gtk_widget_get_realized( view ) ) { - gtk_tree_view_scroll_to_cell( view, path, 0, FALSE, 0, 0 ); - } - gtk_tree_path_free( path ); - good = FALSE; - } - g_free( text ); - } + g_entityClassComment.text(eclass->comments()); } -void EntityInspector_appendAttribute( const char* name, EntityAttribute& attribute ){ - auto row = DialogRow_new( name, attribute.getWidget() ); - DialogVBox_packRow( ui::VBox(g_attributeBox), row ); +void SurfaceFlags_setEntityClass(EntityClass *eclass) +{ + if (eclass == g_current_flags) { + return; + } + + g_current_flags = eclass; + + unsigned int spawnflag_count = 0; + + { + // do a first pass to count the spawn flags, don't touch the widgets, we don't know in what state they are + for (int i = 0; i < MAX_FLAGS; i++) { + if (eclass->flagnames[i] && eclass->flagnames[i][0] != 0 && strcmp(eclass->flagnames[i], "-")) { + spawn_table[spawnflag_count] = i; + spawnflag_count++; + } + } + } + + // disable all remaining boxes + // NOTE: these boxes might not even be on display + { + for (int i = 0; i < g_spawnflag_count; ++i) { + auto widget = ui::CheckButton::from(g_entitySpawnflagsCheck[i]); + auto label = ui::Label::from(gtk_bin_get_child(GTK_BIN(widget))); + label.text(" "); + widget.hide(); + widget.ref(); + g_spawnflagsTable.remove(widget); + } + } + + g_spawnflag_count = spawnflag_count; + + { + for (unsigned int i = 0; (int) i < g_spawnflag_count; ++i) { + auto widget = ui::CheckButton::from(g_entitySpawnflagsCheck[i]); + widget.show(); + + StringOutputStream str(16); + str << LowerCase(eclass->flagnames[spawn_table[i]]); + + g_spawnflagsTable.attach(widget, {i % 4, i % 4 + 1, i / 4, i / 4 + 1}, {GTK_FILL, GTK_FILL}); + widget.unref(); + + auto label = ui::Label::from(gtk_bin_get_child(GTK_BIN(widget))); + label.text(str.c_str()); + } + } +} + +void EntityClassList_selectEntityClass(EntityClass *eclass) +{ + auto model = g_entlist_store; + GtkTreeIter iter; + for (gboolean good = gtk_tree_model_get_iter_first(model, &iter); + good != FALSE; good = gtk_tree_model_iter_next(model, &iter)) { + char *text; + gtk_tree_model_get(model, &iter, 0, &text, -1); + if (strcmp(text, eclass->name()) == 0) { + auto view = ui::TreeView(g_entityClassList); + auto path = gtk_tree_model_get_path(model, &iter); + gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path); + if (gtk_widget_get_realized(view)) { + gtk_tree_view_scroll_to_cell(view, path, 0, FALSE, 0, 0); + } + gtk_tree_path_free(path); + good = FALSE; + } + g_free(text); + } +} + +void EntityInspector_appendAttribute(const char *name, EntityAttribute &attribute) +{ + auto row = DialogRow_new(name, attribute.getWidget()); + DialogVBox_packRow(ui::VBox(g_attributeBox), row); } template -class StatelessAttributeCreator -{ +class StatelessAttributeCreator { public: -static EntityAttribute* create( const char* name ){ - return new Attribute( name ); -} + static EntityAttribute *create(const char *name) + { + return new Attribute(name); + } }; -class EntityAttributeFactory -{ -typedef EntityAttribute* ( *CreateFunc )( const char* name ); -typedef std::map Creators; -Creators m_creators; +class EntityAttributeFactory { + typedef EntityAttribute *( *CreateFunc )(const char *name); + + typedef std::map Creators; + Creators m_creators; public: -EntityAttributeFactory(){ - m_creators.insert( Creators::value_type( "string", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "color", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "integer", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "real", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "shader", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "boolean", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "angle", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "direction", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "angles", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "model", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "sound", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "vector3", &StatelessAttributeCreator::create ) ); - m_creators.insert( Creators::value_type( "real3", &StatelessAttributeCreator::create ) ); -} -EntityAttribute* create( const char* type, const char* name ){ - Creators::iterator i = m_creators.find( type ); - if ( i != m_creators.end() ) { - return ( *i ).second( name ); - } - const ListAttributeType* listType = GlobalEntityClassManager().findListType( type ); - if ( listType != 0 ) { - return new ListAttribute( name, *listType ); - } - return 0; -} + EntityAttributeFactory() + { + m_creators.insert(Creators::value_type("string", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("color", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("integer", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("real", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("shader", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("boolean", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("angle", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("direction", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("angles", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("model", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("sound", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("vector3", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("real3", &StatelessAttributeCreator::create)); + } + + EntityAttribute *create(const char *type, const char *name) + { + Creators::iterator i = m_creators.find(type); + if (i != m_creators.end()) { + return (*i).second(name); + } + const ListAttributeType *listType = GlobalEntityClassManager().findListType(type); + if (listType != 0) { + return new ListAttribute(name, *listType); + } + return 0; + } }; typedef Static GlobalEntityAttributeFactory; -void EntityInspector_setEntityClass( EntityClass *eclass ){ - EntityClassList_selectEntityClass( eclass ); - SurfaceFlags_setEntityClass( eclass ); - - if ( eclass != g_current_attributes ) { - g_current_attributes = eclass; - - container_remove_all( g_attributeBox ); - GlobalEntityAttributes_clear(); - - for ( EntityClassAttributes::const_iterator i = eclass->m_attributes.begin(); i != eclass->m_attributes.end(); ++i ) - { - EntityAttribute* attribute = GlobalEntityAttributeFactory::instance().create( ( *i ).second.m_type.c_str(), ( *i ).first.c_str() ); - if ( attribute != 0 ) { - g_entityAttributes.push_back( attribute ); - EntityInspector_appendAttribute( EntityClassAttributePair_getName( *i ), *g_entityAttributes.back() ); - } - } - } -} +void EntityInspector_setEntityClass(EntityClass *eclass) +{ + EntityClassList_selectEntityClass(eclass); + SurfaceFlags_setEntityClass(eclass); -void EntityInspector_updateSpawnflags(){ - { - int f = atoi( SelectedEntity_getValueForKey( "spawnflags" ) ); - for ( int i = 0; i < g_spawnflag_count; ++i ) - { - int v = !!( f & ( 1 << spawn_table[i] ) ); - - toggle_button_set_active_no_signal( ui::ToggleButton::from( g_entitySpawnflagsCheck[i] ), v ); - } - } - { - // take care of the remaining ones - for ( int i = g_spawnflag_count; i < MAX_FLAGS; ++i ) - { - toggle_button_set_active_no_signal( ui::ToggleButton::from( g_entitySpawnflagsCheck[i] ), FALSE ); - } - } + if (eclass != g_current_attributes) { + g_current_attributes = eclass; + + container_remove_all(g_attributeBox); + GlobalEntityAttributes_clear(); + + for (EntityClassAttributes::const_iterator i = eclass->m_attributes.begin(); + i != eclass->m_attributes.end(); ++i) { + EntityAttribute *attribute = GlobalEntityAttributeFactory::instance().create((*i).second.m_type.c_str(), + (*i).first.c_str()); + if (attribute != 0) { + g_entityAttributes.push_back(attribute); + EntityInspector_appendAttribute(EntityClassAttributePair_getName(*i), *g_entityAttributes.back()); + } + } + } } -void EntityInspector_applySpawnflags(){ - int f, i, v; - char sz[32]; +void EntityInspector_updateSpawnflags() +{ + { + int f = atoi(SelectedEntity_getValueForKey("spawnflags")); + for (int i = 0; i < g_spawnflag_count; ++i) { + int v = !!(f & (1 << spawn_table[i])); + + toggle_button_set_active_no_signal(ui::ToggleButton::from(g_entitySpawnflagsCheck[i]), v); + } + } + { + // take care of the remaining ones + for (int i = g_spawnflag_count; i < MAX_FLAGS; ++i) { + toggle_button_set_active_no_signal(ui::ToggleButton::from(g_entitySpawnflagsCheck[i]), FALSE); + } + } +} + +void EntityInspector_applySpawnflags() +{ + int f, i, v; + char sz[32]; - f = 0; - for ( i = 0; i < g_spawnflag_count; ++i ) - { - v = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_entitySpawnflagsCheck[i] ) ); - f |= v << spawn_table[i]; - } + f = 0; + for (i = 0; i < g_spawnflag_count; ++i) { + v = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_entitySpawnflagsCheck[i])); + f |= v << spawn_table[i]; + } - sprintf( sz, "%i", f ); - const char* value = ( f == 0 ) ? "" : sz; + sprintf(sz, "%i", f); + const char *value = (f == 0) ? "" : sz; - { - StringOutputStream command; - command << "entitySetFlags -flags " << f; - UndoableCommand undo( "entitySetSpawnflags" ); + { + StringOutputStream command; + command << "entitySetFlags -flags " << f; + UndoableCommand undo("entitySetSpawnflags"); - Scene_EntitySetKeyValue_Selected( "spawnflags", value ); - } + Scene_EntitySetKeyValue_Selected("spawnflags", value); + } } -void EntityInspector_updateKeyValues(){ - g_selectedKeyValues.clear(); - g_selectedDefaultKeyValues.clear(); - Entity_GetKeyValues_Selected( g_selectedKeyValues, g_selectedDefaultKeyValues ); +void EntityInspector_updateKeyValues() +{ + g_selectedKeyValues.clear(); + g_selectedDefaultKeyValues.clear(); + Entity_GetKeyValues_Selected(g_selectedKeyValues, g_selectedDefaultKeyValues); - EntityInspector_setEntityClass( GlobalEntityClassManager().findOrInsert( keyvalues_valueforkey( g_selectedKeyValues, "classname" ), false ) ); + EntityInspector_setEntityClass( + GlobalEntityClassManager().findOrInsert(keyvalues_valueforkey(g_selectedKeyValues, "classname"), false)); - EntityInspector_updateSpawnflags(); + EntityInspector_updateSpawnflags(); - ui::ListStore store = g_entprops_store; + ui::ListStore store = g_entprops_store; - // save current key/val pair around filling epair box - // row_select wipes it and sets to first in list - CopiedString strKey( g_entityKeyEntry.text() ); - CopiedString strVal( g_entityValueEntry.text() ); + // save current key/val pair around filling epair box + // row_select wipes it and sets to first in list + CopiedString strKey(g_entityKeyEntry.text()); + CopiedString strVal(g_entityValueEntry.text()); - store.clear(); - // Walk through list and add pairs - for ( KeyValues::iterator i = g_selectedKeyValues.begin(); i != g_selectedKeyValues.end(); ++i ) - { - StringOutputStream key( 64 ); - key << ( *i ).first.c_str(); - StringOutputStream value( 64 ); - value << ( *i ).second.c_str(); - store.append(0, key.c_str(), 1, value.c_str()); - } + store.clear(); + // Walk through list and add pairs + for (KeyValues::iterator i = g_selectedKeyValues.begin(); i != g_selectedKeyValues.end(); ++i) { + StringOutputStream key(64); + key << (*i).first.c_str(); + StringOutputStream value(64); + value << (*i).second.c_str(); + store.append(0, key.c_str(), 1, value.c_str()); + } - g_entityKeyEntry.text( strKey.c_str() ); - g_entityValueEntry.text( strVal.c_str() ); + g_entityKeyEntry.text(strKey.c_str()); + g_entityValueEntry.text(strVal.c_str()); - for ( EntityAttributes::const_iterator i = g_entityAttributes.begin(); i != g_entityAttributes.end(); ++i ) - { - ( *i )->update(); - } + for (EntityAttributes::const_iterator i = g_entityAttributes.begin(); i != g_entityAttributes.end(); ++i) { + (*i)->update(); + } } -class EntityInspectorDraw -{ -IdleDraw m_idleDraw; +class EntityInspectorDraw { + IdleDraw m_idleDraw; public: -EntityInspectorDraw() : m_idleDraw( makeCallbackF(EntityInspector_updateKeyValues) ){ -} -void queueDraw(){ - m_idleDraw.queueDraw(); -} + EntityInspectorDraw() : m_idleDraw(makeCallbackF(EntityInspector_updateKeyValues)) + { + } + + void queueDraw() + { + m_idleDraw.queueDraw(); + } }; EntityInspectorDraw g_EntityInspectorDraw; -void EntityInspector_keyValueChanged(){ - g_EntityInspectorDraw.queueDraw(); +void EntityInspector_keyValueChanged() +{ + g_EntityInspectorDraw.queueDraw(); } -void EntityInspector_selectionChanged( const Selectable& ){ - EntityInspector_keyValueChanged(); + +void EntityInspector_selectionChanged(const Selectable &) +{ + EntityInspector_keyValueChanged(); } // Creates a new entity based on the currently selected brush and entity type. // -void EntityClassList_createEntity(){ - auto view = g_entityClassList; +void EntityClassList_createEntity() +{ + auto view = g_entityClassList; - // find out what type of entity we are trying to create - GtkTreeModel* model; - GtkTreeIter iter; - if ( gtk_tree_selection_get_selected( gtk_tree_view_get_selection( g_entityClassList ), &model, &iter ) == FALSE ) { - ui::alert( view.window(), "You must have a selected class to create an entity", "info" ); - return; - } + // find out what type of entity we are trying to create + GtkTreeModel *model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(g_entityClassList), &model, &iter) == FALSE) { + ui::alert(view.window(), "You must have a selected class to create an entity", "info"); + return; + } - char* text; - gtk_tree_model_get( model, &iter, 0, &text, -1 ); + char *text; + gtk_tree_model_get(model, &iter, 0, &text, -1); - { - StringOutputStream command; - command << "entityCreate -class " << text; + { + StringOutputStream command; + command << "entityCreate -class " << text; - UndoableCommand undo( command.c_str() ); + UndoableCommand undo(command.c_str()); - Entity_createFromSelection( text, g_vector3_identity ); - } - g_free( text ); + Entity_createFromSelection(text, g_vector3_identity); + } + g_free(text); } -void EntityInspector_applyKeyValue(){ - // Get current selection text - StringOutputStream key( 64 ); - key << gtk_entry_get_text( g_entityKeyEntry ); - StringOutputStream value( 64 ); - value << gtk_entry_get_text( g_entityValueEntry ); - - - // TTimo: if you change the classname to worldspawn you won't merge back in the structural brushes but create a parasite entity - if ( !strcmp( key.c_str(), "classname" ) && !strcmp( value.c_str(), "worldspawn" ) ) { - ui::alert( g_entityKeyEntry.window(), "Cannot change \"classname\" key back to worldspawn.", 0, ui::alert_type::OK ); - return; - } - - - // RR2DO2: we don't want spaces in entity keys - if ( strstr( key.c_str(), " " ) ) { - ui::alert( g_entityKeyEntry.window(), "No spaces are allowed in entity keys.", 0, ui::alert_type::OK ); - return; - } - - if ( strcmp( key.c_str(), "classname" ) == 0 ) { - StringOutputStream command; - command << "entitySetClass -class " << value.c_str(); - UndoableCommand undo( command.c_str() ); - Scene_EntitySetClassname_Selected( value.c_str() ); - } - else - { - Scene_EntitySetKeyValue_Selected_Undoable( key.c_str(), value.c_str() ); - } -} +void EntityInspector_applyKeyValue() +{ + // Get current selection text + StringOutputStream key(64); + key << gtk_entry_get_text(g_entityKeyEntry); + StringOutputStream value(64); + value << gtk_entry_get_text(g_entityValueEntry); + + + // TTimo: if you change the classname to worldspawn you won't merge back in the structural brushes but create a parasite entity + if (!strcmp(key.c_str(), "classname") && !strcmp(value.c_str(), "worldspawn")) { + ui::alert(g_entityKeyEntry.window(), "Cannot change \"classname\" key back to worldspawn.", 0, + ui::alert_type::OK); + return; + } + + + // RR2DO2: we don't want spaces in entity keys + if (strstr(key.c_str(), " ")) { + ui::alert(g_entityKeyEntry.window(), "No spaces are allowed in entity keys.", 0, ui::alert_type::OK); + return; + } + + if (strcmp(key.c_str(), "classname") == 0) { + StringOutputStream command; + command << "entitySetClass -class " << value.c_str(); + UndoableCommand undo(command.c_str()); + Scene_EntitySetClassname_Selected(value.c_str()); + } else { + Scene_EntitySetKeyValue_Selected_Undoable(key.c_str(), value.c_str()); + } +} + +void EntityInspector_clearKeyValue() +{ + // Get current selection text + StringOutputStream key(64); + key << gtk_entry_get_text(g_entityKeyEntry); -void EntityInspector_clearKeyValue(){ - // Get current selection text - StringOutputStream key( 64 ); - key << gtk_entry_get_text( g_entityKeyEntry ); - - if ( strcmp( key.c_str(), "classname" ) != 0 ) { - StringOutputStream command; - command << "entityDeleteKey -key " << key.c_str(); - UndoableCommand undo( command.c_str() ); - Scene_EntitySetKeyValue_Selected( key.c_str(), "" ); - } + if (strcmp(key.c_str(), "classname") != 0) { + StringOutputStream command; + command << "entityDeleteKey -key " << key.c_str(); + UndoableCommand undo(command.c_str()); + Scene_EntitySetKeyValue_Selected(key.c_str(), ""); + } } -void EntityInspector_clearAllKeyValues(){ - UndoableCommand undo( "entityClear" ); +void EntityInspector_clearAllKeyValues() +{ + UndoableCommand undo("entityClear"); - // remove all keys except classname - for ( KeyValues::iterator i = g_selectedKeyValues.begin(); i != g_selectedKeyValues.end(); ++i ) - { - if ( strcmp( ( *i ).first.c_str(), "classname" ) != 0 ) { - Scene_EntitySetKeyValue_Selected( ( *i ).first.c_str(), "" ); - } - } + // remove all keys except classname + for (KeyValues::iterator i = g_selectedKeyValues.begin(); i != g_selectedKeyValues.end(); ++i) { + if (strcmp((*i).first.c_str(), "classname") != 0) { + Scene_EntitySetKeyValue_Selected((*i).first.c_str(), ""); + } + } } // ============================================================================= // callbacks -static void EntityClassList_selection_changed( ui::TreeSelection selection, gpointer data ){ - GtkTreeModel* model; - GtkTreeIter selected; - if ( gtk_tree_selection_get_selected( selection, &model, &selected ) ) { - EntityClass* eclass; - gtk_tree_model_get( model, &selected, 1, &eclass, -1 ); - if ( eclass != 0 ) { - SetComment( eclass ); - } - } -} - -static gint EntityClassList_button_press( ui::Widget widget, GdkEventButton *event, gpointer data ){ - if ( event->type == GDK_2BUTTON_PRESS ) { - EntityClassList_createEntity(); - return TRUE; - } - return FALSE; -} - -static gint EntityClassList_keypress( ui::Widget widget, GdkEventKey* event, gpointer data ){ - unsigned int code = gdk_keyval_to_upper( event->keyval ); - - if ( event->keyval == GDK_KEY_Return ) { - EntityClassList_createEntity(); - return TRUE; - } - - // select the entity that starts with the key pressed - if ( code <= 'Z' && code >= 'A' ) { - auto view = ui::TreeView(g_entityClassList); - GtkTreeModel* model; - GtkTreeIter iter; - if ( gtk_tree_selection_get_selected( gtk_tree_view_get_selection( view ), &model, &iter ) == FALSE - || gtk_tree_model_iter_next( model, &iter ) == FALSE ) { - gtk_tree_model_get_iter_first( model, &iter ); - } - - for ( std::size_t count = gtk_tree_model_iter_n_children( model, 0 ); count > 0; --count ) - { - char* text; - gtk_tree_model_get( model, &iter, 0, &text, -1 ); - - if ( toupper( text[0] ) == (int)code ) { - auto path = gtk_tree_model_get_path( model, &iter ); - gtk_tree_selection_select_path( gtk_tree_view_get_selection( view ), path ); - if ( gtk_widget_get_realized( view ) ) { - gtk_tree_view_scroll_to_cell( view, path, 0, FALSE, 0, 0 ); - } - gtk_tree_path_free( path ); - count = 1; - } - - g_free( text ); - - if ( gtk_tree_model_iter_next( model, &iter ) == FALSE ) { - gtk_tree_model_get_iter_first( model, &iter ); - } - } - - return TRUE; - } - return FALSE; +static void EntityClassList_selection_changed(ui::TreeSelection selection, gpointer data) +{ + GtkTreeModel *model; + GtkTreeIter selected; + if (gtk_tree_selection_get_selected(selection, &model, &selected)) { + EntityClass *eclass; + gtk_tree_model_get(model, &selected, 1, &eclass, -1); + if (eclass != 0) { + SetComment(eclass); + } + } +} + +static gint EntityClassList_button_press(ui::Widget widget, GdkEventButton *event, gpointer data) +{ + if (event->type == GDK_2BUTTON_PRESS) { + EntityClassList_createEntity(); + return TRUE; + } + return FALSE; } -static void EntityProperties_selection_changed( ui::TreeSelection selection, gpointer data ){ - // find out what type of entity we are trying to create - GtkTreeModel* model; - GtkTreeIter iter; - if ( gtk_tree_selection_get_selected( selection, &model, &iter ) == FALSE ) { - return; - } - - char* key; - char* val; - gtk_tree_model_get( model, &iter, 0, &key, 1, &val, -1 ); +static gint EntityClassList_keypress(ui::Widget widget, GdkEventKey *event, gpointer data) +{ + unsigned int code = gdk_keyval_to_upper(event->keyval); + + if (event->keyval == GDK_KEY_Return) { + EntityClassList_createEntity(); + return TRUE; + } + + // select the entity that starts with the key pressed + if (code <= 'Z' && code >= 'A') { + auto view = ui::TreeView(g_entityClassList); + GtkTreeModel *model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE + || gtk_tree_model_iter_next(model, &iter) == FALSE) { + gtk_tree_model_get_iter_first(model, &iter); + } + + for (std::size_t count = gtk_tree_model_iter_n_children(model, 0); count > 0; --count) { + char *text; + gtk_tree_model_get(model, &iter, 0, &text, -1); + + if (toupper(text[0]) == (int) code) { + auto path = gtk_tree_model_get_path(model, &iter); + gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path); + if (gtk_widget_get_realized(view)) { + gtk_tree_view_scroll_to_cell(view, path, 0, FALSE, 0, 0); + } + gtk_tree_path_free(path); + count = 1; + } + + g_free(text); + + if (gtk_tree_model_iter_next(model, &iter) == FALSE) { + gtk_tree_model_get_iter_first(model, &iter); + } + } + + return TRUE; + } + return FALSE; +} + +static void EntityProperties_selection_changed(ui::TreeSelection selection, gpointer data) +{ + // find out what type of entity we are trying to create + GtkTreeModel *model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE) { + return; + } - g_entityKeyEntry.text( key ); - g_entityValueEntry.text( val ); + char *key; + char *val; + gtk_tree_model_get(model, &iter, 0, &key, 1, &val, -1); - g_free( key ); - g_free( val ); -} + g_entityKeyEntry.text(key); + g_entityValueEntry.text(val); -static void SpawnflagCheck_toggled( ui::Widget widget, gpointer data ){ - EntityInspector_applySpawnflags(); + g_free(key); + g_free(val); } -static gint EntityEntry_keypress( ui::Entry widget, GdkEventKey* event, gpointer data ){ - if ( event->keyval == GDK_KEY_Return ) { - if ( widget._handle == g_entityKeyEntry._handle ) { - g_entityValueEntry.text( "" ); - gtk_window_set_focus( widget.window(), g_entityValueEntry ); - } - else - { - EntityInspector_applyKeyValue(); - } - return TRUE; - } - if ( event->keyval == GDK_KEY_Escape ) { - gtk_window_set_focus( widget.window(), NULL ); - return TRUE; - } - - return FALSE; +static void SpawnflagCheck_toggled(ui::Widget widget, gpointer data) +{ + EntityInspector_applySpawnflags(); } -void EntityInspector_destroyWindow( ui::Widget widget, gpointer data ){ - g_entitysplit1_position = gtk_paned_get_position( GTK_PANED( g_entity_split1 ) ); - g_entitysplit2_position = gtk_paned_get_position( GTK_PANED( g_entity_split2 ) ); +static gint EntityEntry_keypress(ui::Entry widget, GdkEventKey *event, gpointer data) +{ + if (event->keyval == GDK_KEY_Return) { + if (widget._handle == g_entityKeyEntry._handle) { + g_entityValueEntry.text(""); + gtk_window_set_focus(widget.window(), g_entityValueEntry); + } else { + EntityInspector_applyKeyValue(); + } + return TRUE; + } + if (event->keyval == GDK_KEY_Escape) { + gtk_window_set_focus(widget.window(), NULL); + return TRUE; + } + + return FALSE; +} + +void EntityInspector_destroyWindow(ui::Widget widget, gpointer data) +{ + g_entitysplit1_position = gtk_paned_get_position(GTK_PANED(g_entity_split1)); + g_entitysplit2_position = gtk_paned_get_position(GTK_PANED(g_entity_split2)); - g_entityInspector_windowConstructed = false; - GlobalEntityAttributes_clear(); + g_entityInspector_windowConstructed = false; + GlobalEntityAttributes_clear(); } -ui::Widget EntityInspector_constructWindow( ui::Window toplevel ){ - auto vbox = ui::VBox( FALSE, 2 ); - vbox.show(); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 2 ); +ui::Widget EntityInspector_constructWindow(ui::Window toplevel) +{ + auto vbox = ui::VBox(FALSE, 2); + vbox.show(); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 2); - vbox.connect( "destroy", G_CALLBACK( EntityInspector_destroyWindow ), 0 ); + vbox.connect("destroy", G_CALLBACK(EntityInspector_destroyWindow), 0); - { + { auto split1 = ui::VPaned(ui::New); - vbox.pack_start( split1, TRUE, TRUE, 0 ); - split1.show(); - - g_entity_split1 = split1; - - { - ui::Widget split2 = ui::VPaned(ui::New); - gtk_paned_add1( GTK_PANED( split1 ), split2 ); - split2.show(); - - g_entity_split2 = split2; - - { - // class list - auto scr = ui::ScrolledWindow(ui::New); - scr.show(); - gtk_paned_add1( GTK_PANED( split2 ), scr ); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scr ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); - gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scr ), GTK_SHADOW_IN ); - - { - ui::ListStore store = ui::ListStore::from(gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER )); - - auto view = ui::TreeView( ui::TreeModel::from( store._handle )); - gtk_tree_view_set_enable_search(view, FALSE ); - gtk_tree_view_set_headers_visible( view, FALSE ); - view.connect( "button_press_event", G_CALLBACK( EntityClassList_button_press ), 0 ); - view.connect( "key_press_event", G_CALLBACK( EntityClassList_keypress ), 0 ); - - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn( "Key", renderer, {{"text", 0}} ); - gtk_tree_view_append_column( view, column ); - } - - { - auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection( view )); - selection.connect( "changed", G_CALLBACK( EntityClassList_selection_changed ), 0 ); - } - - view.show(); - - scr.add(view); - - store.unref(); - g_entityClassList = view; - g_entlist_store = store; - } - } - - { - auto scr = ui::ScrolledWindow(ui::New); - scr.show(); - gtk_paned_add2( GTK_PANED( split2 ), scr ); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scr ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); - gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scr ), GTK_SHADOW_IN ); - - { - auto text = ui::TextView(ui::New); - text.dimensions(0, -1); // allow shrinking - gtk_text_view_set_wrap_mode( text, GTK_WRAP_WORD ); - gtk_text_view_set_editable( text, FALSE ); - text.show(); - scr.add(text); - g_entityClassComment = text; - } - } - } - - { - ui::Widget split2 = ui::VPaned(ui::New); - gtk_paned_add2( GTK_PANED( split1 ), split2 ); - split2.show(); - - { - auto vbox2 = ui::VBox( FALSE, 2 ); - vbox2.show(); - gtk_paned_pack1( GTK_PANED( split2 ), vbox2, FALSE, FALSE ); - - { - // Spawnflags (4 colums wide max, or window gets too wide.) - auto table = ui::Table( 4, 4, FALSE ); - vbox2.pack_start( table, FALSE, TRUE, 0 ); - table.show(); - - g_spawnflagsTable = table; - - for ( int i = 0; i < MAX_FLAGS; i++ ) - { - auto check = ui::CheckButton( "" ); - check.ref(); - g_object_set_data( G_OBJECT( check ), "handler", gint_to_pointer( check.connect( "toggled", G_CALLBACK( SpawnflagCheck_toggled ), 0 ) ) ); - g_entitySpawnflagsCheck[i] = check; - } - } - - { - // key/value list - auto scr = ui::ScrolledWindow(ui::New); - scr.show(); - vbox2.pack_start( scr, TRUE, TRUE, 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 ); - - { - ui::ListStore store = ui::ListStore::from(gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_STRING )); - - auto view = ui::TreeView(ui::TreeModel::from(store._handle)); - gtk_tree_view_set_enable_search(view, FALSE ); - gtk_tree_view_set_headers_visible(view, FALSE ); - - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn( "", renderer, {{"text", 0}} ); - gtk_tree_view_append_column(view, column ); - } - - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn( "", renderer, {{"text", 1}} ); - gtk_tree_view_append_column(view, column ); - } - - { - auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); - selection.connect( "changed", G_CALLBACK( EntityProperties_selection_changed ), 0 ); - } - - view.show(); - - scr.add(view); - - store.unref(); - - g_entprops_store = store; - } - } - - { - // key/value entry - auto table = ui::Table( 2, 2, FALSE ); - table.show(); - vbox2.pack_start( table, FALSE, TRUE, 0 ); - gtk_table_set_row_spacings( table, 3 ); - gtk_table_set_col_spacings( table, 5 ); - - { - auto entry = ui::Entry(ui::New); - entry.show(); - table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_widget_set_events( entry , GDK_KEY_PRESS_MASK ); - entry.connect( "key_press_event", G_CALLBACK( EntityEntry_keypress ), 0 ); - g_entityKeyEntry = entry; - } - - { - auto entry = ui::Entry(ui::New); - entry.show(); - table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_widget_set_events( entry , GDK_KEY_PRESS_MASK ); - entry.connect( "key_press_event", G_CALLBACK( EntityEntry_keypress ), 0 ); - g_entityValueEntry = entry; - } - - { - auto label = ui::Label( "Value" ); - label.show(); - table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - - { - auto label = ui::Label( "Key" ); - label.show(); - table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - } - - { - auto hbox = ui::HBox( TRUE, 4 ); - hbox.show(); - vbox2.pack_start( hbox, FALSE, TRUE, 0 ); - - { - auto button = ui::Button( "Clear All" ); - button.show(); - button.connect( "clicked", G_CALLBACK( EntityInspector_clearAllKeyValues ), 0 ); - hbox.pack_start( button, TRUE, TRUE, 0 ); - } - { - auto button = ui::Button( "Delete Key" ); - button.show(); - button.connect( "clicked", G_CALLBACK( EntityInspector_clearKeyValue ), 0 ); - hbox.pack_start( button, TRUE, TRUE, 0 ); - } - } - } - - { - auto scr = ui::ScrolledWindow(ui::New); - scr.show(); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scr ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC ); - - auto viewport = ui::Container::from(gtk_viewport_new( 0, 0 )); - viewport.show(); - gtk_viewport_set_shadow_type( GTK_VIEWPORT( viewport ), GTK_SHADOW_NONE ); - - g_attributeBox = ui::VBox( FALSE, 2 ); - g_attributeBox.show(); - - viewport.add(g_attributeBox); - scr.add(viewport); - gtk_paned_pack2( GTK_PANED( split2 ), scr, FALSE, FALSE ); - } - } - } - - - { - // show the sliders in any case - if ( g_entitysplit2_position > 22 ) { - gtk_paned_set_position( GTK_PANED( g_entity_split2 ), g_entitysplit2_position ); - } - else { - g_entitysplit2_position = 22; - gtk_paned_set_position( GTK_PANED( g_entity_split2 ), 22 ); - } - if ( ( g_entitysplit1_position - g_entitysplit2_position ) > 27 ) { - gtk_paned_set_position( GTK_PANED( g_entity_split1 ), g_entitysplit1_position ); - } - else { - gtk_paned_set_position( GTK_PANED( g_entity_split1 ), g_entitysplit2_position + 27 ); - } - } - - g_entityInspector_windowConstructed = true; - EntityClassList_fill(); - - typedef FreeCaller EntityInspectorSelectionChangedCaller; - GlobalSelectionSystem().addSelectionChangeCallback( EntityInspectorSelectionChangedCaller() ); - GlobalEntityCreator().setKeyValueChangedFunc( EntityInspector_keyValueChanged ); - - // hack - gtk_container_set_focus_chain( GTK_CONTAINER( vbox ), NULL ); - - return vbox; -} - -class EntityInspector : public ModuleObserver -{ -std::size_t m_unrealised; + vbox.pack_start(split1, TRUE, TRUE, 0); + split1.show(); + + g_entity_split1 = split1; + + { + ui::Widget split2 = ui::VPaned(ui::New); + gtk_paned_add1(GTK_PANED(split1), split2); + split2.show(); + + g_entity_split2 = split2; + + { + // class list + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + gtk_paned_add1(GTK_PANED(split2), scr); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN); + + { + ui::ListStore store = ui::ListStore::from(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER)); + + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_enable_search(view, FALSE); + gtk_tree_view_set_headers_visible(view, FALSE); + view.connect("button_press_event", G_CALLBACK(EntityClassList_button_press), 0); + view.connect("key_press_event", G_CALLBACK(EntityClassList_keypress), 0); + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("Key", renderer, {{"text", 0}}); + gtk_tree_view_append_column(view, column); + } + + { + auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); + selection.connect("changed", G_CALLBACK(EntityClassList_selection_changed), 0); + } + + view.show(); + + scr.add(view); + + store.unref(); + g_entityClassList = view; + g_entlist_store = store; + } + } + + { + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + gtk_paned_add2(GTK_PANED(split2), scr); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN); + + { + auto text = ui::TextView(ui::New); + text.dimensions(0, -1); // allow shrinking + gtk_text_view_set_wrap_mode(text, GTK_WRAP_WORD); + gtk_text_view_set_editable(text, FALSE); + text.show(); + scr.add(text); + g_entityClassComment = text; + } + } + } + + { + ui::Widget split2 = ui::VPaned(ui::New); + gtk_paned_add2(GTK_PANED(split1), split2); + split2.show(); + + { + auto vbox2 = ui::VBox(FALSE, 2); + vbox2.show(); + gtk_paned_pack1(GTK_PANED(split2), vbox2, FALSE, FALSE); + + { + // Spawnflags (4 colums wide max, or window gets too wide.) + auto table = ui::Table(4, 4, FALSE); + vbox2.pack_start(table, FALSE, TRUE, 0); + table.show(); + + g_spawnflagsTable = table; + + for (int i = 0; i < MAX_FLAGS; i++) { + auto check = ui::CheckButton(""); + check.ref(); + g_object_set_data(G_OBJECT(check), "handler", gint_to_pointer( + check.connect("toggled", G_CALLBACK(SpawnflagCheck_toggled), 0))); + g_entitySpawnflagsCheck[i] = check; + } + } + + { + // key/value list + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + vbox2.pack_start(scr, TRUE, TRUE, 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); + + { + ui::ListStore store = ui::ListStore::from(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING)); + + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_enable_search(view, FALSE); + gtk_tree_view_set_headers_visible(view, FALSE); + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("", renderer, {{"text", 0}}); + gtk_tree_view_append_column(view, column); + } + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("", renderer, {{"text", 1}}); + gtk_tree_view_append_column(view, column); + } + + { + auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); + selection.connect("changed", G_CALLBACK(EntityProperties_selection_changed), 0); + } + + view.show(); + + scr.add(view); + + store.unref(); + + g_entprops_store = store; + } + } + + { + // key/value entry + auto table = ui::Table(2, 2, FALSE); + table.show(); + vbox2.pack_start(table, FALSE, TRUE, 0); + gtk_table_set_row_spacings(table, 3); + gtk_table_set_col_spacings(table, 5); + + { + auto entry = ui::Entry(ui::New); + entry.show(); + table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); + gtk_widget_set_events(entry, GDK_KEY_PRESS_MASK); + entry.connect("key_press_event", G_CALLBACK(EntityEntry_keypress), 0); + g_entityKeyEntry = entry; + } + + { + auto entry = ui::Entry(ui::New); + entry.show(); + table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); + gtk_widget_set_events(entry, GDK_KEY_PRESS_MASK); + entry.connect("key_press_event", G_CALLBACK(EntityEntry_keypress), 0); + g_entityValueEntry = entry; + } + + { + auto label = ui::Label("Value"); + label.show(); + table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + + { + auto label = ui::Label("Key"); + label.show(); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + } + + { + auto hbox = ui::HBox(TRUE, 4); + hbox.show(); + vbox2.pack_start(hbox, FALSE, TRUE, 0); + + { + auto button = ui::Button("Clear All"); + button.show(); + button.connect("clicked", G_CALLBACK(EntityInspector_clearAllKeyValues), 0); + hbox.pack_start(button, TRUE, TRUE, 0); + } + { + auto button = ui::Button("Delete Key"); + button.show(); + button.connect("clicked", G_CALLBACK(EntityInspector_clearKeyValue), 0); + hbox.pack_start(button, TRUE, TRUE, 0); + } + } + } + + { + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + auto viewport = ui::Container::from(gtk_viewport_new(0, 0)); + viewport.show(); + gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); + + g_attributeBox = ui::VBox(FALSE, 2); + g_attributeBox.show(); + + viewport.add(g_attributeBox); + scr.add(viewport); + gtk_paned_pack2(GTK_PANED(split2), scr, FALSE, FALSE); + } + } + } + + + { + // show the sliders in any case + if (g_entitysplit2_position > 22) { + gtk_paned_set_position(GTK_PANED(g_entity_split2), g_entitysplit2_position); + } else { + g_entitysplit2_position = 22; + gtk_paned_set_position(GTK_PANED(g_entity_split2), 22); + } + if ((g_entitysplit1_position - g_entitysplit2_position) > 27) { + gtk_paned_set_position(GTK_PANED(g_entity_split1), g_entitysplit1_position); + } else { + gtk_paned_set_position(GTK_PANED(g_entity_split1), g_entitysplit2_position + 27); + } + } + + g_entityInspector_windowConstructed = true; + EntityClassList_fill(); + + typedef FreeCaller EntityInspectorSelectionChangedCaller; + GlobalSelectionSystem().addSelectionChangeCallback(EntityInspectorSelectionChangedCaller()); + GlobalEntityCreator().setKeyValueChangedFunc(EntityInspector_keyValueChanged); + + // hack + gtk_container_set_focus_chain(GTK_CONTAINER(vbox), NULL); + + return vbox; +} + +class EntityInspector : public ModuleObserver { + std::size_t m_unrealised; public: -EntityInspector() : m_unrealised( 1 ){ -} -void realise(){ - if ( --m_unrealised == 0 ) { - if ( g_entityInspector_windowConstructed ) { - //globalOutputStream() << "Entity Inspector: realise\n"; - EntityClassList_fill(); - } - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - if ( g_entityInspector_windowConstructed ) { - //globalOutputStream() << "Entity Inspector: unrealise\n"; - EntityClassList_clear(); - } - } -} + EntityInspector() : m_unrealised(1) + { + } + + void realise() + { + if (--m_unrealised == 0) { + if (g_entityInspector_windowConstructed) { + //globalOutputStream() << "Entity Inspector: realise\n"; + EntityClassList_fill(); + } + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + if (g_entityInspector_windowConstructed) { + //globalOutputStream() << "Entity Inspector: unrealise\n"; + EntityClassList_clear(); + } + } + } }; EntityInspector g_EntityInspector; @@ -1571,24 +1690,27 @@ EntityInspector g_EntityInspector; #include "preferencesystem.h" #include "stringio.h" -void EntityInspector_construct(){ - GlobalEntityClassManager().attach( g_EntityInspector ); +void EntityInspector_construct() +{ + GlobalEntityClassManager().attach(g_EntityInspector); - GlobalPreferenceSystem().registerPreference( "EntitySplit1", make_property_string( g_entitysplit1_position ) ); - GlobalPreferenceSystem().registerPreference( "EntitySplit2", make_property_string( g_entitysplit2_position ) ); + GlobalPreferenceSystem().registerPreference("EntitySplit1", make_property_string(g_entitysplit1_position)); + GlobalPreferenceSystem().registerPreference("EntitySplit2", make_property_string(g_entitysplit2_position)); } -void EntityInspector_destroy(){ - GlobalEntityClassManager().detach( g_EntityInspector ); +void EntityInspector_destroy() +{ + GlobalEntityClassManager().detach(g_EntityInspector); } -const char *EntityInspector_getCurrentKey(){ - if ( !GroupDialog_isShown() ) { - return 0; - } - if ( GroupDialog_getPage() != g_page_entity ) { - return 0; - } - return gtk_entry_get_text( g_entityKeyEntry ); +const char *EntityInspector_getCurrentKey() +{ + if (!GroupDialog_isShown()) { + return 0; + } + if (GroupDialog_getPage() != g_page_entity) { + return 0; + } + return gtk_entry_get_text(g_entityKeyEntry); } diff --git a/radiant/entityinspector.h b/radiant/entityinspector.h index e0d359ec..4b200a85 100644 --- a/radiant/entityinspector.h +++ b/radiant/entityinspector.h @@ -24,9 +24,12 @@ #if !defined( INCLUDED_ENTITYINSPECTOR_H ) #define INCLUDED_ENTITYINSPECTOR_H -ui::Widget EntityInspector_constructWindow( ui::Window parent ); +ui::Widget EntityInspector_constructWindow(ui::Window parent); + void EntityInspector_construct(); + void EntityInspector_destroy(); + const char *EntityInspector_getCurrentKey(); #endif diff --git a/radiant/entitylist.cpp b/radiant/entitylist.cpp index 0230fe6d..c13d8d6c 100644 --- a/radiant/entitylist.cpp +++ b/radiant/entitylist.cpp @@ -41,347 +41,377 @@ #include "treemodel.h" void RedrawEntityList(); + typedef FreeCaller RedrawEntityListCaller; -class EntityList -{ +class EntityList { public: -enum EDirty -{ - eDefault, - eSelection, - eInsertRemove, + enum EDirty { + eDefault, + eSelection, + eInsertRemove, + }; + + EDirty m_dirty; + + IdleDraw m_idleDraw; + WindowPositionTracker m_positionTracker; + + ui::Window m_window; + ui::TreeView m_tree_view{ui::null}; + ui::TreeModel m_tree_model{ui::null}; + bool m_selection_disabled; + + EntityList() : + m_dirty(EntityList::eDefault), + m_idleDraw(RedrawEntityListCaller()), + m_window(ui::null), + m_selection_disabled(false) + { + } + + bool visible() + { + return m_window.visible(); + } }; -EDirty m_dirty; - -IdleDraw m_idleDraw; -WindowPositionTracker m_positionTracker; +namespace { + EntityList *g_EntityList; -ui::Window m_window; -ui::TreeView m_tree_view{ui::null}; -ui::TreeModel m_tree_model{ui::null}; -bool m_selection_disabled; - -EntityList() : - m_dirty( EntityList::eDefault ), - m_idleDraw( RedrawEntityListCaller() ), - m_window( ui::null ), - m_selection_disabled( false ){ + inline EntityList &getEntityList() + { + ASSERT_NOTNULL(g_EntityList); + return *g_EntityList; + } } -bool visible() { - return m_window.visible(); -} -}; -namespace +inline Nameable *Node_getNameable(scene::Node &node) { -EntityList* g_EntityList; - -inline EntityList& getEntityList(){ - ASSERT_NOTNULL( g_EntityList ); - return *g_EntityList; -} -} - - -inline Nameable* Node_getNameable( scene::Node& node ){ - return NodeTypeCast::cast( node ); + return NodeTypeCast::cast(node); } -const char* node_get_name( scene::Node& node ){ - Nameable* nameable = Node_getNameable( node ); - return ( nameable != 0 ) - ? nameable->name() - : "node"; +const char *node_get_name(scene::Node &node) +{ + Nameable *nameable = Node_getNameable(node); + return (nameable != 0) + ? nameable->name() + : "node"; } template -inline void gtk_tree_model_get_pointer( ui::TreeModel 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( ui::TreeViewColumn column, ui::CellRenderer renderer, ui::TreeModel 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( node_get_name( *node ) ); - g_object_set( G_OBJECT( renderer ), "text", name, "visible", TRUE, NULL ); - - //globalOutputStream() << "rendering cell " << makeQuoted(name) << "\n"; - auto style = gtk_widget_get_style( ui::TreeView( getEntityList().m_tree_view ) ); - if ( instance->childSelected() ) { - g_object_set( G_OBJECT( renderer ), "cell-background-gdk", &style->base[GTK_STATE_ACTIVE], NULL ); - } - else - { - g_object_set( G_OBJECT( renderer ), "cell-background-gdk", &style->base[GTK_STATE_NORMAL], NULL ); - } - } - else - { - gtk_cell_renderer_set_fixed_size( renderer, -1, 0 ); - g_object_set( G_OBJECT( renderer ), "text", "", "visible", FALSE, NULL ); - } +inline void gtk_tree_model_get_pointer(ui::TreeModel 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); } -static gboolean entitylist_tree_select( ui::TreeSelection selection, ui::TreeModel model, ui::TreePath 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( ui::TreeSelection selection, ui::TreeModel model, ui::TreePath path, gboolean path_currently_selected, gpointer data ){ - return TRUE; +void entitylist_treeviewcolumn_celldatafunc(ui::TreeViewColumn column, ui::CellRenderer renderer, ui::TreeModel 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( node_get_name(*node)); + g_object_set(G_OBJECT(renderer), "text", name, "visible", TRUE, NULL); + + //globalOutputStream() << "rendering cell " << makeQuoted(name) << "\n"; + auto style = gtk_widget_get_style(ui::TreeView(getEntityList().m_tree_view)); + if (instance->childSelected()) { + g_object_set(G_OBJECT(renderer), "cell-background-gdk", &style->base[GTK_STATE_ACTIVE], NULL); + } else { + g_object_set(G_OBJECT(renderer), "cell-background-gdk", &style->base[GTK_STATE_NORMAL], NULL); + } + } else { + gtk_cell_renderer_set_fixed_size(renderer, -1, 0); + g_object_set(G_OBJECT(renderer), "text", "", "visible", FALSE, NULL); + } +} + +static gboolean entitylist_tree_select(ui::TreeSelection selection, ui::TreeModel model, ui::TreePath 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(ui::TreeSelection selection, ui::TreeModel model, ui::TreePath path, + gboolean path_currently_selected, gpointer data) +{ + return TRUE; } -void EntityList_ConnectSignals( ui::TreeView view ){ - auto select = gtk_tree_view_get_selection( view ); - gtk_tree_selection_set_select_function(select, reinterpret_cast(entitylist_tree_select), NULL, 0 ); +void EntityList_ConnectSignals(ui::TreeView view) +{ + auto select = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_select_function(select, reinterpret_cast(entitylist_tree_select), NULL, + 0); } -void EntityList_DisconnectSignals( ui::TreeView view ){ - auto select = gtk_tree_view_get_selection( view ); - gtk_tree_selection_set_select_function(select, reinterpret_cast(entitylist_tree_select_null), 0, 0 ); +void EntityList_DisconnectSignals(ui::TreeView view) +{ + auto select = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_select_function(select, reinterpret_cast(entitylist_tree_select_null), + 0, 0); } +gboolean treemodel_update_selection(ui::TreeModel model, ui::TreePath path, GtkTreeIter *iter, gpointer data) +{ + auto view = ui::TreeView::from(data); -gboolean treemodel_update_selection( ui::TreeModel model, ui::TreePath path, GtkTreeIter* iter, gpointer data ){ - auto view = ui::TreeView::from( data ); - - scene::Instance* instance; - gtk_tree_model_get_pointer( model, iter, 1, &instance ); - Selectable* selectable = Instance_getSelectable( *instance ); + scene::Instance *instance; + gtk_tree_model_get_pointer(model, iter, 1, &instance); + Selectable *selectable = Instance_getSelectable(*instance); - if ( selectable != 0 ) { - auto 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 ); - } - } + if (selectable != 0) { + auto 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; + return FALSE; } -void EntityList_UpdateSelection( ui::TreeModel model, ui::TreeView view ){ - EntityList_DisconnectSignals( view ); - gtk_tree_model_foreach(model, reinterpret_cast(treemodel_update_selection), view._handle ); - EntityList_ConnectSignals( view ); +void EntityList_UpdateSelection(ui::TreeModel model, ui::TreeView view) +{ + EntityList_DisconnectSignals(view); + gtk_tree_model_foreach(model, reinterpret_cast(treemodel_update_selection), view._handle); + EntityList_ConnectSignals(view); } -void RedrawEntityList(){ - switch ( getEntityList().m_dirty ) - { - case EntityList::eInsertRemove: - case EntityList::eSelection: - EntityList_UpdateSelection( getEntityList().m_tree_model, getEntityList().m_tree_view ); - default: - break; - } - getEntityList().m_dirty = EntityList::eDefault; +void RedrawEntityList() +{ + switch (getEntityList().m_dirty) { + case EntityList::eInsertRemove: + case EntityList::eSelection: + EntityList_UpdateSelection(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_queue_draw() +{ + getEntityList().m_idleDraw.queueDraw(); } -void EntityList_SelectionUpdate(){ - if ( getEntityList().m_selection_disabled ) { - return; - } +void EntityList_SelectionUpdate() +{ + if (getEntityList().m_selection_disabled) { + return; + } - if ( getEntityList().m_dirty < EntityList::eSelection ) { - getEntityList().m_dirty = EntityList::eSelection; - } - entitylist_queue_draw(); + if (getEntityList().m_dirty < EntityList::eSelection) { + getEntityList().m_dirty = EntityList::eSelection; + } + entitylist_queue_draw(); } -void EntityList_SelectionChanged( const Selectable& selectable ){ - EntityList_SelectionUpdate(); +void EntityList_SelectionChanged(const Selectable &selectable) +{ + EntityList_SelectionUpdate(); } -void entitylist_treeview_rowcollapsed( ui::TreeView view, GtkTreeIter* iter, ui::TreePath path, gpointer user_data ){ +void entitylist_treeview_rowcollapsed(ui::TreeView view, GtkTreeIter *iter, ui::TreePath path, gpointer user_data) +{ } -void entitylist_treeview_row_expanded( ui::TreeView view, GtkTreeIter* iter, ui::TreePath path, gpointer user_data ){ - EntityList_SelectionUpdate(); +void entitylist_treeview_row_expanded(ui::TreeView view, GtkTreeIter *iter, ui::TreePath path, gpointer user_data) +{ + EntityList_SelectionUpdate(); } -void EntityList_SetShown( bool shown ){ - getEntityList().m_window.visible(shown); -} - -void EntityList_toggleShown(){ - EntityList_SetShown( !getEntityList().visible() ); +void EntityList_SetShown(bool shown) +{ + getEntityList().m_window.visible(shown); } -gint graph_tree_model_compare_name( ui::TreeModel 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; +void EntityList_toggleShown() +{ + EntityList_SetShown(!getEntityList().visible()); } -extern GraphTreeModel* scene_graph_get_tree_model(); -void AttachEntityTreeModel(){ - getEntityList().m_tree_model = ui::TreeModel::from(scene_graph_get_tree_model()); +gint graph_tree_model_compare_name(ui::TreeModel 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 = ui::TreeModel::from(scene_graph_get_tree_model()); - gtk_tree_view_set_model( getEntityList().m_tree_view, getEntityList().m_tree_model ); + gtk_tree_view_set_model(getEntityList().m_tree_view, getEntityList().m_tree_model); } -void DetachEntityTreeModel(){ - getEntityList().m_tree_model = ui::TreeModel(ui::null); +void DetachEntityTreeModel() +{ + getEntityList().m_tree_model = ui::TreeModel(ui::null); - gtk_tree_view_set_model( getEntityList().m_tree_view, 0 ); + gtk_tree_view_set_model(getEntityList().m_tree_view, 0); } -void EntityList_constructWindow( ui::Window main_window ){ - ASSERT_TRUE( !getEntityList().m_window ); +void EntityList_constructWindow(ui::Window main_window) +{ + ASSERT_TRUE(!getEntityList().m_window); - auto window = ui::Window(create_persistent_floating_window( "Entity List", main_window )); + auto window = ui::Window(create_persistent_floating_window("Entity List", main_window)); - window.add_accel_group(global_accel); + window.add_accel_group(global_accel); - getEntityList().m_positionTracker.connect( window ); + getEntityList().m_positionTracker.connect(window); - getEntityList().m_window = window; + getEntityList().m_window = window; - { - auto scr = create_scrolled_window( ui::Policy::AUTOMATIC, ui::Policy::AUTOMATIC ); - window.add(scr); + { + auto scr = create_scrolled_window(ui::Policy::AUTOMATIC, ui::Policy::AUTOMATIC); + window.add(scr); - { + { auto view = ui::TreeView(ui::New); - gtk_tree_view_set_headers_visible(view, FALSE ); + gtk_tree_view_set_headers_visible(view, FALSE); - auto renderer = ui::CellRendererText(ui::New); - auto 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, reinterpret_cast(entitylist_treeviewcolumn_celldatafunc), 0, 0 ); + auto renderer = ui::CellRendererText(ui::New); + auto 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, + reinterpret_cast(entitylist_treeviewcolumn_celldatafunc), + 0, 0); - auto select = gtk_tree_view_get_selection(view ); - gtk_tree_selection_set_mode( select, GTK_SELECTION_MULTIPLE ); + auto select = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(select, GTK_SELECTION_MULTIPLE); - view.connect( "row_expanded", G_CALLBACK( entitylist_treeview_row_expanded ), 0 ); - view.connect( "row_collapsed", G_CALLBACK( entitylist_treeview_rowcollapsed ), 0 ); + view.connect("row_expanded", G_CALLBACK(entitylist_treeview_row_expanded), 0); + view.connect("row_collapsed", G_CALLBACK(entitylist_treeview_rowcollapsed), 0); - gtk_tree_view_append_column(view, column ); + gtk_tree_view_append_column(view, column); - view.show(); - scr.add(view); - getEntityList().m_tree_view = view; - } - } + view.show(); + scr.add(view); + getEntityList().m_tree_view = view; + } + } - EntityList_ConnectSignals( getEntityList().m_tree_view ); - AttachEntityTreeModel(); + EntityList_ConnectSignals(getEntityList().m_tree_view); + AttachEntityTreeModel(); } -void EntityList_destroyWindow(){ - DetachEntityTreeModel(); - EntityList_DisconnectSignals( getEntityList().m_tree_view ); - destroy_floating_window( getEntityList().m_window ); +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; +namespace { + scene::Node *nullNode = 0; } -class NullSelectedInstance : public scene::Instance, public Selectable -{ -class TypeCasts -{ -InstanceTypeCastTable m_casts; -public: -TypeCasts(){ - InstanceStaticCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} -}; +class NullSelectedInstance : public scene::Instance, public Selectable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + InstanceStaticCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; public: -typedef LazyStatic StaticTypeCasts; + typedef LazyStatic StaticTypeCasts; -NullSelectedInstance() : Instance( scene::Path( makeReference( *nullNode ) ), 0, this, StaticTypeCasts::instance().get() ){ -} + NullSelectedInstance() : Instance(scene::Path(makeReference(*nullNode)), 0, this, StaticTypeCasts::instance().get()) + { + } -void setSelected( bool select ){ - ERROR_MESSAGE( "error" ); -} -bool isSelected() const { - return true; -} + void setSelected(bool select) + { + ERROR_MESSAGE("error"); + } + + bool isSelected() const + { + return true; + } }; typedef LazyStatic StaticNullSelectedInstance; -void EntityList_Construct(){ - graph_tree_model_insert( scene_graph_get_tree_model(), StaticNullSelectedInstance::instance() ); +void EntityList_Construct() +{ + graph_tree_model_insert(scene_graph_get_tree_model(), StaticNullSelectedInstance::instance()); - g_EntityList = new EntityList; + g_EntityList = new EntityList; - getEntityList().m_positionTracker.setPosition( c_default_window_pos ); + getEntityList().m_positionTracker.setPosition(c_default_window_pos); - GlobalPreferenceSystem().registerPreference( "EntityInfoDlg", make_property( getEntityList().m_positionTracker ) ); + GlobalPreferenceSystem().registerPreference("EntityInfoDlg", make_property( + getEntityList().m_positionTracker)); - typedef FreeCaller EntityListSelectionChangedCaller; - GlobalSelectionSystem().addSelectionChangeCallback( EntityListSelectionChangedCaller() ); + typedef FreeCaller EntityListSelectionChangedCaller; + GlobalSelectionSystem().addSelectionChangeCallback(EntityListSelectionChangedCaller()); } -void EntityList_Destroy(){ - delete g_EntityList; - graph_tree_model_erase( scene_graph_get_tree_model(), StaticNullSelectedInstance::instance() ); +void EntityList_Destroy() +{ + delete g_EntityList; + + graph_tree_model_erase(scene_graph_get_tree_model(), StaticNullSelectedInstance::instance()); } diff --git a/radiant/entitylist.h b/radiant/entitylist.h index 4830bb8d..38ee5877 100644 --- a/radiant/entitylist.h +++ b/radiant/entitylist.h @@ -25,10 +25,13 @@ #define INCLUDED_ENTITYLIST_H void EntityList_Construct(); + void EntityList_Destroy(); -void EntityList_constructWindow( ui::Window main_window ); +void EntityList_constructWindow(ui::Window main_window); + void EntityList_destroyWindow(); + void EntityList_toggleShown(); #endif diff --git a/radiant/environment.cpp b/radiant/environment.cpp index 1c297f03..81face07 100644 --- a/radiant/environment.cpp +++ b/radiant/environment.cpp @@ -31,153 +31,163 @@ #include "cmdlib.h" int g_argc; -char const** g_argv; - -void args_init( int argc, char const* 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; +char const **g_argv; + +void args_init(int argc, char const *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; } char const *gamedetect_argv_buffer[1024]; -void gamedetect_found_game( char const *game, char *path ){ - int argc; - static char buf[128]; - - if ( g_argv == gamedetect_argv_buffer ) { - return; - } - - globalOutputStream() << "Detected game " << game << " in " << path << "\n"; - - sprintf( buf, "-%s-EnginePath", game ); - argc = 0; - gamedetect_argv_buffer[argc++] = "-global-gamefile"; - gamedetect_argv_buffer[argc++] = game; - gamedetect_argv_buffer[argc++] = buf; - gamedetect_argv_buffer[argc++] = path; - if ( (size_t) ( argc + g_argc ) >= sizeof( gamedetect_argv_buffer ) / sizeof( *gamedetect_argv_buffer ) - 1 ) { - g_argc = sizeof( gamedetect_argv_buffer ) / sizeof( *gamedetect_argv_buffer ) - g_argc - 1; - } - memcpy( gamedetect_argv_buffer + 4, g_argv, sizeof( *gamedetect_argv_buffer ) * g_argc ); - g_argc += argc; - g_argv = gamedetect_argv_buffer; + +void gamedetect_found_game(char const *game, char *path) +{ + int argc; + static char buf[128]; + + if (g_argv == gamedetect_argv_buffer) { + return; + } + + globalOutputStream() << "Detected game " << game << " in " << path << "\n"; + + sprintf(buf, "-%s-EnginePath", game); + argc = 0; + gamedetect_argv_buffer[argc++] = "-global-gamefile"; + gamedetect_argv_buffer[argc++] = game; + gamedetect_argv_buffer[argc++] = buf; + gamedetect_argv_buffer[argc++] = path; + if ((size_t) (argc + g_argc) >= sizeof(gamedetect_argv_buffer) / sizeof(*gamedetect_argv_buffer) - 1) { + g_argc = sizeof(gamedetect_argv_buffer) / sizeof(*gamedetect_argv_buffer) - g_argc - 1; + } + memcpy(gamedetect_argv_buffer + 4, g_argv, sizeof(*gamedetect_argv_buffer) * g_argc); + g_argc += argc; + g_argv = gamedetect_argv_buffer; } -bool gamedetect_check_game( char const *gamefile, const char *checkfile1, const char *checkfile2, char *buf /* must have 64 bytes free after bufpos */, int bufpos ){ - buf[bufpos] = '/'; - - strcpy( buf + bufpos + 1, checkfile1 ); - globalOutputStream() << "Checking for a game file in " << buf << "\n"; - if ( !file_exists( buf ) ) { - return false; - } - - if ( checkfile2 ) { - strcpy( buf + bufpos + 1, checkfile2 ); - globalOutputStream() << "Checking for a game file in " << buf << "\n"; - if ( !file_exists( buf ) ) { - return false; - } - } - - buf[bufpos + 1] = 0; - gamedetect_found_game( gamefile, buf ); - return true; +bool gamedetect_check_game(char const *gamefile, const char *checkfile1, const char *checkfile2, + char *buf /* must have 64 bytes free after bufpos */, int bufpos) +{ + buf[bufpos] = '/'; + + strcpy(buf + bufpos + 1, checkfile1); + globalOutputStream() << "Checking for a game file in " << buf << "\n"; + if (!file_exists(buf)) { + return false; + } + + if (checkfile2) { + strcpy(buf + bufpos + 1, checkfile2); + globalOutputStream() << "Checking for a game file in " << buf << "\n"; + if (!file_exists(buf)) { + return false; + } + } + + buf[bufpos + 1] = 0; + gamedetect_found_game(gamefile, buf); + return true; } -void gamedetect(){ - // if we're inside a Nexuiz install - // default to nexuiz.game (unless the user used an option to inhibit this) - bool nogamedetect = false; - int i; - for ( i = 1; i < g_argc - 1; ++i ) - if ( g_argv[i][0] == '-' ) { - if ( !strcmp( g_argv[i], "-gamedetect" ) ) { - nogamedetect = !strcmp( g_argv[i + 1], "false" ); - } - ++i; - } - if ( !nogamedetect ) { - static char buf[1024 + 64]; - strncpy( buf, environment_get_app_path(), sizeof( buf ) ); - buf[sizeof( buf ) - 1 - 64] = 0; - if ( !strlen( buf ) ) { - return; - } - - char *p = buf + strlen( buf ) - 1; // point directly on the slash of get_app_path - while ( p != buf ) - { - // TODO add more games to this - - // try to detect Nexuiz installs +void gamedetect() +{ + // if we're inside a Nexuiz install + // default to nexuiz.game (unless the user used an option to inhibit this) + bool nogamedetect = false; + int i; + for (i = 1; i < g_argc - 1; ++i) { + if (g_argv[i][0] == '-') { + if (!strcmp(g_argv[i], "-gamedetect")) { + nogamedetect = !strcmp(g_argv[i + 1], "false"); + } + ++i; + } + } + if (!nogamedetect) { + static char buf[1024 + 64]; + strncpy(buf, environment_get_app_path(), sizeof(buf)); + buf[sizeof(buf) - 1 - 64] = 0; + if (!strlen(buf)) { + return; + } + + char *p = buf + strlen(buf) - 1; // point directly on the slash of get_app_path + while (p != buf) { + // TODO add more games to this + + // try to detect Nexuiz installs #if GDEF_OS_WINDOWS - if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz.exe", buf, p - buf ) ) + if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz.exe", buf, p - buf ) ) #elif GDEF_OS_MACOS - if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "Nexuiz.app/Contents/Info.plist", buf, p - buf ) ) + if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "Nexuiz.app/Contents/Info.plist", buf, p - buf ) ) #else - if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz-linux-glx.sh", buf, p - buf ) ) + if (gamedetect_check_game("nexuiz.game", "data/common-spog.pk3", "nexuiz-linux-glx.sh", buf, p - buf)) #endif - { return; } - - // try to detect Quetoo installs - if ( gamedetect_check_game( "quetoo.game", "default/icons/quetoo.png", NULL, buf, p - buf ) ) { - return; - } - - // try to detect Warsow installs - if ( gamedetect_check_game( "warsow.game", "basewsw/dedicated_autoexec.cfg", NULL, buf, p - buf ) ) { - return; - } - - // we found nothing - // go backwards - --p; - while ( p != buf && *p != '/' && *p != '\\' ) - --p; - } - } + { return; } + + // try to detect Quetoo installs + if (gamedetect_check_game("quetoo.game", "default/icons/quetoo.png", NULL, buf, p - buf)) { + return; + } + + // try to detect Warsow installs + if (gamedetect_check_game("warsow.game", "basewsw/dedicated_autoexec.cfg", NULL, buf, p - buf)) { + return; + } + + // we found nothing + // go backwards + --p; + while (p != buf && *p != '/' && *p != '\\') { + --p; + } + } + } } -namespace -{ -CopiedString home_path; -CopiedString app_path; +namespace { + CopiedString home_path; + CopiedString app_path; } -const char* environment_get_home_path(){ - return home_path.c_str(); +const char *environment_get_home_path() +{ + return home_path.c_str(); } -const char* environment_get_app_path(){ - return app_path.c_str(); +const char *environment_get_app_path() +{ + return app_path.c_str(); } -bool portable_app_setup(){ - StringOutputStream confdir( 256 ); - confdir << app_path.c_str() << "settings/"; - if ( file_exists( confdir.c_str() ) ) { - home_path = confdir.c_str(); - return true; - } - return false; +bool portable_app_setup() +{ + StringOutputStream confdir(256); + confdir << app_path.c_str() << "settings/"; + if (file_exists(confdir.c_str())) { + home_path = confdir.c_str(); + return true; + } + return false; } #if GDEF_OS_POSIX @@ -188,69 +198,71 @@ bool portable_app_setup(){ #include -const char* LINK_NAME = +const char *LINK_NAME = #if GDEF_OS_LINUX - "/proc/self/exe" + "/proc/self/exe" #else // FreeBSD and OSX - "/proc/curproc/file" +"/proc/curproc/file" #endif ; /// brief Returns the filename of the executable belonging to the current process, or 0 if not found. -char const* 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; +char const *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 const* 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 ); - - { - char real[PATH_MAX]; - app_path = getexename( real ); - ASSERT_MESSAGE( !string_empty( app_path.c_str() ), "failed to deduce app path" ); - } - - if ( !portable_app_setup() ) { - StringOutputStream home( 256 ); - home << DirectoryCleaned( g_get_user_config_dir() ) << "netradiant/"; - Q_mkdir( home.c_str() ); - home_path = home.c_str(); - } - gamedetect(); +void environment_init(int argc, char const *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); + + { + char real[PATH_MAX]; + app_path = getexename(real); + ASSERT_MESSAGE(!string_empty(app_path.c_str()), "failed to deduce app path"); + } + + if (!portable_app_setup()) { + StringOutputStream home(256); + home << DirectoryCleaned(g_get_user_config_dir()) << "netradiant/"; + Q_mkdir(home.c_str()); + home_path = home.c_str(); + } + gamedetect(); } #elif GDEF_OS_WINDOWS @@ -258,42 +270,42 @@ void environment_init( int argc, char const* argv[] ){ #include void environment_init( int argc, char const* argv[] ){ - args_init( argc, argv ); - - { - // 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(); - } - - if ( !portable_app_setup() ) { - char *appdata = getenv( "APPDATA" ); - StringOutputStream home( 256 ); - if ( !appdata || string_empty( appdata ) ) { - ERROR_MESSAGE( "Application Data folder not available.\n" - "Radiant will use C:\\ for user preferences.\n" ); - home << "C:"; - } - else - { - home << PathCleaned( appdata ); - } - home << "/NetRadiantSettings/"; - Q_mkdir( home.c_str() ); - home_path = home.c_str(); - } - gamedetect(); + args_init( argc, argv ); + + { + // 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(); + } + + if ( !portable_app_setup() ) { + char *appdata = getenv( "APPDATA" ); + StringOutputStream home( 256 ); + if ( !appdata || string_empty( appdata ) ) { + ERROR_MESSAGE( "Application Data folder not available.\n" + "Radiant will use C:\\ for user preferences.\n" ); + home << "C:"; + } + else + { + home << PathCleaned( appdata ); + } + home << "/NetRadiantSettings/"; + Q_mkdir( home.c_str() ); + home_path = home.c_str(); + } + gamedetect(); } #else diff --git a/radiant/environment.h b/radiant/environment.h index b2828f86..173c2abb 100644 --- a/radiant/environment.h +++ b/radiant/environment.h @@ -22,11 +22,13 @@ #if !defined( INCLUDED_ENVIRONMENT_H ) #define INCLUDED_ENVIRONMENT_H -void environment_init( int argc, char const* argv[] ); -const char* environment_get_home_path(); -const char* environment_get_app_path(); +void environment_init(int argc, char const *argv[]); + +const char *environment_get_home_path(); + +const char *environment_get_app_path(); extern int g_argc; -extern char const** g_argv; +extern char const **g_argv; #endif diff --git a/radiant/error.cpp b/radiant/error.cpp index 50a08964..375a9dd6 100644 --- a/radiant/error.cpp +++ b/radiant/error.cpp @@ -34,8 +34,10 @@ #define UNICODE #include #else + #include #include + #endif @@ -54,83 +56,84 @@ if the crash happens before the game is loaded */ -void Error( const char *error, ... ){ - va_list argptr; - char text[4096]; +void Error(const char *error, ...) +{ + va_list argptr; + char text[4096]; - va_start( argptr,error ); - vsprintf( text, error,argptr ); - va_end( argptr ); + va_start(argptr, error); + vsprintf(text, error, argptr); + va_end(argptr); - strcat( text, "\n" ); + strcat(text, "\n"); #if GDEF_OS_WINDOWS - 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 ); - } + 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 ); + } #else - if ( errno != 0 ) { - strcat( text, "errno: " ); - strcat( text, strerror( errno ) ); - strcat( text, "\n" ); - } + if (errno != 0) { + strcat(text, "errno: "); + strcat(text, strerror(errno)); + strcat(text, "\n"); + } #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" ); - } - } + // 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" ); + strcat(text, "An unrecoverable error has occured.\n"); - ERROR_MESSAGE( text ); + ERROR_MESSAGE(text); - // force close logging if necessary - Sys_LogFile( false ); + // force close logging if necessary + Sys_LogFile(false); - _exit( 1 ); + _exit(1); } diff --git a/radiant/error.h b/radiant/error.h index 833908b5..43acdb52 100644 --- a/radiant/error.h +++ b/radiant/error.h @@ -22,6 +22,6 @@ #if !defined( INCLUDED_ERROR_H ) #define INCLUDED_ERROR_H -void Error( const char *error, ... ); +void Error(const char *error, ...); #endif diff --git a/radiant/feedback.cpp b/radiant/feedback.cpp index 33f6552b..00b0023f 100644 --- a/radiant/feedback.cpp +++ b/radiant/feedback.cpp @@ -41,288 +41,294 @@ CDbgDlg g_DbgDlg; -void Feedback_draw2D( VIEWTYPE viewType ){ - g_DbgDlg.draw2D( viewType ); +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( name ), "select" ) ) { - // read the message - ESelectState = SELECT_MESSAGE; - } - else - { - // read the brush - ASSERT_MESSAGE( string_equal( reinterpret_cast( name ), "brush" ), "FEEDBACK PARSE ERROR" ); - ASSERT_MESSAGE( ESelectState == SELECT_MESSAGE, "FEEDBACK PARSE ERROR" ); - ESelectState = SELECT_BRUSH; - globalOutputStream() << message.c_str() << '\n'; - } +void CSelectMsg::saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs) +{ + if (string_equal(reinterpret_cast( name ), "select")) { + // read the message + ESelectState = SELECT_MESSAGE; + } else { + // read the brush + ASSERT_MESSAGE(string_equal(reinterpret_cast( 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( name ), "select" ) ) { - } +void CSelectMsg::saxEndElement(message_info_t *ctx, const xmlChar *name) +{ + if (string_equal(reinterpret_cast( name ), "select")) { + } } -void CSelectMsg::saxCharacters( message_info_t *ctx, const xmlChar *ch, int len ){ - if ( ESelectState == SELECT_MESSAGE ) { - message.write( reinterpret_cast( ch ), len ); - } - else - { - brush.write( reinterpret_cast( ch ), len ); - } +void CSelectMsg::saxCharacters(message_info_t *ctx, const xmlChar *ch, int len) +{ + if (ESelectState == SELECT_MESSAGE) { + message.write(reinterpret_cast( ch ), len); + } else { + brush.write(reinterpret_cast( ch ), len); + } } -IGL2DWindow* CSelectMsg::Highlight(){ - GlobalSelectionSystem().setSelectedAll( false ); - int entitynum, brushnum; - if ( sscanf( reinterpret_cast( brush.c_str() ), "%i %i", &entitynum, &brushnum ) == 2 ) { - SelectBrush( entitynum, brushnum ); - } - return 0; +IGL2DWindow *CSelectMsg::Highlight() +{ + GlobalSelectionSystem().setSelectedAll(false); + int entitynum, brushnum; + if (sscanf(reinterpret_cast( 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( name ), "pointmsg" ) ) { - // read the message - EPointState = POINT_MESSAGE; - } - else - { - // read the brush - ASSERT_MESSAGE( string_equal( reinterpret_cast( name ), "point" ), "FEEDBACK PARSE ERROR" ); - ASSERT_MESSAGE( EPointState == POINT_MESSAGE, "FEEDBACK PARSE ERROR" ); - EPointState = POINT_POINT; - globalOutputStream() << message.c_str() << '\n'; - } +void CPointMsg::saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs) +{ + if (string_equal(reinterpret_cast( name ), "pointmsg")) { + // read the message + EPointState = POINT_MESSAGE; + } else { + // read the brush + ASSERT_MESSAGE(string_equal(reinterpret_cast( 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( name ), "pointmsg" ) ) { - } - else if ( string_equal( reinterpret_cast( name ), "point" ) ) { - sscanf( point.c_str(), "%g %g %g", &( pt[0] ), &( pt[1] ), &( pt[2] ) ); - point.clear(); - } +void CPointMsg::saxEndElement(message_info_t *ctx, const xmlChar *name) +{ + if (string_equal(reinterpret_cast( name ), "pointmsg")) { + } else if (string_equal(reinterpret_cast( 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( ch ), len ); - } - else - { - ASSERT_MESSAGE( EPointState == POINT_POINT, "FEEDBACK PARSE ERROR" ); - point.write( reinterpret_cast( ch ), len ); - } +void CPointMsg::saxCharacters(message_info_t *ctx, const xmlChar *ch, int len) +{ + if (EPointState == POINT_MESSAGE) { + message.write(reinterpret_cast( ch ), len); + } else { + ASSERT_MESSAGE(EPointState == POINT_POINT, "FEEDBACK PARSE ERROR"); + point.write(reinterpret_cast( ch ), len); + } } -IGL2DWindow* CPointMsg::Highlight(){ - return this; +IGL2DWindow *CPointMsg::Highlight() +{ + return this; } -void CPointMsg::DropHighlight(){ +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 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( name ), "windingmsg" ) ) { - // read the message - EPointState = WINDING_MESSAGE; - } - else - { - // read the brush - ASSERT_MESSAGE( string_equal( reinterpret_cast( name ), "winding" ), "FEEDBACK PARSE ERROR" ); - ASSERT_MESSAGE( EPointState == WINDING_MESSAGE, "FEEDBACK PARSE ERROR" ); - EPointState = WINDING_WINDING; - globalOutputStream() << message.c_str() << '\n'; - } +void CWindingMsg::saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs) +{ + if (string_equal(reinterpret_cast( name ), "windingmsg")) { + // read the message + EPointState = WINDING_MESSAGE; + } else { + // read the brush + ASSERT_MESSAGE(string_equal(reinterpret_cast( 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( name ), "windingmsg" ) ) { - } - else if ( string_equal( reinterpret_cast( 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::saxEndElement(message_info_t *ctx, const xmlChar *name) +{ + if (string_equal(reinterpret_cast( name ), "windingmsg")) { + } else if (string_equal(reinterpret_cast( 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( ch ), len ); - } - else - { - ASSERT_MESSAGE( EPointState == WINDING_WINDING, "FEEDBACK PARSE ERROR" ); - winding.write( reinterpret_cast( ch ), len ); - } +void CWindingMsg::saxCharacters(message_info_t *ctx, const xmlChar *ch, int len) +{ + if (EPointState == WINDING_MESSAGE) { + message.write(reinterpret_cast( ch ), len); + } else { + ASSERT_MESSAGE(EPointState == WINDING_WINDING, "FEEDBACK PARSE ERROR"); + winding.write(reinterpret_cast( ch ), len); + } } -IGL2DWindow* CWindingMsg::Highlight(){ - return this; +IGL2DWindow *CWindingMsg::Highlight() +{ + return this; } -void CWindingMsg::DropHighlight(){ +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 ); +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( ui::TreeSelection selection, gpointer data ){ - g_DbgDlg.DropHighlight(); - - GtkTreeModel* model; - GtkTreeIter selected; - if ( gtk_tree_selection_get_selected( selection, &model, &selected ) ) { - auto path = gtk_tree_model_get_path( model, &selected ); - g_DbgDlg.SetHighlight( gtk_tree_path_get_indices( path )[0] ); - gtk_tree_path_free( path ); - } +static void feedback_selection_changed(ui::TreeSelection selection, gpointer data) +{ + g_DbgDlg.DropHighlight(); + + GtkTreeModel *model; + GtkTreeIter selected; + if (gtk_tree_selection_get_selected(selection, &model, &selected)) { + auto 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::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; - } +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( g_ptr_array_index( m_pFeedbackElements, gint( row ) ) ); +ISAXHandler *CDbgDlg::GetElement(std::size_t row) +{ + return static_cast(g_ptr_array_index(m_pFeedbackElements, gint( row )) ); } -void CDbgDlg::Init(){ - DropHighlight(); +void CDbgDlg::Init() +{ + DropHighlight(); - // free all the ISAXHandler*, clean it - while ( m_pFeedbackElements->len ) - { - static_cast( g_ptr_array_index( m_pFeedbackElements, 0 ) )->Release(); - g_ptr_array_remove_index( m_pFeedbackElements, 0 ); - } + // free all the ISAXHandler*, clean it + while (m_pFeedbackElements->len) { + static_cast(g_ptr_array_index(m_pFeedbackElements, 0) )->Release(); + g_ptr_array_remove_index(m_pFeedbackElements, 0); + } - if ( m_clist ) { - m_clist.clear(); - } + if (m_clist) { + m_clist.clear(); + } } -void CDbgDlg::Push( ISAXHandler *pHandler ){ - // push in the list - g_ptr_array_add( m_pFeedbackElements, (void *)pHandler ); +void CDbgDlg::Push(ISAXHandler *pHandler) +{ + // push in the list + g_ptr_array_add(m_pFeedbackElements, (void *) pHandler); - if ( !GetWidget() ) { - Create(); - } + if (!GetWidget()) { + Create(); + } - // put stuff in the list - m_clist.clear(); - for ( std::size_t i = 0; i < static_cast( m_pFeedbackElements->len ); ++i ) - { - m_clist.append(0, GetElement(i)->getName()); - } + // put stuff in the list + m_clist.clear(); + for (std::size_t i = 0; i < static_cast( m_pFeedbackElements->len ); ++i) { + m_clist.append(0, GetElement(i)->getName()); + } - ShowDlg(); + ShowDlg(); } -ui::Window CDbgDlg::BuildDialog(){ - auto window = MainFrame_getWindow().create_floating_window("Q3Map debug window" ); +ui::Window CDbgDlg::BuildDialog() +{ + auto window = MainFrame_getWindow().create_floating_window("Q3Map debug window"); - auto scr = ui::ScrolledWindow(ui::New); - scr.show(); - window.add(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 ); + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + window.add(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); - { - ui::ListStore store = ui::ListStore::from(gtk_list_store_new( 1, G_TYPE_STRING )); + { + ui::ListStore store = ui::ListStore::from(gtk_list_store_new(1, G_TYPE_STRING)); - auto view = ui::TreeView(ui::TreeModel::from(store._handle)); - gtk_tree_view_set_headers_visible(view, FALSE ); + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_headers_visible(view, FALSE); - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn( "", renderer, {{"text", 0}} ); - gtk_tree_view_append_column(view, column ); - } + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("", renderer, {{"text", 0}}); + gtk_tree_view_append_column(view, column); + } - { - auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view )); - gtk_tree_selection_set_mode( selection, GTK_SELECTION_BROWSE ); - selection.connect( "changed", G_CALLBACK( feedback_selection_changed ), NULL ); - } + { + auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); + selection.connect("changed", G_CALLBACK(feedback_selection_changed), NULL); + } - view.show(); + view.show(); - scr.add(view); + scr.add(view); - store.unref(); + store.unref(); - m_clist = store; - } + m_clist = store; + } - return window; + return window; } diff --git a/radiant/feedback.h b/radiant/feedback.h index b683a316..cdb835a0 100644 --- a/radiant/feedback.h +++ b/radiant/feedback.h @@ -36,151 +36,206 @@ // we use these classes to let plugins draw inside the Radiant windows // 2D window like YZ XZ XY -class IGL2DWindow -{ +class IGL2DWindow { public: -virtual ~IGL2DWindow() = default; + virtual ~IGL2DWindow() = default; + // Increment the number of references to this object -virtual void IncRef() = 0; + virtual void IncRef() = 0; + // Decrement the reference count -virtual void DecRef() = 0; -virtual void Draw2D( VIEWTYPE vt ) = 0; + virtual void DecRef() = 0; + + virtual void Draw2D(VIEWTYPE vt) = 0; }; // 3D window -class IGL3DWindow -{ +class IGL3DWindow { public: // Increment the number of references to this object -virtual void IncRef() = 0; + virtual void IncRef() = 0; + // Decrement the reference count -virtual void DecRef() = 0; -virtual void Draw3D() = 0; + 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; +class CSelectMsg : public ISAXHandler { + enum { SELECT_MESSAGE, SELECT_BRUSH } ESelectState; + StringOutputStream message; + StringOutputStream brush; public: -CSelectMsg() { ESelectState = SELECT_MESSAGE; } + 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 ); + 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() { } + 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; +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; } + 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 ); + 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(); + const char *getName() + { return message.c_str(); } + + IGL2DWindow *Highlight(); + + void DropHighlight(); // IGL2DWindow interface -------------------------------- // Increment the number of references to this object -void IncRef() { refCount++; } + void IncRef() + { refCount++; } + // Decrement the reference count -void DecRef() { - refCount--; if ( refCount <= 0 ) { - delete this; - } -} -void Draw2D( VIEWTYPE vt ); + 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; +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; } + 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 ); + 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(); + const char *getName() + { return message.c_str(); } + + IGL2DWindow *Highlight(); + + void DropHighlight(); // IGL2DWindow interface -------------------------------- // Increment the number of references to this object -void IncRef() { refCount++; } + void IncRef() + { refCount++; } + // Decrement the reference count -void DecRef() { - refCount--; if ( refCount <= 0 ) { - delete this; - } -} -void Draw2D( VIEWTYPE vt ); + void DecRef() + { + refCount--; + if (refCount <= 0) { + delete this; + } + } + + void Draw2D(VIEWTYPE vt); }; -class CDbgDlg : public Dialog -{ -GPtrArray *m_pFeedbackElements; +class CDbgDlg : public Dialog { + GPtrArray *m_pFeedbackElements; // the list widget we use in the dialog -ui::ListStore m_clist{ui::null}; -ISAXHandler *m_pHighlight; -IGL2DWindow* m_pDraw2D; + ui::ListStore m_clist{ui::null}; + ISAXHandler *m_pHighlight; + IGL2DWindow *m_pDraw2D; public: -CDbgDlg(){ - m_pFeedbackElements = g_ptr_array_new(); - m_pHighlight = NULL; - m_pDraw2D = NULL; -} + CDbgDlg() + { + m_pFeedbackElements = g_ptr_array_new(); + m_pHighlight = NULL; + m_pDraw2D = NULL; + } + // refresh items -void Push( ISAXHandler * ); + 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() ) { - Destroy(); - } -} + 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()) { + Destroy(); + } + } // void HideDlg(); protected: -ui::Window BuildDialog(); + ui::Window BuildDialog(); }; extern CDbgDlg g_DbgDlg; -void Feedback_draw2D( VIEWTYPE viewType ); +void Feedback_draw2D(VIEWTYPE viewType); #endif diff --git a/radiant/filetypes.cpp b/radiant/filetypes.cpp index 6a08cecd..d8e9cb32 100644 --- a/radiant/filetypes.cpp +++ b/radiant/filetypes.cpp @@ -30,106 +30,124 @@ #include #include -class RadiantFileTypeRegistry : public IFileTypeRegistry -{ -struct filetype_copy_t -{ - filetype_copy_t( const char* moduleName, const filetype_t other ) - : m_can_load( other.can_load ), m_can_import( other.can_import ), m_can_save( other.can_save ), 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(), m_can_load, m_can_save, m_can_import ); - } - bool m_can_load; - bool m_can_import; - bool m_can_save; -private: - CopiedString m_moduleName; - CopiedString m_name; - CopiedString m_pattern; -}; -typedef std::vector filetype_list_t; -std::map m_typelists; +class RadiantFileTypeRegistry : public IFileTypeRegistry { + struct filetype_copy_t { + filetype_copy_t(const char *moduleName, const filetype_t other) + : m_can_load(other.can_load), m_can_import(other.can_import), m_can_save(other.can_save), + 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(), m_can_load, m_can_save, m_can_import); + } + + bool m_can_load; + bool m_can_import; + bool m_can_save; + private: + CopiedString m_moduleName; + CopiedString m_name; + CopiedString m_pattern; + }; + + typedef std::vector filetype_list_t; + std::map 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, bool want_load, bool want_import, bool want_save ){ - filetype_list_t& list_ref = m_typelists[moduleType]; - for ( filetype_list_t::iterator i = list_ref.begin(); i != list_ref.end(); ++i ) - { - if ( want_load && !( *i ).m_can_load ) { - return; - } - if ( want_import && !( *i ).m_can_import ) { - return; - } - if ( want_save && !( *i ).m_can_save ) { - return; - } - typelist->addType( ( *i ).getModuleName(), ( *i ).getType() ); - } -} + 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, bool want_load, bool want_import, bool want_save) + { + filetype_list_t &list_ref = m_typelists[moduleType]; + for (filetype_list_t::iterator i = list_ref.begin(); i != list_ref.end(); ++i) { + if (want_load && !(*i).m_can_load) { + return; + } + if (want_import && !(*i).m_can_import) { + return; + } + if (want_save && !(*i).m_can_save) { + return; + } + typelist->addType((*i).getModuleName(), (*i).getType()); + } + } }; static RadiantFileTypeRegistry g_patterns; -IFileTypeRegistry* GetFileTypeRegistry(){ - return &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(); +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; +class FiletypesAPI { + IFileTypeRegistry *m_filetypes; public: -typedef IFileTypeRegistry Type; -STRING_CONSTANT( Name, "*" ); + typedef IFileTypeRegistry Type; -FiletypesAPI(){ - m_filetypes = GetFileTypeRegistry(); -} -IFileTypeRegistry* getTable(){ - return m_filetypes; -} + STRING_CONSTANT(Name, "*"); + + FiletypesAPI() + { + m_filetypes = GetFileTypeRegistry(); + } + + IFileTypeRegistry *getTable() + { + return m_filetypes; + } }; typedef SingletonModule FiletypesModule; typedef Static StaticFiletypesModule; -StaticRegisterModule staticRegisterFiletypes( StaticFiletypesModule::instance() ); +StaticRegisterModule staticRegisterFiletypes(StaticFiletypesModule::instance()); diff --git a/radiant/filetypes.h b/radiant/filetypes.h index 9e92118a..60cabcad 100644 --- a/radiant/filetypes.h +++ b/radiant/filetypes.h @@ -23,7 +23,9 @@ #define INCLUDED_FILETYPES_H class IFileTypeRegistry; -IFileTypeRegistry* GetFileTypeRegistry(); -const char* findModuleName( IFileTypeRegistry* registry, const char* moduleType, const char* extension ); + +IFileTypeRegistry *GetFileTypeRegistry(); + +const char *findModuleName(IFileTypeRegistry *registry, const char *moduleType, const char *extension); #endif diff --git a/radiant/filters.cpp b/radiant/filters.cpp index 3957af62..e04dd107 100644 --- a/radiant/filters.cpp +++ b/radiant/filters.cpp @@ -37,252 +37,280 @@ #include "commands.h" #include "preferences.h" -struct filters_globals_t -{ - std::size_t exclude; +struct filters_globals_t { + std::size_t exclude; - filters_globals_t() : - exclude( 0 ){ - } + filters_globals_t() : + exclude(0) + { + } }; filters_globals_t g_filters_globals; -inline bool filter_active( int mask ){ - return ( g_filters_globals.exclude & mask ) > 0; +inline bool filter_active(int mask) +{ + return (g_filters_globals.exclude & mask) > 0; } -class FilterWrapper -{ +class FilterWrapper { public: -FilterWrapper( Filter& filter, int mask ) : m_filter( filter ), m_mask( mask ){ -} -void update(){ - m_filter.setActive( filter_active( m_mask ) ); -} + 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; + Filter &m_filter; + int m_mask; }; typedef std::list Filters; Filters g_filters; -typedef std::set Filterables; +typedef std::set 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(); - } - } +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 -{ +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 ); -} + 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; +FilterSystem &GetFilterSystem() +{ + return g_FilterSystem; } -void PerformFiltering(){ - UpdateFilters(); - SceneChangeNotify(); +void PerformFiltering() +{ + UpdateFilters(); + SceneChangeNotify(); } -class ToggleFilterFlag -{ -const unsigned int m_mask; +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 Callback &importCallback ){ - importCallback( ( g_filters_globals.exclude & m_mask ) != 0 ); -} -typedef MemberCaller&), &ToggleFilterFlag::active> ActiveCaller; -void toggle(){ - g_filters_globals.exclude ^= m_mask; - m_item.update(); - PerformFiltering(); -} -void reset(){ - g_filters_globals.exclude = 0; - m_item.update(); - PerformFiltering(); -} -typedef MemberCaller ToggleCaller; + 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 Callback &importCallback) + { + importCallback((g_filters_globals.exclude & m_mask) != 0); + } + + typedef MemberCaller &), &ToggleFilterFlag::active> ActiveCaller; + + void toggle() + { + g_filters_globals.exclude ^= m_mask; + m_item.update(); + PerformFiltering(); + } + + void reset() + { + g_filters_globals.exclude = 0; + m_item.update(); + PerformFiltering(); + } + + typedef MemberCaller ToggleCaller; }; typedef std::list 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 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 InvertFilters(){ - std::list::iterator iter; +void InvertFilters() +{ + std::list::iterator iter; - for ( iter = g_filter_items.begin(); iter != g_filter_items.end(); ++iter ) - { - iter->toggle(); - } + for (iter = g_filter_items.begin(); iter != g_filter_items.end(); ++iter) { + iter->toggle(); + } } -void ResetFilters(){ - std::list::iterator iter; +void ResetFilters() +{ + std::list::iterator iter; - for ( iter = g_filter_items.begin(); iter != g_filter_items.end(); ++iter ) - { - iter->reset(); - } + for (iter = g_filter_items.begin(); iter != g_filter_items.end(); ++iter) { + iter->reset(); + } } -void Filters_constructMenu( ui::Menu 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" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "Decals", "FilterDecals" ); - } - // filter manipulation - menu_separator( menu_in_menu ); - create_menu_item_with_mnemonic( menu_in_menu, "Invert filters", "InvertFilters" ); - create_menu_item_with_mnemonic( menu_in_menu, "Reset filters", "ResetFilters" ); +void Filters_constructMenu(ui::Menu 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"); + create_check_menu_item_with_mnemonic(menu_in_menu, "Decals", "FilterDecals"); + } + // filter manipulation + menu_separator(menu_in_menu); + create_menu_item_with_mnemonic(menu_in_menu, "Invert filters", "InvertFilters"); + create_menu_item_with_mnemonic(menu_in_menu, "Reset filters", "ResetFilters"); } #include "preferencesystem.h" #include "stringio.h" -void ConstructFilters(){ - GlobalPreferenceSystem().registerPreference( "SI_Exclude", make_property_string( g_filters_globals.exclude ) ); - - GlobalCommands_insert( "InvertFilters", makeCallbackF(InvertFilters) ); - GlobalCommands_insert( "ResetFilters", makeCallbackF(ResetFilters) ); - - 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 ) ); - add_filter_command( EXCLUDE_DECALS, "FilterDecals", Accelerator( 'D', (GdkModifierType)GDK_SHIFT_MASK ) ); - } - - PerformFiltering(); +void ConstructFilters() +{ + GlobalPreferenceSystem().registerPreference("SI_Exclude", make_property_string(g_filters_globals.exclude)); + + GlobalCommands_insert("InvertFilters", makeCallbackF(InvertFilters)); + GlobalCommands_insert("ResetFilters", makeCallbackF(ResetFilters)); + + 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)); + add_filter_command(EXCLUDE_DECALS, "FilterDecals", Accelerator('D', (GdkModifierType) GDK_SHIFT_MASK)); + } + + PerformFiltering(); } -void DestroyFilters(){ - g_filters.clear(); +void DestroyFilters() +{ + g_filters.clear(); } #include "modulesystem/singletonmodule.h" #include "modulesystem/moduleregistry.h" -class FilterAPI -{ -FilterSystem* m_filter; +class FilterAPI { + FilterSystem *m_filter; public: -typedef FilterSystem Type; -STRING_CONSTANT( Name, "*" ); + typedef FilterSystem Type; -FilterAPI(){ - ConstructFilters(); + STRING_CONSTANT(Name, "*"); - m_filter = &GetFilterSystem(); -} -~FilterAPI(){ - DestroyFilters(); -} -FilterSystem* getTable(){ - return m_filter; -} + FilterAPI() + { + ConstructFilters(); + + m_filter = &GetFilterSystem(); + } + + ~FilterAPI() + { + DestroyFilters(); + } + + FilterSystem *getTable() + { + return m_filter; + } }; typedef SingletonModule FilterModule; typedef Static StaticFilterModule; -StaticRegisterModule staticRegisterFilter( StaticFilterModule::instance() ); +StaticRegisterModule staticRegisterFilter(StaticFilterModule::instance()); diff --git a/radiant/filters.h b/radiant/filters.h index 9779585a..12c71cd0 100644 --- a/radiant/filters.h +++ b/radiant/filters.h @@ -24,6 +24,6 @@ #if !defined( INCLUDED_FILTERS_H ) #define INCLUDED_FILTERS_H -void Filters_constructMenu( ui::Menu menu_in_menu ); +void Filters_constructMenu(ui::Menu menu_in_menu); #endif diff --git a/radiant/findtexturedialog.cpp b/radiant/findtexturedialog.cpp index d74fc657..2a6c0281 100644 --- a/radiant/findtexturedialog.cpp +++ b/radiant/findtexturedialog.cpp @@ -42,217 +42,243 @@ #include "textureentry.h" - -class FindTextureDialog : public Dialog -{ +class FindTextureDialog : public Dialog { public: -static void setReplaceStr( const char* name ); -static void setFindStr( const char* name ); -static bool isOpen(); -static void show(); -typedef FreeCaller ShowCaller; -static void updateTextures( const char* name ); - -FindTextureDialog(); -virtual ~FindTextureDialog(); -ui::Window BuildDialog(); - -void constructWindow( ui::Window parent ){ - m_parent = parent; - Create(); -} -void destroyWindow(){ - Destroy(); -} + static void setReplaceStr(const char *name); + static void setFindStr(const char *name); -bool m_bSelectedOnly; -CopiedString m_strFind; -CopiedString m_strReplace; -}; + static bool isOpen(); -FindTextureDialog g_FindTextureDialog; -static bool g_bFindActive = true; + static void show(); -namespace -{ -void FindTextureDialog_apply(){ - StringOutputStream find( 256 ); - StringOutputStream replace( 256 ); + typedef FreeCaller ShowCaller; - find << "textures/" << g_FindTextureDialog.m_strFind.c_str(); - replace << "textures/" << g_FindTextureDialog.m_strReplace.c_str(); - FindReplaceTextures( find.c_str(), replace.c_str(), g_FindTextureDialog.m_bSelectedOnly ); -} + static void updateTextures(const char *name); -static void OnApply( ui::Widget widget, gpointer data ){ - g_FindTextureDialog.exportData(); - FindTextureDialog_apply(); -} + FindTextureDialog(); -static void OnFind( ui::Widget widget, gpointer data ){ - g_FindTextureDialog.exportData(); - FindTextureDialog_apply(); -} + virtual ~FindTextureDialog(); -static void OnOK( ui::Widget widget, gpointer data ){ - g_FindTextureDialog.exportData(); - FindTextureDialog_apply(); - g_FindTextureDialog.HideDlg(); -} + ui::Window BuildDialog(); -static void OnClose( ui::Widget widget, gpointer data ){ - g_FindTextureDialog.HideDlg(); -} + void constructWindow(ui::Window parent) + { + m_parent = parent; + Create(); + } + void destroyWindow() + { + Destroy(); + } -static gint find_focus_in( ui::Widget widget, GdkEventFocus *event, gpointer data ){ - g_bFindActive = true; - return FALSE; -} -static gint replace_focus_in( ui::Widget widget, GdkEventFocus *event, gpointer data ){ - g_bFindActive = false; - return FALSE; -} + bool m_bSelectedOnly; + CopiedString m_strFind; + CopiedString m_strReplace; +}; + +FindTextureDialog g_FindTextureDialog; +static bool g_bFindActive = true; + +namespace { + void FindTextureDialog_apply() + { + StringOutputStream find(256); + StringOutputStream replace(256); + + find << "textures/" << g_FindTextureDialog.m_strFind.c_str(); + replace << "textures/" << g_FindTextureDialog.m_strReplace.c_str(); + FindReplaceTextures(find.c_str(), replace.c_str(), g_FindTextureDialog.m_bSelectedOnly); + } + + static void OnApply(ui::Widget widget, gpointer data) + { + g_FindTextureDialog.exportData(); + FindTextureDialog_apply(); + } + + static void OnFind(ui::Widget widget, gpointer data) + { + g_FindTextureDialog.exportData(); + FindTextureDialog_apply(); + } + + static void OnOK(ui::Widget widget, gpointer data) + { + g_FindTextureDialog.exportData(); + FindTextureDialog_apply(); + g_FindTextureDialog.HideDlg(); + } + + static void OnClose(ui::Widget widget, gpointer data) + { + g_FindTextureDialog.HideDlg(); + } + + + static gint find_focus_in(ui::Widget widget, GdkEventFocus *event, gpointer data) + { + g_bFindActive = true; + return FALSE; + } + + static gint replace_focus_in(ui::Widget widget, GdkEventFocus *event, gpointer data) + { + g_bFindActive = false; + return FALSE; + } } // ============================================================================= // FindTextureDialog class -FindTextureDialog::FindTextureDialog(){ - m_bSelectedOnly = FALSE; +FindTextureDialog::FindTextureDialog() +{ + m_bSelectedOnly = FALSE; } -FindTextureDialog::~FindTextureDialog(){ +FindTextureDialog::~FindTextureDialog() +{ } -ui::Window FindTextureDialog::BuildDialog(){ +ui::Window FindTextureDialog::BuildDialog() +{ ui::Widget label{ui::null}; - ui::Widget button{ui::null}; - ui::Entry entry{ui::null}; + ui::Widget button{ui::null}; + ui::Entry entry{ui::null}; - auto dlg = ui::Window(create_floating_window( "Find / Replace Texture(s)", m_parent )); + auto dlg = ui::Window(create_floating_window("Find / Replace Texture(s)", m_parent)); - auto hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - dlg.add(hbox); - gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 ); + auto hbox = ui::HBox(FALSE, 5); + hbox.show(); + dlg.add(hbox); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); - auto vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - hbox.pack_start( vbox, TRUE, TRUE, 0 ); + auto vbox = ui::VBox(FALSE, 5); + vbox.show(); + hbox.pack_start(vbox, TRUE, TRUE, 0); auto table = ui::Table(2, 2, FALSE); - table.show(); - vbox.pack_start( table, TRUE, TRUE, 0 ); + table.show(); + vbox.pack_start(table, TRUE, TRUE, 0); gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5); - label = ui::Label( "Find:" ); - label.show(); + label = ui::Label("Find:"); + label.show(); table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - label = ui::Label( "Replace:" ); - label.show(); + label = ui::Label("Replace:"); + label.show(); table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - entry = ui::Entry(ui::New); - entry.show(); + entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - entry.connect( "focus_in_event", - G_CALLBACK( find_focus_in ), 0 ); - AddDialogData( entry, m_strFind ); - GlobalTextureEntryCompletion::instance().connect( entry ); + entry.connect("focus_in_event", + G_CALLBACK(find_focus_in), 0); + AddDialogData(entry, m_strFind); + GlobalTextureEntryCompletion::instance().connect(entry); - entry = ui::Entry(ui::New); - entry.show(); + entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - entry.connect( "focus_in_event", - G_CALLBACK( replace_focus_in ), 0 ); - AddDialogData( entry, m_strReplace ); - GlobalTextureEntryCompletion::instance().connect( entry ); - - auto check = ui::CheckButton( "Within selected brushes only" ); - check.show(); - vbox.pack_start( check, TRUE, TRUE, 0 ); - AddDialogData( check, m_bSelectedOnly ); - - vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - hbox.pack_start( vbox, FALSE, FALSE, 0 ); - - button = ui::Button( "Apply" ); - button.show(); - vbox.pack_start( button, FALSE, FALSE, 0 ); - button.connect( "clicked", - G_CALLBACK( OnApply ), 0 ); - button.dimensions(60, -1); - - button = ui::Button( "Close" ); - button.show(); - vbox.pack_start( button, FALSE, FALSE, 0 ); - button.connect( "clicked", - G_CALLBACK( OnClose ), 0 ); - button.dimensions(60, -1); - - return dlg; + entry.connect("focus_in_event", + G_CALLBACK(replace_focus_in), 0); + AddDialogData(entry, m_strReplace); + GlobalTextureEntryCompletion::instance().connect(entry); + + auto check = ui::CheckButton("Within selected brushes only"); + check.show(); + vbox.pack_start(check, TRUE, TRUE, 0); + AddDialogData(check, m_bSelectedOnly); + + vbox = ui::VBox(FALSE, 5); + vbox.show(); + hbox.pack_start(vbox, FALSE, FALSE, 0); + + button = ui::Button("Apply"); + button.show(); + vbox.pack_start(button, FALSE, FALSE, 0); + button.connect("clicked", + G_CALLBACK(OnApply), 0); + button.dimensions(60, -1); + + button = ui::Button("Close"); + button.show(); + vbox.pack_start(button, FALSE, FALSE, 0); + button.connect("clicked", + G_CALLBACK(OnClose), 0); + button.dimensions(60, -1); + + return dlg; } -void FindTextureDialog::updateTextures( const char* name ){ - if ( isOpen() ) { - if ( g_bFindActive ) { - setFindStr( name + 9 ); - } - else - { - setReplaceStr( name + 9 ); - } - } +void FindTextureDialog::updateTextures(const char *name) +{ + if (isOpen()) { + if (g_bFindActive) { + setFindStr(name + 9); + } else { + setReplaceStr(name + 9); + } + } } -bool FindTextureDialog::isOpen(){ - return g_FindTextureDialog.GetWidget().visible(); +bool FindTextureDialog::isOpen() +{ + return g_FindTextureDialog.GetWidget().visible(); } -void FindTextureDialog::setFindStr( const char* name ){ - g_FindTextureDialog.exportData(); - g_FindTextureDialog.m_strFind = name; - g_FindTextureDialog.importData(); +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::setReplaceStr(const char *name) +{ + g_FindTextureDialog.exportData(); + g_FindTextureDialog.m_strReplace = name; + g_FindTextureDialog.importData(); } -void FindTextureDialog::show(){ - g_FindTextureDialog.ShowDlg(); +void FindTextureDialog::show() +{ + g_FindTextureDialog.ShowDlg(); } -void FindTextureDialog_constructWindow( ui::Window main_window ){ - g_FindTextureDialog.constructWindow( main_window ); +void FindTextureDialog_constructWindow(ui::Window main_window) +{ + g_FindTextureDialog.constructWindow(main_window); } -void FindTextureDialog_destroyWindow(){ - g_FindTextureDialog.destroyWindow(); +void FindTextureDialog_destroyWindow() +{ + g_FindTextureDialog.destroyWindow(); } -bool FindTextureDialog_isOpen(){ - return g_FindTextureDialog.isOpen(); +bool FindTextureDialog_isOpen() +{ + return g_FindTextureDialog.isOpen(); } -void FindTextureDialog_selectTexture( const char* name ){ - g_FindTextureDialog.updateTextures( name ); +void FindTextureDialog_selectTexture(const char *name) +{ + g_FindTextureDialog.updateTextures(name); } -void FindTextureDialog_Construct(){ - GlobalCommands_insert( "FindReplaceTextures", FindTextureDialog::ShowCaller() ); +void FindTextureDialog_Construct() +{ + GlobalCommands_insert("FindReplaceTextures", FindTextureDialog::ShowCaller()); } -void FindTextureDialog_Destroy(){ +void FindTextureDialog_Destroy() +{ } diff --git a/radiant/findtexturedialog.h b/radiant/findtexturedialog.h index 66022e8b..a367c15b 100644 --- a/radiant/findtexturedialog.h +++ b/radiant/findtexturedialog.h @@ -25,11 +25,15 @@ #define INCLUDED_FINDTEXTUREDIALOG_H void FindTextureDialog_Construct(); + void FindTextureDialog_Destroy(); -void FindTextureDialog_constructWindow( ui::Window main_window ); +void FindTextureDialog_constructWindow(ui::Window main_window); + void FindTextureDialog_destroyWindow(); + bool FindTextureDialog_isOpen(); -void FindTextureDialog_selectTexture( const char* name ); + +void FindTextureDialog_selectTexture(const char *name); #endif diff --git a/radiant/glwidget.cpp b/radiant/glwidget.cpp index 0820d787..7d2904a0 100644 --- a/radiant/glwidget.cpp +++ b/radiant/glwidget.cpp @@ -25,23 +25,26 @@ #include "modulesystem.h" #include "gtkutil/glwidget.h" -class GtkGLAPI -{ -_QERGtkGLTable m_gtkgl; +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; -} + 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" @@ -49,4 +52,4 @@ _QERGtkGLTable* getTable(){ typedef SingletonModule GtkGLModule; typedef Static StaticGtkGLModule; -StaticRegisterModule staticRegisterGtkGL( StaticGtkGLModule::instance() ); +StaticRegisterModule staticRegisterGtkGL(StaticGtkGLModule::instance()); diff --git a/radiant/grid.cpp b/radiant/grid.cpp index df1e1c1a..0c6fd8a2 100644 --- a/radiant/grid.cpp +++ b/radiant/grid.cpp @@ -36,229 +36,267 @@ #include "preferences.h" - Signal0 g_gridChange_callbacks; -void AddGridChangeCallback( const SignalHandler& handler ){ - g_gridChange_callbacks.connectLast( handler ); - handler(); +void AddGridChangeCallback(const SignalHandler &handler) +{ + g_gridChange_callbacks.connectLast(handler); + handler(); } -void GridChangeNotify(){ - g_gridChange_callbacks(); +void GridChangeNotify() +{ + g_gridChange_callbacks(); } -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, +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; +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", + "0.125", + "0.25", + "0.5", + "1", + "2", + "4", + "8", + "16", + "32", + "64", + "128", + "256", }; -inline GridPower GridPower_forGridDefault( int gridDefault ){ - return static_cast( gridDefault - 3 ); +inline GridPower GridPower_forGridDefault(int gridDefault) +{ + return static_cast( gridDefault - 3 ); } -inline int GridDefault_forGridPower( GridPower gridPower ){ - return gridPower + 3; +inline int GridDefault_forGridPower(GridPower gridPower) +{ + return gridPower + 3; } -int g_grid_default = GridDefault_forGridPower( GRIDPOWER_8 ); +int g_grid_default = GridDefault_forGridPower(GRIDPOWER_8); -int g_grid_power = GridPower_forGridDefault( g_grid_default ); +int g_grid_power = GridPower_forGridDefault(g_grid_default); bool g_grid_snap = true; -int Grid_getPower(){ - return g_grid_power; +int Grid_getPower() +{ + return g_grid_power; } -inline float GridSize_forGridPower( int gridPower ){ - return pow( 2.0f, gridPower ); +inline float GridSize_forGridPower(int gridPower) +{ + return pow(2.0f, gridPower); } -float g_gridsize = GridSize_forGridPower( g_grid_power ); +float g_gridsize = GridSize_forGridPower(g_grid_power); -float GetSnapGridSize(){ - return g_grid_snap ? g_gridsize : 0; +float GetSnapGridSize() +{ + return g_grid_snap ? g_gridsize : 0; } -float GetGridSize(){ - return g_gridsize; +float GetGridSize() +{ + return g_gridsize; } -void setGridPower( GridPower power ); +void setGridPower(GridPower power); -class GridMenuItem -{ -GridPower m_id; +class GridMenuItem { + GridPower m_id; -GridMenuItem( const GridMenuItem& other ); // NOT COPYABLE -GridMenuItem& operator=( const GridMenuItem& other ); // NOT ASSIGNABLE + GridMenuItem(const GridMenuItem &other); // NOT COPYABLE + GridMenuItem &operator=(const GridMenuItem &other); // NOT ASSIGNABLE public: -ToggleItem m_item; + 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 SetCaller; -void active( const Callback &importCallback ){ - importCallback( g_grid_power == m_id ); -} -typedef MemberCaller&), &GridMenuItem::active> ExportCaller; + 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 SetCaller; + + void active(const Callback &importCallback) + { + importCallback(g_grid_power == m_id); + } + + typedef MemberCaller &), &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_grid_snap = true; - 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(); +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_grid_snap = true; + 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(){ - g_grid_snap = true; - if ( g_grid_power > GRIDPOWER_0125 ) { - setGridPower( static_cast( --g_grid_power ) ); - } +void GridPrev() +{ + g_grid_snap = true; + if (g_grid_power > GRIDPOWER_0125) { + setGridPower(static_cast( --g_grid_power )); + } } -void GridNext(){ - g_grid_snap = true; - if ( g_grid_power < GRIDPOWER_256 ) { - setGridPower( static_cast( ++g_grid_power ) ); - } +void GridNext() +{ + g_grid_snap = true; + if (g_grid_power < GRIDPOWER_256) { + setGridPower(static_cast( ++g_grid_power )); + } } -void ToggleGridSnap(){ - g_grid_snap = !g_grid_snap; - GridChangeNotify(); +void ToggleGridSnap() +{ + g_grid_snap = !g_grid_snap; + GridChangeNotify(); } -void Grid_registerCommands(){ - GlobalCommands_insert( "GridDown", makeCallbackF(GridPrev), Accelerator( '[' ) ); - GlobalCommands_insert( "GridUp", makeCallbackF(GridNext), Accelerator( ']' ) ); - - GlobalCommands_insert( "ToggleGridSnap", makeCallbackF(ToggleGridSnap) ); - - 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_registerCommands() +{ + GlobalCommands_insert("GridDown", makeCallbackF(GridPrev), Accelerator('[')); + GlobalCommands_insert("GridUp", makeCallbackF(GridNext), Accelerator(']')); + + GlobalCommands_insert("ToggleGridSnap", makeCallbackF(ToggleGridSnap)); + + 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( ui::Menu 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_constructMenu(ui::Menu 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" ); - command_connect_accelerator( "ToggleGridSnap" ); +void Grid_registerShortcuts() +{ + command_connect_accelerator("ToggleGrid"); + command_connect_accelerator("GridDown"); + command_connect_accelerator("GridUp"); + command_connect_accelerator("ToggleGridSnap"); } -void Grid_constructPreferences( PreferencesPage& page ){ - page.appendCombo( - "Default grid spacing", - g_grid_default, - ARRAY_RANGE( g_gridnames ) - ); +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_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Grid", "Grid Settings")); + Grid_constructPreferences(page); } -void Grid_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage( makeCallbackF(Grid_constructPage) ); + +void Grid_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(Grid_constructPage)); } -void Grid_construct(){ - Grid_registerPreferencesPage(); +void Grid_construct() +{ + Grid_registerPreferencesPage(); - g_grid_default = GridDefault_forGridPower( GRIDPOWER_8 ); + g_grid_default = GridDefault_forGridPower(GRIDPOWER_8); - GlobalPreferenceSystem().registerPreference( "GridDefault", make_property_string( g_grid_default ) ); + GlobalPreferenceSystem().registerPreference("GridDefault", make_property_string(g_grid_default)); - g_grid_power = GridPower_forGridDefault( g_grid_default ); - g_gridsize = GridSize_forGridPower( g_grid_power ); + g_grid_power = GridPower_forGridDefault(g_grid_default); + g_gridsize = GridSize_forGridPower(g_grid_power); } -void Grid_destroy(){ +void Grid_destroy() +{ } diff --git a/radiant/grid.h b/radiant/grid.h index d3c28ec2..513f4a02 100644 --- a/radiant/grid.h +++ b/radiant/grid.h @@ -26,17 +26,21 @@ #include "signal/signalfwd.h" float GetSnapGridSize(); + float GetGridSize(); + int Grid_getPower(); -void AddGridChangeCallback( const SignalHandler& handler ); +void AddGridChangeCallback(const SignalHandler &handler); void Grid_registerCommands(); -void Grid_constructMenu( ui::Menu menu ); + +void Grid_constructMenu(ui::Menu menu); void Grid_registerShortcuts(); void Grid_construct(); + void Grid_destroy(); #endif diff --git a/radiant/groupdialog.cpp b/radiant/groupdialog.cpp index 1be74bf7..0da79fb3 100644 --- a/radiant/groupdialog.cpp +++ b/radiant/groupdialog.cpp @@ -45,159 +45,188 @@ #include "gtkutil/window.h" -class GroupDlg -{ +class GroupDlg { public: -ui::Widget m_pNotebook{ui::null}; -ui::Window m_window{ui::null}; + ui::Widget m_pNotebook{ui::null}; + ui::Window m_window{ui::null}; -GroupDlg(); -void Create( ui::Window parent ); + GroupDlg(); -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 ); - m_window.show(); -} -void Hide(){ - m_window.hide(); -} + void Create(ui::Window 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); + m_window.show(); + } -WindowPositionTracker m_position_tracker; + void Hide() + { + m_window.hide(); + } + + WindowPositionTracker m_position_tracker; }; -namespace -{ -GroupDlg g_GroupDlg; +namespace { + GroupDlg g_GroupDlg; -std::size_t g_current_page; -std::vector &)>> g_pages; + std::size_t g_current_page; + std::vector &)>> g_pages; } -void GroupDialog_updatePageTitle( ui::Window window, std::size_t pageIndex ){ - if ( pageIndex < g_pages.size() ) { - g_pages[pageIndex]( PointerCaller( window ) ); - } +void GroupDialog_updatePageTitle(ui::Window window, std::size_t pageIndex) +{ + if (pageIndex < g_pages.size()) { + g_pages[pageIndex](PointerCaller(window)); + } } -static gboolean switch_page( GtkNotebook *notebook, gpointer page, guint page_num, gpointer data ){ - GroupDialog_updatePageTitle( ui::Window::from(data), page_num ); - g_current_page = page_num; +static gboolean switch_page(GtkNotebook *notebook, gpointer page, guint page_num, gpointer data) +{ + GroupDialog_updatePageTitle(ui::Window::from(data), page_num); + g_current_page = page_num; - return FALSE; + return FALSE; } -GroupDlg::GroupDlg() : m_window( ui::null ){ - m_position_tracker.setPosition( c_default_window_pos ); +GroupDlg::GroupDlg() : m_window(ui::null) +{ + m_position_tracker.setPosition(c_default_window_pos); } -void GroupDlg::Create( ui::Window parent ){ - ASSERT_MESSAGE( !m_window, "dialog already created" ); +void GroupDlg::Create(ui::Window parent) +{ + ASSERT_MESSAGE(!m_window, "dialog already created"); - auto window = ui::Window(create_persistent_floating_window( "Entities", parent )); + auto window = ui::Window(create_persistent_floating_window("Entities", parent)); - global_accel_connect_window( window ); + global_accel_connect_window(window); - window_connect_focus_in_clear_focus_widget( window ); + window_connect_focus_in_clear_focus_widget(window); - m_window = window; + m_window = window; #if GDEF_OS_WINDOWS - if ( g_multimon_globals.m_bStartOnPrimMon ) { - WindowPosition pos( m_position_tracker.getPosition() ); - PositionWindowOnPrimaryScreen( pos ); - m_position_tracker.setPosition( pos ); - } + 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 ); + m_position_tracker.connect(window); - { - ui::Widget notebook = ui::Widget::from(gtk_notebook_new()); - notebook.show(); - window.add(notebook); - gtk_notebook_set_tab_pos( GTK_NOTEBOOK( notebook ), GTK_POS_BOTTOM ); - m_pNotebook = notebook; + { + ui::Widget notebook = ui::Widget::from(gtk_notebook_new()); + notebook.show(); + window.add(notebook); + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_BOTTOM); + m_pNotebook = notebook; - notebook.connect( "switch_page", G_CALLBACK( switch_page ), (gpointer) window ); - } + notebook.connect("switch_page", G_CALLBACK(switch_page), (gpointer) window); + } } -ui::Widget GroupDialog_addPage( const char* tabLabel, ui::Widget widget, const Callback &)>& title ){ - ui::Widget w = ui::Label( tabLabel ); - w.show(); - auto page = ui::Widget::from(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 ); +ui::Widget GroupDialog_addPage(const char *tabLabel, ui::Widget widget, + const Callback &)> &title) +{ + ui::Widget w = ui::Label(tabLabel); + w.show(); + auto page = ui::Widget::from(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; + return page; } -bool GroupDialog_isShown(){ - return g_GroupDlg.m_window.visible(); +bool GroupDialog_isShown() +{ + return g_GroupDlg.m_window.visible(); } -void GroupDialog_setShown( bool shown ){ - shown ? g_GroupDlg.Show() : g_GroupDlg.Hide(); + +void GroupDialog_setShown(bool shown) +{ + shown ? g_GroupDlg.Show() : g_GroupDlg.Hide(); } -void GroupDialog_ToggleShow(){ - GroupDialog_setShown( !GroupDialog_isShown() ); + +void GroupDialog_ToggleShow() +{ + GroupDialog_setShown(!GroupDialog_isShown()); } -void GroupDialog_constructWindow( ui::Window main_window ){ - g_GroupDlg.Create( main_window ); +void GroupDialog_constructWindow(ui::Window main_window) +{ + g_GroupDlg.Create(main_window); } -void GroupDialog_destroyWindow(){ - ASSERT_TRUE( g_GroupDlg.m_window ); - destroy_floating_window( g_GroupDlg.m_window ); - g_GroupDlg.m_window = ui::Window{ui::null}; + +void GroupDialog_destroyWindow() +{ + ASSERT_TRUE(g_GroupDlg.m_window); + destroy_floating_window(g_GroupDlg.m_window); + g_GroupDlg.m_window = ui::Window{ui::null}; } -ui::Window GroupDialog_getWindow(){ - return ui::Window(g_GroupDlg.m_window); +ui::Window GroupDialog_getWindow() +{ + return ui::Window(g_GroupDlg.m_window); } -void GroupDialog_show(){ - g_GroupDlg.Show(); + +void GroupDialog_show() +{ + g_GroupDlg.Show(); } -ui::Widget GroupDialog_getPage(){ - return ui::Widget::from(gtk_notebook_get_nth_page( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), gint( g_current_page ) )); +ui::Widget GroupDialog_getPage() +{ + return ui::Widget::from(gtk_notebook_get_nth_page(GTK_NOTEBOOK(g_GroupDlg.m_pNotebook), gint(g_current_page))); } -void GroupDialog_setPage( ui::Widget 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_setPage(ui::Widget 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( ui::Widget page ){ - if ( GroupDialog_getPage() == page ) { - GroupDialog_ToggleShow(); - } - else - { - g_GroupDlg.m_window.show(); - GroupDialog_setPage( page ); - } +void GroupDialog_showPage(ui::Widget page) +{ + if (GroupDialog_getPage() == page) { + GroupDialog_ToggleShow(); + } else { + g_GroupDlg.m_window.show(); + 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_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( ui::Widget page ){ - if ( GroupDialog_getPage() == page ) { - GroupDialog_updatePageTitle( g_GroupDlg.m_window, g_current_page ); - } +void GroupDialog_updatePageTitle(ui::Widget page) +{ + if (GroupDialog_getPage() == page) { + GroupDialog_updatePageTitle(g_GroupDlg.m_window, g_current_page); + } } #include "preferencesystem.h" -void GroupDialog_Construct(){ - GlobalPreferenceSystem().registerPreference( "EntityWnd", make_property( g_GroupDlg.m_position_tracker ) ); +void GroupDialog_Construct() +{ + GlobalPreferenceSystem().registerPreference("EntityWnd", make_property( + g_GroupDlg.m_position_tracker)); - GlobalCommands_insert( "ViewEntityInfo", makeCallbackF(GroupDialog_ToggleShow), Accelerator( 'N' ) ); + GlobalCommands_insert("ViewEntityInfo", makeCallbackF(GroupDialog_ToggleShow), Accelerator('N')); } -void GroupDialog_Destroy(){ + +void GroupDialog_Destroy() +{ } diff --git a/radiant/groupdialog.h b/radiant/groupdialog.h index f136f382..63f36a02 100644 --- a/radiant/groupdialog.h +++ b/radiant/groupdialog.h @@ -27,22 +27,33 @@ #include "generic/callback.h" void GroupDialog_Construct(); + void GroupDialog_Destroy(); -void GroupDialog_constructWindow( ui::Window main_window ); +void GroupDialog_constructWindow(ui::Window main_window); + void GroupDialog_destroyWindow(); + ui::Window GroupDialog_getWindow(); + void GroupDialog_show(); -inline void RawStringExport( const char* string, const Callback &importer ){ - importer( string ); +inline void RawStringExport(const char *string, const Callback &importer) +{ + importer(string); } + typedef ConstPointerCaller &), RawStringExport> RawStringExportCaller; -ui::Widget GroupDialog_addPage( const char* tabLabel, ui::Widget widget, const Callback &)>& title ); -void GroupDialog_showPage( ui::Widget page ); -void GroupDialog_updatePageTitle( ui::Widget page ); +ui::Widget GroupDialog_addPage(const char *tabLabel, ui::Widget widget, + const Callback &)> &title); + +void GroupDialog_showPage(ui::Widget page); + +void GroupDialog_updatePageTitle(ui::Widget page); + bool GroupDialog_isShown(); + ui::Widget GroupDialog_getPage(); #endif diff --git a/radiant/gtkdlgs.cpp b/radiant/gtkdlgs.cpp index a7e3fbce..286bb076 100644 --- a/radiant/gtkdlgs.cpp +++ b/radiant/gtkdlgs.cpp @@ -75,484 +75,494 @@ // ============================================================================= // Project settings dialog -class GameComboConfiguration -{ +class GameComboConfiguration { public: -const char* basegame_dir; -const char* basegame; -const char* known_dir; -const char* known; -const char* custom; - -GameComboConfiguration() : - basegame_dir( g_pGameDescription->getRequiredKeyValue( "basegame" ) ), - basegame( g_pGameDescription->getRequiredKeyValue( "basegamename" ) ), - known_dir( g_pGameDescription->getKeyValue( "knowngame" ) ), - known( g_pGameDescription->getKeyValue( "knowngamename" ) ), - custom( g_pGameDescription->getRequiredKeyValue( "unknowngamename" ) ){ -} + const char *basegame_dir; + const char *basegame; + const char *known_dir; + const char *known; + const char *custom; + + GameComboConfiguration() : + basegame_dir(g_pGameDescription->getRequiredKeyValue("basegame")), + basegame(g_pGameDescription->getRequiredKeyValue("basegamename")), + known_dir(g_pGameDescription->getKeyValue("knowngame")), + known(g_pGameDescription->getKeyValue("knowngamename")), + custom(g_pGameDescription->getRequiredKeyValue("unknowngamename")) + { + } }; typedef LazyStatic LazyStaticGameComboConfiguration; -inline GameComboConfiguration& globalGameComboConfiguration(){ - return LazyStaticGameComboConfiguration::instance(); +inline GameComboConfiguration &globalGameComboConfiguration() +{ + return LazyStaticGameComboConfiguration::instance(); } -struct gamecombo_t -{ - gamecombo_t( int _game, const char* _fs_game, bool _sensitive ) - : game( _game ), fs_game( _fs_game ), sensitive( _sensitive ) - {} - int game; - const char* fs_game; - bool sensitive; +struct gamecombo_t { + gamecombo_t(int _game, const char *_fs_game, bool _sensitive) + : game(_game), fs_game(_fs_game), sensitive(_sensitive) + {} + + int game; + const char *fs_game; + bool sensitive; }; -gamecombo_t gamecombo_for_dir( const char* dir ){ - if ( string_equal( dir, globalGameComboConfiguration().basegame_dir ) ) { - return gamecombo_t( 0, "", false ); - } - else if ( string_equal( dir, globalGameComboConfiguration().known_dir ) ) { - return gamecombo_t( 1, dir, false ); - } - else - { - return gamecombo_t( string_empty( globalGameComboConfiguration().known_dir ) ? 1 : 2, dir, true ); - } +gamecombo_t gamecombo_for_dir(const char *dir) +{ + if (string_equal(dir, globalGameComboConfiguration().basegame_dir)) { + return gamecombo_t(0, "", false); + } else if (string_equal(dir, globalGameComboConfiguration().known_dir)) { + return gamecombo_t(1, dir, false); + } else { + return gamecombo_t(string_empty(globalGameComboConfiguration().known_dir) ? 1 : 2, dir, true); + } } -gamecombo_t gamecombo_for_gamename( const char* gamename ){ - if ( ( strlen( gamename ) == 0 ) || !strcmp( gamename, globalGameComboConfiguration().basegame ) ) { - return gamecombo_t( 0, "", false ); - } - else if ( !strcmp( gamename, globalGameComboConfiguration().known ) ) { - return gamecombo_t( 1, globalGameComboConfiguration().known_dir, false ); - } - else - { - return gamecombo_t( string_empty( globalGameComboConfiguration().known_dir ) ? 1 : 2, "", true ); - } +gamecombo_t gamecombo_for_gamename(const char *gamename) +{ + if ((strlen(gamename) == 0) || !strcmp(gamename, globalGameComboConfiguration().basegame)) { + return gamecombo_t(0, "", false); + } else if (!strcmp(gamename, globalGameComboConfiguration().known)) { + return gamecombo_t(1, globalGameComboConfiguration().known_dir, false); + } else { + return gamecombo_t(string_empty(globalGameComboConfiguration().known_dir) ? 1 : 2, "", true); + } } -inline void path_copy_clean( char* destination, const char* source ){ - char* i = destination; +inline void path_copy_clean(char *destination, const char *source) +{ + char *i = destination; - while ( *source != '\0' ) - { - *i++ = ( *source == '\\' ) ? '/' : *source; - ++source; - } + while (*source != '\0') { + *i++ = (*source == '\\') ? '/' : *source; + ++source; + } - if ( i != destination && *( i - 1 ) != '/' ) { - *( i++ ) = '/'; - } + if (i != destination && *(i - 1) != '/') { + *(i++) = '/'; + } - *i = '\0'; + *i = '\0'; } -struct GameCombo -{ - ui::ComboBoxText game_select{ui::null}; - ui::Entry fsgame_entry{ui::null}; +struct GameCombo { + ui::ComboBoxText game_select{ui::null}; + ui::Entry fsgame_entry{ui::null}; }; -gboolean OnSelchangeComboWhatgame( ui::Widget widget, GameCombo* combo ){ - const char *gamename; - { - GtkTreeIter iter; - gtk_combo_box_get_active_iter( combo->game_select, &iter ); - gtk_tree_model_get( gtk_combo_box_get_model( combo->game_select ), &iter, 0, (gpointer*)&gamename, -1 ); - } +gboolean OnSelchangeComboWhatgame(ui::Widget widget, GameCombo *combo) +{ + const char *gamename; + { + GtkTreeIter iter; + gtk_combo_box_get_active_iter(combo->game_select, &iter); + gtk_tree_model_get(gtk_combo_box_get_model(combo->game_select), &iter, 0, (gpointer *) &gamename, -1); + } - gamecombo_t gamecombo = gamecombo_for_gamename( gamename ); + gamecombo_t gamecombo = gamecombo_for_gamename(gamename); - combo->fsgame_entry.text( gamecombo.fs_game ); - gtk_widget_set_sensitive( combo->fsgame_entry , gamecombo.sensitive ); + combo->fsgame_entry.text(gamecombo.fs_game); + gtk_widget_set_sensitive(combo->fsgame_entry, gamecombo.sensitive); - return FALSE; + return FALSE; } -class MappingMode -{ +class MappingMode { public: -bool do_mapping_mode; -const char* sp_mapping_mode; -const char* mp_mapping_mode; - -MappingMode() : - do_mapping_mode( !string_empty( g_pGameDescription->getKeyValue( "show_gamemode" ) ) ), - sp_mapping_mode( "Single Player mapping mode" ), - mp_mapping_mode( "Multiplayer mapping mode" ){ -} + bool do_mapping_mode; + const char *sp_mapping_mode; + const char *mp_mapping_mode; + + MappingMode() : + do_mapping_mode(!string_empty(g_pGameDescription->getKeyValue("show_gamemode"))), + sp_mapping_mode("Single Player mapping mode"), + mp_mapping_mode("Multiplayer mapping mode") + { + } }; typedef LazyStatic LazyStaticMappingMode; -inline MappingMode& globalMappingMode(){ - return LazyStaticMappingMode::instance(); +inline MappingMode &globalMappingMode() +{ + return LazyStaticMappingMode::instance(); } -class ProjectSettingsDialog -{ +class ProjectSettingsDialog { public: -GameCombo game_combo; -ui::ComboBox gamemode_combo{ui::null}; + GameCombo game_combo; + ui::ComboBox gamemode_combo{ui::null}; }; -ui::Window ProjectSettingsDialog_construct( ProjectSettingsDialog& dialog, ModalDialog& modal ){ - auto window = MainFrame_getWindow().create_dialog_window("Project Settings", G_CALLBACK(dialog_delete_callback ), &modal ); - - { - auto table1 = create_dialog_table( 1, 2, 4, 4, 4 ); - window.add(table1); - { - auto vbox = create_dialog_vbox( 4 ); +ui::Window ProjectSettingsDialog_construct(ProjectSettingsDialog &dialog, ModalDialog &modal) +{ + auto window = MainFrame_getWindow().create_dialog_window("Project Settings", G_CALLBACK(dialog_delete_callback), + &modal); + + { + auto table1 = create_dialog_table(1, 2, 4, 4, 4); + window.add(table1); + { + auto vbox = create_dialog_vbox(4); table1.attach(vbox, {1, 2, 0, 1}, {GTK_FILL, GTK_FILL}); - { - auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &modal ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - } - { - auto button = create_dialog_button( "Cancel", G_CALLBACK( dialog_button_cancel ), &modal ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - } - } - { - auto frame = create_dialog_frame( "Project settings" ); + { + auto button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &modal); + vbox.pack_start(button, FALSE, FALSE, 0); + } + { + auto button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &modal); + vbox.pack_start(button, FALSE, FALSE, 0); + } + } + { + auto frame = create_dialog_frame("Project settings"); table1.attach(frame, {0, 1, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL}); - { - auto table2 = create_dialog_table( ( globalMappingMode().do_mapping_mode ) ? 4 : 3, 2, 4, 4, 4 ); - frame.add(table2); + { + auto table2 = create_dialog_table((globalMappingMode().do_mapping_mode) ? 4 : 3, 2, 4, 4, 4); + frame.add(table2); - { - auto label = ui::Label( "Select mod" ); - label.show(); + { + auto label = ui::Label("Select mod"); + label.show(); table2.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - } - { - dialog.game_combo.game_select = ui::ComboBoxText(ui::New); - - gtk_combo_box_text_append_text( dialog.game_combo.game_select, globalGameComboConfiguration().basegame ); - if ( globalGameComboConfiguration().known[0] != '\0' ) { - gtk_combo_box_text_append_text( dialog.game_combo.game_select, globalGameComboConfiguration().known ); - } - gtk_combo_box_text_append_text( dialog.game_combo.game_select, globalGameComboConfiguration().custom ); - - dialog.game_combo.game_select.show(); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + } + { + dialog.game_combo.game_select = ui::ComboBoxText(ui::New); + + gtk_combo_box_text_append_text(dialog.game_combo.game_select, + globalGameComboConfiguration().basegame); + if (globalGameComboConfiguration().known[0] != '\0') { + gtk_combo_box_text_append_text(dialog.game_combo.game_select, + globalGameComboConfiguration().known); + } + gtk_combo_box_text_append_text(dialog.game_combo.game_select, + globalGameComboConfiguration().custom); + + dialog.game_combo.game_select.show(); table2.attach(dialog.game_combo.game_select, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - dialog.game_combo.game_select.connect( "changed", G_CALLBACK( OnSelchangeComboWhatgame ), &dialog.game_combo ); - } + dialog.game_combo.game_select.connect("changed", G_CALLBACK(OnSelchangeComboWhatgame), + &dialog.game_combo); + } - { - auto label = ui::Label( "fs_game" ); - label.show(); + { + auto label = ui::Label("fs_game"); + label.show(); table2.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table2.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - dialog.game_combo.fsgame_entry = entry; - } + dialog.game_combo.fsgame_entry = entry; + } - if ( globalMappingMode().do_mapping_mode ) { - auto label = ui::Label( "Mapping mode" ); - label.show(); + if (globalMappingMode().do_mapping_mode) { + auto label = ui::Label("Mapping mode"); + label.show(); table2.attach(label, {0, 1, 3, 4}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); - auto combo = ui::ComboBoxText(ui::New); - gtk_combo_box_text_append_text( combo, globalMappingMode().sp_mapping_mode ); - gtk_combo_box_text_append_text( combo, globalMappingMode().mp_mapping_mode ); + auto combo = ui::ComboBoxText(ui::New); + gtk_combo_box_text_append_text(combo, globalMappingMode().sp_mapping_mode); + gtk_combo_box_text_append_text(combo, globalMappingMode().mp_mapping_mode); - combo.show(); + combo.show(); table2.attach(combo, {1, 2, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); - dialog.gamemode_combo = combo; - } - } - } - } - - // initialise the fs_game selection from the project settings into the dialog - const char* dir = gamename_get(); - gamecombo_t gamecombo = gamecombo_for_dir( dir ); - - gtk_combo_box_set_active( dialog.game_combo.game_select, gamecombo.game ); - dialog.game_combo.fsgame_entry.text( gamecombo.fs_game ); - gtk_widget_set_sensitive( dialog.game_combo.fsgame_entry , gamecombo.sensitive ); - - if ( globalMappingMode().do_mapping_mode ) { - const char *gamemode = gamemode_get(); - if ( string_empty( gamemode ) || string_equal( gamemode, "sp" ) ) { - gtk_combo_box_set_active( dialog.gamemode_combo, 0 ); - } - else - { - gtk_combo_box_set_active( dialog.gamemode_combo, 1 ); - } - } - - return window; + dialog.gamemode_combo = combo; + } + } + } + } + + // initialise the fs_game selection from the project settings into the dialog + const char *dir = gamename_get(); + gamecombo_t gamecombo = gamecombo_for_dir(dir); + + gtk_combo_box_set_active(dialog.game_combo.game_select, gamecombo.game); + dialog.game_combo.fsgame_entry.text(gamecombo.fs_game); + gtk_widget_set_sensitive(dialog.game_combo.fsgame_entry, gamecombo.sensitive); + + if (globalMappingMode().do_mapping_mode) { + const char *gamemode = gamemode_get(); + if (string_empty(gamemode) || string_equal(gamemode, "sp")) { + gtk_combo_box_set_active(dialog.gamemode_combo, 0); + } else { + gtk_combo_box_set_active(dialog.gamemode_combo, 1); + } + } + + return window; } -void ProjectSettingsDialog_ok( ProjectSettingsDialog& dialog ){ - const char* dir = gtk_entry_get_text( dialog.game_combo.fsgame_entry ); +void ProjectSettingsDialog_ok(ProjectSettingsDialog &dialog) +{ + const char *dir = gtk_entry_get_text(dialog.game_combo.fsgame_entry); - const char* new_gamename = path_equal( dir, globalGameComboConfiguration().basegame_dir ) - ? "" - : dir; + const char *new_gamename = path_equal(dir, globalGameComboConfiguration().basegame_dir) + ? "" + : dir; - if ( !path_equal( new_gamename, gamename_get() ) ) { - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Changing Game Name" ); + if (!path_equal(new_gamename, gamename_get())) { + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Changing Game Name"); - EnginePath_Unrealise(); + EnginePath_Unrealise(); - gamename_set( new_gamename ); + gamename_set(new_gamename); - EnginePath_Realise(); - } + EnginePath_Realise(); + } - if ( globalMappingMode().do_mapping_mode ) { - // read from gamemode_combo - int active = gtk_combo_box_get_active( dialog.gamemode_combo ); - if ( active == -1 || active == 0 ) { - gamemode_set( "sp" ); - } - else - { - gamemode_set( "mp" ); - } - } + if (globalMappingMode().do_mapping_mode) { + // read from gamemode_combo + int active = gtk_combo_box_get_active(dialog.gamemode_combo); + if (active == -1 || active == 0) { + gamemode_set("sp"); + } else { + gamemode_set("mp"); + } + } } -void DoProjectSettings(){ - if ( ConfirmModified( "Edit Project Settings" ) ) { - ModalDialog modal; - ProjectSettingsDialog dialog; +void DoProjectSettings() +{ + if (ConfirmModified("Edit Project Settings")) { + ModalDialog modal; + ProjectSettingsDialog dialog; - ui::Window window = ProjectSettingsDialog_construct( dialog, modal ); + ui::Window window = ProjectSettingsDialog_construct(dialog, modal); - if ( modal_dialog_show( window, modal ) == eIDOK ) { - ProjectSettingsDialog_ok( dialog ); - } + if (modal_dialog_show(window, modal) == eIDOK) { + ProjectSettingsDialog_ok(dialog); + } - window.destroy(); - } + window.destroy(); + } } // ============================================================================= // Arbitrary Sides dialog -void DoSides( int type, int axis ){ - ModalDialog dialog; - - auto window = MainFrame_getWindow().create_dialog_window("Arbitrary sides", G_CALLBACK(dialog_delete_callback ), &dialog ); - - auto accel = ui::AccelGroup(ui::New); - window.add_accel_group( accel ); - - auto sides_entry = ui::Entry(ui::New); - { - auto hbox = create_dialog_hbox( 4, 4 ); - window.add(hbox); - { - auto label = ui::Label( "Sides:" ); - label.show(); - hbox.pack_start( label, FALSE, FALSE, 0 ); - } - { - auto entry = sides_entry; - entry.show(); - hbox.pack_start( entry, FALSE, FALSE, 0 ); - gtk_widget_grab_focus( entry ); - } - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, TRUE, TRUE, 0 ); - { - auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - { - auto button = create_dialog_button( "Cancel", G_CALLBACK( dialog_button_cancel ), &dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - } - } - - if ( modal_dialog_show( window, dialog ) == eIDOK ) { - const char *str = gtk_entry_get_text( sides_entry ); - - Scene_BrushConstructPrefab( GlobalSceneGraph(), (EBrushPrefab)type, atoi( str ), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); - } - - window.destroy(); +void DoSides(int type, int axis) +{ + ModalDialog dialog; + + auto window = MainFrame_getWindow().create_dialog_window("Arbitrary sides", G_CALLBACK(dialog_delete_callback), + &dialog); + + auto accel = ui::AccelGroup(ui::New); + window.add_accel_group(accel); + + auto sides_entry = ui::Entry(ui::New); + { + auto hbox = create_dialog_hbox(4, 4); + window.add(hbox); + { + auto label = ui::Label("Sides:"); + label.show(); + hbox.pack_start(label, FALSE, FALSE, 0); + } + { + auto entry = sides_entry; + entry.show(); + hbox.pack_start(entry, FALSE, FALSE, 0); + gtk_widget_grab_focus(entry); + } + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, TRUE, TRUE, 0); + { + auto button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + { + auto button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + } + } + + if (modal_dialog_show(window, dialog) == eIDOK) { + const char *str = gtk_entry_get_text(sides_entry); + + Scene_BrushConstructPrefab(GlobalSceneGraph(), (EBrushPrefab) type, atoi(str), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); + } + + window.destroy(); } // ============================================================================= // About dialog (no program is complete without one) -void about_button_changelog( ui::Widget widget, gpointer data ){ - StringOutputStream log( 256 ); - log << "https://gitlab.com/xonotic/netradiant/commits/master"; - OpenURL( log.c_str() ); +void about_button_changelog(ui::Widget widget, gpointer data) +{ + StringOutputStream log(256); + log << "https://gitlab.com/xonotic/netradiant/commits/master"; + OpenURL(log.c_str()); } -void about_button_credits( ui::Widget widget, gpointer data ){ - StringOutputStream cred( 256 ); - cred << "https://gitlab.com/xonotic/netradiant/graphs/master"; - OpenURL( cred.c_str() ); +void about_button_credits(ui::Widget widget, gpointer data) +{ + StringOutputStream cred(256); + cred << "https://gitlab.com/xonotic/netradiant/graphs/master"; + OpenURL(cred.c_str()); } -void about_button_issues( ui::Widget widget, gpointer data ){ - StringOutputStream cred( 256 ); - cred << "https://gitlab.com/xonotic/netradiant/issues"; - OpenURL( cred.c_str() ); +void about_button_issues(ui::Widget widget, gpointer data) +{ + StringOutputStream cred(256); + cred << "https://gitlab.com/xonotic/netradiant/issues"; + OpenURL(cred.c_str()); } -void DoAbout(){ - ModalDialog dialog; - ModalDialogButton ok_button( dialog, eIDOK ); - - auto window = MainFrame_getWindow().create_modal_dialog_window("About NetRadiant", dialog ); - - { - auto vbox = create_dialog_vbox( 4, 4 ); - window.add(vbox); - - { - auto hbox = create_dialog_hbox( 4 ); - vbox.pack_start( hbox, FALSE, TRUE, 0 ); - - { - auto vbox2 = create_dialog_vbox( 4 ); - hbox.pack_start( vbox2, TRUE, FALSE, 0 ); - { - auto frame = create_dialog_frame( 0, ui::Shadow::IN ); - vbox2.pack_start( frame, FALSE, FALSE, 0 ); - { - auto image = new_local_image( "logo.png" ); - image.show(); - frame.add(image); - } - } - } - - { - char const *label_text = "NetRadiant " RADIANT_VERSION "\n" - __DATE__ "\n\n" - RADIANT_ABOUTMSG "\n\n" - "This program is free software\n" - "licensed under the GNU GPL.\n\n" - "NetRadiant is unsupported, however\n" - "you may report your problems at\n" - "https://gitlab.com/xonotic/netradiant/issues"; - - auto label = ui::Label( label_text ); - - label.show(); - hbox.pack_start( label, FALSE, FALSE, 0 ); - gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); - gtk_label_set_justify( label, GTK_JUSTIFY_LEFT ); - } - - { - auto vbox2 = create_dialog_vbox( 4 ); - hbox.pack_start( vbox2, FALSE, TRUE, 0 ); - { - auto button = create_modal_dialog_button( "OK", ok_button ); - vbox2.pack_start( button, FALSE, FALSE, 0 ); - } - { - auto button = create_dialog_button( "Credits", G_CALLBACK( about_button_credits ), 0 ); - vbox2.pack_start( button, FALSE, FALSE, 0 ); - } - { - auto button = create_dialog_button( "Changes", G_CALLBACK( about_button_changelog ), 0 ); - vbox2.pack_start( button, FALSE, FALSE, 0 ); - } - { - auto button = create_dialog_button( "Issues", G_CALLBACK( about_button_issues ), 0 ); - vbox2.pack_start( button, FALSE, FALSE, 0 ); - } - } - } - { - auto frame = create_dialog_frame( "OpenGL Properties" ); - vbox.pack_start( frame, FALSE, FALSE, 0 ); - { - auto table = create_dialog_table( 3, 2, 4, 4, 4 ); - frame.add(table); - { - auto label = ui::Label( "Vendor:" ); - label.show(); +void DoAbout() +{ + ModalDialog dialog; + ModalDialogButton ok_button(dialog, eIDOK); + + auto window = MainFrame_getWindow().create_modal_dialog_window("About NetRadiant", dialog); + + { + auto vbox = create_dialog_vbox(4, 4); + window.add(vbox); + + { + auto hbox = create_dialog_hbox(4); + vbox.pack_start(hbox, FALSE, TRUE, 0); + + { + auto vbox2 = create_dialog_vbox(4); + hbox.pack_start(vbox2, TRUE, FALSE, 0); + { + auto frame = create_dialog_frame(0, ui::Shadow::IN); + vbox2.pack_start(frame, FALSE, FALSE, 0); + { + auto image = new_local_image("logo.png"); + image.show(); + frame.add(image); + } + } + } + + { + char const *label_text = "NetRadiant " RADIANT_VERSION "\n" + __DATE__ "\n\n" + RADIANT_ABOUTMSG "\n\n" + "This program is free software\n" + "licensed under the GNU GPL.\n\n" + "NetRadiant is unsupported, however\n" + "you may report your problems at\n" + "https://gitlab.com/xonotic/netradiant/issues"; + + auto label = ui::Label(label_text); + + label.show(); + hbox.pack_start(label, FALSE, FALSE, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_label_set_justify(label, GTK_JUSTIFY_LEFT); + } + + { + auto vbox2 = create_dialog_vbox(4); + hbox.pack_start(vbox2, FALSE, TRUE, 0); + { + auto button = create_modal_dialog_button("OK", ok_button); + vbox2.pack_start(button, FALSE, FALSE, 0); + } + { + auto button = create_dialog_button("Credits", G_CALLBACK(about_button_credits), 0); + vbox2.pack_start(button, FALSE, FALSE, 0); + } + { + auto button = create_dialog_button("Changes", G_CALLBACK(about_button_changelog), 0); + vbox2.pack_start(button, FALSE, FALSE, 0); + } + { + auto button = create_dialog_button("Issues", G_CALLBACK(about_button_issues), 0); + vbox2.pack_start(button, FALSE, FALSE, 0); + } + } + } + { + auto frame = create_dialog_frame("OpenGL Properties"); + vbox.pack_start(frame, FALSE, FALSE, 0); + { + auto table = create_dialog_table(3, 2, 4, 4, 4); + frame.add(table); + { + auto label = ui::Label("Vendor:"); + label.show(); table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto label = ui::Label( "Version:" ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto label = ui::Label("Version:"); + label.show(); table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto label = ui::Label( "Renderer:" ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto label = ui::Label("Renderer:"); + label.show(); table.attach(label, {0, 1, 2, 3}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto label = ui::Label( reinterpret_cast( glGetString( GL_VENDOR ) ) ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto label = ui::Label(reinterpret_cast( glGetString(GL_VENDOR))); + label.show(); table.attach(label, {1, 2, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto label = ui::Label( reinterpret_cast( glGetString( GL_VERSION ) ) ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto label = ui::Label(reinterpret_cast( glGetString(GL_VERSION))); + label.show(); table.attach(label, {1, 2, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto label = ui::Label( reinterpret_cast( glGetString( GL_RENDERER ) ) ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto label = ui::Label(reinterpret_cast( glGetString(GL_RENDERER))); + label.show(); table.attach(label, {1, 2, 2, 3}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - } - { - auto frame = create_dialog_frame( "OpenGL Extensions" ); - vbox.pack_start( frame, TRUE, TRUE, 0 ); - { - auto sc_extensions = create_scrolled_window( ui::Policy::AUTOMATIC, ui::Policy::ALWAYS, 4 ); - frame.add(sc_extensions); - { - auto text_extensions = ui::TextView(ui::New); - gtk_text_view_set_editable( text_extensions, FALSE ); - sc_extensions.add(text_extensions); - text_extensions.text(reinterpret_cast(glGetString(GL_EXTENSIONS))); - gtk_text_view_set_wrap_mode( text_extensions, GTK_WRAP_WORD ); - text_extensions.show(); - } - } - } - } - } - - modal_dialog_show( window, dialog ); - - window.destroy(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + } + { + auto frame = create_dialog_frame("OpenGL Extensions"); + vbox.pack_start(frame, TRUE, TRUE, 0); + { + auto sc_extensions = create_scrolled_window(ui::Policy::AUTOMATIC, ui::Policy::ALWAYS, 4); + frame.add(sc_extensions); + { + auto text_extensions = ui::TextView(ui::New); + gtk_text_view_set_editable(text_extensions, FALSE); + sc_extensions.add(text_extensions); + text_extensions.text(reinterpret_cast(glGetString(GL_EXTENSIONS))); + gtk_text_view_set_wrap_mode(text_extensions, GTK_WRAP_WORD); + text_extensions.show(); + } + } + } + } + } + + modal_dialog_show(window, dialog); + + window.destroy(); } // ============================================================================= @@ -562,107 +572,110 @@ void DoAbout(){ static float last_used_texture_layout_scale_x = 4.0; static float last_used_texture_layout_scale_y = 4.0; -EMessageBoxReturn DoTextureLayout( float *fx, float *fy ){ - ModalDialog dialog; - ModalDialogButton ok_button( dialog, eIDOK ); - ModalDialogButton cancel_button( dialog, eIDCANCEL ); - ui::Entry x{ui::null}; - ui::Entry y{ui::null}; - - auto window = MainFrame_getWindow().create_modal_dialog_window("Patch texture layout", dialog ); - - auto accel = ui::AccelGroup(ui::New); - window.add_accel_group( accel ); - - { - auto hbox = create_dialog_hbox( 4, 4 ); - window.add(hbox); - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, TRUE, TRUE, 0 ); - { - auto label = ui::Label( "Texture will be fit across the patch based\n" - "on the x and y values given. Values of 1x1\n" - "will \"fit\" the texture. 2x2 will repeat\n" - "it twice, etc." ); - label.show(); - vbox.pack_start( label, TRUE, TRUE, 0 ); - gtk_label_set_justify( label, GTK_JUSTIFY_LEFT ); - } - { - auto table = create_dialog_table( 2, 2, 4, 4 ); - table.show(); - vbox.pack_start( table, TRUE, TRUE, 0 ); - { - auto label = ui::Label( "Texture x:" ); - label.show(); +EMessageBoxReturn DoTextureLayout(float *fx, float *fy) +{ + ModalDialog dialog; + ModalDialogButton ok_button(dialog, eIDOK); + ModalDialogButton cancel_button(dialog, eIDCANCEL); + ui::Entry x{ui::null}; + ui::Entry y{ui::null}; + + auto window = MainFrame_getWindow().create_modal_dialog_window("Patch texture layout", dialog); + + auto accel = ui::AccelGroup(ui::New); + window.add_accel_group(accel); + + { + auto hbox = create_dialog_hbox(4, 4); + window.add(hbox); + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, TRUE, TRUE, 0); + { + auto label = ui::Label("Texture will be fit across the patch based\n" + "on the x and y values given. Values of 1x1\n" + "will \"fit\" the texture. 2x2 will repeat\n" + "it twice, etc."); + label.show(); + vbox.pack_start(label, TRUE, TRUE, 0); + gtk_label_set_justify(label, GTK_JUSTIFY_LEFT); + } + { + auto table = create_dialog_table(2, 2, 4, 4); + table.show(); + vbox.pack_start(table, TRUE, TRUE, 0); + { + auto label = ui::Label("Texture x:"); + label.show(); table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto label = ui::Label( "Texture y:" ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto label = ui::Label("Texture y:"); + label.show(); table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - x = entry; - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + x = entry; + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - y = entry; - } - } - } - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, FALSE, FALSE, 0 ); - { - auto button = create_modal_dialog_button( "OK", ok_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - { - auto button = create_modal_dialog_button( "Cancel", cancel_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - } - } - - // Initialize with last used values - char buf[16]; - - sprintf( buf, "%f", last_used_texture_layout_scale_x ); - x.text( buf ); - - sprintf( buf, "%f", last_used_texture_layout_scale_y ); - y.text( buf ); - - // Set focus after intializing the values - gtk_widget_grab_focus( x ); - - EMessageBoxReturn ret = modal_dialog_show( window, dialog ); - if ( ret == eIDOK ) { - *fx = static_cast( atof( gtk_entry_get_text( x ) ) ); - *fy = static_cast( atof( gtk_entry_get_text( y ) ) ); - - // Remember last used values - last_used_texture_layout_scale_x = *fx; - last_used_texture_layout_scale_y = *fy; - } - - window.destroy(); - - return ret; + y = entry; + } + } + } + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, FALSE, FALSE, 0); + { + auto button = create_modal_dialog_button("OK", ok_button); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + { + auto button = create_modal_dialog_button("Cancel", cancel_button); + vbox.pack_start(button, FALSE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + } + } + + // Initialize with last used values + char buf[16]; + + sprintf(buf, "%f", last_used_texture_layout_scale_x); + x.text(buf); + + sprintf(buf, "%f", last_used_texture_layout_scale_y); + y.text(buf); + + // Set focus after intializing the values + gtk_widget_grab_focus(x); + + EMessageBoxReturn ret = modal_dialog_show(window, dialog); + if (ret == eIDOK) { + *fx = static_cast( atof(gtk_entry_get_text(x))); + *fy = static_cast( atof(gtk_entry_get_text(y))); + + // Remember last used values + last_used_texture_layout_scale_x = *fx; + last_used_texture_layout_scale_y = *fy; + } + + window.destroy(); + + return ret; } // ============================================================================= @@ -672,326 +685,338 @@ EMessageBoxReturn DoTextureLayout( float *fx, float *fy ){ static ui::Window text_editor{ui::null}; static ui::Widget text_widget{ui::null}; // slave, text widget from the gtk editor -static gint editor_delete( ui::Widget widget, gpointer data ){ - if ( ui::alert( widget.window(), "Close the shader editor ?", "Radiant", ui::alert_type::YESNO, ui::alert_icon::Question ) == ui::alert_response::NO ) { - return TRUE; - } +static gint editor_delete(ui::Widget widget, gpointer data) +{ + if (ui::alert(widget.window(), "Close the shader editor ?", "Radiant", ui::alert_type::YESNO, + ui::alert_icon::Question) == ui::alert_response::NO) { + return TRUE; + } - text_editor.hide(); + text_editor.hide(); - return TRUE; + return TRUE; } -static void editor_save( ui::Widget widget, gpointer data ){ - FILE *f = fopen( (char*)g_object_get_data( G_OBJECT( data ), "filename" ), "w" ); - gpointer text = g_object_get_data( G_OBJECT( data ), "text" ); +static void editor_save(ui::Widget widget, gpointer data) +{ + FILE *f = fopen((char *) g_object_get_data(G_OBJECT(data), "filename"), "w"); + gpointer text = g_object_get_data(G_OBJECT(data), "text"); - if ( f == 0 ) { - ui::alert( ui::Widget::from(data).window(), "Error saving file !" ); - return; - } + if (f == 0) { + ui::alert(ui::Widget::from(data).window(), "Error saving file !"); + return; + } - char *str = gtk_editable_get_chars( GTK_EDITABLE( text ), 0, -1 ); - fwrite( str, 1, strlen( str ), f ); - fclose( f ); + char *str = gtk_editable_get_chars(GTK_EDITABLE(text), 0, -1); + fwrite(str, 1, strlen(str), f); + fclose(f); } -static void editor_close( ui::Widget widget, gpointer data ){ - if ( ui::alert( text_editor.window(), "Close the shader editor ?", "Radiant", ui::alert_type::YESNO, ui::alert_icon::Question ) == ui::alert_response::NO ) { - return; - } +static void editor_close(ui::Widget widget, gpointer data) +{ + if (ui::alert(text_editor.window(), "Close the shader editor ?", "Radiant", ui::alert_type::YESNO, + ui::alert_icon::Question) == ui::alert_response::NO) { + return; + } - text_editor.hide(); + text_editor.hide(); } -static void CreateGtkTextEditor(){ - auto dlg = ui::Window( ui::window_type::TOP ); - - dlg.connect( "delete_event", - G_CALLBACK( editor_delete ), 0 ); - gtk_window_set_default_size( dlg, 600, 300 ); - - auto vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - dlg.add(vbox); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - auto scr = ui::ScrolledWindow(ui::New); - scr.show(); - vbox.pack_start( scr, TRUE, TRUE, 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 ); - - auto text = ui::TextView(ui::New); - scr.add(text); - text.show(); - g_object_set_data( G_OBJECT( dlg ), "text", (gpointer) text ); - gtk_text_view_set_editable( text, TRUE ); - - auto hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox.pack_start( hbox, FALSE, TRUE, 0 ); - - auto button = ui::Button( "Close" ); - button.show(); - hbox.pack_end(button, FALSE, FALSE, 0); - button.connect( "clicked", - G_CALLBACK( editor_close ), dlg ); - button.dimensions(60, -1); - - button = ui::Button( "Save" ); - button.show(); - hbox.pack_end(button, FALSE, FALSE, 0); - button.connect( "clicked", - G_CALLBACK( editor_save ), dlg ); - button.dimensions(60, -1); - - text_editor = dlg; - text_widget = text; +static void CreateGtkTextEditor() +{ + auto dlg = ui::Window(ui::window_type::TOP); + + dlg.connect("delete_event", + G_CALLBACK(editor_delete), 0); + gtk_window_set_default_size(dlg, 600, 300); + + auto vbox = ui::VBox(FALSE, 5); + vbox.show(); + dlg.add(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + vbox.pack_start(scr, TRUE, TRUE, 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); + + auto text = ui::TextView(ui::New); + scr.add(text); + text.show(); + g_object_set_data(G_OBJECT(dlg), "text", (gpointer) text); + gtk_text_view_set_editable(text, TRUE); + + auto hbox = ui::HBox(FALSE, 5); + hbox.show(); + vbox.pack_start(hbox, FALSE, TRUE, 0); + + auto button = ui::Button("Close"); + button.show(); + hbox.pack_end(button, FALSE, FALSE, 0); + button.connect("clicked", + G_CALLBACK(editor_close), dlg); + button.dimensions(60, -1); + + button = ui::Button("Save"); + button.show(); + hbox.pack_end(button, FALSE, FALSE, 0); + button.connect("clicked", + G_CALLBACK(editor_save), dlg); + button.dimensions(60, -1); + + text_editor = dlg; + text_widget = text; } -static void DoGtkTextEditor( const char* filename, guint cursorpos ){ - if ( !text_editor ) { - CreateGtkTextEditor(); // build it the first time we need it +static void DoGtkTextEditor(const char *filename, guint cursorpos) +{ + if (!text_editor) { + CreateGtkTextEditor(); // build it the first time we need it - } - // Load file - FILE *f = fopen( filename, "r" ); + } + // Load file + FILE *f = fopen(filename, "r"); - if ( f == 0 ) { - globalOutputStream() << "Unable to load file " << filename << " in shader editor.\n"; - text_editor.hide(); - } - else - { - fseek( f, 0, SEEK_END ); - int len = ftell( f ); - void *buf = malloc( len ); - void *old_filename; + if (f == 0) { + globalOutputStream() << "Unable to load file " << filename << " in shader editor.\n"; + text_editor.hide(); + } else { + fseek(f, 0, SEEK_END); + int len = ftell(f); + void *buf = malloc(len); + void *old_filename; - rewind( f ); - fread( buf, 1, len, f ); + rewind(f); + fread(buf, 1, len, f); - gtk_window_set_title( text_editor, filename ); + gtk_window_set_title(text_editor, filename); - auto text_buffer = gtk_text_view_get_buffer(ui::TextView::from(text_widget)); - gtk_text_buffer_set_text( text_buffer, (char*)buf, len ); + auto text_buffer = gtk_text_view_get_buffer(ui::TextView::from(text_widget)); + gtk_text_buffer_set_text(text_buffer, (char *) buf, len); - old_filename = g_object_get_data( G_OBJECT( text_editor ), "filename" ); - if ( old_filename ) { - free( old_filename ); - } - g_object_set_data( G_OBJECT( text_editor ), "filename", strdup( filename ) ); + old_filename = g_object_get_data(G_OBJECT(text_editor), "filename"); + if (old_filename) { + free(old_filename); + } + g_object_set_data(G_OBJECT(text_editor), "filename", strdup(filename)); - // trying to show later - text_editor.show(); + // trying to show later + text_editor.show(); #if GDEF_OS_WINDOWS - ui::process(); + ui::process(); #endif - // only move the cursor if it's not exceeding the size.. - // NOTE: this is erroneous, cursorpos is the offset in bytes, not in characters - // len is the max size in bytes, not in characters either, but the character count is below that limit.. - // thinking .. the difference between character count and byte count would be only because of CR/LF? - { - GtkTextIter text_iter; - // character offset, not byte offset - gtk_text_buffer_get_iter_at_offset( text_buffer, &text_iter, cursorpos ); - gtk_text_buffer_place_cursor( text_buffer, &text_iter ); - } + // only move the cursor if it's not exceeding the size.. + // NOTE: this is erroneous, cursorpos is the offset in bytes, not in characters + // len is the max size in bytes, not in characters either, but the character count is below that limit.. + // thinking .. the difference between character count and byte count would be only because of CR/LF? + { + GtkTextIter text_iter; + // character offset, not byte offset + gtk_text_buffer_get_iter_at_offset(text_buffer, &text_iter, cursorpos); + gtk_text_buffer_place_cursor(text_buffer, &text_iter); + } #if GDEF_OS_WINDOWS - gtk_widget_queue_draw( text_widget ); + gtk_widget_queue_draw( text_widget ); #endif - free( buf ); - fclose( f ); - } + free(buf); + fclose(f); + } } // ============================================================================= // Light Intensity dialog -EMessageBoxReturn DoLightIntensityDlg( int *intensity ){ - ModalDialog dialog; - ui::Entry intensity_entry{ui::null}; - ModalDialogButton ok_button( dialog, eIDOK ); - ModalDialogButton cancel_button( dialog, eIDCANCEL ); - - ui::Window window = MainFrame_getWindow().create_modal_dialog_window("Light intensity", dialog, -1, -1 ); - - auto accel_group = ui::AccelGroup(ui::New); - window.add_accel_group( accel_group ); - - { - auto hbox = create_dialog_hbox( 4, 4 ); - window.add(hbox); - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, TRUE, TRUE, 0 ); - { - auto label = ui::Label( "ESC for default, ENTER to validate" ); - label.show(); - vbox.pack_start( label, FALSE, FALSE, 0 ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); - vbox.pack_start( entry, TRUE, TRUE, 0 ); - - gtk_widget_grab_focus( entry ); - - intensity_entry = entry; - } - } - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, FALSE, FALSE, 0 ); - - { - auto button = create_modal_dialog_button( "OK", ok_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel_group, GDK_KEY_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE ); - } - { - auto button = create_modal_dialog_button( "Cancel", cancel_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel_group, GDK_KEY_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE ); - } - } - } - - char buf[16]; - sprintf( buf, "%d", *intensity ); - intensity_entry.text(buf); - - EMessageBoxReturn ret = modal_dialog_show( window, dialog ); - if ( ret == eIDOK ) { - *intensity = atoi( gtk_entry_get_text( intensity_entry ) ); - } - - window.destroy(); - - return ret; +EMessageBoxReturn DoLightIntensityDlg(int *intensity) +{ + ModalDialog dialog; + ui::Entry intensity_entry{ui::null}; + ModalDialogButton ok_button(dialog, eIDOK); + ModalDialogButton cancel_button(dialog, eIDCANCEL); + + ui::Window window = MainFrame_getWindow().create_modal_dialog_window("Light intensity", dialog, -1, -1); + + auto accel_group = ui::AccelGroup(ui::New); + window.add_accel_group(accel_group); + + { + auto hbox = create_dialog_hbox(4, 4); + window.add(hbox); + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, TRUE, TRUE, 0); + { + auto label = ui::Label("ESC for default, ENTER to validate"); + label.show(); + vbox.pack_start(label, FALSE, FALSE, 0); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); + vbox.pack_start(entry, TRUE, TRUE, 0); + + gtk_widget_grab_focus(entry); + + intensity_entry = entry; + } + } + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, FALSE, FALSE, 0); + + { + auto button = create_modal_dialog_button("OK", ok_button); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_add_accelerator(button, "clicked", accel_group, GDK_KEY_Return, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + } + { + auto button = create_modal_dialog_button("Cancel", cancel_button); + vbox.pack_start(button, FALSE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel_group, GDK_KEY_Escape, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + } + } + } + + char buf[16]; + sprintf(buf, "%d", *intensity); + intensity_entry.text(buf); + + EMessageBoxReturn ret = modal_dialog_show(window, dialog); + if (ret == eIDOK) { + *intensity = atoi(gtk_entry_get_text(intensity_entry)); + } + + window.destroy(); + + return ret; } // ============================================================================= // Add new shader tag dialog -EMessageBoxReturn DoShaderTagDlg( CopiedString* tag, const char* title ){ - ModalDialog dialog; - ModalDialogButton ok_button( dialog, eIDOK ); - ModalDialogButton cancel_button( dialog, eIDCANCEL ); - - auto window = MainFrame_getWindow().create_modal_dialog_window(title, dialog, -1, -1 ); - - auto accel_group = ui::AccelGroup(ui::New); - window.add_accel_group( accel_group ); - - auto textentry = ui::Entry(ui::New); - { - auto hbox = create_dialog_hbox( 4, 4 ); - window.add(hbox); - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, TRUE, TRUE, 0 ); - { - //GtkLabel* label = GTK_LABEL(gtk_label_new("Enter one ore more tags separated by spaces")); - auto label = ui::Label( "ESC to cancel, ENTER to validate" ); - label.show(); - vbox.pack_start( label, FALSE, FALSE, 0 ); - } - { - auto entry = textentry; - entry.show(); - vbox.pack_start( entry, TRUE, TRUE, 0 ); - - gtk_widget_grab_focus( entry ); - } - } - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, FALSE, FALSE, 0 ); - - { - auto button = create_modal_dialog_button( "OK", ok_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel_group, GDK_KEY_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE ); - } - { - auto button = create_modal_dialog_button( "Cancel", cancel_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel_group, GDK_KEY_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE ); - } - } - } - - EMessageBoxReturn ret = modal_dialog_show( window, dialog ); - if ( ret == eIDOK ) { - *tag = gtk_entry_get_text( textentry ); - } - - window.destroy(); - - return ret; +EMessageBoxReturn DoShaderTagDlg(CopiedString *tag, const char *title) +{ + ModalDialog dialog; + ModalDialogButton ok_button(dialog, eIDOK); + ModalDialogButton cancel_button(dialog, eIDCANCEL); + + auto window = MainFrame_getWindow().create_modal_dialog_window(title, dialog, -1, -1); + + auto accel_group = ui::AccelGroup(ui::New); + window.add_accel_group(accel_group); + + auto textentry = ui::Entry(ui::New); + { + auto hbox = create_dialog_hbox(4, 4); + window.add(hbox); + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, TRUE, TRUE, 0); + { + //GtkLabel* label = GTK_LABEL(gtk_label_new("Enter one ore more tags separated by spaces")); + auto label = ui::Label("ESC to cancel, ENTER to validate"); + label.show(); + vbox.pack_start(label, FALSE, FALSE, 0); + } + { + auto entry = textentry; + entry.show(); + vbox.pack_start(entry, TRUE, TRUE, 0); + + gtk_widget_grab_focus(entry); + } + } + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, FALSE, FALSE, 0); + + { + auto button = create_modal_dialog_button("OK", ok_button); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_add_accelerator(button, "clicked", accel_group, GDK_KEY_Return, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + } + { + auto button = create_modal_dialog_button("Cancel", cancel_button); + vbox.pack_start(button, FALSE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel_group, GDK_KEY_Escape, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + } + } + } + + EMessageBoxReturn ret = modal_dialog_show(window, dialog); + if (ret == eIDOK) { + *tag = gtk_entry_get_text(textentry); + } + + window.destroy(); + + return ret; } -EMessageBoxReturn DoShaderInfoDlg( const char* name, const char* filename, const char* title ){ - ModalDialog dialog; - ModalDialogButton ok_button( dialog, eIDOK ); - - auto window = MainFrame_getWindow().create_modal_dialog_window(title, dialog, -1, -1 ); - - auto accel_group = ui::AccelGroup(ui::New); - window.add_accel_group( accel_group ); - - { - auto hbox = create_dialog_hbox( 4, 4 ); - window.add(hbox); - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, FALSE, FALSE, 0 ); - { - auto label = ui::Label( "The selected shader" ); - label.show(); - vbox.pack_start( label, FALSE, FALSE, 0 ); - } - { - auto label = ui::Label( name ); - label.show(); - vbox.pack_start( label, FALSE, FALSE, 0 ); - } - { - auto label = ui::Label( "is located in file" ); - label.show(); - vbox.pack_start( label, FALSE, FALSE, 0 ); - } - { - auto label = ui::Label( filename ); - label.show(); - vbox.pack_start( label, FALSE, FALSE, 0 ); - } - { - auto button = create_modal_dialog_button( "OK", ok_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel_group, GDK_KEY_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE ); - } - } - } - - EMessageBoxReturn ret = modal_dialog_show( window, dialog ); - - window.destroy(); - - return ret; +EMessageBoxReturn DoShaderInfoDlg(const char *name, const char *filename, const char *title) +{ + ModalDialog dialog; + ModalDialogButton ok_button(dialog, eIDOK); + + auto window = MainFrame_getWindow().create_modal_dialog_window(title, dialog, -1, -1); + + auto accel_group = ui::AccelGroup(ui::New); + window.add_accel_group(accel_group); + + { + auto hbox = create_dialog_hbox(4, 4); + window.add(hbox); + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, FALSE, FALSE, 0); + { + auto label = ui::Label("The selected shader"); + label.show(); + vbox.pack_start(label, FALSE, FALSE, 0); + } + { + auto label = ui::Label(name); + label.show(); + vbox.pack_start(label, FALSE, FALSE, 0); + } + { + auto label = ui::Label("is located in file"); + label.show(); + vbox.pack_start(label, FALSE, FALSE, 0); + } + { + auto label = ui::Label(filename); + label.show(); + vbox.pack_start(label, FALSE, FALSE, 0); + } + { + auto button = create_modal_dialog_button("OK", ok_button); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_add_accelerator(button, "clicked", accel_group, GDK_KEY_Return, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + } + } + } + + EMessageBoxReturn ret = modal_dialog_show(window, dialog); + + window.destroy(); + + return ret; } - #if GDEF_OS_WINDOWS #include #endif @@ -1002,34 +1027,33 @@ bool g_TextEditor_useWin32Editor = true; #else // custom shader editor bool g_TextEditor_useCustomEditor = false; -CopiedString g_TextEditor_editorCommand( "" ); +CopiedString g_TextEditor_editorCommand(""); #endif -void DoTextEditor( const char* filename, int cursorpos ){ +void DoTextEditor(const char *filename, int cursorpos) +{ #if GDEF_OS_WINDOWS - if ( g_TextEditor_useWin32Editor ) { - globalOutputStream() << "opening file '" << filename << "' (line " << cursorpos << " info ignored)\n"; - ShellExecute( (HWND)GDK_WINDOW_HWND( gtk_widget_get_window( MainFrame_getWindow() ) ), "open", filename, 0, 0, SW_SHOW ); - return; - } + if ( g_TextEditor_useWin32Editor ) { + globalOutputStream() << "opening file '" << filename << "' (line " << cursorpos << " info ignored)\n"; + ShellExecute( (HWND)GDK_WINDOW_HWND( gtk_widget_get_window( MainFrame_getWindow() ) ), "open", filename, 0, 0, SW_SHOW ); + return; + } #else - // check if a custom editor is set - if ( g_TextEditor_useCustomEditor && !g_TextEditor_editorCommand.empty() ) { - StringOutputStream strEditCommand( 256 ); - strEditCommand << g_TextEditor_editorCommand.c_str() << " \"" << filename << "\""; - - globalOutputStream() << "Launching: " << strEditCommand.c_str() << "\n"; - // note: linux does not return false if the command failed so it will assume success - if ( Q_Exec( 0, const_cast( strEditCommand.c_str() ), 0, true, false ) == false ) { - globalOutputStream() << "Failed to execute " << strEditCommand.c_str() << ", using default\n"; - } - else - { - // the command (appeared) to run successfully, no need to do anything more - return; - } - } + // check if a custom editor is set + if (g_TextEditor_useCustomEditor && !g_TextEditor_editorCommand.empty()) { + StringOutputStream strEditCommand(256); + strEditCommand << g_TextEditor_editorCommand.c_str() << " \"" << filename << "\""; + + globalOutputStream() << "Launching: " << strEditCommand.c_str() << "\n"; + // note: linux does not return false if the command failed so it will assume success + if (Q_Exec(0, const_cast( strEditCommand.c_str()), 0, true, false) == false) { + globalOutputStream() << "Failed to execute " << strEditCommand.c_str() << ", using default\n"; + } else { + // the command (appeared) to run successfully, no need to do anything more + return; + } + } #endif - DoGtkTextEditor( filename, cursorpos ); + DoGtkTextEditor(filename, cursorpos); } diff --git a/radiant/gtkdlgs.h b/radiant/gtkdlgs.h index 0dad793a..fa8ac889 100644 --- a/radiant/gtkdlgs.h +++ b/radiant/gtkdlgs.h @@ -35,23 +35,31 @@ #include "qerplugin.h" #include "string/string.h" -EMessageBoxReturn DoLightIntensityDlg( int *intensity ); -EMessageBoxReturn DoShaderTagDlg( CopiedString *tag, const char* title ); -EMessageBoxReturn DoShaderInfoDlg( const char* name, const char* filename, const char* title ); -EMessageBoxReturn DoTextureLayout( float *fx, float *fy ); -void DoTextEditor( const char* filename, int cursorpos ); +EMessageBoxReturn DoLightIntensityDlg(int *intensity); + +EMessageBoxReturn DoShaderTagDlg(CopiedString *tag, const char *title); + +EMessageBoxReturn DoShaderInfoDlg(const char *name, const char *filename, const char *title); + +EMessageBoxReturn DoTextureLayout(float *fx, float *fy); + +void DoTextEditor(const char *filename, int cursorpos); void DoProjectSettings(); void DoFind(); -void DoSides( int type, int axis ); + +void DoSides(int type, int axis); + void DoAbout(); #if GDEF_OS_WINDOWS extern bool g_TextEditor_useWin32Editor; #else + #include "string/stringfwd.h" + extern bool g_TextEditor_useCustomEditor; extern CopiedString g_TextEditor_editorCommand; #endif diff --git a/radiant/gtkmisc.cpp b/radiant/gtkmisc.cpp index 85554502..e4e784c1 100644 --- a/radiant/gtkmisc.cpp +++ b/radiant/gtkmisc.cpp @@ -50,98 +50,114 @@ // ============================================================================= // Misc stuff -void command_connect_accelerator( const char* name ){ - const Command& command = GlobalCommands_find( name ); - GlobalShortcuts_register( name, 1 ); - global_accel_group_connect( command.m_accelerator, command.m_callback ); +void command_connect_accelerator(const char *name) +{ + const Command &command = GlobalCommands_find(name); + GlobalShortcuts_register(name, 1); + global_accel_group_connect(command.m_accelerator, command.m_callback); } -void command_disconnect_accelerator( const char* name ){ - const Command& command = GlobalCommands_find( name ); - global_accel_group_disconnect( command.m_accelerator, command.m_callback ); +void command_disconnect_accelerator(const char *name) +{ + const Command &command = GlobalCommands_find(name); + global_accel_group_disconnect(command.m_accelerator, command.m_callback); } -void toggle_add_accelerator( const char* name ){ - const Toggle& toggle = GlobalToggles_find( name ); - GlobalShortcuts_register( name, 2 ); - global_accel_group_connect( toggle.m_command.m_accelerator, toggle.m_command.m_callback ); +void toggle_add_accelerator(const char *name) +{ + const Toggle &toggle = GlobalToggles_find(name); + GlobalShortcuts_register(name, 2); + global_accel_group_connect(toggle.m_command.m_accelerator, toggle.m_command.m_callback); } -void toggle_remove_accelerator( const char* name ){ - const Toggle& toggle = GlobalToggles_find( name ); - global_accel_group_disconnect( toggle.m_command.m_accelerator, toggle.m_command.m_callback ); +void toggle_remove_accelerator(const char *name) +{ + const Toggle &toggle = GlobalToggles_find(name); + global_accel_group_disconnect(toggle.m_command.m_accelerator, toggle.m_command.m_callback); } -ui::CheckMenuItem create_check_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const char* commandName ){ - GlobalShortcuts_register( commandName, 2 ); - const Toggle& toggle = GlobalToggles_find( commandName ); - global_accel_group_connect( toggle.m_command.m_accelerator, toggle.m_command.m_callback ); - return create_check_menu_item_with_mnemonic( menu, mnemonic, toggle ); +ui::CheckMenuItem create_check_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const char *commandName) +{ + GlobalShortcuts_register(commandName, 2); + const Toggle &toggle = GlobalToggles_find(commandName); + global_accel_group_connect(toggle.m_command.m_accelerator, toggle.m_command.m_callback); + return create_check_menu_item_with_mnemonic(menu, mnemonic, toggle); } -ui::MenuItem create_menu_item_with_mnemonic( ui::Menu menu, const char *mnemonic, const char* commandName ){ - GlobalShortcuts_register( commandName, 1 ); - const Command& command = GlobalCommands_find( commandName ); - global_accel_group_connect( command.m_accelerator, command.m_callback ); - return create_menu_item_with_mnemonic( menu, mnemonic, command ); +ui::MenuItem create_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const char *commandName) +{ + GlobalShortcuts_register(commandName, 1); + const Command &command = GlobalCommands_find(commandName); + global_accel_group_connect(command.m_accelerator, command.m_callback); + return create_menu_item_with_mnemonic(menu, mnemonic, command); } -ui::ToolButton toolbar_append_button( ui::Toolbar toolbar, const char* description, const char* icon, const char* commandName ){ - return toolbar_append_button( toolbar, description, icon, GlobalCommands_find( commandName ) ); +ui::ToolButton +toolbar_append_button(ui::Toolbar toolbar, const char *description, const char *icon, const char *commandName) +{ + return toolbar_append_button(toolbar, description, icon, GlobalCommands_find(commandName)); } -ui::ToggleToolButton toolbar_append_toggle_button( ui::Toolbar toolbar, const char* description, const char* icon, const char* commandName ){ - return toolbar_append_toggle_button( toolbar, description, icon, GlobalToggles_find( commandName ) ); +ui::ToggleToolButton +toolbar_append_toggle_button(ui::Toolbar 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( ui::Window parent, Vector3& color, const char* title ){ - GdkColor clr = { 0, guint16(color[0] * 65535), guint16(color[1] * 65535), guint16(color[2] * 65535) }; - ModalDialog dialog; - - auto dlg = ui::Window::from(gtk_color_selection_dialog_new( title )); - gtk_color_selection_set_current_color( GTK_COLOR_SELECTION( gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG( dlg )) ), &clr ); - dlg.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), &dialog ); - GtkWidget *ok_button, *cancel_button; - g_object_get(G_OBJECT(dlg), "ok-button", &ok_button, "cancel-button", &cancel_button, nullptr); - ui::Widget::from(ok_button).connect( "clicked", G_CALLBACK( dialog_button_ok ), &dialog ); - ui::Widget::from(cancel_button).connect( "clicked", G_CALLBACK( dialog_button_cancel ), &dialog ); - - if ( parent ) { - gtk_window_set_transient_for( dlg, parent ); - } - - bool ok = modal_dialog_show( dlg, dialog ) == eIDOK; - if ( ok ) { - gtk_color_selection_get_current_color( GTK_COLOR_SELECTION( gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG( dlg )) ), &clr ); - color[0] = clr.red / 65535.0f; - color[1] = clr.green / 65535.0f; - color[2] = clr.blue / 65535.0f; - } - - dlg.destroy(); - - return ok; +bool color_dialog(ui::Window parent, Vector3 &color, const char *title) +{ + GdkColor clr = {0, guint16(color[0] * 65535), guint16(color[1] * 65535), guint16(color[2] * 65535)}; + ModalDialog dialog; + + auto dlg = ui::Window::from(gtk_color_selection_dialog_new(title)); + gtk_color_selection_set_current_color( + GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dlg))), &clr); + dlg.connect("delete_event", G_CALLBACK(dialog_delete_callback), &dialog); + GtkWidget *ok_button, *cancel_button; + g_object_get(G_OBJECT(dlg), "ok-button", &ok_button, "cancel-button", &cancel_button, nullptr); + ui::Widget::from(ok_button).connect("clicked", G_CALLBACK(dialog_button_ok), &dialog); + ui::Widget::from(cancel_button).connect("clicked", G_CALLBACK(dialog_button_cancel), &dialog); + + if (parent) { + gtk_window_set_transient_for(dlg, parent); + } + + bool ok = modal_dialog_show(dlg, dialog) == eIDOK; + if (ok) { + gtk_color_selection_get_current_color( + GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dlg))), + &clr); + color[0] = clr.red / 65535.0f; + color[1] = clr.green / 65535.0f; + color[2] = clr.blue / 65535.0f; + } + + dlg.destroy(); + + return ok; } -void button_clicked_entry_browse_file( ui::Widget widget, ui::Entry entry ){ - const char *filename = widget.file_dialog( TRUE, "Choose File", gtk_entry_get_text( entry ) ); +void button_clicked_entry_browse_file(ui::Widget widget, ui::Entry entry) +{ + const char *filename = widget.file_dialog(TRUE, "Choose File", gtk_entry_get_text(entry)); - if ( filename != 0 ) { - entry.text(filename); - } + if (filename != 0) { + entry.text(filename); + } } -void button_clicked_entry_browse_directory( ui::Widget widget, ui::Entry entry ){ - const char* text = gtk_entry_get_text( entry ); - char *dir = dir_dialog( widget.window(), "Choose Directory", path_is_absolute( text ) ? text : "" ); - - if ( dir != 0 ) { - gchar* converted = g_filename_to_utf8( dir, -1, 0, 0, 0 ); - entry.text(converted); - g_free( dir ); - g_free( converted ); - } +void button_clicked_entry_browse_directory(ui::Widget widget, ui::Entry entry) +{ + const char *text = gtk_entry_get_text(entry); + char *dir = dir_dialog(widget.window(), "Choose Directory", path_is_absolute(text) ? text : ""); + + if (dir != 0) { + gchar *converted = g_filename_to_utf8(dir, -1, 0, 0, 0); + entry.text(converted); + g_free(dir); + g_free(converted); + } } diff --git a/radiant/gtkmisc.h b/radiant/gtkmisc.h index e867d6a2..03797977 100644 --- a/radiant/gtkmisc.h +++ b/radiant/gtkmisc.h @@ -33,28 +33,39 @@ #include -void command_connect_accelerator( const char* commandName ); -void command_disconnect_accelerator( const char* commandName ); -void toggle_add_accelerator( const char* commandName ); -void toggle_remove_accelerator( const char* name ); +void command_connect_accelerator(const char *commandName); + +void command_disconnect_accelerator(const char *commandName); + +void toggle_add_accelerator(const char *commandName); + +void toggle_remove_accelerator(const char *name); // this also sets up the shortcut using command_connect_accelerator -ui::MenuItem create_menu_item_with_mnemonic( ui::Menu menu, const char *mnemonic, const char* commandName ); +ui::MenuItem create_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const char *commandName); + // this also sets up the shortcut using command_connect_accelerator -ui::CheckMenuItem create_check_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const char* commandName ); +ui::CheckMenuItem create_check_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const char *commandName); // this DOES NOT set up the shortcut using command_connect_accelerator -ui::ToolButton toolbar_append_button( ui::Toolbar toolbar, const char* description, const char* icon, const char* commandName ); +ui::ToolButton +toolbar_append_button(ui::Toolbar toolbar, const char *description, const char *icon, const char *commandName); + // this DOES NOT set up the shortcut using command_connect_accelerator -ui::ToggleToolButton toolbar_append_toggle_button( ui::Toolbar toolbar, const char* description, const char* icon, const char* commandName ); +ui::ToggleToolButton +toolbar_append_toggle_button(ui::Toolbar toolbar, const char *description, const char *icon, const char *commandName); + +template +class BasicVector3; -template class BasicVector3; typedef BasicVector3 Vector3; -bool color_dialog( ui::Window parent, Vector3& color, const char* title = "Choose Color" ); -void button_clicked_entry_browse_file( ui::Widget widget, ui::Entry entry ); -void button_clicked_entry_browse_directory( ui::Widget widget, ui::Entry entry ); +bool color_dialog(ui::Window parent, Vector3 &color, const char *title = "Choose Color"); + +void button_clicked_entry_browse_file(ui::Widget widget, ui::Entry entry); + +void button_clicked_entry_browse_directory(ui::Widget widget, ui::Entry entry); #endif diff --git a/radiant/help.cpp b/radiant/help.cpp index b11743d6..4ab85c38 100644 --- a/radiant/help.cpp +++ b/radiant/help.cpp @@ -39,95 +39,94 @@ /*! the urls to fire up in the game packs help menus */ -namespace -{ -std::list mHelpURLs; +namespace { + std::list mHelpURLs; } /*! needed for hooking in Gtk+ */ -void HandleHelpCommand( CopiedString& str ){ - OpenURL( str.c_str() ); +void HandleHelpCommand(CopiedString &str) +{ + OpenURL(str.c_str()); } -void process_xlink( const char* filename, const char *menu_name, const char *base_url, ui::Menu menu ){ - if ( file_exists( filename ) ) { - xmlDocPtr pDoc = xmlParseFile( filename ); - if ( pDoc ) { - globalOutputStream() << "Processing .xlink file '" << filename << "'\n"; - // create sub menu - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, menu_name ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - // 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( "url" ) ); - ASSERT_NOTNULL( prop ); - if ( strstr( reinterpret_cast( prop ), "http://" ) || - strstr( reinterpret_cast( prop ), "https://" ) ) { - // complete URL - url = reinterpret_cast( prop ); - } - else - { - // relative URL - StringOutputStream full( 256 ); - full << base_url << reinterpret_cast( prop ); - url = full.c_str(); - } - - mHelpURLs.push_back( url ); - - xmlFree( prop ); - - prop = xmlGetProp( pNode, reinterpret_cast( "name" ) ); - ASSERT_NOTNULL( prop ); - create_menu_item_with_mnemonic( menu_in_menu, reinterpret_cast( prop ), ReferenceCaller( mHelpURLs.back() ) ); - xmlFree( prop ); - } - pNode = pNode->next; - } - } - xmlFreeDoc( pDoc ); - } - else - { - globalOutputStream() << "'" << filename << "' parse failed\n"; - } - } - else - { - globalOutputStream() << "'" << filename << "' not found\n"; - } +void process_xlink(const char *filename, const char *menu_name, const char *base_url, ui::Menu menu) +{ + if (file_exists(filename)) { + xmlDocPtr pDoc = xmlParseFile(filename); + if (pDoc) { + globalOutputStream() << "Processing .xlink file '" << filename << "'\n"; + // create sub menu + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, menu_name); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + // 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( "url" )); + ASSERT_NOTNULL(prop); + if (strstr(reinterpret_cast( prop ), "http://") || + strstr(reinterpret_cast( prop ), "https://")) { + // complete URL + url = reinterpret_cast( prop ); + } else { + // relative URL + StringOutputStream full(256); + full << base_url << reinterpret_cast( prop ); + url = full.c_str(); + } + + mHelpURLs.push_back(url); + + xmlFree(prop); + + prop = xmlGetProp(pNode, reinterpret_cast( "name" )); + ASSERT_NOTNULL(prop); + create_menu_item_with_mnemonic(menu_in_menu, reinterpret_cast( prop ), + ReferenceCaller( + 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( ui::Menu menu ){ - StringOutputStream filename( 256 ); - filename << AppPath_get() << "global.xlink"; - process_xlink( filename.c_str(), "General", AppPath_get(), menu ); +void create_game_help_menu(ui::Menu 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 ); + 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::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 ); - } + for ( std::list::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 } diff --git a/radiant/help.h b/radiant/help.h index 1e85100a..e16cb8b9 100644 --- a/radiant/help.h +++ b/radiant/help.h @@ -24,6 +24,6 @@ #if !defined( INCLUDED_HELP_H ) #define INCLUDED_HELP_H -void create_game_help_menu( ui::Menu menu ); +void create_game_help_menu(ui::Menu menu); #endif diff --git a/radiant/image.cpp b/radiant/image.cpp index c81b3617..71f365a7 100644 --- a/radiant/image.cpp +++ b/radiant/image.cpp @@ -32,33 +32,37 @@ typedef Modules<_QERPlugImageTable> ImageModules; -ImageModules& Textures_getImageModules(); + +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 ) const { - 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(); - } - } - } - }; +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) const + { + 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(); + } + } + } + }; - Textures_getImageModules().foreachModule( LoadImageVisitor( name, image ) ); + Textures_getImageModules().foreachModule(LoadImageVisitor(name, image)); - return image; + return image; } diff --git a/radiant/image.h b/radiant/image.h index fe0c8e6d..b05323bb 100644 --- a/radiant/image.h +++ b/radiant/image.h @@ -23,6 +23,7 @@ #define INCLUDED_IMAGE_H class Image; -Image* QERApp_LoadImage( void* environment, const char* name ); + +Image *QERApp_LoadImage(void *environment, const char *name); #endif diff --git a/radiant/main.cpp b/radiant/main.cpp index cd328b37..006842a9 100644 --- a/radiant/main.cpp +++ b/radiant/main.cpp @@ -95,122 +95,113 @@ #endif 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" ); - } - - // spam it... - globalErrorStream() << buf << "\n"; - - if (is_fatal) { - ERROR_MESSAGE( "GTK+ error: " << buf ); +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"); + } + + // spam it... + globalErrorStream() << buf << "\n"; + + if (is_fatal) { + ERROR_MESSAGE("GTK+ error: " << buf); } } @@ -218,156 +209,175 @@ void error_redirect( const gchar *domain, GLogLevelFlags log_level, const gchar #include "crtdbg.h" #endif -void crt_init(){ +void crt_init() +{ #if GDEF_COMPILER_MSVC && GDEF_DEBUG - _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif } -class Lock -{ -bool m_locked; +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; -} + 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; +class ScopedLock { + Lock &m_lock; public: -ScopedLock( Lock& lock ) : m_lock( lock ){ - m_lock.lock(); -} -~ScopedLock(){ - m_lock.unlock(); -} + ScopedLock(Lock &lock) : m_lock(lock) + { + m_lock.lock(); + } + + ~ScopedLock() + { + m_lock.unlock(); + } }; -class LineLimitedTextOutputStream : public TextOutputStream -{ -TextOutputStream& outputStream; -std::size_t count; +class LineLimitedTextOutputStream : public TextOutputStream { + TextOutputStream &outputStream; + std::size_t count; public: -LineLimitedTextOutputStream( TextOutputStream& outputStream, std::size_t count ) - : outputStream( outputStream ), count( count ){ -} -std::size_t write( const char* buffer, std::size_t length ){ - if ( count != 0 ) { - const char* p = buffer; - const char* end = buffer + length; - for (;; ) - { - p = std::find( p, end, '\n' ); - if ( p == end ) { - break; - } - ++p; - if ( --count == 0 ) { - length = p - buffer; - break; - } - } - outputStream.write( buffer, length ); - } - return length; -} + LineLimitedTextOutputStream(TextOutputStream &outputStream, std::size_t count) + : outputStream(outputStream), count(count) + { + } + + std::size_t write(const char *buffer, std::size_t length) + { + if (count != 0) { + const char *p = buffer; + const char *end = buffer + length; + for (;;) { + p = std::find(p, end, '\n'); + if (p == end) { + break; + } + ++p; + if (--count == 0) { + length = p - buffer; + break; + } + } + outputStream.write(buffer, length); + } + return length; + } }; -class PopupDebugMessageHandler : public DebugMessageHandler -{ -StringOutputStream m_buffer; -Lock m_lock; +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"; - LineLimitedTextOutputStream outputStream( getOutputStream(), 24 ); - write_stack_trace( outputStream ); - getOutputStream() << "----------------\n"; - globalErrorStream() << m_buffer.c_str(); - if ( !m_lock.locked() ) { - ScopedLock lock( m_lock ); - if (GDEF_DEBUG) { - m_buffer << "Break into the debugger?\n"; - bool handled = ui::alert(ui::root, m_buffer.c_str(), "Radiant - Runtime Error", ui::alert_type::YESNO, ui::alert_icon::Error) == ui::alert_response::NO; - m_buffer.clear(); - return handled; - } else { - m_buffer << "Please report this error to the developers\n"; - ui::alert(ui::root, m_buffer.c_str(), "Radiant - Runtime Error", ui::alert_type::OK, ui::alert_icon::Error); - m_buffer.clear(); + TextOutputStream &getOutputStream() + { + if (!m_lock.locked()) { + return m_buffer; } - } - return true; -} + return globalErrorStream(); + } + + bool handleMessage() + { + getOutputStream() << "----------------\n"; + LineLimitedTextOutputStream outputStream(getOutputStream(), 24); + write_stack_trace(outputStream); + getOutputStream() << "----------------\n"; + globalErrorStream() << m_buffer.c_str(); + if (!m_lock.locked()) { + ScopedLock lock(m_lock); + if (GDEF_DEBUG) { + m_buffer << "Break into the debugger?\n"; + bool handled = ui::alert(ui::root, m_buffer.c_str(), "Radiant - Runtime Error", ui::alert_type::YESNO, + ui::alert_icon::Error) == ui::alert_response::NO; + m_buffer.clear(); + return handled; + } else { + m_buffer << "Please report this error to the developers\n"; + ui::alert(ui::root, m_buffer.c_str(), "Radiant - Runtime Error", ui::alert_type::OK, + ui::alert_icon::Error); + m_buffer.clear(); + } + } + return true; + } }; typedef Static GlobalPopupDebugMessageHandler; -void streams_init(){ - GlobalErrorStream::instance().setOutputStream( getSysPrintErrorStream() ); - GlobalOutputStream::instance().setOutputStream( getSysPrintOutputStream() ); +void streams_init() +{ + GlobalErrorStream::instance().setOutputStream(getSysPrintErrorStream()); + GlobalOutputStream::instance().setOutputStream(getSysPrintOutputStream()); } -void paths_init(){ - g_strSettingsPath = environment_get_home_path(); +void paths_init() +{ + g_strSettingsPath = environment_get_home_path(); - Q_mkdir( g_strSettingsPath.c_str() ); + Q_mkdir(g_strSettingsPath.c_str()); - g_strAppPath = environment_get_app_path(); + 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() ); - } + // 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; + // 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_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 +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 if (GDEF_DEBUG) { return true; } @@ -395,119 +405,122 @@ bool check_version(){ return bVerIsGood; } -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(); - ui::alert( ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error ); - } - - // in debug, never prompt to clean registry, turn console logging auto after a failed start - if (!GDEF_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 (ui::alert(ui::root, msg.c_str(), "Radiant - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) { - g_GamesDialog.Reset(); - } - - msg.clear(); - msg << "Logging console output to " << SettingsPath_get() - << "radiant.log\nRefer to the log if Radiant fails to start again."; - - ui::alert(ui::root, msg.c_str(), "Radiant - Console Log", ui::alert_type::OK); - } - - // 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 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(); + ui::alert(ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error); + } + + // in debug, never prompt to clean registry, turn console logging auto after a failed start + if (!GDEF_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 (ui::alert(ui::root, msg.c_str(), "Radiant - Startup Failure", ui::alert_type::YESNO, + ui::alert_icon::Question) == ui::alert_response::YES) { + g_GamesDialog.Reset(); + } + + msg.clear(); + msg << "Logging console output to " << SettingsPath_get() + << "radiant.log\nRefer to the log if Radiant fails to start again."; + + ui::alert(ui::root, msg.c_str(), "Radiant - Console Log", ui::alert_type::OK); + } + + // 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"; +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(); - ui::alert( ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error ); - } + // close the primary + if (remove(g_pidFile.c_str()) == -1) { + StringOutputStream msg(256); + msg << "WARNING: Could not delete " << g_pidFile.c_str(); + ui::alert(ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error); + } } /*! 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(); - ui::alert( ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error ); - } - - // in debug, never prompt to clean registry, turn console logging auto after a failed start - if (!GDEF_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 (ui::alert(ui::root, msg.c_str(), "Radiant - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) { - Preferences_Reset(); - } - - msg.clear(); - msg << "Logging console output to " << SettingsPath_get() - << "radiant.log\nRefer to the log if Radiant fails to start again."; - - ui::alert(ui::root, msg.c_str(), "Radiant - Console Log", ui::alert_type::OK); - } - - // 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 ); - } - } +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(); + ui::alert(ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error); + } + + // in debug, never prompt to clean registry, turn console logging auto after a failed start + if (!GDEF_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 (ui::alert(ui::root, msg.c_str(), "Radiant - Startup Failure", ui::alert_type::YESNO, + ui::alert_icon::Question) == ui::alert_response::YES) { + Preferences_Reset(); + } + + msg.clear(); + msg << "Logging console output to " << SettingsPath_get() + << "radiant.log\nRefer to the log if Radiant fails to start again."; + + ui::alert(ui::root, msg.c_str(), "Radiant - Console Log", ui::alert_type::OK); + } + + // 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); + } + } } @@ -515,167 +528,170 @@ void create_local_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 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() ); +void user_shortcuts_init() +{ + StringOutputStream path(256); + path << SettingsPath_get() << g_pGameDescription->mGameFile.c_str() << '/'; + LoadCommandMap(path.c_str()); + SaveCommandMap(path.c_str()); } -void user_shortcuts_save(){ - StringOutputStream path( 256 ); - path << SettingsPath_get() << g_pGameDescription->mGameFile.c_str() << '/'; - SaveCommandMap( path.c_str() ); +void user_shortcuts_save() +{ + StringOutputStream path(256); + path << SettingsPath_get() << g_pGameDescription->mGameFile.c_str() << '/'; + SaveCommandMap(path.c_str()); } -int main( int argc, char* argv[] ){ - crt_init(); +int main(int argc, char *argv[]) +{ + crt_init(); - streams_init(); + streams_init(); #if GDEF_OS_WINDOWS - HMODULE lib; - lib = LoadLibrary( "dwmapi.dll" ); - if ( lib != 0 ) { - void ( WINAPI *qDwmEnableComposition )( bool bEnable ) = ( void (WINAPI *) ( bool bEnable ) )GetProcAddress( lib, "DwmEnableComposition" ); - if ( qDwmEnableComposition ) { - qDwmEnableComposition( FALSE ); - } - FreeLibrary( lib ); - } + HMODULE lib; + lib = LoadLibrary( "dwmapi.dll" ); + if ( lib != 0 ) { + void ( WINAPI *qDwmEnableComposition )( bool bEnable ) = ( void (WINAPI *) ( bool bEnable ) )GetProcAddress( lib, "DwmEnableComposition" ); + if ( qDwmEnableComposition ) { + qDwmEnableComposition( FALSE ); + } + FreeLibrary( lib ); + } #endif - const char* mapname = NULL; + const char *mapname = NULL; char const *error = NULL; - if ( !ui::init( &argc, &argv, "", &error) ) { - g_print( "%s\n", error ); - return -1; - } - - // Gtk already removed parsed `--options` - if (argc == 2) { - if ( strlen( argv[1] ) > 1 ) { - if ( g_str_has_suffix( argv[1], ".map" ) ) { - if ( g_path_is_absolute( argv[1] ) ) { - mapname = argv[1]; - } - else { - mapname = g_build_filename( g_get_current_dir(), argv[1], NULL ); - } - } - else { - g_print( "bad file name, will not load: %s\n", argv[1] ); - } - } - } - else if (argc > 2) { - g_print ( "%s\n", "too many arguments" ); - return -1; - } - - // 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 | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION ), 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 | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION ), 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 | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION ), 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 | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION ), 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 | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION ), error_redirect, 0 ); - - GlobalDebugMessageHandler::instance().setHandler( GlobalPopupDebugMessageHandler::instance() ); - - environment_init(argc, (char const **) argv); + if (!ui::init(&argc, &argv, "", &error)) { + g_print("%s\n", error); + return -1; + } - paths_init(); + // Gtk already removed parsed `--options` + if (argc == 2) { + if (strlen(argv[1]) > 1) { + if (g_str_has_suffix(argv[1], ".map")) { + if (g_path_is_absolute(argv[1])) { + mapname = argv[1]; + } else { + mapname = g_build_filename(g_get_current_dir(), argv[1], NULL); + } + } else { + g_print("bad file name, will not load: %s\n", argv[1]); + } + } + } else if (argc > 2) { + g_print("%s\n", "too many arguments"); + return -1; + } - if ( !check_version() ) { - return EXIT_FAILURE; - } + // 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 | + G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), 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 | + G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), 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 | + G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), 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 | + G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), 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 | + G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), error_redirect, 0); + + GlobalDebugMessageHandler::instance().setHandler(GlobalPopupDebugMessageHandler::instance()); + + environment_init(argc, (char const **) argv); + + paths_init(); + + if (!check_version()) { + return EXIT_FAILURE; + } - show_splash(); + show_splash(); - create_global_pid(); + create_global_pid(); - GlobalPreferences_Init(); + GlobalPreferences_Init(); - g_GamesDialog.Init(); + g_GamesDialog.Init(); - g_strGameToolsPath = g_pGameDescription->mGameToolsPath; + g_strGameToolsPath = g_pGameDescription->mGameToolsPath; - remove_global_pid(); + remove_global_pid(); - g_Preferences.Init(); // must occur before create_local_pid() to allow preferences to be reset + g_Preferences.Init(); // must occur before create_local_pid() to allow preferences to be reset - create_local_pid(); + create_local_pid(); - // 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; - } + // 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(); + Radiant_Initialise(); - user_shortcuts_init(); + user_shortcuts_init(); - g_pParentWnd = 0; - g_pParentWnd = new MainFrame(); + g_pParentWnd = 0; + g_pParentWnd = new MainFrame(); - hide_splash(); + hide_splash(); - if ( mapname != NULL ) { - Map_LoadFile( mapname ); - } - else if ( g_bLoadLastMap && !g_strLastMap.empty() ) { - Map_LoadFile( g_strLastMap.c_str() ); - } - else - { - Map_New(); - } + if (mapname != NULL) { + Map_LoadFile(mapname); + } else 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() ); + // load up shaders now that we have the map loaded + // eviltypeguy + TextureBrowser_ShowStartupShaders(GlobalTextureBrowser()); - remove_local_pid(); + remove_local_pid(); - ui::main(); + ui::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; - } + // 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(); + Map_Free(); - if ( !Map_Unnamed( g_map ) ) { - g_strLastMap = Map_Name( g_map ); - } + if (!Map_Unnamed(g_map)) { + g_strLastMap = Map_Name(g_map); + } - delete g_pParentWnd; + delete g_pParentWnd; - user_shortcuts_save(); + user_shortcuts_save(); - Radiant_Shutdown(); + Radiant_Shutdown(); - // close the log file if any - Sys_LogFile( false ); + // close the log file if any + Sys_LogFile(false); - return EXIT_SUCCESS; + return EXIT_SUCCESS; } diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index 2eed7bff..36794f83 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -102,26 +102,26 @@ #include "texwindow.h" -struct layout_globals_t -{ - WindowPosition m_position; - - - int nXYHeight; - int nXYWidth; - int nCamWidth; - int nCamHeight; - int nState; - - layout_globals_t() : - m_position( -1, -1, 640, 480 ), - - nXYHeight( 300 ), - nXYWidth( 300 ), - nCamWidth( 200 ), - nCamHeight( 200 ), - nState( GDK_WINDOW_STATE_MAXIMIZED ){ - } +struct layout_globals_t { + WindowPosition m_position; + + + int nXYHeight; + int nXYWidth; + int nCamWidth; + int nCamHeight; + int nState; + + layout_globals_t() : + m_position(-1, -1, 640, 480), + + nXYHeight(300), + nXYWidth(300), + nCamWidth(200), + nCamHeight(200), + nState(GDK_WINDOW_STATE_MAXIMIZED) + { + } }; layout_globals_t g_layout_globals; @@ -132,57 +132,69 @@ glwindow_globals_t g_glwindow_globals; bool g_vfsInitialized = false; -void VFS_Init(){ - if ( g_vfsInitialized ) return; - QE_InitVFS(); - GlobalFileSystem().initialise(); - g_vfsInitialized = true; -} -void VFS_Shutdown(){ - if ( !g_vfsInitialized ) return; - GlobalFileSystem().shutdown(); - g_vfsInitialized = false; -} -void VFS_Refresh(){ - if ( !g_vfsInitialized ) return; - GlobalFileSystem().clear(); - QE_InitVFS(); - GlobalFileSystem().refresh(); - g_vfsInitialized = true; - // also refresg models - RefreshReferences(); - // also refresh texture browser - TextureBrowser_RefreshShaders(); -} -void VFS_Restart(){ - VFS_Shutdown(); - VFS_Init(); +void VFS_Init() +{ + if (g_vfsInitialized) { return; } + QE_InitVFS(); + GlobalFileSystem().initialise(); + g_vfsInitialized = true; } -class VFSModuleObserver : public ModuleObserver +void VFS_Shutdown() { -public: -void realise(){ - VFS_Init(); + if (!g_vfsInitialized) { return; } + GlobalFileSystem().shutdown(); + g_vfsInitialized = false; } -void unrealise(){ - VFS_Shutdown(); + +void VFS_Refresh() +{ + if (!g_vfsInitialized) { return; } + GlobalFileSystem().clear(); + QE_InitVFS(); + GlobalFileSystem().refresh(); + g_vfsInitialized = true; + // also refresg models + RefreshReferences(); + // also refresh texture browser + TextureBrowser_RefreshShaders(); +} + +void VFS_Restart() +{ + VFS_Shutdown(); + VFS_Init(); } + +class VFSModuleObserver : public ModuleObserver { +public: + void realise() + { + VFS_Init(); + } + + void unrealise() + { + VFS_Shutdown(); + } }; VFSModuleObserver g_VFSModuleObserver; -void VFS_Construct(){ - Radiant_attachHomePathsObserver( g_VFSModuleObserver ); +void VFS_Construct() +{ + Radiant_attachHomePathsObserver(g_VFSModuleObserver); } -void VFS_Destroy(){ - Radiant_detachHomePathsObserver( g_VFSModuleObserver ); + +void VFS_Destroy() +{ + Radiant_detachHomePathsObserver(g_VFSModuleObserver); } // Home Paths #if GDEF_OS_WINDOWS -#include + #include #include const GUID qFOLDERID_SavedGames = {0x4C5C32FF, 0xBB9D, 0x43b0, {0xB5, 0xB4, 0x2D, 0x72, 0xE5, 0x4E, 0xAA, 0xA4}}; #define qREFKNOWNFOLDERID GUID @@ -191,15 +203,16 @@ const GUID qFOLDERID_SavedGames = {0x4C5C32FF, 0xBB9D, 0x43b0, {0xB5, 0xB4, 0x2D typedef HRESULT ( WINAPI qSHGetKnownFolderPath_t )( qREFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath ); static qSHGetKnownFolderPath_t *qSHGetKnownFolderPath; #endif -void HomePaths_Realise(){ - do - { - const char* prefix = g_pGameDescription->getKeyValue( "prefix" ); - if ( !string_empty( prefix ) ) { - StringOutputStream path( 256 ); + +void HomePaths_Realise() +{ + do { + const char *prefix = g_pGameDescription->getKeyValue("prefix"); + if (!string_empty(prefix)) { + StringOutputStream path(256); #if GDEF_OS_MACOS - path.clear(); + path.clear(); path << DirectoryCleaned( g_get_home_dir() ) << "Library/Application Support" << ( prefix + 1 ) << "/"; if ( file_is_directory( path.c_str() ) ) { g_qeglobals.m_userEnginePath = path.c_str(); @@ -210,7 +223,7 @@ void HomePaths_Realise(){ #endif #if GDEF_OS_WINDOWS - TCHAR mydocsdir[MAX_PATH + 1]; + TCHAR mydocsdir[MAX_PATH + 1]; wchar_t *mydocsdirw; HMODULE shfolder = LoadLibrary( "shfolder.dll" ); if ( shfolder ) { @@ -249,64 +262,72 @@ void HomePaths_Realise(){ #endif #if GDEF_OS_POSIX - path.clear(); - path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/"; - g_qeglobals.m_userEnginePath = path.c_str(); - break; + path.clear(); + path << DirectoryCleaned(g_get_home_dir()) << prefix << "/"; + g_qeglobals.m_userEnginePath = path.c_str(); + break; #endif - } + } - g_qeglobals.m_userEnginePath = EnginePath_get(); - } - while ( 0 ); + g_qeglobals.m_userEnginePath = EnginePath_get(); + } while (0); - Q_mkdir( g_qeglobals.m_userEnginePath.c_str() ); + Q_mkdir(g_qeglobals.m_userEnginePath.c_str()); - { - StringOutputStream path( 256 ); - path << g_qeglobals.m_userEnginePath.c_str() << gamename_get() << '/'; - g_qeglobals.m_userGamePath = path.c_str(); - } - ASSERT_MESSAGE( !string_empty( g_qeglobals.m_userGamePath.c_str() ), "HomePaths_Realise: user-game-path is empty" ); - Q_mkdir( g_qeglobals.m_userGamePath.c_str() ); + { + StringOutputStream path(256); + path << g_qeglobals.m_userEnginePath.c_str() << gamename_get() << '/'; + g_qeglobals.m_userGamePath = path.c_str(); + } + ASSERT_MESSAGE(!string_empty(g_qeglobals.m_userGamePath.c_str()), "HomePaths_Realise: user-game-path is empty"); + Q_mkdir(g_qeglobals.m_userGamePath.c_str()); } ModuleObservers g_homePathObservers; -void Radiant_attachHomePathsObserver( ModuleObserver& observer ){ - g_homePathObservers.attach( observer ); +void Radiant_attachHomePathsObserver(ModuleObserver &observer) +{ + g_homePathObservers.attach(observer); } -void Radiant_detachHomePathsObserver( ModuleObserver& observer ){ - g_homePathObservers.detach( observer ); +void Radiant_detachHomePathsObserver(ModuleObserver &observer) +{ + g_homePathObservers.detach(observer); } -class HomePathsModuleObserver : public ModuleObserver -{ -std::size_t m_unrealised; +class HomePathsModuleObserver : public ModuleObserver { + std::size_t m_unrealised; public: -HomePathsModuleObserver() : m_unrealised( 1 ){ -} -void realise(){ - if ( --m_unrealised == 0 ) { - HomePaths_Realise(); - g_homePathObservers.realise(); - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - g_homePathObservers.unrealise(); - } -} + HomePathsModuleObserver() : m_unrealised(1) + { + } + + void realise() + { + if (--m_unrealised == 0) { + HomePaths_Realise(); + g_homePathObservers.realise(); + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + g_homePathObservers.unrealise(); + } + } }; HomePathsModuleObserver g_HomePathsModuleObserver; -void HomePaths_Construct(){ - Radiant_attachEnginePathObserver( g_HomePathsModuleObserver ); +void HomePaths_Construct() +{ + Radiant_attachEnginePathObserver(g_HomePathsModuleObserver); } -void HomePaths_Destroy(){ - Radiant_detachEnginePathObserver( g_HomePathsModuleObserver ); + +void HomePaths_Destroy() +{ + Radiant_detachEnginePathObserver(g_HomePathsModuleObserver); } @@ -316,39 +337,45 @@ CopiedString g_strEnginePath; ModuleObservers g_enginePathObservers; std::size_t g_enginepath_unrealised = 1; -void Radiant_attachEnginePathObserver( ModuleObserver& observer ){ - g_enginePathObservers.attach( observer ); +void Radiant_attachEnginePathObserver(ModuleObserver &observer) +{ + g_enginePathObservers.attach(observer); } -void Radiant_detachEnginePathObserver( ModuleObserver& observer ){ - g_enginePathObservers.detach( observer ); +void Radiant_detachEnginePathObserver(ModuleObserver &observer) +{ + g_enginePathObservers.detach(observer); } -void EnginePath_Realise(){ - if ( --g_enginepath_unrealised == 0 ) { - g_enginePathObservers.realise(); - } +void EnginePath_Realise() +{ + if (--g_enginepath_unrealised == 0) { + g_enginePathObservers.realise(); + } } -const char* EnginePath_get(){ - ASSERT_MESSAGE( g_enginepath_unrealised == 0, "EnginePath_get: engine path not realised" ); - return g_strEnginePath.c_str(); +const char *EnginePath_get() +{ + ASSERT_MESSAGE(g_enginepath_unrealised == 0, "EnginePath_get: engine path not realised"); + return g_strEnginePath.c_str(); } -void EnginePath_Unrealise(){ - if ( ++g_enginepath_unrealised == 1 ) { - g_enginePathObservers.unrealise(); - } +void EnginePath_Unrealise() +{ + if (++g_enginepath_unrealised == 1) { + g_enginePathObservers.unrealise(); + } } -void setEnginePath( const char* path ){ - StringOutputStream buffer( 256 ); - buffer << DirectoryCleaned( path ); - if ( !path_equal( buffer.c_str(), g_strEnginePath.c_str() ) ) { +void setEnginePath(const char *path) +{ + StringOutputStream buffer(256); + buffer << DirectoryCleaned(path); + if (!path_equal(buffer.c_str(), g_strEnginePath.c_str())) { #if 0 - while ( !ConfirmModified( "Paths Changed" ) ) + while ( !ConfirmModified( "Paths Changed" ) ) { if ( Map_Unnamed( g_map ) ) { Map_SaveAs(); @@ -361,67 +388,73 @@ void setEnginePath( const char* path ){ Map_RegionOff(); #endif - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Changing Engine Path" ); + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Changing Engine Path"); - EnginePath_Unrealise(); + EnginePath_Unrealise(); - g_strEnginePath = buffer.c_str(); + g_strEnginePath = buffer.c_str(); - EnginePath_Realise(); - } + EnginePath_Realise(); + } } // Pak Path -CopiedString g_strPakPath[g_pakPathCount] = { "", "", "", "", "" }; +CopiedString g_strPakPath[g_pakPathCount] = {"", "", "", "", ""}; ModuleObservers g_pakPathObservers[g_pakPathCount]; -std::size_t g_pakpath_unrealised[g_pakPathCount] = { 1, 1, 1, 1, 1 }; +std::size_t g_pakpath_unrealised[g_pakPathCount] = {1, 1, 1, 1, 1}; -void Radiant_attachPakPathObserver( int num, ModuleObserver& observer ){ - g_pakPathObservers[num].attach( observer ); +void Radiant_attachPakPathObserver(int num, ModuleObserver &observer) +{ + g_pakPathObservers[num].attach(observer); } -void Radiant_detachPakPathObserver( int num, ModuleObserver& observer ){ - g_pakPathObservers[num].detach( observer ); +void Radiant_detachPakPathObserver(int num, ModuleObserver &observer) +{ + g_pakPathObservers[num].detach(observer); } -void PakPath_Realise( int num ){ - if ( --g_pakpath_unrealised[num] == 0 ) { - g_pakPathObservers[num].realise(); - } +void PakPath_Realise(int num) +{ + if (--g_pakpath_unrealised[num] == 0) { + g_pakPathObservers[num].realise(); + } } -const char* PakPath_get( int num ){ - std::string message = "PakPath_get: pak path " + std::to_string(num) + " not realised"; - ASSERT_MESSAGE( g_pakpath_unrealised[num] == 0, message.c_str() ); - return g_strPakPath[num].c_str(); +const char *PakPath_get(int num) +{ + std::string message = "PakPath_get: pak path " + std::to_string(num) + " not realised"; + ASSERT_MESSAGE(g_pakpath_unrealised[num] == 0, message.c_str()); + return g_strPakPath[num].c_str(); } -void PakPath_Unrealise( int num ){ - if ( ++g_pakpath_unrealised[num] == 1 ) { - g_pakPathObservers[num].unrealise(); - } +void PakPath_Unrealise(int num) +{ + if (++g_pakpath_unrealised[num] == 1) { + g_pakPathObservers[num].unrealise(); + } } -void setPakPath( int num, const char* path ){ - if (!g_strcmp0( path, "")) { - g_strPakPath[num] = ""; - return; - } +void setPakPath(int num, const char *path) +{ + if (!g_strcmp0(path, "")) { + g_strPakPath[num] = ""; + return; + } - StringOutputStream buffer( 256 ); - buffer << DirectoryCleaned( path ); - if ( !path_equal( buffer.c_str(), g_strPakPath[num].c_str() ) ) { - std::string message = "Changing Pak Path " + std::to_string(num); - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", message.c_str() ); + StringOutputStream buffer(256); + buffer << DirectoryCleaned(path); + if (!path_equal(buffer.c_str(), g_strPakPath[num].c_str())) { + std::string message = "Changing Pak Path " + std::to_string(num); + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", message.c_str()); - PakPath_Unrealise(num); + PakPath_Unrealise(num); - g_strPakPath[num] = buffer.c_str(); + g_strPakPath[num] = buffer.c_str(); - PakPath_Realise(num); - } + PakPath_Realise(num); + } } @@ -429,26 +462,30 @@ void setPakPath( int num, const char* path ){ CopiedString g_strAppPath; ///< holds the full path of the executable -const char* AppPath_get(){ - return g_strAppPath.c_str(); +const char *AppPath_get() +{ + return g_strAppPath.c_str(); } /// the path to the local rc-dir -const char* LocalRcPath_get( void ){ - static CopiedString rc_path; - if ( rc_path.empty() ) { - StringOutputStream stream( 256 ); - stream << GlobalRadiant().getSettingsPath() << g_pGameDescription->mGameFile.c_str() << "/"; - rc_path = stream.c_str(); - } - return rc_path.c_str(); +const char *LocalRcPath_get(void) +{ + static CopiedString rc_path; + if (rc_path.empty()) { + StringOutputStream stream(256); + stream << GlobalRadiant().getSettingsPath() << g_pGameDescription->mGameFile.c_str() << "/"; + rc_path = stream.c_str(); + } + return rc_path.c_str(); } /// directory for temp files /// NOTE: on *nix this is were we check for .pid CopiedString g_strSettingsPath; -const char* SettingsPath_get(){ - return g_strSettingsPath.c_str(); + +const char *SettingsPath_get() +{ + return g_strSettingsPath.c_str(); } @@ -463,204 +500,235 @@ const char* SettingsPath_get(){ */ CopiedString g_strGameToolsPath; ///< this is set by g_GamesDialog -const char* GameToolsPath_get(){ - return g_strGameToolsPath.c_str(); +const char *GameToolsPath_get() +{ + return g_strGameToolsPath.c_str(); } struct EnginePath { - static void Export(const CopiedString &self, const Callback &returnz) { - returnz(self.c_str()); - } - - static void Import(CopiedString &self, const char *value) { - setEnginePath( value ); -} + static void Export(const CopiedString &self, const Callback &returnz) + { + returnz(self.c_str()); + } + + static void Import(CopiedString &self, const char *value) + { + setEnginePath(value); + } }; struct PakPath0 { - static void Export( const CopiedString &self, const Callback &returnz ) { - returnz( self.c_str() ); - } - - static void Import( CopiedString &self, const char *value ) { - setPakPath( 0, value ); - } + static void Export(const CopiedString &self, const Callback &returnz) + { + returnz(self.c_str()); + } + + static void Import(CopiedString &self, const char *value) + { + setPakPath(0, value); + } }; -struct PakPath1 { - static void Export( const CopiedString &self, const Callback &returnz ) { - returnz( self.c_str() ); - } - static void Import( CopiedString &self, const char *value ) { - setPakPath( 1, value ); - } +struct PakPath1 { + static void Export(const CopiedString &self, const Callback &returnz) + { + returnz(self.c_str()); + } + + static void Import(CopiedString &self, const char *value) + { + setPakPath(1, value); + } }; -struct PakPath2 { - static void Export( const CopiedString &self, const Callback &returnz ) { - returnz( self.c_str() ); - } - static void Import( CopiedString &self, const char *value ) { - setPakPath( 2, value ); - } +struct PakPath2 { + static void Export(const CopiedString &self, const Callback &returnz) + { + returnz(self.c_str()); + } + + static void Import(CopiedString &self, const char *value) + { + setPakPath(2, value); + } }; -struct PakPath3 { - static void Export( const CopiedString &self, const Callback &returnz ) { - returnz( self.c_str() ); - } - static void Import( CopiedString &self, const char *value ) { - setPakPath( 3, value ); - } +struct PakPath3 { + static void Export(const CopiedString &self, const Callback &returnz) + { + returnz(self.c_str()); + } + + static void Import(CopiedString &self, const char *value) + { + setPakPath(3, value); + } }; -struct PakPath4 { - static void Export( const CopiedString &self, const Callback &returnz ) { - returnz( self.c_str() ); - } - static void Import( CopiedString &self, const char *value ) { - setPakPath( 4, value ); - } +struct PakPath4 { + static void Export(const CopiedString &self, const Callback &returnz) + { + returnz(self.c_str()); + } + + static void Import(CopiedString &self, const char *value) + { + setPakPath(4, value); + } }; bool g_disableEnginePath = false; bool g_disableHomePath = false; -void Paths_constructPreferences( PreferencesPage& page ){ - page.appendPathEntry( "Engine Path", true, make_property(g_strEnginePath) ); - - page.appendCheckBox( - "", "Do not use Engine Path", - g_disableEnginePath - ); - - page.appendCheckBox( - "", "Do not use Home Path", - g_disableHomePath - ); - - for ( int i = 0; i < g_pakPathCount; i++ ) { - std::string label = "Pak Path " + std::to_string(i); - switch (i) { - case 0: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; - case 1: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; - case 2: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; - case 3: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; - case 4: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; - } - } -} -void Paths_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Paths", "Path Settings" ) ); - Paths_constructPreferences( page ); +void Paths_constructPreferences(PreferencesPage &page) +{ + page.appendPathEntry("Engine Path", true, make_property(g_strEnginePath)); + + page.appendCheckBox( + "", "Do not use Engine Path", + g_disableEnginePath + ); + + page.appendCheckBox( + "", "Do not use Home Path", + g_disableHomePath + ); + + for (int i = 0; i < g_pakPathCount; i++) { + std::string label = "Pak Path " + std::to_string(i); + switch (i) { + case 0: + page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); + break; + case 1: + page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); + break; + case 2: + page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); + break; + case 3: + page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); + break; + case 4: + page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); + break; + } + } +} + +void Paths_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Paths", "Path Settings")); + Paths_constructPreferences(page); } -void Paths_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage( makeCallbackF(Paths_constructPage) ); + +void Paths_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(Paths_constructPage)); } -class PathsDialog : public Dialog -{ +class PathsDialog : public Dialog { public: -ui::Window BuildDialog(){ - auto frame = create_dialog_frame( "Path settings", ui::Shadow::ETCHED_IN ); + ui::Window BuildDialog() + { + auto frame = create_dialog_frame("Path settings", ui::Shadow::ETCHED_IN); - auto vbox2 = create_dialog_vbox( 0, 4 ); - frame.add(vbox2); + auto vbox2 = create_dialog_vbox(0, 4); + frame.add(vbox2); - { - PreferencesPage preferencesPage( *this, vbox2 ); - Paths_constructPreferences( preferencesPage ); - } + { + PreferencesPage preferencesPage(*this, vbox2); + Paths_constructPreferences(preferencesPage); + } - return ui::Window(create_simple_modal_dialog_window( "Engine Path Not Found", m_modal, frame )); -} + return ui::Window(create_simple_modal_dialog_window("Engine Path Not Found", m_modal, frame)); + } }; PathsDialog g_PathsDialog; -void EnginePath_verify(){ - if ( !file_exists( g_strEnginePath.c_str() ) ) { - g_PathsDialog.Create(); - g_PathsDialog.DoModal(); - g_PathsDialog.Destroy(); - } +void EnginePath_verify() +{ + if (!file_exists(g_strEnginePath.c_str())) { + g_PathsDialog.Create(); + g_PathsDialog.DoModal(); + g_PathsDialog.Destroy(); + } } -namespace -{ -CopiedString g_gamename; -CopiedString g_gamemode; -ModuleObservers g_gameNameObservers; -ModuleObservers g_gameModeObservers; +namespace { + CopiedString g_gamename; + CopiedString g_gamemode; + ModuleObservers g_gameNameObservers; + ModuleObservers g_gameModeObservers; } -void Radiant_attachGameNameObserver( ModuleObserver& observer ){ - g_gameNameObservers.attach( observer ); +void Radiant_attachGameNameObserver(ModuleObserver &observer) +{ + g_gameNameObservers.attach(observer); } -void Radiant_detachGameNameObserver( ModuleObserver& observer ){ - g_gameNameObservers.detach( observer ); +void Radiant_detachGameNameObserver(ModuleObserver &observer) +{ + g_gameNameObservers.detach(observer); } -const char* basegame_get(){ - return g_pGameDescription->getRequiredKeyValue( "basegame" ); +const char *basegame_get() +{ + return g_pGameDescription->getRequiredKeyValue("basegame"); } -const char* gamename_get(){ - const char* gamename = g_gamename.c_str(); - if ( string_empty( gamename ) ) { - return basegame_get(); - } - return gamename; +const char *gamename_get() +{ + const char *gamename = g_gamename.c_str(); + if (string_empty(gamename)) { + return basegame_get(); + } + return gamename; } -void gamename_set( const char* gamename ){ - if ( !string_equal( gamename, g_gamename.c_str() ) ) { - g_gameNameObservers.unrealise(); - g_gamename = gamename; - g_gameNameObservers.realise(); - } +void gamename_set(const char *gamename) +{ + if (!string_equal(gamename, g_gamename.c_str())) { + g_gameNameObservers.unrealise(); + g_gamename = gamename; + g_gameNameObservers.realise(); + } } -void Radiant_attachGameModeObserver( ModuleObserver& observer ){ - g_gameModeObservers.attach( observer ); +void Radiant_attachGameModeObserver(ModuleObserver &observer) +{ + g_gameModeObservers.attach(observer); } -void Radiant_detachGameModeObserver( ModuleObserver& observer ){ - g_gameModeObservers.detach( observer ); +void Radiant_detachGameModeObserver(ModuleObserver &observer) +{ + g_gameModeObservers.detach(observer); } -const char* gamemode_get(){ - return g_gamemode.c_str(); +const char *gamemode_get() +{ + return g_gamemode.c_str(); } -void gamemode_set( const char* gamemode ){ - if ( !string_equal( gamemode, g_gamemode.c_str() ) ) { - g_gameModeObservers.unrealise(); - g_gamemode = gamemode; - g_gameModeObservers.realise(); - } +void gamemode_set(const char *gamemode) +{ + if (!string_equal(gamemode, g_gamemode.c_str())) { + g_gameModeObservers.unrealise(); + g_gamemode = gamemode; + g_gameModeObservers.realise(); + } } #include "os/dir.h" -const char* const c_library_extension = +const char *const c_library_extension = #if defined( CMAKE_SHARED_MODULE_SUFFIX ) - CMAKE_SHARED_MODULE_SUFFIX + CMAKE_SHARED_MODULE_SUFFIX #elif GDEF_OS_WINDOWS - "dll" + "dll" #elif GDEF_OS_MACOS "dylib" #elif GDEF_OS_LINUX || GDEF_OS_BSD @@ -668,55 +736,62 @@ const char* const c_library_extension = #endif ; -void Radiant_loadModules( const char* path ){ - Directory_forEach(path, matchFileExtension(c_library_extension, [&](const char *name) { - char fullname[1024]; - ASSERT_MESSAGE(strlen(path) + strlen(name) < 1024, ""); - strcpy(fullname, path); - strcat(fullname, name); - globalOutputStream() << "Found '" << fullname << "'\n"; - GlobalModuleServer_loadModule(fullname); - })); +void Radiant_loadModules(const char *path) +{ + Directory_forEach(path, matchFileExtension(c_library_extension, [&](const char *name) { + char fullname[1024]; + ASSERT_MESSAGE(strlen(path) + strlen(name) < 1024, ""); + strcpy(fullname, path); + strcat(fullname, name); + globalOutputStream() << "Found '" << fullname << "'\n"; + GlobalModuleServer_loadModule(fullname); + })); } -void Radiant_loadModulesFromRoot( const char* directory ){ - { - StringOutputStream path( 256 ); - path << directory << g_pluginsDir; - Radiant_loadModules( path.c_str() ); - } +void Radiant_loadModulesFromRoot(const char *directory) +{ + { + StringOutputStream path(256); + path << directory << g_pluginsDir; + Radiant_loadModules(path.c_str()); + } - if ( !string_equal( g_pluginsDir, g_modulesDir ) ) { - StringOutputStream path( 256 ); - path << directory << g_modulesDir; - Radiant_loadModules( path.c_str() ); - } + if (!string_equal(g_pluginsDir, g_modulesDir)) { + StringOutputStream path(256); + path << directory << g_modulesDir; + Radiant_loadModules(path.c_str()); + } } //! Make COLOR_BRUSHES override worldspawn eclass colour. -void SetWorldspawnColour( const Vector3& colour ){ - EntityClass* worldspawn = GlobalEntityClassManager().findOrInsert( "worldspawn", true ); - eclass_release_state( worldspawn ); - worldspawn->color = colour; - eclass_capture_state( worldspawn ); +void SetWorldspawnColour(const Vector3 &colour) +{ + EntityClass *worldspawn = GlobalEntityClassManager().findOrInsert("worldspawn", true); + eclass_release_state(worldspawn); + worldspawn->color = colour; + eclass_capture_state(worldspawn); } -class WorldspawnColourEntityClassObserver : public ModuleObserver -{ -std::size_t m_unrealised; +class WorldspawnColourEntityClassObserver : public ModuleObserver { + std::size_t m_unrealised; public: -WorldspawnColourEntityClassObserver() : m_unrealised( 1 ){ -} -void realise(){ - if ( --m_unrealised == 0 ) { - SetWorldspawnColour( g_xywindow_globals.color_brushes ); - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - } -} + WorldspawnColourEntityClassObserver() : m_unrealised(1) + { + } + + void realise() + { + if (--m_unrealised == 0) { + SetWorldspawnColour(g_xywindow_globals.color_brushes); + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + } + } }; WorldspawnColourEntityClassObserver g_WorldspawnColourEntityClassObserver; @@ -724,1837 +799,1964 @@ WorldspawnColourEntityClassObserver g_WorldspawnColourEntityClassObserver; ModuleObservers g_gameToolsPathObservers; -void Radiant_attachGameToolsPathObserver( ModuleObserver& observer ){ - g_gameToolsPathObservers.attach( observer ); +void Radiant_attachGameToolsPathObserver(ModuleObserver &observer) +{ + g_gameToolsPathObservers.attach(observer); } -void Radiant_detachGameToolsPathObserver( ModuleObserver& observer ){ - g_gameToolsPathObservers.detach( observer ); +void Radiant_detachGameToolsPathObserver(ModuleObserver &observer) +{ + g_gameToolsPathObservers.detach(observer); } -void Radiant_Initialise(){ - GlobalModuleServer_Initialise(); +void Radiant_Initialise() +{ + GlobalModuleServer_Initialise(); - Radiant_loadModulesFromRoot( AppPath_get() ); + Radiant_loadModulesFromRoot(AppPath_get()); - Preferences_Load(); + Preferences_Load(); - bool success = Radiant_Construct( GlobalModuleServer_get() ); - ASSERT_MESSAGE( success, "module system failed to initialise - see radiant.log for error messages" ); + bool success = Radiant_Construct(GlobalModuleServer_get()); + ASSERT_MESSAGE(success, "module system failed to initialise - see radiant.log for error messages"); - g_gameToolsPathObservers.realise(); - g_gameModeObservers.realise(); - g_gameNameObservers.realise(); + g_gameToolsPathObservers.realise(); + g_gameModeObservers.realise(); + g_gameNameObservers.realise(); } -void Radiant_Shutdown(){ - g_gameNameObservers.unrealise(); - g_gameModeObservers.unrealise(); - g_gameToolsPathObservers.unrealise(); +void Radiant_Shutdown() +{ + g_gameNameObservers.unrealise(); + g_gameModeObservers.unrealise(); + g_gameToolsPathObservers.unrealise(); - if ( !g_preferences_globals.disable_ini ) { - globalOutputStream() << "Start writing prefs\n"; - Preferences_Save(); - globalOutputStream() << "Done prefs\n"; - } + if (!g_preferences_globals.disable_ini) { + globalOutputStream() << "Start writing prefs\n"; + Preferences_Save(); + globalOutputStream() << "Done prefs\n"; + } - Radiant_Destroy(); + Radiant_Destroy(); - GlobalModuleServer_Shutdown(); + GlobalModuleServer_Shutdown(); } -void Exit(){ - if ( ConfirmModified( "Exit Radiant" ) ) { - gtk_main_quit(); - } +void Exit() +{ + if (ConfirmModified("Exit Radiant")) { + gtk_main_quit(); + } } -void Undo(){ - GlobalUndoSystem().undo(); - SceneChangeNotify(); +void Undo() +{ + GlobalUndoSystem().undo(); + SceneChangeNotify(); } -void Redo(){ - GlobalUndoSystem().redo(); - SceneChangeNotify(); +void Redo() +{ + GlobalUndoSystem().redo(); + SceneChangeNotify(); } -void deleteSelection(){ - UndoableCommand undo( "deleteSelected" ); - Select_Delete(); +void deleteSelection() +{ + UndoableCommand undo("deleteSelected"); + Select_Delete(); } -void Map_ExportSelected( TextOutputStream& ostream ){ - Map_ExportSelected( ostream, Map_getFormat( g_map ) ); +void Map_ExportSelected(TextOutputStream &ostream) +{ + Map_ExportSelected(ostream, Map_getFormat(g_map)); } -void Map_ImportSelected( TextInputStream& istream ){ - Map_ImportSelected( istream, Map_getFormat( g_map ) ); +void Map_ImportSelected(TextInputStream &istream) +{ + Map_ImportSelected(istream, Map_getFormat(g_map)); } -void Selection_Copy(){ - clipboard_copy( Map_ExportSelected ); +void Selection_Copy() +{ + clipboard_copy(Map_ExportSelected); } -void Selection_Paste(){ - clipboard_paste( Map_ImportSelected ); +void Selection_Paste() +{ + clipboard_paste(Map_ImportSelected); } -void Copy(){ - if ( SelectedFaces_empty() ) { - Selection_Copy(); - } - else - { - SelectedFaces_copyTexture(); - } +void Copy() +{ + if (SelectedFaces_empty()) { + Selection_Copy(); + } else { + SelectedFaces_copyTexture(); + } } -void Paste(){ - if ( SelectedFaces_empty() ) { - UndoableCommand undo( "paste" ); +void Paste() +{ + if (SelectedFaces_empty()) { + UndoableCommand undo("paste"); - GlobalSelectionSystem().setSelectedAll( false ); - Selection_Paste(); - } - else - { - SelectedFaces_pasteTexture(); - } + GlobalSelectionSystem().setSelectedAll(false); + Selection_Paste(); + } else { + SelectedFaces_pasteTexture(); + } } -void PasteToCamera(){ - CamWnd& camwnd = *g_pParentWnd->GetCamWnd(); - GlobalSelectionSystem().setSelectedAll( false ); +void PasteToCamera() +{ + CamWnd &camwnd = *g_pParentWnd->GetCamWnd(); + GlobalSelectionSystem().setSelectedAll(false); - UndoableCommand undo( "pasteToCamera" ); + UndoableCommand undo("pasteToCamera"); - Selection_Paste(); + Selection_Paste(); - // Work out the delta - Vector3 mid; - Select_GetMid( mid ); - Vector3 delta = vector3_subtracted( vector3_snapped( Camera_getOrigin( camwnd ), GetSnapGridSize() ), mid ); + // Work out the delta + Vector3 mid; + Select_GetMid(mid); + Vector3 delta = vector3_subtracted(vector3_snapped(Camera_getOrigin(camwnd), GetSnapGridSize()), mid); - // Move to camera - GlobalSelectionSystem().translateSelected( delta ); + // Move to camera + GlobalSelectionSystem().translateSelected(delta); } -void ColorScheme_Original(){ - TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), Vector3( 0.25f, 0.25f, 0.25f ) ); - - g_camwindow_globals.color_selbrushes3d = Vector3( 1.0f, 0.0f, 0.0f ); - g_camwindow_globals.color_cameraback = Vector3( 0.25f, 0.25f, 0.25f ); - CamWnd_Update( *g_pParentWnd->GetCamWnd() ); - - g_xywindow_globals.color_gridback = Vector3( 1.0f, 1.0f, 1.0f ); - g_xywindow_globals.color_gridminor = Vector3( 0.75f, 0.75f, 0.75f ); - g_xywindow_globals.color_gridmajor = Vector3( 0.5f, 0.5f, 0.5f ); - g_xywindow_globals.color_gridminor_alt = Vector3( 0.5f, 0.0f, 0.0f ); - g_xywindow_globals.color_gridmajor_alt = Vector3( 1.0f, 0.0f, 0.0f ); - g_xywindow_globals.color_gridblock = Vector3( 0.0f, 0.0f, 1.0f ); - g_xywindow_globals.color_gridtext = Vector3( 0.0f, 0.0f, 0.0f ); - g_xywindow_globals.color_selbrushes = Vector3( 1.0f, 0.0f, 0.0f ); - g_xywindow_globals.color_clipper = Vector3( 0.0f, 0.0f, 1.0f ); - g_xywindow_globals.color_brushes = Vector3( 0.0f, 0.0f, 0.0f ); - SetWorldspawnColour( g_xywindow_globals.color_brushes ); - g_xywindow_globals.color_viewname = Vector3( 0.5f, 0.0f, 0.75f ); - XY_UpdateAllWindows(); -} - -void ColorScheme_QER(){ - TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), Vector3( 0.25f, 0.25f, 0.25f ) ); +void ColorScheme_Original() +{ + TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f)); + + g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f); + g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f); + CamWnd_Update(*g_pParentWnd->GetCamWnd()); + + g_xywindow_globals.color_gridback = Vector3(1.0f, 1.0f, 1.0f); + g_xywindow_globals.color_gridminor = Vector3(0.75f, 0.75f, 0.75f); + g_xywindow_globals.color_gridmajor = Vector3(0.5f, 0.5f, 0.5f); + g_xywindow_globals.color_gridminor_alt = Vector3(0.5f, 0.0f, 0.0f); + g_xywindow_globals.color_gridmajor_alt = Vector3(1.0f, 0.0f, 0.0f); + g_xywindow_globals.color_gridblock = Vector3(0.0f, 0.0f, 1.0f); + g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f); + g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f); + g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f); + g_xywindow_globals.color_brushes = Vector3(0.0f, 0.0f, 0.0f); + SetWorldspawnColour(g_xywindow_globals.color_brushes); + g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f); + XY_UpdateAllWindows(); +} + +void ColorScheme_QER() +{ + TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f)); + + g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f); + g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f); + CamWnd_Update(*g_pParentWnd->GetCamWnd()); + + g_xywindow_globals.color_gridback = Vector3(1.0f, 1.0f, 1.0f); + g_xywindow_globals.color_gridminor = Vector3(1.0f, 1.0f, 1.0f); + g_xywindow_globals.color_gridmajor = Vector3(0.5f, 0.5f, 0.5f); + g_xywindow_globals.color_gridblock = Vector3(0.0f, 0.0f, 1.0f); + g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f); + g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f); + g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f); + g_xywindow_globals.color_brushes = Vector3(0.0f, 0.0f, 0.0f); + SetWorldspawnColour(g_xywindow_globals.color_brushes); + g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f); + XY_UpdateAllWindows(); +} + +void ColorScheme_Black() +{ + TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f)); - g_camwindow_globals.color_cameraback = Vector3( 0.25f, 0.25f, 0.25f ); - g_camwindow_globals.color_selbrushes3d = Vector3( 1.0f, 0.0f, 0.0f ); - CamWnd_Update( *g_pParentWnd->GetCamWnd() ); + g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f); + g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f); + CamWnd_Update(*g_pParentWnd->GetCamWnd()); - g_xywindow_globals.color_gridback = Vector3( 1.0f, 1.0f, 1.0f ); - g_xywindow_globals.color_gridminor = Vector3( 1.0f, 1.0f, 1.0f ); - g_xywindow_globals.color_gridmajor = Vector3( 0.5f, 0.5f, 0.5f ); - g_xywindow_globals.color_gridblock = Vector3( 0.0f, 0.0f, 1.0f ); - g_xywindow_globals.color_gridtext = Vector3( 0.0f, 0.0f, 0.0f ); - g_xywindow_globals.color_selbrushes = Vector3( 1.0f, 0.0f, 0.0f ); - g_xywindow_globals.color_clipper = Vector3( 0.0f, 0.0f, 1.0f ); - g_xywindow_globals.color_brushes = Vector3( 0.0f, 0.0f, 0.0f ); - SetWorldspawnColour( g_xywindow_globals.color_brushes ); - g_xywindow_globals.color_viewname = Vector3( 0.5f, 0.0f, 0.75f ); - XY_UpdateAllWindows(); + g_xywindow_globals.color_gridback = Vector3(0.0f, 0.0f, 0.0f); + g_xywindow_globals.color_gridminor = Vector3(0.2f, 0.2f, 0.2f); + g_xywindow_globals.color_gridmajor = Vector3(0.3f, 0.5f, 0.5f); + g_xywindow_globals.color_gridblock = Vector3(0.0f, 0.0f, 1.0f); + g_xywindow_globals.color_gridtext = Vector3(1.0f, 1.0f, 1.0f); + g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f); + g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f); + g_xywindow_globals.color_brushes = Vector3(1.0f, 1.0f, 1.0f); + SetWorldspawnColour(g_xywindow_globals.color_brushes); + g_xywindow_globals.color_viewname = Vector3(0.7f, 0.7f, 0.0f); + XY_UpdateAllWindows(); } -void ColorScheme_Black(){ - TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), Vector3( 0.25f, 0.25f, 0.25f ) ); +/* ydnar: to emulate maya/max/lightwave color schemes */ +void ColorScheme_Ydnar() +{ + TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f)); + + g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f); + g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f); + CamWnd_Update(*g_pParentWnd->GetCamWnd()); + + g_xywindow_globals.color_gridback = Vector3(0.77f, 0.77f, 0.77f); + g_xywindow_globals.color_gridminor = Vector3(0.83f, 0.83f, 0.83f); + g_xywindow_globals.color_gridmajor = Vector3(0.89f, 0.89f, 0.89f); + g_xywindow_globals.color_gridblock = Vector3(1.0f, 1.0f, 1.0f); + g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f); + g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f); + g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f); + g_xywindow_globals.color_brushes = Vector3(0.0f, 0.0f, 0.0f); + SetWorldspawnColour(g_xywindow_globals.color_brushes); + g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f); + XY_UpdateAllWindows(); +} + +typedef Callback GetColourCallback; +typedef Callback SetColourCallback; + +class ChooseColour { + GetColourCallback m_get; + SetColourCallback m_set; +public: + ChooseColour(const GetColourCallback &get, const SetColourCallback &set) + : m_get(get), m_set(set) + { + } + + void operator()() + { + Vector3 colour; + m_get(colour); + color_dialog(MainFrame_getWindow(), colour); + m_set(colour); + } +}; - g_camwindow_globals.color_cameraback = Vector3( 0.25f, 0.25f, 0.25f ); - g_camwindow_globals.color_selbrushes3d = Vector3( 1.0f, 0.0f, 0.0f ); - CamWnd_Update( *g_pParentWnd->GetCamWnd() ); - g_xywindow_globals.color_gridback = Vector3( 0.0f, 0.0f, 0.0f ); - g_xywindow_globals.color_gridminor = Vector3( 0.2f, 0.2f, 0.2f ); - g_xywindow_globals.color_gridmajor = Vector3( 0.3f, 0.5f, 0.5f ); - g_xywindow_globals.color_gridblock = Vector3( 0.0f, 0.0f, 1.0f ); - g_xywindow_globals.color_gridtext = Vector3( 1.0f, 1.0f, 1.0f ); - g_xywindow_globals.color_selbrushes = Vector3( 1.0f, 0.0f, 0.0f ); - g_xywindow_globals.color_clipper = Vector3( 0.0f, 0.0f, 1.0f ); - g_xywindow_globals.color_brushes = Vector3( 1.0f, 1.0f, 1.0f ); - SetWorldspawnColour( g_xywindow_globals.color_brushes ); - g_xywindow_globals.color_viewname = Vector3( 0.7f, 0.7f, 0.0f ); - XY_UpdateAllWindows(); +void Colour_get(const Vector3 &colour, Vector3 &other) +{ + other = colour; } -/* ydnar: to emulate maya/max/lightwave color schemes */ -void ColorScheme_Ydnar(){ - TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), Vector3( 0.25f, 0.25f, 0.25f ) ); - - g_camwindow_globals.color_cameraback = Vector3( 0.25f, 0.25f, 0.25f ); - g_camwindow_globals.color_selbrushes3d = Vector3( 1.0f, 0.0f, 0.0f ); - CamWnd_Update( *g_pParentWnd->GetCamWnd() ); +typedef ConstReferenceCaller ColourGetCaller; - g_xywindow_globals.color_gridback = Vector3( 0.77f, 0.77f, 0.77f ); - g_xywindow_globals.color_gridminor = Vector3( 0.83f, 0.83f, 0.83f ); - g_xywindow_globals.color_gridmajor = Vector3( 0.89f, 0.89f, 0.89f ); - g_xywindow_globals.color_gridblock = Vector3( 1.0f, 1.0f, 1.0f ); - g_xywindow_globals.color_gridtext = Vector3( 0.0f, 0.0f, 0.0f ); - g_xywindow_globals.color_selbrushes = Vector3( 1.0f, 0.0f, 0.0f ); - g_xywindow_globals.color_clipper = Vector3( 0.0f, 0.0f, 1.0f ); - g_xywindow_globals.color_brushes = Vector3( 0.0f, 0.0f, 0.0f ); - SetWorldspawnColour( g_xywindow_globals.color_brushes ); - g_xywindow_globals.color_viewname = Vector3( 0.5f, 0.0f, 0.75f ); - XY_UpdateAllWindows(); +void Colour_set(Vector3 &colour, const Vector3 &other) +{ + colour = other; + SceneChangeNotify(); } -typedef Callback GetColourCallback; -typedef Callback SetColourCallback; +typedef ReferenceCaller ColourSetCaller; -class ChooseColour +void BrushColour_set(const Vector3 &other) { -GetColourCallback m_get; -SetColourCallback m_set; -public: -ChooseColour( const GetColourCallback& get, const SetColourCallback& set ) - : m_get( get ), m_set( set ){ -} -void operator()(){ - Vector3 colour; - m_get( colour ); - color_dialog( MainFrame_getWindow(), colour ); - m_set( colour ); + g_xywindow_globals.color_brushes = other; + SetWorldspawnColour(g_xywindow_globals.color_brushes); + SceneChangeNotify(); } -}; - +typedef FreeCaller BrushColourSetCaller; -void Colour_get( const Vector3& colour, Vector3& other ){ - other = colour; +void ClipperColour_set(const Vector3 &other) +{ + g_xywindow_globals.color_clipper = other; + Brush_clipperColourChanged(); + SceneChangeNotify(); } -typedef ConstReferenceCaller ColourGetCaller; -void Colour_set( Vector3& colour, const Vector3& other ){ - colour = other; - SceneChangeNotify(); -} -typedef ReferenceCaller ColourSetCaller; +typedef FreeCaller ClipperColourSetCaller; -void BrushColour_set( const Vector3& other ){ - g_xywindow_globals.color_brushes = other; - SetWorldspawnColour( g_xywindow_globals.color_brushes ); - SceneChangeNotify(); +void TextureBrowserColour_get(Vector3 &other) +{ + other = TextureBrowser_getBackgroundColour(GlobalTextureBrowser()); } -typedef FreeCaller BrushColourSetCaller; -void ClipperColour_set( const Vector3& other ){ - g_xywindow_globals.color_clipper = other; - Brush_clipperColourChanged(); - SceneChangeNotify(); -} -typedef FreeCaller ClipperColourSetCaller; +typedef FreeCaller TextureBrowserColourGetCaller; -void TextureBrowserColour_get( Vector3& other ){ - other = TextureBrowser_getBackgroundColour( GlobalTextureBrowser() ); +void TextureBrowserColour_set(const Vector3 &other) +{ + TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), other); } -typedef FreeCaller TextureBrowserColourGetCaller; -void TextureBrowserColour_set( const Vector3& other ){ - TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), other ); -} -typedef FreeCaller TextureBrowserColourSetCaller; +typedef FreeCaller TextureBrowserColourSetCaller; -class ColoursMenu -{ +class ColoursMenu { public: -ChooseColour m_textureback; -ChooseColour m_xyback; -ChooseColour m_gridmajor; -ChooseColour m_gridminor; -ChooseColour m_gridmajor_alt; -ChooseColour m_gridminor_alt; -ChooseColour m_gridtext; -ChooseColour m_gridblock; -ChooseColour m_cameraback; -ChooseColour m_brush; -ChooseColour m_selectedbrush; -ChooseColour m_selectedbrush3d; -ChooseColour m_clipper; -ChooseColour m_viewname; - -ColoursMenu() : - m_textureback( TextureBrowserColourGetCaller(), TextureBrowserColourSetCaller() ), - m_xyback( ColourGetCaller( g_xywindow_globals.color_gridback ), ColourSetCaller( g_xywindow_globals.color_gridback ) ), - m_gridmajor( ColourGetCaller( g_xywindow_globals.color_gridmajor ), ColourSetCaller( g_xywindow_globals.color_gridmajor ) ), - m_gridminor( ColourGetCaller( g_xywindow_globals.color_gridminor ), ColourSetCaller( g_xywindow_globals.color_gridminor ) ), - m_gridmajor_alt( ColourGetCaller( g_xywindow_globals.color_gridmajor_alt ), ColourSetCaller( g_xywindow_globals.color_gridmajor_alt ) ), - m_gridminor_alt( ColourGetCaller( g_xywindow_globals.color_gridminor_alt ), ColourSetCaller( g_xywindow_globals.color_gridminor_alt ) ), - m_gridtext( ColourGetCaller( g_xywindow_globals.color_gridtext ), ColourSetCaller( g_xywindow_globals.color_gridtext ) ), - m_gridblock( ColourGetCaller( g_xywindow_globals.color_gridblock ), ColourSetCaller( g_xywindow_globals.color_gridblock ) ), - m_cameraback( ColourGetCaller( g_camwindow_globals.color_cameraback ), ColourSetCaller( g_camwindow_globals.color_cameraback ) ), - m_brush( ColourGetCaller( g_xywindow_globals.color_brushes ), BrushColourSetCaller() ), - m_selectedbrush( ColourGetCaller( g_xywindow_globals.color_selbrushes ), ColourSetCaller( g_xywindow_globals.color_selbrushes ) ), - m_selectedbrush3d( ColourGetCaller( g_camwindow_globals.color_selbrushes3d ), ColourSetCaller( g_camwindow_globals.color_selbrushes3d ) ), - m_clipper( ColourGetCaller( g_xywindow_globals.color_clipper ), ClipperColourSetCaller() ), - m_viewname( ColourGetCaller( g_xywindow_globals.color_viewname ), ColourSetCaller( g_xywindow_globals.color_viewname ) ){ -} + ChooseColour m_textureback; + ChooseColour m_xyback; + ChooseColour m_gridmajor; + ChooseColour m_gridminor; + ChooseColour m_gridmajor_alt; + ChooseColour m_gridminor_alt; + ChooseColour m_gridtext; + ChooseColour m_gridblock; + ChooseColour m_cameraback; + ChooseColour m_brush; + ChooseColour m_selectedbrush; + ChooseColour m_selectedbrush3d; + ChooseColour m_clipper; + ChooseColour m_viewname; + + ColoursMenu() : + m_textureback(TextureBrowserColourGetCaller(), TextureBrowserColourSetCaller()), + m_xyback(ColourGetCaller(g_xywindow_globals.color_gridback), + ColourSetCaller(g_xywindow_globals.color_gridback)), + m_gridmajor(ColourGetCaller(g_xywindow_globals.color_gridmajor), + ColourSetCaller(g_xywindow_globals.color_gridmajor)), + m_gridminor(ColourGetCaller(g_xywindow_globals.color_gridminor), + ColourSetCaller(g_xywindow_globals.color_gridminor)), + m_gridmajor_alt(ColourGetCaller(g_xywindow_globals.color_gridmajor_alt), + ColourSetCaller(g_xywindow_globals.color_gridmajor_alt)), + m_gridminor_alt(ColourGetCaller(g_xywindow_globals.color_gridminor_alt), + ColourSetCaller(g_xywindow_globals.color_gridminor_alt)), + m_gridtext(ColourGetCaller(g_xywindow_globals.color_gridtext), + ColourSetCaller(g_xywindow_globals.color_gridtext)), + m_gridblock(ColourGetCaller(g_xywindow_globals.color_gridblock), + ColourSetCaller(g_xywindow_globals.color_gridblock)), + m_cameraback(ColourGetCaller(g_camwindow_globals.color_cameraback), + ColourSetCaller(g_camwindow_globals.color_cameraback)), + m_brush(ColourGetCaller(g_xywindow_globals.color_brushes), BrushColourSetCaller()), + m_selectedbrush(ColourGetCaller(g_xywindow_globals.color_selbrushes), + ColourSetCaller(g_xywindow_globals.color_selbrushes)), + m_selectedbrush3d(ColourGetCaller(g_camwindow_globals.color_selbrushes3d), + ColourSetCaller(g_camwindow_globals.color_selbrushes3d)), + m_clipper(ColourGetCaller(g_xywindow_globals.color_clipper), ClipperColourSetCaller()), + m_viewname(ColourGetCaller(g_xywindow_globals.color_viewname), + ColourSetCaller(g_xywindow_globals.color_viewname)) + { + } }; ColoursMenu g_ColoursMenu; -ui::MenuItem create_colours_menu(){ - auto colours_menu_item = new_sub_menu_item_with_mnemonic( "Colors" ); - auto menu_in_menu = ui::Menu::from( gtk_menu_item_get_submenu( colours_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - - auto menu_3 = create_sub_menu_with_mnemonic( menu_in_menu, "Themes" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_3 ); - } - - create_menu_item_with_mnemonic( menu_3, "QE4 Original", "ColorSchemeOriginal" ); - create_menu_item_with_mnemonic( menu_3, "Q3Radiant Original", "ColorSchemeQER" ); - create_menu_item_with_mnemonic( menu_3, "Black and Green", "ColorSchemeBlackAndGreen" ); - create_menu_item_with_mnemonic( menu_3, "Maya/Max/Lightwave Emulation", "ColorSchemeYdnar" ); - - menu_separator( menu_in_menu ); - - create_menu_item_with_mnemonic( menu_in_menu, "_Texture Background...", "ChooseTextureBackgroundColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Grid Background...", "ChooseGridBackgroundColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Grid Major...", "ChooseGridMajorColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Grid Minor...", "ChooseGridMinorColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Grid Major Small...", "ChooseSmallGridMajorColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Grid Minor Small...", "ChooseSmallGridMinorColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Grid Text...", "ChooseGridTextColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Grid Block...", "ChooseGridBlockColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Default Brush...", "ChooseBrushColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Camera Background...", "ChooseCameraBackgroundColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Selected Brush...", "ChooseSelectedBrushColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Selected Brush (Camera)...", "ChooseCameraSelectedBrushColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Clipper...", "ChooseClipperColor" ); - create_menu_item_with_mnemonic( menu_in_menu, "Active View name...", "ChooseOrthoViewNameColor" ); - - return colours_menu_item; -} - - -void Restart(){ - PluginsMenu_clear(); - PluginToolbar_clear(); +ui::MenuItem create_colours_menu() +{ + auto colours_menu_item = new_sub_menu_item_with_mnemonic("Colors"); + auto menu_in_menu = ui::Menu::from(gtk_menu_item_get_submenu(colours_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + + auto menu_3 = create_sub_menu_with_mnemonic(menu_in_menu, "Themes"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_3); + } + + create_menu_item_with_mnemonic(menu_3, "QE4 Original", "ColorSchemeOriginal"); + create_menu_item_with_mnemonic(menu_3, "Q3Radiant Original", "ColorSchemeQER"); + create_menu_item_with_mnemonic(menu_3, "Black and Green", "ColorSchemeBlackAndGreen"); + create_menu_item_with_mnemonic(menu_3, "Maya/Max/Lightwave Emulation", "ColorSchemeYdnar"); + + menu_separator(menu_in_menu); + + create_menu_item_with_mnemonic(menu_in_menu, "_Texture Background...", "ChooseTextureBackgroundColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Grid Background...", "ChooseGridBackgroundColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Grid Major...", "ChooseGridMajorColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Grid Minor...", "ChooseGridMinorColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Grid Major Small...", "ChooseSmallGridMajorColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Grid Minor Small...", "ChooseSmallGridMinorColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Grid Text...", "ChooseGridTextColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Grid Block...", "ChooseGridBlockColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Default Brush...", "ChooseBrushColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Camera Background...", "ChooseCameraBackgroundColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Selected Brush...", "ChooseSelectedBrushColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Selected Brush (Camera)...", "ChooseCameraSelectedBrushColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Clipper...", "ChooseClipperColor"); + create_menu_item_with_mnemonic(menu_in_menu, "Active View name...", "ChooseOrthoViewNameColor"); + + return colours_menu_item; +} + + +void Restart() +{ + PluginsMenu_clear(); + PluginToolbar_clear(); - Radiant_Shutdown(); - Radiant_Initialise(); + Radiant_Shutdown(); + Radiant_Initialise(); - PluginsMenu_populate(); + PluginsMenu_populate(); - PluginToolbar_populate(); + PluginToolbar_populate(); } -void thunk_OnSleep(){ - g_pParentWnd->OnSleep(); +void thunk_OnSleep() +{ + g_pParentWnd->OnSleep(); } -void OpenHelpURL(){ - OpenURL( "https://gitlab.com/xonotic/xonotic/wikis/Mapping" ); +void OpenHelpURL() +{ + OpenURL("https://gitlab.com/xonotic/xonotic/wikis/Mapping"); } -void OpenBugReportURL(){ - OpenURL( "https://gitlab.com/xonotic/netradiant/issues" ); +void OpenBugReportURL() +{ + OpenURL("https://gitlab.com/xonotic/netradiant/issues"); } ui::Widget g_page_console{ui::null}; -void Console_ToggleShow(){ - GroupDialog_showPage( g_page_console ); +void Console_ToggleShow() +{ + GroupDialog_showPage(g_page_console); } ui::Widget g_page_entity{ui::null}; -void EntityInspector_ToggleShow(){ - GroupDialog_showPage( g_page_entity ); +void EntityInspector_ToggleShow() +{ + GroupDialog_showPage(g_page_entity); } +void SetClipMode(bool enable); -void SetClipMode( bool enable ); void ModeChangeNotify(); typedef void ( *ToolMode )(); + ToolMode g_currentToolMode = 0; bool g_currentToolModeSupportsComponentEditing = false; ToolMode g_defaultToolMode = 0; - -void SelectionSystem_DefaultMode(){ - GlobalSelectionSystem().SetMode( SelectionSystem::ePrimitive ); - GlobalSelectionSystem().SetComponentMode( SelectionSystem::eDefault ); - ModeChangeNotify(); +void SelectionSystem_DefaultMode() +{ + GlobalSelectionSystem().SetMode(SelectionSystem::ePrimitive); + GlobalSelectionSystem().SetComponentMode(SelectionSystem::eDefault); + ModeChangeNotify(); } -bool EdgeMode(){ - return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent - && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eEdge; +bool EdgeMode() +{ + return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent + && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eEdge; } -bool VertexMode(){ - return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent - && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex; +bool VertexMode() +{ + return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent + && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex; } -bool FaceMode(){ - return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent - && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace; +bool FaceMode() +{ + return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent + && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace; } -template -class BoolFunctionExport -{ +template +class BoolFunctionExport { public: -static void apply( const Callback & importCallback ){ - importCallback( BoolFunction() ); -} + static void apply(const Callback &importCallback) + { + importCallback(BoolFunction()); + } }; typedef FreeCaller &), &BoolFunctionExport::apply> EdgeModeApplyCaller; EdgeModeApplyCaller g_edgeMode_button_caller; -Callback &)> g_edgeMode_button_callback( g_edgeMode_button_caller ); -ToggleItem g_edgeMode_button( g_edgeMode_button_callback ); +Callback &)> g_edgeMode_button_callback(g_edgeMode_button_caller); +ToggleItem g_edgeMode_button(g_edgeMode_button_callback); typedef FreeCaller &), &BoolFunctionExport::apply> VertexModeApplyCaller; VertexModeApplyCaller g_vertexMode_button_caller; -Callback &)> g_vertexMode_button_callback( g_vertexMode_button_caller ); -ToggleItem g_vertexMode_button( g_vertexMode_button_callback ); +Callback &)> g_vertexMode_button_callback(g_vertexMode_button_caller); +ToggleItem g_vertexMode_button(g_vertexMode_button_callback); typedef FreeCaller &), &BoolFunctionExport::apply> FaceModeApplyCaller; FaceModeApplyCaller g_faceMode_button_caller; -Callback &)> g_faceMode_button_callback( g_faceMode_button_caller ); -ToggleItem g_faceMode_button( g_faceMode_button_callback ); +Callback &)> g_faceMode_button_callback(g_faceMode_button_caller); +ToggleItem g_faceMode_button(g_faceMode_button_callback); -void ComponentModeChanged(){ - g_edgeMode_button.update(); - g_vertexMode_button.update(); - g_faceMode_button.update(); +void ComponentModeChanged() +{ + g_edgeMode_button.update(); + g_vertexMode_button.update(); + g_faceMode_button.update(); } -void ComponentMode_SelectionChanged( const Selectable& selectable ){ - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent - && GlobalSelectionSystem().countSelected() == 0 ) { - SelectionSystem_DefaultMode(); - ComponentModeChanged(); - } +void ComponentMode_SelectionChanged(const Selectable &selectable) +{ + if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent + && GlobalSelectionSystem().countSelected() == 0) { + SelectionSystem_DefaultMode(); + ComponentModeChanged(); + } } -void SelectEdgeMode(){ +void SelectEdgeMode() +{ #if 0 - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { GlobalSelectionSystem().Select( false ); } #endif - if ( EdgeMode() ) { - SelectionSystem_DefaultMode(); - } - else if ( GlobalSelectionSystem().countSelected() != 0 ) { - if ( !g_currentToolModeSupportsComponentEditing ) { - g_defaultToolMode(); - } + if (EdgeMode()) { + SelectionSystem_DefaultMode(); + } else if (GlobalSelectionSystem().countSelected() != 0) { + if (!g_currentToolModeSupportsComponentEditing) { + g_defaultToolMode(); + } - GlobalSelectionSystem().SetMode( SelectionSystem::eComponent ); - GlobalSelectionSystem().SetComponentMode( SelectionSystem::eEdge ); - } + GlobalSelectionSystem().SetMode(SelectionSystem::eComponent); + GlobalSelectionSystem().SetComponentMode(SelectionSystem::eEdge); + } - ComponentModeChanged(); + ComponentModeChanged(); - ModeChangeNotify(); + ModeChangeNotify(); } -void SelectVertexMode(){ +void SelectVertexMode() +{ #if 0 - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { GlobalSelectionSystem().Select( false ); } #endif - if ( VertexMode() ) { - SelectionSystem_DefaultMode(); - } - else if ( GlobalSelectionSystem().countSelected() != 0 ) { - if ( !g_currentToolModeSupportsComponentEditing ) { - g_defaultToolMode(); - } + if (VertexMode()) { + SelectionSystem_DefaultMode(); + } else if (GlobalSelectionSystem().countSelected() != 0) { + if (!g_currentToolModeSupportsComponentEditing) { + g_defaultToolMode(); + } - GlobalSelectionSystem().SetMode( SelectionSystem::eComponent ); - GlobalSelectionSystem().SetComponentMode( SelectionSystem::eVertex ); - } + GlobalSelectionSystem().SetMode(SelectionSystem::eComponent); + GlobalSelectionSystem().SetComponentMode(SelectionSystem::eVertex); + } - ComponentModeChanged(); + ComponentModeChanged(); - ModeChangeNotify(); + ModeChangeNotify(); } -void SelectFaceMode(){ +void SelectFaceMode() +{ #if 0 - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { GlobalSelectionSystem().Select( false ); } #endif - if ( FaceMode() ) { - SelectionSystem_DefaultMode(); - } - else if ( GlobalSelectionSystem().countSelected() != 0 ) { - if ( !g_currentToolModeSupportsComponentEditing ) { - g_defaultToolMode(); - } + if (FaceMode()) { + SelectionSystem_DefaultMode(); + } else if (GlobalSelectionSystem().countSelected() != 0) { + if (!g_currentToolModeSupportsComponentEditing) { + g_defaultToolMode(); + } - GlobalSelectionSystem().SetMode( SelectionSystem::eComponent ); - GlobalSelectionSystem().SetComponentMode( SelectionSystem::eFace ); - } + GlobalSelectionSystem().SetMode(SelectionSystem::eComponent); + GlobalSelectionSystem().SetComponentMode(SelectionSystem::eFace); + } - ComponentModeChanged(); + ComponentModeChanged(); - ModeChangeNotify(); + ModeChangeNotify(); } -class CloneSelected : public scene::Graph::Walker -{ -bool doMakeUnique; -NodeSmartReference worldspawn; +class CloneSelected : public scene::Graph::Walker { + bool doMakeUnique; + NodeSmartReference worldspawn; public: -CloneSelected( bool d ) : doMakeUnique( d ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.size() == 1 ) { - return true; - } - - // ignore worldspawn, but keep checking children - NodeSmartReference me( path.top().get() ); - if ( me == worldspawn ) { - return true; - } + CloneSelected(bool d) : doMakeUnique(d), worldspawn(Map_FindOrInsertWorldspawn(g_map)) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.size() == 1) { + return true; + } + + // ignore worldspawn, but keep checking children + NodeSmartReference me(path.top().get()); + if (me == worldspawn) { + return true; + } + + if (!path.top().get().isRoot()) { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected()) { + return false; + } + } + + return true; + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + if (path.size() == 1) { + return; + } + + // ignore worldspawn, but keep checking children + NodeSmartReference me(path.top().get()); + if (me == worldspawn) { + return; + } + + if (!path.top().get().isRoot()) { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected()) { + NodeSmartReference clone(Node_Clone(path.top())); + if (doMakeUnique) { + Map_gatherNamespaced(clone); + } + Node_getTraversable(path.parent().get())->insert(clone); + } + } + } +}; - if ( !path.top().get().isRoot() ) { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() ) { - return false; - } - } +void Scene_Clone_Selected(scene::Graph &graph, bool doMakeUnique) +{ + graph.traverse(CloneSelected(doMakeUnique)); - return true; + Map_mergeClonedNames(); } -void post( const scene::Path& path, scene::Instance& instance ) const { - if ( path.size() == 1 ) { - return; - } - - // ignore worldspawn, but keep checking children - NodeSmartReference me( path.top().get() ); - if ( me == worldspawn ) { - return; - } - if ( !path.top().get().isRoot() ) { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() ) { - NodeSmartReference clone( Node_Clone( path.top() ) ); - if ( doMakeUnique ) { - Map_gatherNamespaced( clone ); - } - Node_getTraversable( path.parent().get() )->insert( clone ); - } - } -} +enum ENudgeDirection { + eNudgeUp = 1, + eNudgeDown = 3, + eNudgeLeft = 0, + eNudgeRight = 2, }; -void Scene_Clone_Selected( scene::Graph& graph, bool doMakeUnique ){ - graph.traverse( CloneSelected( doMakeUnique ) ); +struct AxisBase { + Vector3 x; + Vector3 y; + Vector3 z; - Map_mergeClonedNames(); -} - -enum ENudgeDirection -{ - eNudgeUp = 1, - eNudgeDown = 3, - eNudgeLeft = 0, - eNudgeRight = 2, + AxisBase(const Vector3 &x_, const Vector3 &y_, const Vector3 &z_) + : x(x_), y(y_), z(z_) + { + } }; -struct AxisBase +AxisBase AxisBase_forViewType(VIEWTYPE viewtype) { - Vector3 x; - Vector3 y; - Vector3 z; - AxisBase( const Vector3& x_, const Vector3& y_, const Vector3& z_ ) - : x( x_ ), y( y_ ), z( z_ ){ - } -}; - -AxisBase AxisBase_forViewType( VIEWTYPE viewtype ){ - switch ( viewtype ) - { - case XY: - return AxisBase( g_vector3_axis_x, g_vector3_axis_y, g_vector3_axis_z ); - case XZ: - return AxisBase( g_vector3_axis_x, g_vector3_axis_z, g_vector3_axis_y ); - case YZ: - return AxisBase( g_vector3_axis_y, g_vector3_axis_z, g_vector3_axis_x ); - } + switch (viewtype) { + case XY: + return AxisBase(g_vector3_axis_x, g_vector3_axis_y, g_vector3_axis_z); + case XZ: + return AxisBase(g_vector3_axis_x, g_vector3_axis_z, g_vector3_axis_y); + case YZ: + return AxisBase(g_vector3_axis_y, g_vector3_axis_z, g_vector3_axis_x); + } - ERROR_MESSAGE( "invalid viewtype" ); - return AxisBase( Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ) ); + ERROR_MESSAGE("invalid viewtype"); + return AxisBase(Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(0, 0, 0)); } -Vector3 AxisBase_axisForDirection( const AxisBase& axes, ENudgeDirection direction ){ - switch ( direction ) - { - case eNudgeLeft: - return vector3_negated( axes.x ); - case eNudgeUp: - return axes.y; - case eNudgeRight: - return axes.x; - case eNudgeDown: - return vector3_negated( axes.y ); - } - - ERROR_MESSAGE( "invalid direction" ); - return Vector3( 0, 0, 0 ); -} - -void NudgeSelection( ENudgeDirection direction, float fAmount, VIEWTYPE viewtype ){ - AxisBase axes( AxisBase_forViewType( viewtype ) ); - Vector3 view_direction( vector3_negated( axes.z ) ); - Vector3 nudge( vector3_scaled( AxisBase_axisForDirection( axes, direction ), fAmount ) ); - GlobalSelectionSystem().NudgeManipulator( nudge, view_direction ); +Vector3 AxisBase_axisForDirection(const AxisBase &axes, ENudgeDirection direction) +{ + switch (direction) { + case eNudgeLeft: + return vector3_negated(axes.x); + case eNudgeUp: + return axes.y; + case eNudgeRight: + return axes.x; + case eNudgeDown: + return vector3_negated(axes.y); + } + + ERROR_MESSAGE("invalid direction"); + return Vector3(0, 0, 0); +} + +void NudgeSelection(ENudgeDirection direction, float fAmount, VIEWTYPE viewtype) +{ + AxisBase axes(AxisBase_forViewType(viewtype)); + Vector3 view_direction(vector3_negated(axes.z)); + Vector3 nudge(vector3_scaled(AxisBase_axisForDirection(axes, direction), fAmount)); + GlobalSelectionSystem().NudgeManipulator(nudge, view_direction); } -void Selection_Clone(){ - if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) { - UndoableCommand undo( "cloneSelected" ); +void Selection_Clone() +{ + if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) { + UndoableCommand undo("cloneSelected"); - Scene_Clone_Selected( GlobalSceneGraph(), false ); + Scene_Clone_Selected(GlobalSceneGraph(), false); - //NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); - //NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); - } + //NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); + //NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); + } } -void Selection_Clone_MakeUnique(){ - if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) { - UndoableCommand undo( "cloneSelectedMakeUnique" ); +void Selection_Clone_MakeUnique() +{ + if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) { + UndoableCommand undo("cloneSelectedMakeUnique"); - Scene_Clone_Selected( GlobalSceneGraph(), true ); + Scene_Clone_Selected(GlobalSceneGraph(), true); - //NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); - //NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); - } + //NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); + //NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); + } } // called when the escape key is used (either on the main window or on an inspector) -void Selection_Deselect(){ - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { - if ( GlobalSelectionSystem().countSelectedComponents() != 0 ) { - GlobalSelectionSystem().setSelectedAllComponents( false ); - } - else - { - SelectionSystem_DefaultMode(); - ComponentModeChanged(); - } - } - else - { - if ( GlobalSelectionSystem().countSelectedComponents() != 0 ) { - GlobalSelectionSystem().setSelectedAllComponents( false ); - } - else - { - GlobalSelectionSystem().setSelectedAll( false ); - } - } -} - - -void Selection_NudgeUp(){ - UndoableCommand undo( "nudgeSelectedUp" ); - NudgeSelection( eNudgeUp, GetGridSize(), GlobalXYWnd_getCurrentViewType() ); +void Selection_Deselect() +{ + if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent) { + if (GlobalSelectionSystem().countSelectedComponents() != 0) { + GlobalSelectionSystem().setSelectedAllComponents(false); + } else { + SelectionSystem_DefaultMode(); + ComponentModeChanged(); + } + } else { + if (GlobalSelectionSystem().countSelectedComponents() != 0) { + GlobalSelectionSystem().setSelectedAllComponents(false); + } else { + GlobalSelectionSystem().setSelectedAll(false); + } + } +} + + +void Selection_NudgeUp() +{ + UndoableCommand undo("nudgeSelectedUp"); + NudgeSelection(eNudgeUp, GetGridSize(), GlobalXYWnd_getCurrentViewType()); } -void Selection_NudgeDown(){ - UndoableCommand undo( "nudgeSelectedDown" ); - NudgeSelection( eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType() ); +void Selection_NudgeDown() +{ + UndoableCommand undo("nudgeSelectedDown"); + NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); } -void Selection_NudgeLeft(){ - UndoableCommand undo( "nudgeSelectedLeft" ); - NudgeSelection( eNudgeLeft, GetGridSize(), GlobalXYWnd_getCurrentViewType() ); +void Selection_NudgeLeft() +{ + UndoableCommand undo("nudgeSelectedLeft"); + NudgeSelection(eNudgeLeft, GetGridSize(), GlobalXYWnd_getCurrentViewType()); } -void Selection_NudgeRight(){ - UndoableCommand undo( "nudgeSelectedRight" ); - NudgeSelection( eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType() ); +void Selection_NudgeRight() +{ + UndoableCommand undo("nudgeSelectedRight"); + NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); } -void TranslateToolExport( const Callback & importCallback ){ - importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eTranslate ); +void TranslateToolExport(const Callback &importCallback) +{ + importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eTranslate); } -void RotateToolExport( const Callback & importCallback ){ - importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eRotate ); +void RotateToolExport(const Callback &importCallback) +{ + importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eRotate); } -void ScaleToolExport( const Callback & importCallback ){ - importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eScale ); +void ScaleToolExport(const Callback &importCallback) +{ + importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eScale); } -void DragToolExport( const Callback & importCallback ){ - importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eDrag ); +void DragToolExport(const Callback &importCallback) +{ + importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eDrag); } -void ClipperToolExport( const Callback & importCallback ){ - importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip ); +void ClipperToolExport(const Callback &importCallback) +{ + importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip); } FreeCaller &), TranslateToolExport> g_translatemode_button_caller; -Callback &)> g_translatemode_button_callback( g_translatemode_button_caller ); -ToggleItem g_translatemode_button( g_translatemode_button_callback ); +Callback &)> g_translatemode_button_callback(g_translatemode_button_caller); +ToggleItem g_translatemode_button(g_translatemode_button_callback); FreeCaller &), RotateToolExport> g_rotatemode_button_caller; -Callback &)> g_rotatemode_button_callback( g_rotatemode_button_caller ); -ToggleItem g_rotatemode_button( g_rotatemode_button_callback ); +Callback &)> g_rotatemode_button_callback(g_rotatemode_button_caller); +ToggleItem g_rotatemode_button(g_rotatemode_button_callback); FreeCaller &), ScaleToolExport> g_scalemode_button_caller; -Callback &)> g_scalemode_button_callback( g_scalemode_button_caller ); -ToggleItem g_scalemode_button( g_scalemode_button_callback ); +Callback &)> g_scalemode_button_callback(g_scalemode_button_caller); +ToggleItem g_scalemode_button(g_scalemode_button_callback); FreeCaller &), DragToolExport> g_dragmode_button_caller; -Callback &)> g_dragmode_button_callback( g_dragmode_button_caller ); -ToggleItem g_dragmode_button( g_dragmode_button_callback ); +Callback &)> g_dragmode_button_callback(g_dragmode_button_caller); +ToggleItem g_dragmode_button(g_dragmode_button_callback); FreeCaller &), ClipperToolExport> g_clipper_button_caller; -Callback &)> g_clipper_button_callback( g_clipper_button_caller ); -ToggleItem g_clipper_button( g_clipper_button_callback ); +Callback &)> g_clipper_button_callback(g_clipper_button_caller); +ToggleItem g_clipper_button(g_clipper_button_callback); -void ToolChanged(){ - g_translatemode_button.update(); - g_rotatemode_button.update(); - g_scalemode_button.update(); - g_dragmode_button.update(); - g_clipper_button.update(); +void ToolChanged() +{ + g_translatemode_button.update(); + g_rotatemode_button.update(); + g_scalemode_button.update(); + g_dragmode_button.update(); + g_clipper_button.update(); } -const char* const c_ResizeMode_status = "QE4 Drag Tool: move and resize objects"; +const char *const c_ResizeMode_status = "QE4 Drag Tool: move and resize objects"; -void DragMode(){ - if ( g_currentToolMode == DragMode && g_defaultToolMode != DragMode ) { - g_defaultToolMode(); - } - else - { - g_currentToolMode = DragMode; - g_currentToolModeSupportsComponentEditing = true; +void DragMode() +{ + if (g_currentToolMode == DragMode && g_defaultToolMode != DragMode) { + g_defaultToolMode(); + } else { + g_currentToolMode = DragMode; + g_currentToolModeSupportsComponentEditing = true; - OnClipMode( false ); + OnClipMode(false); - Sys_Status( c_ResizeMode_status ); - GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eDrag ); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status(c_ResizeMode_status); + GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eDrag); + ToolChanged(); + ModeChangeNotify(); + } } -const char* const c_TranslateMode_status = "Translate Tool: translate objects and components"; +const char *const c_TranslateMode_status = "Translate Tool: translate objects and components"; -void TranslateMode(){ - if ( g_currentToolMode == TranslateMode && g_defaultToolMode != TranslateMode ) { - g_defaultToolMode(); - } - else - { - g_currentToolMode = TranslateMode; - g_currentToolModeSupportsComponentEditing = true; +void TranslateMode() +{ + if (g_currentToolMode == TranslateMode && g_defaultToolMode != TranslateMode) { + g_defaultToolMode(); + } else { + g_currentToolMode = TranslateMode; + g_currentToolModeSupportsComponentEditing = true; - OnClipMode( false ); + OnClipMode(false); - Sys_Status( c_TranslateMode_status ); - GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eTranslate ); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status(c_TranslateMode_status); + GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eTranslate); + ToolChanged(); + ModeChangeNotify(); + } } -const char* const c_RotateMode_status = "Rotate Tool: rotate objects and components"; +const char *const c_RotateMode_status = "Rotate Tool: rotate objects and components"; -void RotateMode(){ - if ( g_currentToolMode == RotateMode && g_defaultToolMode != RotateMode ) { - g_defaultToolMode(); - } - else - { - g_currentToolMode = RotateMode; - g_currentToolModeSupportsComponentEditing = true; +void RotateMode() +{ + if (g_currentToolMode == RotateMode && g_defaultToolMode != RotateMode) { + g_defaultToolMode(); + } else { + g_currentToolMode = RotateMode; + g_currentToolModeSupportsComponentEditing = true; - OnClipMode( false ); + OnClipMode(false); - Sys_Status( c_RotateMode_status ); - GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eRotate ); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status(c_RotateMode_status); + GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eRotate); + ToolChanged(); + ModeChangeNotify(); + } } -const char* const c_ScaleMode_status = "Scale Tool: scale objects and components"; +const char *const c_ScaleMode_status = "Scale Tool: scale objects and components"; -void ScaleMode(){ - if ( g_currentToolMode == ScaleMode && g_defaultToolMode != ScaleMode ) { - g_defaultToolMode(); - } - else - { - g_currentToolMode = ScaleMode; - g_currentToolModeSupportsComponentEditing = true; +void ScaleMode() +{ + if (g_currentToolMode == ScaleMode && g_defaultToolMode != ScaleMode) { + g_defaultToolMode(); + } else { + g_currentToolMode = ScaleMode; + g_currentToolModeSupportsComponentEditing = true; - OnClipMode( false ); + OnClipMode(false); - Sys_Status( c_ScaleMode_status ); - GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eScale ); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status(c_ScaleMode_status); + GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eScale); + ToolChanged(); + ModeChangeNotify(); + } } -const char* const c_ClipperMode_status = "Clipper Tool: apply clip planes to objects"; +const char *const c_ClipperMode_status = "Clipper Tool: apply clip planes to objects"; -void ClipperMode(){ - if ( g_currentToolMode == ClipperMode && g_defaultToolMode != ClipperMode ) { - g_defaultToolMode(); - } - else - { - g_currentToolMode = ClipperMode; - g_currentToolModeSupportsComponentEditing = false; +void ClipperMode() +{ + if (g_currentToolMode == ClipperMode && g_defaultToolMode != ClipperMode) { + g_defaultToolMode(); + } else { + g_currentToolMode = ClipperMode; + g_currentToolModeSupportsComponentEditing = false; - SelectionSystem_DefaultMode(); + SelectionSystem_DefaultMode(); - OnClipMode( true ); + OnClipMode(true); - Sys_Status( c_ClipperMode_status ); - GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eClip ); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status(c_ClipperMode_status); + GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eClip); + ToolChanged(); + ModeChangeNotify(); + } } -void Texdef_Rotate( float angle ){ - StringOutputStream command; - command << "brushRotateTexture -angle " << angle; - UndoableCommand undo( command.c_str() ); - Select_RotateTexture( angle ); +void Texdef_Rotate(float angle) +{ + StringOutputStream command; + command << "brushRotateTexture -angle " << angle; + UndoableCommand undo(command.c_str()); + Select_RotateTexture(angle); } -void Texdef_RotateClockwise(){ - Texdef_Rotate( static_cast( fabs( g_si_globals.rotate ) ) ); +void Texdef_RotateClockwise() +{ + Texdef_Rotate(static_cast( fabs(g_si_globals.rotate))); } -void Texdef_RotateAntiClockwise(){ - Texdef_Rotate( static_cast( -fabs( g_si_globals.rotate ) ) ); +void Texdef_RotateAntiClockwise() +{ + Texdef_Rotate(static_cast( -fabs(g_si_globals.rotate))); } -void Texdef_Scale( float x, float y ){ - StringOutputStream command; - command << "brushScaleTexture -x " << x << " -y " << y; - UndoableCommand undo( command.c_str() ); - Select_ScaleTexture( x, y ); +void Texdef_Scale(float x, float y) +{ + StringOutputStream command; + command << "brushScaleTexture -x " << x << " -y " << y; + UndoableCommand undo(command.c_str()); + Select_ScaleTexture(x, y); } -void Texdef_ScaleUp(){ - Texdef_Scale( 0, g_si_globals.scale[1] ); +void Texdef_ScaleUp() +{ + Texdef_Scale(0, g_si_globals.scale[1]); } -void Texdef_ScaleDown(){ - Texdef_Scale( 0, -g_si_globals.scale[1] ); +void Texdef_ScaleDown() +{ + Texdef_Scale(0, -g_si_globals.scale[1]); } -void Texdef_ScaleLeft(){ - Texdef_Scale( -g_si_globals.scale[0],0 ); +void Texdef_ScaleLeft() +{ + Texdef_Scale(-g_si_globals.scale[0], 0); } -void Texdef_ScaleRight(){ - Texdef_Scale( g_si_globals.scale[0],0 ); +void Texdef_ScaleRight() +{ + Texdef_Scale(g_si_globals.scale[0], 0); } -void Texdef_Shift( float x, float y ){ - StringOutputStream command; - command << "brushShiftTexture -x " << x << " -y " << y; - UndoableCommand undo( command.c_str() ); - Select_ShiftTexture( x, y ); +void Texdef_Shift(float x, float y) +{ + StringOutputStream command; + command << "brushShiftTexture -x " << x << " -y " << y; + UndoableCommand undo(command.c_str()); + Select_ShiftTexture(x, y); } -void Texdef_ShiftLeft(){ - Texdef_Shift( -g_si_globals.shift[0], 0 ); +void Texdef_ShiftLeft() +{ + Texdef_Shift(-g_si_globals.shift[0], 0); } -void Texdef_ShiftRight(){ - Texdef_Shift( g_si_globals.shift[0], 0 ); +void Texdef_ShiftRight() +{ + Texdef_Shift(g_si_globals.shift[0], 0); } -void Texdef_ShiftUp(){ - Texdef_Shift( 0, g_si_globals.shift[1] ); +void Texdef_ShiftUp() +{ + Texdef_Shift(0, g_si_globals.shift[1]); } -void Texdef_ShiftDown(){ - Texdef_Shift( 0, -g_si_globals.shift[1] ); +void Texdef_ShiftDown() +{ + Texdef_Shift(0, -g_si_globals.shift[1]); } - -class SnappableSnapToGridSelected : public scene::Graph::Walker -{ -float m_snap; +class SnappableSnapToGridSelected : public scene::Graph::Walker { + float m_snap; public: -SnappableSnapToGridSelected( float snap ) - : m_snap( snap ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - Snappable* snappable = Node_getSnappable( path.top() ); - if ( snappable != 0 - && Instance_getSelectable( instance )->isSelected() ) { - snappable->snapto( m_snap ); - } - } - return true; -} + SnappableSnapToGridSelected(float snap) + : m_snap(snap) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + Snappable *snappable = Node_getSnappable(path.top()); + if (snappable != 0 + && Instance_getSelectable(instance)->isSelected()) { + snappable->snapto(m_snap); + } + } + return true; + } }; -void Scene_SnapToGrid_Selected( scene::Graph& graph, float snap ){ - graph.traverse( SnappableSnapToGridSelected( snap ) ); +void Scene_SnapToGrid_Selected(scene::Graph &graph, float snap) +{ + graph.traverse(SnappableSnapToGridSelected(snap)); } -class ComponentSnappableSnapToGridSelected : public scene::Graph::Walker -{ -float m_snap; +class ComponentSnappableSnapToGridSelected : public scene::Graph::Walker { + float m_snap; public: -ComponentSnappableSnapToGridSelected( float snap ) - : m_snap( snap ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - ComponentSnappable* componentSnappable = Instance_getComponentSnappable( instance ); - if ( componentSnappable != 0 - && Instance_getSelectable( instance )->isSelected() ) { - componentSnappable->snapComponents( m_snap ); - } - } - return true; -} + ComponentSnappableSnapToGridSelected(float snap) + : m_snap(snap) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + ComponentSnappable *componentSnappable = Instance_getComponentSnappable(instance); + if (componentSnappable != 0 + && Instance_getSelectable(instance)->isSelected()) { + componentSnappable->snapComponents(m_snap); + } + } + return true; + } }; -void Scene_SnapToGrid_Component_Selected( scene::Graph& graph, float snap ){ - graph.traverse( ComponentSnappableSnapToGridSelected( snap ) ); +void Scene_SnapToGrid_Component_Selected(scene::Graph &graph, float snap) +{ + graph.traverse(ComponentSnappableSnapToGridSelected(snap)); } -void Selection_SnapToGrid(){ - StringOutputStream command; - command << "snapSelected -grid " << GetGridSize(); - UndoableCommand undo( command.c_str() ); +void Selection_SnapToGrid() +{ + StringOutputStream command; + command << "snapSelected -grid " << GetGridSize(); + UndoableCommand undo(command.c_str()); - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { - Scene_SnapToGrid_Component_Selected( GlobalSceneGraph(), GetGridSize() ); - } - else - { - Scene_SnapToGrid_Selected( GlobalSceneGraph(), GetGridSize() ); - } + if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent) { + Scene_SnapToGrid_Component_Selected(GlobalSceneGraph(), GetGridSize()); + } else { + Scene_SnapToGrid_Selected(GlobalSceneGraph(), GetGridSize()); + } } -static gint qe_every_second( gpointer data ){ - GdkModifierType mask; +static gint qe_every_second(gpointer data) +{ + GdkModifierType mask; - gdk_window_get_pointer( 0, 0, 0, &mask ); + gdk_window_get_pointer(0, 0, 0, &mask); - if ( ( mask & ( GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK ) ) == 0 ) { - QE_CheckAutoSave(); - } + if ((mask & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) == 0) { + QE_CheckAutoSave(); + } - return TRUE; + return TRUE; } guint s_qe_every_second_id = 0; -void EverySecondTimer_enable(){ - if ( s_qe_every_second_id == 0 ) { - s_qe_every_second_id = g_timeout_add( 1000, qe_every_second, 0 ); - } +void EverySecondTimer_enable() +{ + if (s_qe_every_second_id == 0) { + s_qe_every_second_id = g_timeout_add(1000, qe_every_second, 0); + } } -void EverySecondTimer_disable(){ - if ( s_qe_every_second_id != 0 ) { - g_source_remove( s_qe_every_second_id ); - s_qe_every_second_id = 0; - } +void EverySecondTimer_disable() +{ + if (s_qe_every_second_id != 0) { + g_source_remove(s_qe_every_second_id); + s_qe_every_second_id = 0; + } } -gint window_realize_remove_decoration( ui::Widget widget, gpointer data ){ - gdk_window_set_decorations( gtk_widget_get_window(widget), (GdkWMDecoration)( GDK_DECOR_ALL | GDK_DECOR_MENU | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE ) ); - return FALSE; +gint window_realize_remove_decoration(ui::Widget widget, gpointer data) +{ + gdk_window_set_decorations(gtk_widget_get_window(widget), + (GdkWMDecoration) (GDK_DECOR_ALL | GDK_DECOR_MENU | GDK_DECOR_MINIMIZE | + GDK_DECOR_MAXIMIZE)); + return FALSE; } -class WaitDialog -{ +class WaitDialog { public: -ui::Window m_window{ui::null}; -ui::Label m_label{ui::null}; + ui::Window m_window{ui::null}; + ui::Label m_label{ui::null}; }; -WaitDialog create_wait_dialog( const char* title, const char* text ){ - WaitDialog dialog; +WaitDialog create_wait_dialog(const char *title, const char *text) +{ + WaitDialog dialog; - dialog.m_window = MainFrame_getWindow().create_floating_window(title); - gtk_window_set_resizable( dialog.m_window, FALSE ); - gtk_container_set_border_width( GTK_CONTAINER( dialog.m_window ), 0 ); - gtk_window_set_position( dialog.m_window, GTK_WIN_POS_CENTER_ON_PARENT ); + dialog.m_window = MainFrame_getWindow().create_floating_window(title); + gtk_window_set_resizable(dialog.m_window, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(dialog.m_window), 0); + gtk_window_set_position(dialog.m_window, GTK_WIN_POS_CENTER_ON_PARENT); - dialog.m_window.connect( "realize", G_CALLBACK( window_realize_remove_decoration ), 0 ); + dialog.m_window.connect("realize", G_CALLBACK(window_realize_remove_decoration), 0); - { - dialog.m_label = ui::Label( text ); - gtk_misc_set_alignment( GTK_MISC( dialog.m_label ), 0.0, 0.5 ); - gtk_label_set_justify( dialog.m_label, GTK_JUSTIFY_LEFT ); - dialog.m_label.show(); - dialog.m_label.dimensions(200, -1); + { + dialog.m_label = ui::Label(text); + gtk_misc_set_alignment(GTK_MISC(dialog.m_label), 0.0, 0.5); + gtk_label_set_justify(dialog.m_label, GTK_JUSTIFY_LEFT); + dialog.m_label.show(); + dialog.m_label.dimensions(200, -1); - dialog.m_window.add(dialog.m_label); - } - return dialog; + dialog.m_window.add(dialog.m_label); + } + return dialog; } -namespace -{ -clock_t g_lastRedrawTime = 0; -const clock_t c_redrawInterval = clock_t( CLOCKS_PER_SEC / 10 ); +namespace { + clock_t g_lastRedrawTime = 0; + const clock_t c_redrawInterval = clock_t(CLOCKS_PER_SEC / 10); -bool redrawRequired(){ - clock_t currentTime = std::clock(); - if ( currentTime - g_lastRedrawTime >= c_redrawInterval ) { - g_lastRedrawTime = currentTime; - return true; - } - return false; -} + bool redrawRequired() + { + clock_t currentTime = std::clock(); + if (currentTime - g_lastRedrawTime >= c_redrawInterval) { + g_lastRedrawTime = currentTime; + return true; + } + return false; + } } -bool MainFrame_isActiveApp(){ - //globalOutputStream() << "listing\n"; - GList* list = gtk_window_list_toplevels(); - for ( GList* i = list; i != 0; i = g_list_next( i ) ) - { - //globalOutputStream() << "toplevel.. "; - if ( gtk_window_is_active( ui::Window::from( i->data ) ) ) { - //globalOutputStream() << "is active\n"; - return true; - } - //globalOutputStream() << "not active\n"; - } - return false; +bool MainFrame_isActiveApp() +{ + //globalOutputStream() << "listing\n"; + GList *list = gtk_window_list_toplevels(); + for (GList *i = list; i != 0; i = g_list_next(i)) { + //globalOutputStream() << "toplevel.. "; + if (gtk_window_is_active(ui::Window::from(i->data))) { + //globalOutputStream() << "is active\n"; + return true; + } + //globalOutputStream() << "not active\n"; + } + return false; } typedef std::list StringStack; StringStack g_wait_stack; WaitDialog g_wait; -bool ScreenUpdates_Enabled(){ - return g_wait_stack.empty(); -} - -void ScreenUpdates_process(){ - if ( redrawRequired() && g_wait.m_window.visible() ) { - ui::process(); - } -} - - -void ScreenUpdates_Disable( const char* message, const char* title ){ - if ( g_wait_stack.empty() ) { - EverySecondTimer_disable(); - - ui::process(); - - bool isActiveApp = MainFrame_isActiveApp(); - - g_wait = create_wait_dialog( title, message ); - gtk_grab_add( g_wait.m_window ); - - if ( isActiveApp ) { - g_wait.m_window.show(); - ScreenUpdates_process(); - } - } - else if ( g_wait.m_window.visible() ) { - g_wait.m_label.text(message); - ScreenUpdates_process(); - } - g_wait_stack.push_back( message ); +bool ScreenUpdates_Enabled() +{ + return g_wait_stack.empty(); } -void ScreenUpdates_Enable(){ - ASSERT_MESSAGE( !ScreenUpdates_Enabled(), "screen updates already enabled" ); - g_wait_stack.pop_back(); - if ( g_wait_stack.empty() ) { - EverySecondTimer_enable(); - //gtk_widget_set_sensitive(MainFrame_getWindow(), TRUE); - - gtk_grab_remove( g_wait.m_window ); - destroy_floating_window( g_wait.m_window ); - g_wait.m_window = ui::Window{ui::null}; - - //gtk_window_present(MainFrame_getWindow()); - } - else if ( g_wait.m_window.visible() ) { - g_wait.m_label.text(g_wait_stack.back().c_str()); - ScreenUpdates_process(); - } +void ScreenUpdates_process() +{ + if (redrawRequired() && g_wait.m_window.visible()) { + ui::process(); + } } +void ScreenUpdates_Disable(const char *message, const char *title) +{ + if (g_wait_stack.empty()) { + EverySecondTimer_disable(); -void GlobalCamera_UpdateWindow(){ - if ( g_pParentWnd != 0 ) { - CamWnd_Update( *g_pParentWnd->GetCamWnd() ); - } -} - -void XY_UpdateWindow( MainFrame& mainframe ){ - if ( mainframe.GetXYWnd() != 0 ) { - XYWnd_Update( *mainframe.GetXYWnd() ); - } -} + ui::process(); -void XZ_UpdateWindow( MainFrame& mainframe ){ - if ( mainframe.GetXZWnd() != 0 ) { - XYWnd_Update( *mainframe.GetXZWnd() ); - } -} + bool isActiveApp = MainFrame_isActiveApp(); -void YZ_UpdateWindow( MainFrame& mainframe ){ - if ( mainframe.GetYZWnd() != 0 ) { - XYWnd_Update( *mainframe.GetYZWnd() ); - } -} - -void XY_UpdateAllWindows( MainFrame& mainframe ){ - XY_UpdateWindow( mainframe ); - XZ_UpdateWindow( mainframe ); - YZ_UpdateWindow( mainframe ); -} + g_wait = create_wait_dialog(title, message); + gtk_grab_add(g_wait.m_window); -void XY_UpdateAllWindows(){ - if ( g_pParentWnd != 0 ) { - XY_UpdateAllWindows( *g_pParentWnd ); - } -} - -void UpdateAllWindows(){ - GlobalCamera_UpdateWindow(); - XY_UpdateAllWindows(); + if (isActiveApp) { + g_wait.m_window.show(); + ScreenUpdates_process(); + } + } else if (g_wait.m_window.visible()) { + g_wait.m_label.text(message); + ScreenUpdates_process(); + } + g_wait_stack.push_back(message); } +void ScreenUpdates_Enable() +{ + ASSERT_MESSAGE(!ScreenUpdates_Enabled(), "screen updates already enabled"); + g_wait_stack.pop_back(); + if (g_wait_stack.empty()) { + EverySecondTimer_enable(); + //gtk_widget_set_sensitive(MainFrame_getWindow(), TRUE); -void ModeChangeNotify(){ - SceneChangeNotify(); -} + gtk_grab_remove(g_wait.m_window); + destroy_floating_window(g_wait.m_window); + g_wait.m_window = ui::Window{ui::null}; -void ClipperChangeNotify(){ - GlobalCamera_UpdateWindow(); - XY_UpdateAllWindows(); + //gtk_window_present(MainFrame_getWindow()); + } else if (g_wait.m_window.visible()) { + g_wait.m_label.text(g_wait_stack.back().c_str()); + ScreenUpdates_process(); + } } -LatchedValue g_Layout_viewStyle( 0, "Window Layout" ); -LatchedValue g_Layout_enableDetachableMenus( true, "Detachable Menus" ); -LatchedValue g_Layout_enablePatchToolbar( true, "Patch Toolbar" ); -LatchedValue g_Layout_enablePluginToolbar( true, "Plugin Toolbar" ); - - - -ui::MenuItem create_file_menu(){ - // File menu - auto file_menu_item = new_sub_menu_item_with_mnemonic( "_File" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( file_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } - - create_menu_item_with_mnemonic( menu, "_New Map", "NewMap" ); - menu_separator( menu ); - -#if 0 - //++timo temporary experimental stuff for sleep mode.. - create_menu_item_with_mnemonic( menu, "_Sleep", "Sleep" ); - menu_separator( menu ); - // end experimental -#endif - - create_menu_item_with_mnemonic( menu, "_Open...", "OpenMap" ); - - create_menu_item_with_mnemonic( menu, "_Import...", "ImportMap" ); - create_menu_item_with_mnemonic( menu, "_Save", "SaveMap" ); - create_menu_item_with_mnemonic( menu, "Save _as...", "SaveMapAs" ); - create_menu_item_with_mnemonic( menu, "_Export selected...", "ExportSelected" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Save re_gion...", "SaveRegion" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "_Refresh models", "RefreshReferences" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Pro_ject settings...", "ProjectSettings" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "_Pointfile...", "TogglePointfile" ); - menu_separator( menu ); - MRU_constructMenu( menu ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "E_xit", "Exit" ); - - return file_menu_item; +void GlobalCamera_UpdateWindow() +{ + if (g_pParentWnd != 0) { + CamWnd_Update(*g_pParentWnd->GetCamWnd()); + } } -ui::MenuItem create_edit_menu(){ - // Edit menu - auto edit_menu_item = new_sub_menu_item_with_mnemonic( "_Edit" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( edit_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } - create_menu_item_with_mnemonic( menu, "_Undo", "Undo" ); - create_menu_item_with_mnemonic( menu, "_Redo", "Redo" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "_Copy", "Copy" ); - create_menu_item_with_mnemonic( menu, "_Paste", "Paste" ); - create_menu_item_with_mnemonic( menu, "P_aste To Camera", "PasteToCamera" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "_Duplicate", "CloneSelection" ); - create_menu_item_with_mnemonic( menu, "Duplicate, make uni_que", "CloneSelectionAndMakeUnique" ); - create_menu_item_with_mnemonic( menu, "D_elete", "DeleteSelection" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Pa_rent", "ParentSelection" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "C_lear Selection", "UnSelectSelection" ); - create_menu_item_with_mnemonic( menu, "_Invert Selection", "InvertSelection" ); - create_menu_item_with_mnemonic( menu, "Select i_nside", "SelectInside" ); - create_menu_item_with_mnemonic( menu, "Select _touching", "SelectTouching" ); - - auto convert_menu = create_sub_menu_with_mnemonic( menu, "E_xpand Selection" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( convert_menu ); - } - create_menu_item_with_mnemonic( convert_menu, "To Whole _Entities", "ExpandSelectionToEntities" ); +void XY_UpdateWindow(MainFrame &mainframe) +{ + if (mainframe.GetXYWnd() != 0) { + XYWnd_Update(*mainframe.GetXYWnd()); + } +} - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Pre_ferences...", "Preferences" ); +void XZ_UpdateWindow(MainFrame &mainframe) +{ + if (mainframe.GetXZWnd() != 0) { + XYWnd_Update(*mainframe.GetXZWnd()); + } +} - return edit_menu_item; +void YZ_UpdateWindow(MainFrame &mainframe) +{ + if (mainframe.GetYZWnd() != 0) { + XYWnd_Update(*mainframe.GetYZWnd()); + } } -void fill_view_xy_top_menu( ui::Menu menu ){ - create_check_menu_item_with_mnemonic( menu, "XY (Top) View", "ToggleView" ); +void XY_UpdateAllWindows(MainFrame &mainframe) +{ + XY_UpdateWindow(mainframe); + XZ_UpdateWindow(mainframe); + YZ_UpdateWindow(mainframe); } +void XY_UpdateAllWindows() +{ + if (g_pParentWnd != 0) { + XY_UpdateAllWindows(*g_pParentWnd); + } +} -void fill_view_yz_side_menu( ui::Menu menu ){ - create_check_menu_item_with_mnemonic( menu, "YZ (Side) View", "ToggleSideView" ); +void UpdateAllWindows() +{ + GlobalCamera_UpdateWindow(); + XY_UpdateAllWindows(); } -void fill_view_xz_front_menu( ui::Menu menu ){ - create_check_menu_item_with_mnemonic( menu, "XZ (Front) View", "ToggleFrontView" ); +void ModeChangeNotify() +{ + SceneChangeNotify(); } +void ClipperChangeNotify() +{ + GlobalCamera_UpdateWindow(); + XY_UpdateAllWindows(); +} -ui::Widget g_toggle_z_item{ui::null}; -ui::Widget g_toggle_console_item{ui::null}; -ui::Widget g_toggle_entity_item{ui::null}; -ui::Widget g_toggle_entitylist_item{ui::null}; -ui::MenuItem create_view_menu( MainFrame::EViewStyle style ){ - // View menu - auto view_menu_item = new_sub_menu_item_with_mnemonic( "Vie_w" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( view_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } +LatchedValue g_Layout_viewStyle(0, "Window Layout"); +LatchedValue g_Layout_enableDetachableMenus(true, "Detachable Menus"); +LatchedValue g_Layout_enablePatchToolbar(true, "Patch Toolbar"); +LatchedValue g_Layout_enablePluginToolbar(true, "Plugin Toolbar"); - if ( style == MainFrame::eFloating ) { - fill_view_camera_menu( menu ); - fill_view_xy_top_menu( menu ); - fill_view_yz_side_menu( menu ); - fill_view_xz_front_menu( menu ); - } - if ( style == MainFrame::eFloating || style == MainFrame::eSplit ) { - create_menu_item_with_mnemonic( menu, "Console View", "ToggleConsole" ); - create_menu_item_with_mnemonic( menu, "Texture Browser", "ToggleTextures" ); - create_menu_item_with_mnemonic( menu, "Entity Inspector", "ToggleEntityInspector" ); - } - else - { - create_menu_item_with_mnemonic( menu, "Entity Inspector", "ViewEntityInfo" ); - } - create_menu_item_with_mnemonic( menu, "_Surface Inspector", "SurfaceInspector" ); - create_menu_item_with_mnemonic( menu, "Entity List", "EntityList" ); - menu_separator( menu ); - { - auto camera_menu = create_sub_menu_with_mnemonic( menu, "Camera" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( camera_menu ); - } - create_menu_item_with_mnemonic( camera_menu, "_Center", "CenterView" ); - create_menu_item_with_mnemonic( camera_menu, "_Up Floor", "UpFloor" ); - create_menu_item_with_mnemonic( camera_menu, "_Down Floor", "DownFloor" ); - menu_separator( camera_menu ); - create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane In", "CubicClipZoomIn" ); - create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane Out", "CubicClipZoomOut" ); - menu_separator( camera_menu ); - create_menu_item_with_mnemonic( camera_menu, "Next leak spot", "NextLeakSpot" ); - create_menu_item_with_mnemonic( camera_menu, "Previous leak spot", "PrevLeakSpot" ); - menu_separator( camera_menu ); - create_menu_item_with_mnemonic( camera_menu, "Look Through Selected", "LookThroughSelected" ); - create_menu_item_with_mnemonic( camera_menu, "Look Through Camera", "LookThroughCamera" ); - } - menu_separator( menu ); - { - auto orthographic_menu = create_sub_menu_with_mnemonic( menu, "Orthographic" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( orthographic_menu ); - } - if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft || style == MainFrame::eFloating ) { - create_menu_item_with_mnemonic( orthographic_menu, "_Next (XY, YZ, XY)", "NextView" ); - create_menu_item_with_mnemonic( orthographic_menu, "XY (Top)", "ViewTop" ); - create_menu_item_with_mnemonic( orthographic_menu, "YZ", "ViewSide" ); - create_menu_item_with_mnemonic( orthographic_menu, "XZ", "ViewFront" ); - menu_separator( orthographic_menu ); - } +ui::MenuItem create_file_menu() +{ + // File menu + auto file_menu_item = new_sub_menu_item_with_mnemonic("_File"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(file_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - create_menu_item_with_mnemonic( orthographic_menu, "_XY 100%", "Zoom100" ); - create_menu_item_with_mnemonic( orthographic_menu, "XY Zoom _In", "ZoomIn" ); - create_menu_item_with_mnemonic( orthographic_menu, "XY Zoom _Out", "ZoomOut" ); - } + create_menu_item_with_mnemonic(menu, "_New Map", "NewMap"); + menu_separator(menu); +#if 0 + //++timo temporary experimental stuff for sleep mode.. + create_menu_item_with_mnemonic( menu, "_Sleep", "Sleep" ); menu_separator( menu ); + // end experimental +#endif - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Show" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_check_menu_item_with_mnemonic( menu_in_menu, "Show _Angles", "ShowAngles" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "Show _Names", "ShowNames" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "Show Blocks", "ShowBlocks" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "Show C_oordinates", "ShowCoordinates" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "Show Window Outline", "ShowWindowOutline" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "Show Axes", "ShowAxes" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "Show Workzone", "ShowWorkzone" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "Show Stats", "ShowStats" ); - } - - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Filter" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - Filters_constructMenu( menu_in_menu ); - } - menu_separator( menu ); - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Hide/Show" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Hide Selected", "HideSelected" ); - create_menu_item_with_mnemonic( menu_in_menu, "Show Hidden", "ShowHidden" ); - } - menu_separator( menu ); - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Region" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "_Off", "RegionOff" ); - create_menu_item_with_mnemonic( menu_in_menu, "_Set XY", "RegionSetXY" ); - create_menu_item_with_mnemonic( menu_in_menu, "Set _Brush", "RegionSetBrush" ); - create_menu_item_with_mnemonic( menu_in_menu, "Set Se_lected Brushes", "RegionSetSelection" ); - } + create_menu_item_with_mnemonic(menu, "_Open...", "OpenMap"); + + create_menu_item_with_mnemonic(menu, "_Import...", "ImportMap"); + create_menu_item_with_mnemonic(menu, "_Save", "SaveMap"); + create_menu_item_with_mnemonic(menu, "Save _as...", "SaveMapAs"); + create_menu_item_with_mnemonic(menu, "_Export selected...", "ExportSelected"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Save re_gion...", "SaveRegion"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "_Refresh models", "RefreshReferences"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Pro_ject settings...", "ProjectSettings"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "_Pointfile...", "TogglePointfile"); + menu_separator(menu); + MRU_constructMenu(menu); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "E_xit", "Exit"); + + return file_menu_item; +} + +ui::MenuItem create_edit_menu() +{ + // Edit menu + auto edit_menu_item = new_sub_menu_item_with_mnemonic("_Edit"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(edit_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } + create_menu_item_with_mnemonic(menu, "_Undo", "Undo"); + create_menu_item_with_mnemonic(menu, "_Redo", "Redo"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "_Copy", "Copy"); + create_menu_item_with_mnemonic(menu, "_Paste", "Paste"); + create_menu_item_with_mnemonic(menu, "P_aste To Camera", "PasteToCamera"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "_Duplicate", "CloneSelection"); + create_menu_item_with_mnemonic(menu, "Duplicate, make uni_que", "CloneSelectionAndMakeUnique"); + create_menu_item_with_mnemonic(menu, "D_elete", "DeleteSelection"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Pa_rent", "ParentSelection"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "C_lear Selection", "UnSelectSelection"); + create_menu_item_with_mnemonic(menu, "_Invert Selection", "InvertSelection"); + create_menu_item_with_mnemonic(menu, "Select i_nside", "SelectInside"); + create_menu_item_with_mnemonic(menu, "Select _touching", "SelectTouching"); + + auto convert_menu = create_sub_menu_with_mnemonic(menu, "E_xpand Selection"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(convert_menu); + } + create_menu_item_with_mnemonic(convert_menu, "To Whole _Entities", "ExpandSelectionToEntities"); + + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Pre_ferences...", "Preferences"); + + return edit_menu_item; +} + +void fill_view_xy_top_menu(ui::Menu menu) +{ + create_check_menu_item_with_mnemonic(menu, "XY (Top) View", "ToggleView"); +} - command_connect_accelerator( "CenterXYView" ); - return view_menu_item; +void fill_view_yz_side_menu(ui::Menu menu) +{ + create_check_menu_item_with_mnemonic(menu, "YZ (Side) View", "ToggleSideView"); } -ui::MenuItem create_selection_menu(){ - // Selection menu - auto selection_menu_item = new_sub_menu_item_with_mnemonic( "M_odify" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( selection_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } - - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Components" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_check_menu_item_with_mnemonic( menu_in_menu, "_Edges", "DragEdges" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "_Vertices", "DragVertices" ); - create_check_menu_item_with_mnemonic( menu_in_menu, "_Faces", "DragFaces" ); - } - menu_separator( menu ); +void fill_view_xz_front_menu(ui::Menu menu) +{ + create_check_menu_item_with_mnemonic(menu, "XZ (Front) View", "ToggleFrontView"); +} - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Nudge" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Nudge Left", "SelectNudgeLeft" ); - create_menu_item_with_mnemonic( menu_in_menu, "Nudge Right", "SelectNudgeRight" ); - create_menu_item_with_mnemonic( menu_in_menu, "Nudge Up", "SelectNudgeUp" ); - create_menu_item_with_mnemonic( menu_in_menu, "Nudge Down", "SelectNudgeDown" ); - } - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Rotate" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Rotate X", "RotateSelectionX" ); - create_menu_item_with_mnemonic( menu_in_menu, "Rotate Y", "RotateSelectionY" ); - create_menu_item_with_mnemonic( menu_in_menu, "Rotate Z", "RotateSelectionZ" ); - } - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Flip" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Flip _X", "MirrorSelectionX" ); - create_menu_item_with_mnemonic( menu_in_menu, "Flip _Y", "MirrorSelectionY" ); - create_menu_item_with_mnemonic( menu_in_menu, "Flip _Z", "MirrorSelectionZ" ); - } - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Arbitrary rotation...", "ArbitraryRotation" ); - create_menu_item_with_mnemonic( menu, "Arbitrary scale...", "ArbitraryScale" ); - return selection_menu_item; -} +ui::Widget g_toggle_z_item{ui::null}; +ui::Widget g_toggle_console_item{ui::null}; +ui::Widget g_toggle_entity_item{ui::null}; +ui::Widget g_toggle_entitylist_item{ui::null}; -ui::MenuItem create_bsp_menu(){ - // BSP menu - auto bsp_menu_item = new_sub_menu_item_with_mnemonic( "_Build" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( bsp_menu_item ) ); +ui::MenuItem create_view_menu(MainFrame::EViewStyle style) +{ + // View menu + auto view_menu_item = new_sub_menu_item_with_mnemonic("Vie_w"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(view_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } + + if (style == MainFrame::eFloating) { + fill_view_camera_menu(menu); + fill_view_xy_top_menu(menu); + fill_view_yz_side_menu(menu); + fill_view_xz_front_menu(menu); + } + if (style == MainFrame::eFloating || style == MainFrame::eSplit) { + create_menu_item_with_mnemonic(menu, "Console View", "ToggleConsole"); + create_menu_item_with_mnemonic(menu, "Texture Browser", "ToggleTextures"); + create_menu_item_with_mnemonic(menu, "Entity Inspector", "ToggleEntityInspector"); + } else { + create_menu_item_with_mnemonic(menu, "Entity Inspector", "ViewEntityInfo"); + } + create_menu_item_with_mnemonic(menu, "_Surface Inspector", "SurfaceInspector"); + create_menu_item_with_mnemonic(menu, "Entity List", "EntityList"); + + menu_separator(menu); + { + auto camera_menu = create_sub_menu_with_mnemonic(menu, "Camera"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(camera_menu); + } + create_menu_item_with_mnemonic(camera_menu, "_Center", "CenterView"); + create_menu_item_with_mnemonic(camera_menu, "_Up Floor", "UpFloor"); + create_menu_item_with_mnemonic(camera_menu, "_Down Floor", "DownFloor"); + menu_separator(camera_menu); + create_menu_item_with_mnemonic(camera_menu, "Far Clip Plane In", "CubicClipZoomIn"); + create_menu_item_with_mnemonic(camera_menu, "Far Clip Plane Out", "CubicClipZoomOut"); + menu_separator(camera_menu); + create_menu_item_with_mnemonic(camera_menu, "Next leak spot", "NextLeakSpot"); + create_menu_item_with_mnemonic(camera_menu, "Previous leak spot", "PrevLeakSpot"); + menu_separator(camera_menu); + create_menu_item_with_mnemonic(camera_menu, "Look Through Selected", "LookThroughSelected"); + create_menu_item_with_mnemonic(camera_menu, "Look Through Camera", "LookThroughCamera"); + } + menu_separator(menu); + { + auto orthographic_menu = create_sub_menu_with_mnemonic(menu, "Orthographic"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(orthographic_menu); + } + if (style == MainFrame::eRegular || style == MainFrame::eRegularLeft || style == MainFrame::eFloating) { + create_menu_item_with_mnemonic(orthographic_menu, "_Next (XY, YZ, XY)", "NextView"); + create_menu_item_with_mnemonic(orthographic_menu, "XY (Top)", "ViewTop"); + create_menu_item_with_mnemonic(orthographic_menu, "YZ", "ViewSide"); + create_menu_item_with_mnemonic(orthographic_menu, "XZ", "ViewFront"); + menu_separator(orthographic_menu); + } + + create_menu_item_with_mnemonic(orthographic_menu, "_XY 100%", "Zoom100"); + create_menu_item_with_mnemonic(orthographic_menu, "XY Zoom _In", "ZoomIn"); + create_menu_item_with_mnemonic(orthographic_menu, "XY Zoom _Out", "ZoomOut"); + } + + menu_separator(menu); + + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Show"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_check_menu_item_with_mnemonic(menu_in_menu, "Show _Angles", "ShowAngles"); + create_check_menu_item_with_mnemonic(menu_in_menu, "Show _Names", "ShowNames"); + create_check_menu_item_with_mnemonic(menu_in_menu, "Show Blocks", "ShowBlocks"); + create_check_menu_item_with_mnemonic(menu_in_menu, "Show C_oordinates", "ShowCoordinates"); + create_check_menu_item_with_mnemonic(menu_in_menu, "Show Window Outline", "ShowWindowOutline"); + create_check_menu_item_with_mnemonic(menu_in_menu, "Show Axes", "ShowAxes"); + create_check_menu_item_with_mnemonic(menu_in_menu, "Show Workzone", "ShowWorkzone"); + create_check_menu_item_with_mnemonic(menu_in_menu, "Show Stats", "ShowStats"); + } + + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Filter"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + Filters_constructMenu(menu_in_menu); + } + menu_separator(menu); + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Hide/Show"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Hide Selected", "HideSelected"); + create_menu_item_with_mnemonic(menu_in_menu, "Show Hidden", "ShowHidden"); + } + menu_separator(menu); + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Region"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "_Off", "RegionOff"); + create_menu_item_with_mnemonic(menu_in_menu, "_Set XY", "RegionSetXY"); + create_menu_item_with_mnemonic(menu_in_menu, "Set _Brush", "RegionSetBrush"); + create_menu_item_with_mnemonic(menu_in_menu, "Set Se_lected Brushes", "RegionSetSelection"); + } + + command_connect_accelerator("CenterXYView"); + + return view_menu_item; +} + +ui::MenuItem create_selection_menu() +{ + // Selection menu + auto selection_menu_item = new_sub_menu_item_with_mnemonic("M_odify"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(selection_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } + + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Components"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_check_menu_item_with_mnemonic(menu_in_menu, "_Edges", "DragEdges"); + create_check_menu_item_with_mnemonic(menu_in_menu, "_Vertices", "DragVertices"); + create_check_menu_item_with_mnemonic(menu_in_menu, "_Faces", "DragFaces"); + } + + menu_separator(menu); + + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Nudge"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Nudge Left", "SelectNudgeLeft"); + create_menu_item_with_mnemonic(menu_in_menu, "Nudge Right", "SelectNudgeRight"); + create_menu_item_with_mnemonic(menu_in_menu, "Nudge Up", "SelectNudgeUp"); + create_menu_item_with_mnemonic(menu_in_menu, "Nudge Down", "SelectNudgeDown"); + } + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Rotate"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Rotate X", "RotateSelectionX"); + create_menu_item_with_mnemonic(menu_in_menu, "Rotate Y", "RotateSelectionY"); + create_menu_item_with_mnemonic(menu_in_menu, "Rotate Z", "RotateSelectionZ"); + } + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Flip"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Flip _X", "MirrorSelectionX"); + create_menu_item_with_mnemonic(menu_in_menu, "Flip _Y", "MirrorSelectionY"); + create_menu_item_with_mnemonic(menu_in_menu, "Flip _Z", "MirrorSelectionZ"); + } + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Arbitrary rotation...", "ArbitraryRotation"); + create_menu_item_with_mnemonic(menu, "Arbitrary scale...", "ArbitraryScale"); + + return selection_menu_item; +} + +ui::MenuItem create_bsp_menu() +{ + // BSP menu + auto bsp_menu_item = new_sub_menu_item_with_mnemonic("_Build"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(bsp_menu_item)); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - create_menu_item_with_mnemonic( menu, "Customize...", "BuildMenuCustomize" ); + create_menu_item_with_mnemonic(menu, "Customize...", "BuildMenuCustomize"); - menu_separator( menu ); + menu_separator(menu); - Build_constructMenu( menu ); + Build_constructMenu(menu); - g_bsp_menu = menu; + g_bsp_menu = menu; - return bsp_menu_item; + return bsp_menu_item; } -ui::MenuItem create_grid_menu(){ - // Grid menu - auto grid_menu_item = new_sub_menu_item_with_mnemonic( "_Grid" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( grid_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } +ui::MenuItem create_grid_menu() +{ + // Grid menu + auto grid_menu_item = new_sub_menu_item_with_mnemonic("_Grid"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(grid_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - Grid_constructMenu( menu ); + Grid_constructMenu(menu); - return grid_menu_item; + return grid_menu_item; } -ui::MenuItem create_misc_menu(){ - // Misc menu - auto misc_menu_item = new_sub_menu_item_with_mnemonic( "M_isc" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( misc_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } +ui::MenuItem create_misc_menu() +{ + // Misc menu + auto misc_menu_item = new_sub_menu_item_with_mnemonic("M_isc"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(misc_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } #if 0 - create_menu_item_with_mnemonic( menu, "_Benchmark", makeCallbackF(GlobalCamera_Benchmark) ); + create_menu_item_with_mnemonic( menu, "_Benchmark", makeCallbackF(GlobalCamera_Benchmark) ); #endif menu.add(create_colours_menu()); - create_menu_item_with_mnemonic( menu, "Find brush...", "FindBrush" ); - create_menu_item_with_mnemonic( menu, "Map Info...", "MapInfo" ); - // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394 + create_menu_item_with_mnemonic(menu, "Find brush...", "FindBrush"); + create_menu_item_with_mnemonic(menu, "Map Info...", "MapInfo"); + // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394 // create_menu_item_with_mnemonic(menu, "_Print XY View", FreeCaller()); - create_menu_item_with_mnemonic( menu, "_Background select", makeCallbackF(WXY_BackgroundSelect) ); - return misc_menu_item; + create_menu_item_with_mnemonic(menu, "_Background select", makeCallbackF(WXY_BackgroundSelect)); + return misc_menu_item; } -ui::MenuItem create_entity_menu(){ - // Brush menu - auto entity_menu_item = new_sub_menu_item_with_mnemonic( "E_ntity" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( entity_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } +ui::MenuItem create_entity_menu() +{ + // Brush menu + auto entity_menu_item = new_sub_menu_item_with_mnemonic("E_ntity"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(entity_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - Entity_constructMenu( menu ); + Entity_constructMenu(menu); - return entity_menu_item; + return entity_menu_item; } -ui::MenuItem create_brush_menu(){ - // Brush menu - auto brush_menu_item = new_sub_menu_item_with_mnemonic( "B_rush" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( brush_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } +ui::MenuItem create_brush_menu() +{ + // Brush menu + auto brush_menu_item = new_sub_menu_item_with_mnemonic("B_rush"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(brush_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - Brush_constructMenu( menu ); + Brush_constructMenu(menu); - return brush_menu_item; + return brush_menu_item; } -ui::MenuItem create_patch_menu(){ - // Curve menu - auto patch_menu_item = new_sub_menu_item_with_mnemonic( "_Curve" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( patch_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } +ui::MenuItem create_patch_menu() +{ + // Curve menu + auto patch_menu_item = new_sub_menu_item_with_mnemonic("_Curve"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(patch_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - Patch_constructMenu( menu ); + Patch_constructMenu(menu); - return patch_menu_item; + return patch_menu_item; } -ui::MenuItem create_help_menu(){ - // Help menu - auto help_menu_item = new_sub_menu_item_with_mnemonic( "_Help" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( help_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } +ui::MenuItem create_help_menu() +{ + // Help menu + auto help_menu_item = new_sub_menu_item_with_mnemonic("_Help"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(help_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - create_menu_item_with_mnemonic( menu, "Manual", "OpenManual" ); + create_menu_item_with_mnemonic(menu, "Manual", "OpenManual"); - // this creates all the per-game drop downs for the game pack helps - // it will take care of hooking the Sys_OpenURL calls etc. - create_game_help_menu( menu ); + // this creates all the per-game drop downs for the game pack helps + // it will take care of hooking the Sys_OpenURL calls etc. + create_game_help_menu(menu); - create_menu_item_with_mnemonic( menu, "Bug report", makeCallbackF(OpenBugReportURL) ); - create_menu_item_with_mnemonic( menu, "Shortcuts list", makeCallbackF(DoCommandListDlg) ); - create_menu_item_with_mnemonic( menu, "_About", makeCallbackF(DoAbout) ); + create_menu_item_with_mnemonic(menu, "Bug report", makeCallbackF(OpenBugReportURL)); + create_menu_item_with_mnemonic(menu, "Shortcuts list", makeCallbackF(DoCommandListDlg)); + create_menu_item_with_mnemonic(menu, "_About", makeCallbackF(DoAbout)); - return help_menu_item; + return help_menu_item; } -ui::MenuBar create_main_menu( MainFrame::EViewStyle style ){ - auto menu_bar = ui::MenuBar::from( gtk_menu_bar_new() ); - menu_bar.show(); +ui::MenuBar create_main_menu(MainFrame::EViewStyle style) +{ + auto menu_bar = ui::MenuBar::from(gtk_menu_bar_new()); + menu_bar.show(); - menu_bar.add(create_file_menu()); - menu_bar.add(create_edit_menu()); - menu_bar.add(create_view_menu(style)); - menu_bar.add(create_selection_menu()); - menu_bar.add(create_bsp_menu()); - menu_bar.add(create_grid_menu()); - menu_bar.add(create_misc_menu()); - menu_bar.add(create_entity_menu()); - menu_bar.add(create_brush_menu()); - menu_bar.add(create_patch_menu()); - menu_bar.add(create_plugins_menu()); - menu_bar.add(create_help_menu()); + menu_bar.add(create_file_menu()); + menu_bar.add(create_edit_menu()); + menu_bar.add(create_view_menu(style)); + menu_bar.add(create_selection_menu()); + menu_bar.add(create_bsp_menu()); + menu_bar.add(create_grid_menu()); + menu_bar.add(create_misc_menu()); + menu_bar.add(create_entity_menu()); + menu_bar.add(create_brush_menu()); + menu_bar.add(create_patch_menu()); + menu_bar.add(create_plugins_menu()); + menu_bar.add(create_help_menu()); - return menu_bar; + return menu_bar; } -void PatchInspector_registerShortcuts(){ - command_connect_accelerator( "PatchInspector" ); -} - -void Patch_registerShortcuts(){ - command_connect_accelerator( "InvertCurveTextureX" ); - command_connect_accelerator( "InvertCurveTextureY" ); - command_connect_accelerator( "PatchInsertInsertColumn" ); - command_connect_accelerator( "PatchInsertInsertRow" ); - command_connect_accelerator( "PatchDeleteLastColumn" ); - command_connect_accelerator( "PatchDeleteLastRow" ); - command_connect_accelerator( "NaturalizePatch" ); - //command_connect_accelerator("CapCurrentCurve"); +void PatchInspector_registerShortcuts() +{ + command_connect_accelerator("PatchInspector"); } -void Manipulators_registerShortcuts(){ - toggle_add_accelerator( "MouseRotate" ); - toggle_add_accelerator( "MouseTranslate" ); - toggle_add_accelerator( "MouseScale" ); - toggle_add_accelerator( "MouseDrag" ); - toggle_add_accelerator( "ToggleClipper" ); +void Patch_registerShortcuts() +{ + command_connect_accelerator("InvertCurveTextureX"); + command_connect_accelerator("InvertCurveTextureY"); + command_connect_accelerator("PatchInsertInsertColumn"); + command_connect_accelerator("PatchInsertInsertRow"); + command_connect_accelerator("PatchDeleteLastColumn"); + command_connect_accelerator("PatchDeleteLastRow"); + command_connect_accelerator("NaturalizePatch"); + //command_connect_accelerator("CapCurrentCurve"); } -void TexdefNudge_registerShortcuts(){ - command_connect_accelerator( "TexRotateClock" ); - command_connect_accelerator( "TexRotateCounter" ); - command_connect_accelerator( "TexScaleUp" ); - command_connect_accelerator( "TexScaleDown" ); - command_connect_accelerator( "TexScaleLeft" ); - command_connect_accelerator( "TexScaleRight" ); - command_connect_accelerator( "TexShiftUp" ); - command_connect_accelerator( "TexShiftDown" ); - command_connect_accelerator( "TexShiftLeft" ); - command_connect_accelerator( "TexShiftRight" ); +void Manipulators_registerShortcuts() +{ + toggle_add_accelerator("MouseRotate"); + toggle_add_accelerator("MouseTranslate"); + toggle_add_accelerator("MouseScale"); + toggle_add_accelerator("MouseDrag"); + toggle_add_accelerator("ToggleClipper"); } -void SelectNudge_registerShortcuts(){ - command_connect_accelerator( "MoveSelectionDOWN" ); - command_connect_accelerator( "MoveSelectionUP" ); - //command_connect_accelerator("SelectNudgeLeft"); - //command_connect_accelerator("SelectNudgeRight"); - //command_connect_accelerator("SelectNudgeUp"); - //command_connect_accelerator("SelectNudgeDown"); +void TexdefNudge_registerShortcuts() +{ + command_connect_accelerator("TexRotateClock"); + command_connect_accelerator("TexRotateCounter"); + command_connect_accelerator("TexScaleUp"); + command_connect_accelerator("TexScaleDown"); + command_connect_accelerator("TexScaleLeft"); + command_connect_accelerator("TexScaleRight"); + command_connect_accelerator("TexShiftUp"); + command_connect_accelerator("TexShiftDown"); + command_connect_accelerator("TexShiftLeft"); + command_connect_accelerator("TexShiftRight"); +} + +void SelectNudge_registerShortcuts() +{ + command_connect_accelerator("MoveSelectionDOWN"); + command_connect_accelerator("MoveSelectionUP"); + //command_connect_accelerator("SelectNudgeLeft"); + //command_connect_accelerator("SelectNudgeRight"); + //command_connect_accelerator("SelectNudgeUp"); + //command_connect_accelerator("SelectNudgeDown"); } -void SnapToGrid_registerShortcuts(){ - command_connect_accelerator( "SnapToGrid" ); +void SnapToGrid_registerShortcuts() +{ + command_connect_accelerator("SnapToGrid"); } -void SelectByType_registerShortcuts(){ - command_connect_accelerator( "SelectAllOfType" ); +void SelectByType_registerShortcuts() +{ + command_connect_accelerator("SelectAllOfType"); } -void SurfaceInspector_registerShortcuts(){ - command_connect_accelerator( "FitTexture" ); +void SurfaceInspector_registerShortcuts() +{ + command_connect_accelerator("FitTexture"); } -void register_shortcuts(){ - PatchInspector_registerShortcuts(); - Patch_registerShortcuts(); - Grid_registerShortcuts(); - XYWnd_registerShortcuts(); - CamWnd_registerShortcuts(); - Manipulators_registerShortcuts(); - SurfaceInspector_registerShortcuts(); - TexdefNudge_registerShortcuts(); - SelectNudge_registerShortcuts(); - SnapToGrid_registerShortcuts(); - SelectByType_registerShortcuts(); -} - -void File_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_button( toolbar, "Open an existing map (CTRL + O)", "file_open.png", "OpenMap" ); - toolbar_append_button( toolbar, "Save the active map (CTRL + S)", "file_save.png", "SaveMap" ); +void register_shortcuts() +{ + PatchInspector_registerShortcuts(); + Patch_registerShortcuts(); + Grid_registerShortcuts(); + XYWnd_registerShortcuts(); + CamWnd_registerShortcuts(); + Manipulators_registerShortcuts(); + SurfaceInspector_registerShortcuts(); + TexdefNudge_registerShortcuts(); + SelectNudge_registerShortcuts(); + SnapToGrid_registerShortcuts(); + SelectByType_registerShortcuts(); +} + +void File_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_button(toolbar, "Open an existing map (CTRL + O)", "file_open.png", "OpenMap"); + toolbar_append_button(toolbar, "Save the active map (CTRL + S)", "file_save.png", "SaveMap"); } -void UndoRedo_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_button( toolbar, "Undo (CTRL + Z)", "undo.png", "Undo" ); - toolbar_append_button( toolbar, "Redo (CTRL + Y)", "redo.png", "Redo" ); +void UndoRedo_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_button(toolbar, "Undo (CTRL + Z)", "undo.png", "Undo"); + toolbar_append_button(toolbar, "Redo (CTRL + Y)", "redo.png", "Redo"); } -void RotateFlip_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_button( toolbar, "x-axis Flip", "brush_flipx.png", "MirrorSelectionX" ); - toolbar_append_button( toolbar, "x-axis Rotate", "brush_rotatex.png", "RotateSelectionX" ); - toolbar_append_button( toolbar, "y-axis Flip", "brush_flipy.png", "MirrorSelectionY" ); - toolbar_append_button( toolbar, "y-axis Rotate", "brush_rotatey.png", "RotateSelectionY" ); - toolbar_append_button( toolbar, "z-axis Flip", "brush_flipz.png", "MirrorSelectionZ" ); - toolbar_append_button( toolbar, "z-axis Rotate", "brush_rotatez.png", "RotateSelectionZ" ); +void RotateFlip_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_button(toolbar, "x-axis Flip", "brush_flipx.png", "MirrorSelectionX"); + toolbar_append_button(toolbar, "x-axis Rotate", "brush_rotatex.png", "RotateSelectionX"); + toolbar_append_button(toolbar, "y-axis Flip", "brush_flipy.png", "MirrorSelectionY"); + toolbar_append_button(toolbar, "y-axis Rotate", "brush_rotatey.png", "RotateSelectionY"); + toolbar_append_button(toolbar, "z-axis Flip", "brush_flipz.png", "MirrorSelectionZ"); + toolbar_append_button(toolbar, "z-axis Rotate", "brush_rotatez.png", "RotateSelectionZ"); } -void Select_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_button( toolbar, "Select touching", "selection_selecttouching.png", "SelectTouching" ); - toolbar_append_button( toolbar, "Select inside", "selection_selectinside.png", "SelectInside" ); +void Select_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_button(toolbar, "Select touching", "selection_selecttouching.png", "SelectTouching"); + toolbar_append_button(toolbar, "Select inside", "selection_selectinside.png", "SelectInside"); } -void CSG_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_button( toolbar, "CSG Subtract (SHIFT + U)", "selection_csgsubtract.png", "CSGSubtract" ); - toolbar_append_button( toolbar, "CSG Merge (CTRL + U)", "selection_csgmerge.png", "CSGMerge" ); - toolbar_append_button( toolbar, "Hollow", "selection_makehollow.png", "CSGHollow" ); +void CSG_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_button(toolbar, "CSG Subtract (SHIFT + U)", "selection_csgsubtract.png", "CSGSubtract"); + toolbar_append_button(toolbar, "CSG Merge (CTRL + U)", "selection_csgmerge.png", "CSGMerge"); + toolbar_append_button(toolbar, "Hollow", "selection_makehollow.png", "CSGHollow"); } -void ComponentModes_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_toggle_button( toolbar, "Select Vertices (V)", "modify_vertices.png", "DragVertices" ); - toolbar_append_toggle_button( toolbar, "Select Edges (E)", "modify_edges.png", "DragEdges" ); - toolbar_append_toggle_button( toolbar, "Select Faces (F)", "modify_faces.png", "DragFaces" ); +void ComponentModes_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_toggle_button(toolbar, "Select Vertices (V)", "modify_vertices.png", "DragVertices"); + toolbar_append_toggle_button(toolbar, "Select Edges (E)", "modify_edges.png", "DragEdges"); + toolbar_append_toggle_button(toolbar, "Select Faces (F)", "modify_faces.png", "DragFaces"); } -void Clipper_constructToolbar( ui::Toolbar toolbar ){ +void Clipper_constructToolbar(ui::Toolbar toolbar) +{ - toolbar_append_toggle_button( toolbar, "Clipper (X)", "view_clipper.png", "ToggleClipper" ); + toolbar_append_toggle_button(toolbar, "Clipper (X)", "view_clipper.png", "ToggleClipper"); } -void XYWnd_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_button( toolbar, "Change views", "view_change.png", "NextView" ); +void XYWnd_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_button(toolbar, "Change views", "view_change.png", "NextView"); } -void Manipulators_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_toggle_button( toolbar, "Translate (W)", "select_mousetranslate.png", "MouseTranslate" ); - toolbar_append_toggle_button( toolbar, "Rotate (R)", "select_mouserotate.png", "MouseRotate" ); - toolbar_append_toggle_button( toolbar, "Scale", "select_mousescale.png", "MouseScale" ); - toolbar_append_toggle_button( toolbar, "Resize (Q)", "select_mouseresize.png", "MouseDrag" ); +void Manipulators_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_toggle_button(toolbar, "Translate (W)", "select_mousetranslate.png", "MouseTranslate"); + toolbar_append_toggle_button(toolbar, "Rotate (R)", "select_mouserotate.png", "MouseRotate"); + toolbar_append_toggle_button(toolbar, "Scale", "select_mousescale.png", "MouseScale"); + toolbar_append_toggle_button(toolbar, "Resize (Q)", "select_mouseresize.png", "MouseDrag"); - Clipper_constructToolbar( toolbar ); + Clipper_constructToolbar(toolbar); } -ui::Toolbar create_main_toolbar( MainFrame::EViewStyle style ){ - auto toolbar = ui::Toolbar::from( gtk_toolbar_new() ); - gtk_orientable_set_orientation( GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL ); - gtk_toolbar_set_style( toolbar, GTK_TOOLBAR_ICONS ); +ui::Toolbar create_main_toolbar(MainFrame::EViewStyle style) +{ + auto toolbar = ui::Toolbar::from(gtk_toolbar_new()); + gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL); + gtk_toolbar_set_style(toolbar, GTK_TOOLBAR_ICONS); - toolbar.show(); + toolbar.show(); - auto space = [&]() { - auto btn = ui::ToolItem::from(gtk_separator_tool_item_new()); - btn.show(); - toolbar.add(btn); - }; + auto space = [&]() { + auto btn = ui::ToolItem::from(gtk_separator_tool_item_new()); + btn.show(); + toolbar.add(btn); + }; - File_constructToolbar( toolbar ); + File_constructToolbar(toolbar); - space(); + space(); - UndoRedo_constructToolbar( toolbar ); + UndoRedo_constructToolbar(toolbar); - space(); + space(); - RotateFlip_constructToolbar( toolbar ); + RotateFlip_constructToolbar(toolbar); - space(); + space(); - Select_constructToolbar( toolbar ); + Select_constructToolbar(toolbar); - space(); + space(); - CSG_constructToolbar( toolbar ); + CSG_constructToolbar(toolbar); - space(); + space(); - ComponentModes_constructToolbar( toolbar ); + ComponentModes_constructToolbar(toolbar); - if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft || style == MainFrame::eFloating ) { - space(); + if (style == MainFrame::eRegular || style == MainFrame::eRegularLeft || style == MainFrame::eFloating) { + space(); - XYWnd_constructToolbar( toolbar ); - } + XYWnd_constructToolbar(toolbar); + } - space(); + space(); - CamWnd_constructToolbar( toolbar ); + CamWnd_constructToolbar(toolbar); - space(); + space(); - Manipulators_constructToolbar( toolbar ); + Manipulators_constructToolbar(toolbar); - if ( g_Layout_enablePatchToolbar.m_value ) { - space(); + if (g_Layout_enablePatchToolbar.m_value) { + space(); - Patch_constructToolbar( toolbar ); - } + Patch_constructToolbar(toolbar); + } - space(); + space(); - toolbar_append_toggle_button( toolbar, "Texture Lock (SHIFT +T)", "texture_lock.png", "TogTexLock" ); + toolbar_append_toggle_button(toolbar, "Texture Lock (SHIFT +T)", "texture_lock.png", "TogTexLock"); - space(); + space(); - /*auto g_view_entities_button =*/ toolbar_append_button( toolbar, "Entities (N)", "entities.png", "ToggleEntityInspector" ); - auto g_view_console_button = toolbar_append_button( toolbar, "Console (O)", "console.png", "ToggleConsole" ); - auto g_view_textures_button = toolbar_append_button( toolbar, "Texture Browser (T)", "texture_browser.png", "ToggleTextures" ); - // TODO: call light inspector - //GtkButton* g_view_lightinspector_button = toolbar_append_button(toolbar, "Light Inspector", "lightinspector.png", "ToggleLightInspector"); + /*auto g_view_entities_button =*/ toolbar_append_button(toolbar, "Entities (N)", "entities.png", + "ToggleEntityInspector"); + auto g_view_console_button = toolbar_append_button(toolbar, "Console (O)", "console.png", "ToggleConsole"); + auto g_view_textures_button = toolbar_append_button(toolbar, "Texture Browser (T)", "texture_browser.png", + "ToggleTextures"); + // TODO: call light inspector + //GtkButton* g_view_lightinspector_button = toolbar_append_button(toolbar, "Light Inspector", "lightinspector.png", "ToggleLightInspector"); - space(); - /*auto g_refresh_models_button =*/ toolbar_append_button( toolbar, "Refresh Models", "refresh_models.png", "RefreshReferences" ); + space(); + /*auto g_refresh_models_button =*/ toolbar_append_button(toolbar, "Refresh Models", "refresh_models.png", + "RefreshReferences"); - // disable the console and texture button in the regular layouts - if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft ) { - gtk_widget_set_sensitive( g_view_console_button , FALSE ); - gtk_widget_set_sensitive( g_view_textures_button , FALSE ); - } + // disable the console and texture button in the regular layouts + if (style == MainFrame::eRegular || style == MainFrame::eRegularLeft) { + gtk_widget_set_sensitive(g_view_console_button, FALSE); + gtk_widget_set_sensitive(g_view_textures_button, FALSE); + } - return toolbar; + return toolbar; } -ui::Widget create_main_statusbar( ui::Widget pStatusLabel[c_count_status] ){ - auto table = ui::Table( 1, c_count_status, FALSE ); - table.show(); - - { - auto label = ui::Label( "Label" ); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - gtk_misc_set_padding( GTK_MISC( label ), 4, 2 ); - label.show(); - table.attach(label, {0, 1, 0, 1}); - pStatusLabel[c_command_status] = ui::Widget(label ); - } - - for (unsigned int i = 1; (int) i < c_count_status; ++i) - { - auto frame = ui::Frame(); - frame.show(); - table.attach(frame, {i, i + 1, 0, 1}); - gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN ); - - auto label = ui::Label( "Label" ); - gtk_label_set_ellipsize( label, PANGO_ELLIPSIZE_END ); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - gtk_misc_set_padding( GTK_MISC( label ), 4, 2 ); - label.show(); - frame.add(label); - pStatusLabel[i] = ui::Widget(label ); - } - - return ui::Widget(table ); +ui::Widget create_main_statusbar(ui::Widget pStatusLabel[c_count_status]) +{ + auto table = ui::Table(1, c_count_status, FALSE); + table.show(); + + { + auto label = ui::Label("Label"); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_misc_set_padding(GTK_MISC(label), 4, 2); + label.show(); + table.attach(label, {0, 1, 0, 1}); + pStatusLabel[c_command_status] = ui::Widget(label); + } + + for (unsigned int i = 1; (int) i < c_count_status; ++i) { + auto frame = ui::Frame(); + frame.show(); + table.attach(frame, {i, i + 1, 0, 1}); + gtk_frame_set_shadow_type(frame, GTK_SHADOW_IN); + + auto label = ui::Label("Label"); + gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_misc_set_padding(GTK_MISC(label), 4, 2); + label.show(); + frame.add(label); + pStatusLabel[i] = ui::Widget(label); + } + + return ui::Widget(table); } #if 0 -WidgetFocusPrinter g_mainframeWidgetFocusPrinter( "mainframe" ); + WidgetFocusPrinter g_mainframeWidgetFocusPrinter( "mainframe" ); class WindowFocusPrinter { @@ -2593,99 +2795,108 @@ WindowFocusPrinter g_mainframeFocusPrinter( "mainframe" ); #endif -class MainWindowActive -{ -static gboolean notify( ui::Window window, gpointer dummy, MainWindowActive* self ){ - if ( g_wait.m_window && gtk_window_is_active( window ) && !g_wait.m_window.visible() ) { - g_wait.m_window.show(); - } +class MainWindowActive { + static gboolean notify(ui::Window window, gpointer dummy, MainWindowActive *self) + { + if (g_wait.m_window && gtk_window_is_active(window) && !g_wait.m_window.visible()) { + g_wait.m_window.show(); + } + + return FALSE; + } - return FALSE; -} public: -void connect( ui::Window toplevel_window ){ - toplevel_window.connect( "notify::is-active", G_CALLBACK( notify ), this ); -} + void connect(ui::Window toplevel_window) + { + toplevel_window.connect("notify::is-active", G_CALLBACK(notify), this); + } }; MainWindowActive g_MainWindowActive; -SignalHandlerId XYWindowDestroyed_connect( const SignalHandler& handler ){ - return g_pParentWnd->GetXYWnd()->onDestroyed.connectFirst( handler ); +SignalHandlerId XYWindowDestroyed_connect(const SignalHandler &handler) +{ + return g_pParentWnd->GetXYWnd()->onDestroyed.connectFirst(handler); } -void XYWindowDestroyed_disconnect( SignalHandlerId id ){ - g_pParentWnd->GetXYWnd()->onDestroyed.disconnect( id ); +void XYWindowDestroyed_disconnect(SignalHandlerId id) +{ + g_pParentWnd->GetXYWnd()->onDestroyed.disconnect(id); } -MouseEventHandlerId XYWindowMouseDown_connect( const MouseEventHandler& handler ){ - return g_pParentWnd->GetXYWnd()->onMouseDown.connectFirst( handler ); +MouseEventHandlerId XYWindowMouseDown_connect(const MouseEventHandler &handler) +{ + return g_pParentWnd->GetXYWnd()->onMouseDown.connectFirst(handler); } -void XYWindowMouseDown_disconnect( MouseEventHandlerId id ){ - g_pParentWnd->GetXYWnd()->onMouseDown.disconnect( id ); +void XYWindowMouseDown_disconnect(MouseEventHandlerId id) +{ + g_pParentWnd->GetXYWnd()->onMouseDown.disconnect(id); } // ============================================================================= // MainFrame class -MainFrame* g_pParentWnd = 0; +MainFrame *g_pParentWnd = 0; ui::Window MainFrame_getWindow() { - return g_pParentWnd ? g_pParentWnd->m_window : ui::Window{ui::null}; + return g_pParentWnd ? g_pParentWnd->m_window : ui::Window{ui::null}; } std::vector g_floating_windows; -MainFrame::MainFrame() : m_idleRedrawStatusText( RedrawStatusTextCaller( *this ) ){ - m_pXYWnd = 0; - m_pCamWnd = 0; - m_pZWnd = 0; - m_pYZWnd = 0; - m_pXZWnd = 0; - m_pActiveXY = 0; - - for (auto &n : m_pStatusLabel) { +MainFrame::MainFrame() : m_idleRedrawStatusText(RedrawStatusTextCaller(*this)) +{ + m_pXYWnd = 0; + m_pCamWnd = 0; + m_pZWnd = 0; + m_pYZWnd = 0; + m_pXZWnd = 0; + m_pActiveXY = 0; + + for (auto &n : m_pStatusLabel) { n = NULL; - } + } - m_bSleeping = false; + m_bSleeping = false; - Create(); + Create(); } -MainFrame::~MainFrame(){ - SaveWindowInfo(); +MainFrame::~MainFrame() +{ + SaveWindowInfo(); - m_window.hide(); + m_window.hide(); - Shutdown(); + Shutdown(); - for ( std::vector::iterator i = g_floating_windows.begin(); i != g_floating_windows.end(); ++i ) - { - i->destroy(); - } + for (std::vector::iterator i = g_floating_windows.begin(); i != g_floating_windows.end(); ++i) { + i->destroy(); + } - m_window.destroy(); + m_window.destroy(); } -void MainFrame::SetActiveXY( XYWnd* p ){ - if ( m_pActiveXY ) { - m_pActiveXY->SetActive( false ); - } +void MainFrame::SetActiveXY(XYWnd *p) +{ + if (m_pActiveXY) { + m_pActiveXY->SetActive(false); + } - m_pActiveXY = p; + m_pActiveXY = p; - if ( m_pActiveXY ) { - m_pActiveXY->SetActive( true ); - } + if (m_pActiveXY) { + m_pActiveXY->SetActive(true); + } } -void MainFrame::ReleaseContexts(){ +void MainFrame::ReleaseContexts() +{ #if 0 - if ( m_pXYWnd ) { + if ( m_pXYWnd ) { m_pXYWnd->DestroyContext(); } if ( m_pYZWnd ) { @@ -2706,9 +2917,10 @@ void MainFrame::ReleaseContexts(){ #endif } -void MainFrame::CreateContexts(){ +void MainFrame::CreateContexts() +{ #if 0 - if ( m_pCamWnd ) { + if ( m_pCamWnd ) { m_pCamWnd->CreateContext(); } if ( m_pXYWnd ) { @@ -2733,9 +2945,10 @@ void MainFrame::CreateContexts(){ //#define DBG_SLEEP #endif -void MainFrame::OnSleep(){ +void MainFrame::OnSleep() +{ #if 0 - m_bSleeping ^= 1; + m_bSleeping ^= 1; if ( m_bSleeping ) { // useful when trying to debug crashes in the sleep code globalOutputStream() << "Going into sleep mode..\n"; @@ -2787,35 +3000,38 @@ void MainFrame::OnSleep(){ } -ui::Window create_splash(){ - auto window = ui::Window( ui::window_type::TOP ); - gtk_window_set_decorated(window, false); - gtk_window_set_resizable(window, false); - gtk_window_set_modal(window, true); - gtk_window_set_default_size( window, -1, -1 ); - gtk_window_set_position( window, GTK_WIN_POS_CENTER ); - gtk_container_set_border_width(window, 0); +ui::Window create_splash() +{ + auto window = ui::Window(ui::window_type::TOP); + gtk_window_set_decorated(window, false); + gtk_window_set_resizable(window, false); + gtk_window_set_modal(window, true); + gtk_window_set_default_size(window, -1, -1); + gtk_window_set_position(window, GTK_WIN_POS_CENTER); + gtk_container_set_border_width(window, 0); - auto image = new_local_image( "splash.png" ); - image.show(); - window.add(image); + auto image = new_local_image("splash.png"); + image.show(); + window.add(image); - window.dimensions(-1, -1); - window.show(); + window.dimensions(-1, -1); + window.show(); - return window; + return window; } static ui::Window splash_screen{ui::null}; -void show_splash(){ - splash_screen = create_splash(); +void show_splash() +{ + splash_screen = create_splash(); - ui::process(); + ui::process(); } -void hide_splash(){ - splash_screen.destroy(); +void hide_splash() +{ + splash_screen.destroy(); } WindowPositionTracker g_posCamWnd; @@ -2823,674 +3039,722 @@ WindowPositionTracker g_posXYWnd; WindowPositionTracker g_posXZWnd; WindowPositionTracker g_posYZWnd; -static gint mainframe_delete( ui::Widget widget, GdkEvent *event, gpointer data ){ - if ( ConfirmModified( "Exit Radiant" ) ) { - gtk_main_quit(); - } +static gint mainframe_delete(ui::Widget widget, GdkEvent *event, gpointer data) +{ + if (ConfirmModified("Exit Radiant")) { + gtk_main_quit(); + } - return TRUE; + return TRUE; } -void MainFrame::Create(){ - ui::Window window = ui::Window( ui::window_type::TOP ); +void MainFrame::Create() +{ + ui::Window window = ui::Window(ui::window_type::TOP); - GlobalWindowObservers_connectTopLevel( window ); + GlobalWindowObservers_connectTopLevel(window); - gtk_window_set_transient_for( splash_screen, window ); + gtk_window_set_transient_for(splash_screen, window); #if !GDEF_OS_WINDOWS - { - GdkPixbuf* pixbuf = pixbuf_new_from_file_with_mask( "bitmaps/icon.png" ); - if ( pixbuf != 0 ) { - gtk_window_set_icon( window, pixbuf ); - g_object_unref( pixbuf ); - } - } + { + GdkPixbuf *pixbuf = pixbuf_new_from_file_with_mask("bitmaps/icon.png"); + if (pixbuf != 0) { + gtk_window_set_icon(window, pixbuf); + g_object_unref(pixbuf); + } + } #endif - gtk_widget_add_events( window , GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK ); - window.connect( "delete_event", G_CALLBACK( mainframe_delete ), this ); + gtk_widget_add_events(window, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK); + window.connect("delete_event", G_CALLBACK(mainframe_delete), this); - m_position_tracker.connect( window ); + m_position_tracker.connect(window); #if 0 - g_mainframeWidgetFocusPrinter.connect( window ); + g_mainframeWidgetFocusPrinter.connect( window ); g_mainframeFocusPrinter.connect( window ); #endif - g_MainWindowActive.connect( window ); + g_MainWindowActive.connect(window); - GetPlugInMgr().Init( window ); + GetPlugInMgr().Init(window); - auto vbox = ui::VBox( FALSE, 0 ); - window.add(vbox); - vbox.show(); + auto vbox = ui::VBox(FALSE, 0); + window.add(vbox); + vbox.show(); - global_accel_connect_window( window ); + global_accel_connect_window(window); - m_nCurrentStyle = (EViewStyle)g_Layout_viewStyle.m_value; + m_nCurrentStyle = (EViewStyle) g_Layout_viewStyle.m_value; - register_shortcuts(); + register_shortcuts(); - auto main_menu = create_main_menu( CurrentStyle() ); - vbox.pack_start( main_menu, FALSE, FALSE, 0 ); + auto main_menu = create_main_menu(CurrentStyle()); + vbox.pack_start(main_menu, FALSE, FALSE, 0); - auto main_toolbar = create_main_toolbar( CurrentStyle() ); - vbox.pack_start( main_toolbar, FALSE, FALSE, 0 ); + auto main_toolbar = create_main_toolbar(CurrentStyle()); + vbox.pack_start(main_toolbar, FALSE, FALSE, 0); - auto plugin_toolbar = create_plugin_toolbar(); - if ( !g_Layout_enablePluginToolbar.m_value ) { - plugin_toolbar.hide(); - } - vbox.pack_start( plugin_toolbar, FALSE, FALSE, 0 ); + auto plugin_toolbar = create_plugin_toolbar(); + if (!g_Layout_enablePluginToolbar.m_value) { + plugin_toolbar.hide(); + } + vbox.pack_start(plugin_toolbar, FALSE, FALSE, 0); - ui::Widget main_statusbar = create_main_statusbar(reinterpret_cast(m_pStatusLabel)); - vbox.pack_end(main_statusbar, FALSE, TRUE, 2); + ui::Widget main_statusbar = create_main_statusbar(reinterpret_cast(m_pStatusLabel)); + vbox.pack_end(main_statusbar, FALSE, TRUE, 2); - GroupDialog_constructWindow( window ); - g_page_entity = GroupDialog_addPage( "Entities", EntityInspector_constructWindow( GroupDialog_getWindow() ), RawStringExportCaller( "Entities" ) ); + GroupDialog_constructWindow(window); + g_page_entity = GroupDialog_addPage("Entities", EntityInspector_constructWindow(GroupDialog_getWindow()), + RawStringExportCaller("Entities")); - if ( FloatingGroupDialog() ) { - g_page_console = GroupDialog_addPage( "Console", Console_constructWindow( GroupDialog_getWindow() ), RawStringExportCaller( "Console" ) ); - } + if (FloatingGroupDialog()) { + g_page_console = GroupDialog_addPage("Console", Console_constructWindow(GroupDialog_getWindow()), + RawStringExportCaller("Console")); + } #if GDEF_OS_WINDOWS - if ( g_multimon_globals.m_bStartOnPrimMon ) { + if ( g_multimon_globals.m_bStartOnPrimMon ) { PositionWindowOnPrimaryScreen( g_layout_globals.m_position ); window_set_position( window, g_layout_globals.m_position ); } else #endif - if ( g_layout_globals.nState & GDK_WINDOW_STATE_MAXIMIZED ) { - gtk_window_maximize( window ); - WindowPosition default_position( -1, -1, 640, 480 ); - window_set_position( window, default_position ); - } - else - { - window_set_position( window, g_layout_globals.m_position ); - } - - m_window = window; - - window.show(); - - if ( CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft ) { - { - ui::Widget vsplit = ui::VPaned(ui::New); - m_vSplit = vsplit; - vbox.pack_start( vsplit, TRUE, TRUE, 0 ); - vsplit.show(); - - // console - ui::Widget console_window = Console_constructWindow( window ); - gtk_paned_pack2( GTK_PANED( vsplit ), console_window, FALSE, TRUE ); - - { - ui::Widget hsplit = ui::HPaned(ui::New); - hsplit.show(); - m_hSplit = hsplit; - gtk_paned_add1( GTK_PANED( vsplit ), hsplit ); - - // xy - m_pXYWnd = new XYWnd(); - m_pXYWnd->SetViewType( XY ); - ui::Widget xy_window = ui::Widget(create_framed_widget( m_pXYWnd->GetWidget( ) )); - - { - ui::Widget vsplit2 = ui::VPaned(ui::New); - vsplit2.show(); - m_vSplit2 = vsplit2; - - if ( CurrentStyle() == eRegular ) { - gtk_paned_add1( GTK_PANED( hsplit ), xy_window ); - gtk_paned_add2( GTK_PANED( hsplit ), vsplit2 ); - } - else - { - gtk_paned_add1( GTK_PANED( hsplit ), vsplit2 ); - gtk_paned_add2( GTK_PANED( hsplit ), xy_window ); - } - - - // camera - m_pCamWnd = NewCamWnd(); - GlobalCamera_setCamWnd( *m_pCamWnd ); - CamWnd_setParent( *m_pCamWnd, window ); - auto camera_window = create_framed_widget( CamWnd_getWidget( *m_pCamWnd ) ); - - gtk_paned_add1( GTK_PANED( vsplit2 ), camera_window ); - - // textures - auto texture_window = create_framed_widget( TextureBrowser_constructWindow( window ) ); - - gtk_paned_add2( GTK_PANED( vsplit2 ), texture_window ); - } - } - } - - gtk_paned_set_position( GTK_PANED( m_vSplit ), g_layout_globals.nXYHeight ); - - if ( CurrentStyle() == eRegular ) { - gtk_paned_set_position( GTK_PANED( m_hSplit ), g_layout_globals.nXYWidth ); - } - else - { - gtk_paned_set_position( GTK_PANED( m_hSplit ), g_layout_globals.nCamWidth ); - } - - gtk_paned_set_position( GTK_PANED( m_vSplit2 ), g_layout_globals.nCamHeight ); - } - else if ( CurrentStyle() == eFloating ) { - { - ui::Window window = ui::Window(create_persistent_floating_window( "Camera", m_window )); - global_accel_connect_window( window ); - g_posCamWnd.connect( window ); + if (g_layout_globals.nState & GDK_WINDOW_STATE_MAXIMIZED) { + gtk_window_maximize(window); + WindowPosition default_position(-1, -1, 640, 480); + window_set_position(window, default_position); + } else { + window_set_position(window, g_layout_globals.m_position); + } + + m_window = window; + + window.show(); + + if (CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft) { + { + ui::Widget vsplit = ui::VPaned(ui::New); + m_vSplit = vsplit; + vbox.pack_start(vsplit, TRUE, TRUE, 0); + vsplit.show(); + + // console + ui::Widget console_window = Console_constructWindow(window); + gtk_paned_pack2(GTK_PANED(vsplit), console_window, FALSE, TRUE); + + { + ui::Widget hsplit = ui::HPaned(ui::New); + hsplit.show(); + m_hSplit = hsplit; + gtk_paned_add1(GTK_PANED(vsplit), hsplit); + + // xy + m_pXYWnd = new XYWnd(); + m_pXYWnd->SetViewType(XY); + ui::Widget xy_window = ui::Widget(create_framed_widget(m_pXYWnd->GetWidget())); + + { + ui::Widget vsplit2 = ui::VPaned(ui::New); + vsplit2.show(); + m_vSplit2 = vsplit2; + + if (CurrentStyle() == eRegular) { + gtk_paned_add1(GTK_PANED(hsplit), xy_window); + gtk_paned_add2(GTK_PANED(hsplit), vsplit2); + } else { + gtk_paned_add1(GTK_PANED(hsplit), vsplit2); + gtk_paned_add2(GTK_PANED(hsplit), xy_window); + } + + + // camera + m_pCamWnd = NewCamWnd(); + GlobalCamera_setCamWnd(*m_pCamWnd); + CamWnd_setParent(*m_pCamWnd, window); + auto camera_window = create_framed_widget(CamWnd_getWidget(*m_pCamWnd)); + + gtk_paned_add1(GTK_PANED(vsplit2), camera_window); + + // textures + auto texture_window = create_framed_widget(TextureBrowser_constructWindow(window)); + + gtk_paned_add2(GTK_PANED(vsplit2), texture_window); + } + } + } + + gtk_paned_set_position(GTK_PANED(m_vSplit), g_layout_globals.nXYHeight); + + if (CurrentStyle() == eRegular) { + gtk_paned_set_position(GTK_PANED(m_hSplit), g_layout_globals.nXYWidth); + } else { + gtk_paned_set_position(GTK_PANED(m_hSplit), g_layout_globals.nCamWidth); + } + + gtk_paned_set_position(GTK_PANED(m_vSplit2), g_layout_globals.nCamHeight); + } else if (CurrentStyle() == eFloating) { + { + ui::Window window = ui::Window(create_persistent_floating_window("Camera", m_window)); + global_accel_connect_window(window); + g_posCamWnd.connect(window); - window.show(); + window.show(); - m_pCamWnd = NewCamWnd(); - GlobalCamera_setCamWnd( *m_pCamWnd ); + m_pCamWnd = NewCamWnd(); + GlobalCamera_setCamWnd(*m_pCamWnd); - { - auto frame = create_framed_widget( CamWnd_getWidget( *m_pCamWnd ) ); - window.add(frame); - } - CamWnd_setParent( *m_pCamWnd, window ); - - g_floating_windows.push_back( window ); - } + { + auto frame = create_framed_widget(CamWnd_getWidget(*m_pCamWnd)); + window.add(frame); + } + CamWnd_setParent(*m_pCamWnd, window); - { - ui::Window window = ui::Window(create_persistent_floating_window( ViewType_getTitle( XY ), m_window )); - global_accel_connect_window( window ); - g_posXYWnd.connect( window ); + g_floating_windows.push_back(window); + } + + { + ui::Window window = ui::Window(create_persistent_floating_window(ViewType_getTitle(XY), m_window)); + global_accel_connect_window(window); + g_posXYWnd.connect(window); - m_pXYWnd = new XYWnd(); - m_pXYWnd->m_parent = window; - m_pXYWnd->SetViewType( XY ); + m_pXYWnd = new XYWnd(); + m_pXYWnd->m_parent = window; + m_pXYWnd->SetViewType(XY); - { - auto frame = create_framed_widget( m_pXYWnd->GetWidget() ); - window.add(frame); - } - XY_Top_Shown_Construct( window ); + { + auto frame = create_framed_widget(m_pXYWnd->GetWidget()); + window.add(frame); + } + XY_Top_Shown_Construct(window); - g_floating_windows.push_back( window ); - } + g_floating_windows.push_back(window); + } - { - ui::Window window = ui::Window(create_persistent_floating_window( ViewType_getTitle( XZ ), m_window )); - global_accel_connect_window( window ); - g_posXZWnd.connect( window ); + { + ui::Window window = ui::Window(create_persistent_floating_window(ViewType_getTitle(XZ), m_window)); + global_accel_connect_window(window); + g_posXZWnd.connect(window); - m_pXZWnd = new XYWnd(); - m_pXZWnd->m_parent = window; - m_pXZWnd->SetViewType( XZ ); + m_pXZWnd = new XYWnd(); + m_pXZWnd->m_parent = window; + m_pXZWnd->SetViewType(XZ); - { - auto frame = create_framed_widget( m_pXZWnd->GetWidget() ); - window.add(frame); - } + { + auto frame = create_framed_widget(m_pXZWnd->GetWidget()); + window.add(frame); + } - XZ_Front_Shown_Construct( window ); + XZ_Front_Shown_Construct(window); - g_floating_windows.push_back( window ); - } + g_floating_windows.push_back(window); + } - { - ui::Window window = ui::Window(create_persistent_floating_window( ViewType_getTitle( YZ ), m_window )); - global_accel_connect_window( window ); - g_posYZWnd.connect( window ); + { + ui::Window window = ui::Window(create_persistent_floating_window(ViewType_getTitle(YZ), m_window)); + global_accel_connect_window(window); + g_posYZWnd.connect(window); - m_pYZWnd = new XYWnd(); - m_pYZWnd->m_parent = window; - m_pYZWnd->SetViewType( YZ ); + m_pYZWnd = new XYWnd(); + m_pYZWnd->m_parent = window; + m_pYZWnd->SetViewType(YZ); - { - auto frame = create_framed_widget( m_pYZWnd->GetWidget() ); - window.add(frame); - } + { + auto frame = create_framed_widget(m_pYZWnd->GetWidget()); + window.add(frame); + } - YZ_Side_Shown_Construct( window ); + YZ_Side_Shown_Construct(window); - g_floating_windows.push_back( window ); - } + g_floating_windows.push_back(window); + } - { - auto frame = create_framed_widget( TextureBrowser_constructWindow( GroupDialog_getWindow() ) ); - g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() ); - } + { + auto frame = create_framed_widget(TextureBrowser_constructWindow(GroupDialog_getWindow())); + g_page_textures = GroupDialog_addPage("Textures", frame, TextureBrowserExportTitleCaller()); + } - GroupDialog_show(); - } - else // 4 way - { - m_pCamWnd = NewCamWnd(); - GlobalCamera_setCamWnd( *m_pCamWnd ); - CamWnd_setParent( *m_pCamWnd, window ); + GroupDialog_show(); + } else // 4 way + { + m_pCamWnd = NewCamWnd(); + GlobalCamera_setCamWnd(*m_pCamWnd); + CamWnd_setParent(*m_pCamWnd, window); - ui::Widget camera = CamWnd_getWidget( *m_pCamWnd ); + ui::Widget camera = CamWnd_getWidget(*m_pCamWnd); - m_pYZWnd = new XYWnd(); - m_pYZWnd->SetViewType( YZ ); + m_pYZWnd = new XYWnd(); + m_pYZWnd->SetViewType(YZ); - ui::Widget yz = m_pYZWnd->GetWidget(); + ui::Widget yz = m_pYZWnd->GetWidget(); - m_pXYWnd = new XYWnd(); - m_pXYWnd->SetViewType( XY ); + m_pXYWnd = new XYWnd(); + m_pXYWnd->SetViewType(XY); - ui::Widget xy = m_pXYWnd->GetWidget(); + ui::Widget xy = m_pXYWnd->GetWidget(); - m_pXZWnd = new XYWnd(); - m_pXZWnd->SetViewType( XZ ); + m_pXZWnd = new XYWnd(); + m_pXZWnd->SetViewType(XZ); - ui::Widget xz = m_pXZWnd->GetWidget(); + ui::Widget xz = m_pXZWnd->GetWidget(); - auto split = create_split_views( camera, yz, xy, xz ); - vbox.pack_start( split, TRUE, TRUE, 0 ); + auto split = create_split_views(camera, yz, xy, xz); + vbox.pack_start(split, TRUE, TRUE, 0); - { - auto frame = create_framed_widget( TextureBrowser_constructWindow( window ) ); - g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() ); - } - } + { + auto frame = create_framed_widget(TextureBrowser_constructWindow(window)); + g_page_textures = GroupDialog_addPage("Textures", frame, TextureBrowserExportTitleCaller()); + } + } - EntityList_constructWindow( window ); - PreferencesDialog_constructWindow( window ); - FindTextureDialog_constructWindow( window ); - SurfaceInspector_constructWindow( window ); - PatchInspector_constructWindow( window ); + EntityList_constructWindow(window); + PreferencesDialog_constructWindow(window); + FindTextureDialog_constructWindow(window); + SurfaceInspector_constructWindow(window); + PatchInspector_constructWindow(window); - SetActiveXY( m_pXYWnd ); + SetActiveXY(m_pXYWnd); - AddGridChangeCallback( SetGridStatusCaller( *this ) ); - AddGridChangeCallback( ReferenceCaller( *this ) ); + AddGridChangeCallback(SetGridStatusCaller(*this)); + AddGridChangeCallback(ReferenceCaller(*this)); - g_defaultToolMode = DragMode; - g_defaultToolMode(); - SetStatusText( m_command_status, c_TranslateMode_status ); + g_defaultToolMode = DragMode; + g_defaultToolMode(); + SetStatusText(m_command_status, c_TranslateMode_status); - EverySecondTimer_enable(); + EverySecondTimer_enable(); - //GlobalShortcuts_reportUnregistered(); + //GlobalShortcuts_reportUnregistered(); } -void MainFrame::SaveWindowInfo(){ - if ( !FloatingGroupDialog() ) { - g_layout_globals.nXYHeight = gtk_paned_get_position( GTK_PANED( m_vSplit ) ); +void MainFrame::SaveWindowInfo() +{ + if (!FloatingGroupDialog()) { + g_layout_globals.nXYHeight = gtk_paned_get_position(GTK_PANED(m_vSplit)); - if ( CurrentStyle() != eRegular ) { - g_layout_globals.nCamWidth = gtk_paned_get_position( GTK_PANED( m_hSplit ) ); - } - else - { - g_layout_globals.nXYWidth = gtk_paned_get_position( GTK_PANED( m_hSplit ) ); - } + if (CurrentStyle() != eRegular) { + g_layout_globals.nCamWidth = gtk_paned_get_position(GTK_PANED(m_hSplit)); + } else { + g_layout_globals.nXYWidth = gtk_paned_get_position(GTK_PANED(m_hSplit)); + } - g_layout_globals.nCamHeight = gtk_paned_get_position( GTK_PANED( m_vSplit2 ) ); - } + g_layout_globals.nCamHeight = gtk_paned_get_position(GTK_PANED(m_vSplit2)); + } - g_layout_globals.m_position = m_position_tracker.getPosition(); + g_layout_globals.m_position = m_position_tracker.getPosition(); - g_layout_globals.nState = gdk_window_get_state( gtk_widget_get_window(m_window ) ); + g_layout_globals.nState = gdk_window_get_state(gtk_widget_get_window(m_window)); } -void MainFrame::Shutdown(){ - EverySecondTimer_disable(); +void MainFrame::Shutdown() +{ + EverySecondTimer_disable(); - EntityList_destroyWindow(); + EntityList_destroyWindow(); - delete m_pXYWnd; - m_pXYWnd = 0; - delete m_pYZWnd; - m_pYZWnd = 0; - delete m_pXZWnd; - m_pXZWnd = 0; + delete m_pXYWnd; + m_pXYWnd = 0; + delete m_pYZWnd; + m_pYZWnd = 0; + delete m_pXZWnd; + m_pXZWnd = 0; - TextureBrowser_destroyWindow(); + TextureBrowser_destroyWindow(); - DeleteCamWnd( m_pCamWnd ); - m_pCamWnd = 0; + DeleteCamWnd(m_pCamWnd); + m_pCamWnd = 0; - PreferencesDialog_destroyWindow(); - SurfaceInspector_destroyWindow(); - FindTextureDialog_destroyWindow(); - PatchInspector_destroyWindow(); + PreferencesDialog_destroyWindow(); + SurfaceInspector_destroyWindow(); + FindTextureDialog_destroyWindow(); + PatchInspector_destroyWindow(); - g_DbgDlg.destroyWindow(); + g_DbgDlg.destroyWindow(); - // destroying group-dialog last because it may contain texture-browser - GroupDialog_destroyWindow(); + // destroying group-dialog last because it may contain texture-browser + GroupDialog_destroyWindow(); } -void MainFrame::RedrawStatusText(){ - ui::Label::from(m_pStatusLabel[c_command_status]).text(m_command_status.c_str()); - ui::Label::from(m_pStatusLabel[c_position_status]).text(m_position_status.c_str()); - ui::Label::from(m_pStatusLabel[c_brushcount_status]).text(m_brushcount_status.c_str()); - ui::Label::from(m_pStatusLabel[c_texture_status]).text(m_texture_status.c_str()); - ui::Label::from(m_pStatusLabel[c_grid_status]).text(m_grid_status.c_str()); +void MainFrame::RedrawStatusText() +{ + ui::Label::from(m_pStatusLabel[c_command_status]).text(m_command_status.c_str()); + ui::Label::from(m_pStatusLabel[c_position_status]).text(m_position_status.c_str()); + ui::Label::from(m_pStatusLabel[c_brushcount_status]).text(m_brushcount_status.c_str()); + ui::Label::from(m_pStatusLabel[c_texture_status]).text(m_texture_status.c_str()); + ui::Label::from(m_pStatusLabel[c_grid_status]).text(m_grid_status.c_str()); } -void MainFrame::UpdateStatusText(){ - m_idleRedrawStatusText.queueDraw(); +void MainFrame::UpdateStatusText() +{ + m_idleRedrawStatusText.queueDraw(); } -void MainFrame::SetStatusText( CopiedString& status_text, const char* pText ){ - status_text = pText; - UpdateStatusText(); +void MainFrame::SetStatusText(CopiedString &status_text, const char *pText) +{ + status_text = pText; + UpdateStatusText(); } -void Sys_Status( const char* status ){ - if ( g_pParentWnd != 0 ) { - g_pParentWnd->SetStatusText( g_pParentWnd->m_command_status, status ); - } +void Sys_Status(const char *status) +{ + if (g_pParentWnd != 0) { + g_pParentWnd->SetStatusText(g_pParentWnd->m_command_status, status); + } } -int getRotateIncrement(){ - return static_cast( g_si_globals.rotate ); +int getRotateIncrement() +{ + return static_cast( g_si_globals.rotate ); } -int getFarClipDistance(){ - return g_camwindow_globals.m_nCubicScale; +int getFarClipDistance() +{ + return g_camwindow_globals.m_nCubicScale; } float ( *GridStatus_getGridSize )() = GetGridSize; + int ( *GridStatus_getRotateIncrement )() = getRotateIncrement; + int ( *GridStatus_getFarClipDistance )() = getFarClipDistance; + bool ( *GridStatus_getTextureLockEnabled )(); -void MainFrame::SetGridStatus(){ - StringOutputStream status( 64 ); - const char* lock = ( GridStatus_getTextureLockEnabled() ) ? "ON" : "OFF"; - status << ( GetSnapGridSize() > 0 ? "G:" : "g:" ) << GridStatus_getGridSize() - << " R:" << GridStatus_getRotateIncrement() - << " C:" << GridStatus_getFarClipDistance() - << " L:" << lock; - SetStatusText( m_grid_status, status.c_str() ); +void MainFrame::SetGridStatus() +{ + StringOutputStream status(64); + const char *lock = (GridStatus_getTextureLockEnabled()) ? "ON" : "OFF"; + status << (GetSnapGridSize() > 0 ? "G:" : "g:") << GridStatus_getGridSize() + << " R:" << GridStatus_getRotateIncrement() + << " C:" << GridStatus_getFarClipDistance() + << " L:" << lock; + SetStatusText(m_grid_status, status.c_str()); } -void GridStatus_onTextureLockEnabledChanged(){ - if ( g_pParentWnd != 0 ) { - g_pParentWnd->SetGridStatus(); - } +void GridStatus_onTextureLockEnabledChanged() +{ + if (g_pParentWnd != 0) { + g_pParentWnd->SetGridStatus(); + } } -void GlobalGL_sharedContextCreated(){ - GLFont *g_font = NULL; +void GlobalGL_sharedContextCreated() +{ + GLFont *g_font = NULL; - // report OpenGL information - globalOutputStream() << "GL_VENDOR: " << reinterpret_cast( glGetString( GL_VENDOR ) ) << "\n"; - globalOutputStream() << "GL_RENDERER: " << reinterpret_cast( glGetString( GL_RENDERER ) ) << "\n"; - globalOutputStream() << "GL_VERSION: " << reinterpret_cast( glGetString( GL_VERSION ) ) << "\n"; - const auto extensions = reinterpret_cast( glGetString(GL_EXTENSIONS ) ); + // report OpenGL information + globalOutputStream() << "GL_VENDOR: " << reinterpret_cast( glGetString(GL_VENDOR)) << "\n"; + globalOutputStream() << "GL_RENDERER: " << reinterpret_cast( glGetString(GL_RENDERER)) << "\n"; + globalOutputStream() << "GL_VERSION: " << reinterpret_cast( glGetString(GL_VERSION)) << "\n"; + const auto extensions = reinterpret_cast( glGetString(GL_EXTENSIONS)); globalOutputStream() << "GL_EXTENSIONS: " << (extensions ? extensions : "") << "\n"; - QGL_sharedContextCreated( GlobalOpenGL() ); + QGL_sharedContextCreated(GlobalOpenGL()); - ShaderCache_extensionsInitialised(); + ShaderCache_extensionsInitialised(); - GlobalShaderCache().realise(); - Textures_Realise(); + GlobalShaderCache().realise(); + Textures_Realise(); #if GDEF_OS_WINDOWS - /* win32 is dodgy here, just use courier new then */ + /* win32 is dodgy here, just use courier new then */ g_font = glfont_create( "arial 9" ); #else - auto settings = gtk_settings_get_default(); - gchar *fontname; - g_object_get( settings, "gtk-font-name", &fontname, NULL ); - g_font = glfont_create( fontname ); + auto settings = gtk_settings_get_default(); + gchar *fontname; + g_object_get(settings, "gtk-font-name", &fontname, NULL); + g_font = glfont_create(fontname); #endif - GlobalOpenGL().m_font = g_font; + GlobalOpenGL().m_font = g_font; } -void GlobalGL_sharedContextDestroyed(){ - Textures_Unrealise(); - GlobalShaderCache().unrealise(); +void GlobalGL_sharedContextDestroyed() +{ + Textures_Unrealise(); + GlobalShaderCache().unrealise(); - QGL_sharedContextDestroyed( GlobalOpenGL() ); + QGL_sharedContextDestroyed(GlobalOpenGL()); } -void Layout_constructPreferences( PreferencesPage& page ){ - { - const char* layouts[] = { "window1.png", "window2.png", "window3.png", "window4.png" }; - page.appendRadioIcons( - "Window Layout", - STRING_ARRAY_RANGE( layouts ), - make_property( g_Layout_viewStyle ) - ); - } - page.appendCheckBox( - "", "Detachable Menus", - make_property( g_Layout_enableDetachableMenus ) - ); - if ( !string_empty( g_pGameDescription->getKeyValue( "no_patch" ) ) ) { - page.appendCheckBox( - "", "Patch Toolbar", - make_property( g_Layout_enablePatchToolbar ) - ); - } - page.appendCheckBox( - "", "Plugin Toolbar", - make_property( g_Layout_enablePluginToolbar ) - ); -} - -void Layout_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Layout", "Layout Preferences" ) ); - Layout_constructPreferences( page ); +void Layout_constructPreferences(PreferencesPage &page) +{ + { + const char *layouts[] = {"window1.png", "window2.png", "window3.png", "window4.png"}; + page.appendRadioIcons( + "Window Layout", + STRING_ARRAY_RANGE(layouts), + make_property(g_Layout_viewStyle) + ); + } + page.appendCheckBox( + "", "Detachable Menus", + make_property(g_Layout_enableDetachableMenus) + ); + if (!string_empty(g_pGameDescription->getKeyValue("no_patch"))) { + page.appendCheckBox( + "", "Patch Toolbar", + make_property(g_Layout_enablePatchToolbar) + ); + } + page.appendCheckBox( + "", "Plugin Toolbar", + make_property(g_Layout_enablePluginToolbar) + ); +} + +void Layout_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Layout", "Layout Preferences")); + Layout_constructPreferences(page); } -void Layout_registerPreferencesPage(){ - PreferencesDialog_addInterfacePage( makeCallbackF(Layout_constructPage) ); +void Layout_registerPreferencesPage() +{ + PreferencesDialog_addInterfacePage(makeCallbackF(Layout_constructPage)); } #include "preferencesystem.h" #include "stringio.h" -void MainFrame_Construct(){ - GlobalCommands_insert( "OpenManual", makeCallbackF(OpenHelpURL), Accelerator( GDK_KEY_F1 ) ); - - GlobalCommands_insert( "Sleep", makeCallbackF(thunk_OnSleep), Accelerator( 'P', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "NewMap", makeCallbackF(NewMap) ); - GlobalCommands_insert( "OpenMap", makeCallbackF(OpenMap), Accelerator( 'O', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "ImportMap", makeCallbackF(ImportMap) ); - GlobalCommands_insert( "SaveMap", makeCallbackF(SaveMap), Accelerator( 'S', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "SaveMapAs", makeCallbackF(SaveMapAs) ); - GlobalCommands_insert( "ExportSelected", makeCallbackF(ExportMap) ); - GlobalCommands_insert( "SaveRegion", makeCallbackF(SaveRegion) ); - GlobalCommands_insert( "RefreshReferences", makeCallbackF(VFS_Refresh) ); - GlobalCommands_insert( "ProjectSettings", makeCallbackF(DoProjectSettings) ); - GlobalCommands_insert( "Exit", makeCallbackF(Exit) ); - - GlobalCommands_insert( "Undo", makeCallbackF(Undo), Accelerator( 'Z', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "Redo", makeCallbackF(Redo), Accelerator( 'Y', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "Copy", makeCallbackF(Copy), Accelerator( 'C', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "Paste", makeCallbackF(Paste), Accelerator( 'V', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "PasteToCamera", makeCallbackF(PasteToCamera), Accelerator( 'V', (GdkModifierType)GDK_MOD1_MASK ) ); - GlobalCommands_insert( "CloneSelection", makeCallbackF(Selection_Clone), Accelerator( GDK_KEY_space ) ); - GlobalCommands_insert( "CloneSelectionAndMakeUnique", makeCallbackF(Selection_Clone_MakeUnique), Accelerator( GDK_KEY_space, (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "DeleteSelection", makeCallbackF(deleteSelection), Accelerator( GDK_KEY_BackSpace ) ); - GlobalCommands_insert( "ParentSelection", makeCallbackF(Scene_parentSelected) ); - GlobalCommands_insert( "UnSelectSelection", makeCallbackF(Selection_Deselect), Accelerator( GDK_KEY_Escape ) ); - GlobalCommands_insert( "InvertSelection", makeCallbackF(Select_Invert), Accelerator( 'I' ) ); - GlobalCommands_insert( "SelectInside", makeCallbackF(Select_Inside) ); - GlobalCommands_insert( "SelectTouching", makeCallbackF(Select_Touching) ); - GlobalCommands_insert( "ExpandSelectionToEntities", makeCallbackF(Scene_ExpandSelectionToEntities), Accelerator( 'E', (GdkModifierType)( GDK_MOD1_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "Preferences", makeCallbackF(PreferencesDialog_showDialog), Accelerator( 'P' ) ); - - GlobalCommands_insert( "ToggleConsole", makeCallbackF(Console_ToggleShow), Accelerator( 'O' ) ); - GlobalCommands_insert( "ToggleEntityInspector", makeCallbackF(EntityInspector_ToggleShow), Accelerator( 'N' ) ); - GlobalCommands_insert( "EntityList", makeCallbackF(EntityList_toggleShown), Accelerator( 'L' ) ); - - GlobalCommands_insert( "ShowHidden", makeCallbackF(Select_ShowAllHidden), Accelerator( 'H', (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "HideSelected", makeCallbackF(HideSelected), Accelerator( 'H' ) ); - - GlobalToggles_insert( "DragVertices", makeCallbackF(SelectVertexMode), ToggleItem::AddCallbackCaller( g_vertexMode_button ), Accelerator( 'V' ) ); - GlobalToggles_insert( "DragEdges", makeCallbackF(SelectEdgeMode), ToggleItem::AddCallbackCaller( g_edgeMode_button ), Accelerator( 'E' ) ); - GlobalToggles_insert( "DragFaces", makeCallbackF(SelectFaceMode), ToggleItem::AddCallbackCaller( g_faceMode_button ), Accelerator( 'F' ) ); - - GlobalCommands_insert( "MirrorSelectionX", makeCallbackF(Selection_Flipx) ); - GlobalCommands_insert( "RotateSelectionX", makeCallbackF(Selection_Rotatex) ); - GlobalCommands_insert( "MirrorSelectionY", makeCallbackF(Selection_Flipy) ); - GlobalCommands_insert( "RotateSelectionY", makeCallbackF(Selection_Rotatey) ); - GlobalCommands_insert( "MirrorSelectionZ", makeCallbackF(Selection_Flipz) ); - GlobalCommands_insert( "RotateSelectionZ", makeCallbackF(Selection_Rotatez) ); - - GlobalCommands_insert( "ArbitraryRotation", makeCallbackF(DoRotateDlg) ); - GlobalCommands_insert( "ArbitraryScale", makeCallbackF(DoScaleDlg) ); - - GlobalCommands_insert( "BuildMenuCustomize", makeCallbackF(DoBuildMenu) ); - - GlobalCommands_insert( "FindBrush", makeCallbackF(DoFind) ); - - GlobalCommands_insert( "MapInfo", makeCallbackF(DoMapInfo), Accelerator( 'M' ) ); - - - GlobalToggles_insert( "ToggleClipper", makeCallbackF(ClipperMode), ToggleItem::AddCallbackCaller( g_clipper_button ), Accelerator( 'X' ) ); - - GlobalToggles_insert( "MouseTranslate", makeCallbackF(TranslateMode), ToggleItem::AddCallbackCaller( g_translatemode_button ), Accelerator( 'W' ) ); - GlobalToggles_insert( "MouseRotate", makeCallbackF(RotateMode), ToggleItem::AddCallbackCaller( g_rotatemode_button ), Accelerator( 'R' ) ); - GlobalToggles_insert( "MouseScale", makeCallbackF(ScaleMode), ToggleItem::AddCallbackCaller( g_scalemode_button ) ); - GlobalToggles_insert( "MouseDrag", makeCallbackF(DragMode), ToggleItem::AddCallbackCaller( g_dragmode_button ), Accelerator( 'Q' ) ); - - GlobalCommands_insert( "ColorSchemeOriginal", makeCallbackF(ColorScheme_Original) ); - GlobalCommands_insert( "ColorSchemeQER", makeCallbackF(ColorScheme_QER) ); - GlobalCommands_insert( "ColorSchemeBlackAndGreen", makeCallbackF(ColorScheme_Black) ); - GlobalCommands_insert( "ColorSchemeYdnar", makeCallbackF(ColorScheme_Ydnar) ); - GlobalCommands_insert( "ChooseTextureBackgroundColor", makeCallback( g_ColoursMenu.m_textureback ) ); - GlobalCommands_insert( "ChooseGridBackgroundColor", makeCallback( g_ColoursMenu.m_xyback ) ); - GlobalCommands_insert( "ChooseGridMajorColor", makeCallback( g_ColoursMenu.m_gridmajor ) ); - GlobalCommands_insert( "ChooseGridMinorColor", makeCallback( g_ColoursMenu.m_gridminor ) ); - GlobalCommands_insert( "ChooseSmallGridMajorColor", makeCallback( g_ColoursMenu.m_gridmajor_alt ) ); - GlobalCommands_insert( "ChooseSmallGridMinorColor", makeCallback( g_ColoursMenu.m_gridminor_alt ) ); - GlobalCommands_insert( "ChooseGridTextColor", makeCallback( g_ColoursMenu.m_gridtext ) ); - GlobalCommands_insert( "ChooseGridBlockColor", makeCallback( g_ColoursMenu.m_gridblock ) ); - GlobalCommands_insert( "ChooseBrushColor", makeCallback( g_ColoursMenu.m_brush ) ); - GlobalCommands_insert( "ChooseCameraBackgroundColor", makeCallback( g_ColoursMenu.m_cameraback ) ); - GlobalCommands_insert( "ChooseSelectedBrushColor", makeCallback( g_ColoursMenu.m_selectedbrush ) ); - GlobalCommands_insert( "ChooseCameraSelectedBrushColor", makeCallback( g_ColoursMenu.m_selectedbrush3d ) ); - GlobalCommands_insert( "ChooseClipperColor", makeCallback( g_ColoursMenu.m_clipper ) ); - GlobalCommands_insert( "ChooseOrthoViewNameColor", makeCallback( g_ColoursMenu.m_viewname ) ); - - - GlobalCommands_insert( "CSGSubtract", makeCallbackF(CSG_Subtract), Accelerator( 'U', (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "CSGMerge", makeCallbackF(CSG_Merge), Accelerator( 'U', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "CSGHollow", makeCallbackF(CSG_MakeHollow) ); - - Grid_registerCommands(); - - GlobalCommands_insert( "SnapToGrid", makeCallbackF(Selection_SnapToGrid), Accelerator( 'G', (GdkModifierType)GDK_CONTROL_MASK ) ); - - GlobalCommands_insert( "SelectAllOfType", makeCallbackF(Select_AllOfType), Accelerator( 'A', (GdkModifierType)GDK_SHIFT_MASK ) ); - - GlobalCommands_insert( "TexRotateClock", makeCallbackF(Texdef_RotateClockwise), Accelerator( GDK_KEY_Next, (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "TexRotateCounter", makeCallbackF(Texdef_RotateAntiClockwise), Accelerator( GDK_KEY_Prior, (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "TexScaleUp", makeCallbackF(Texdef_ScaleUp), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "TexScaleDown", makeCallbackF(Texdef_ScaleDown), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "TexScaleLeft", makeCallbackF(Texdef_ScaleLeft), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "TexScaleRight", makeCallbackF(Texdef_ScaleRight), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "TexShiftUp", makeCallbackF(Texdef_ShiftUp), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "TexShiftDown", makeCallbackF(Texdef_ShiftDown), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "TexShiftLeft", makeCallbackF(Texdef_ShiftLeft), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "TexShiftRight", makeCallbackF(Texdef_ShiftRight), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_SHIFT_MASK ) ); - - GlobalCommands_insert( "MoveSelectionDOWN", makeCallbackF(Selection_MoveDown), Accelerator( GDK_KEY_KP_Subtract ) ); - GlobalCommands_insert( "MoveSelectionUP", makeCallbackF(Selection_MoveUp), Accelerator( GDK_KEY_KP_Add ) ); - - GlobalCommands_insert( "SelectNudgeLeft", makeCallbackF(Selection_NudgeLeft), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_MOD1_MASK ) ); - GlobalCommands_insert( "SelectNudgeRight", makeCallbackF(Selection_NudgeRight), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_MOD1_MASK ) ); - GlobalCommands_insert( "SelectNudgeUp", makeCallbackF(Selection_NudgeUp), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_MOD1_MASK ) ); - GlobalCommands_insert( "SelectNudgeDown", makeCallbackF(Selection_NudgeDown), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_MOD1_MASK ) ); - - Patch_registerCommands(); - XYShow_registerCommands(); - - typedef FreeCaller ComponentModeSelectionChangedCaller; - GlobalSelectionSystem().addSelectionChangeCallback( ComponentModeSelectionChangedCaller() ); - - GlobalPreferenceSystem().registerPreference( "DetachableMenus", make_property_string( g_Layout_enableDetachableMenus.m_latched ) ); - GlobalPreferenceSystem().registerPreference( "PatchToolBar", make_property_string( g_Layout_enablePatchToolbar.m_latched ) ); - GlobalPreferenceSystem().registerPreference( "PluginToolBar", make_property_string( g_Layout_enablePluginToolbar.m_latched ) ); - GlobalPreferenceSystem().registerPreference( "QE4StyleWindows", make_property_string( g_Layout_viewStyle.m_latched ) ); - GlobalPreferenceSystem().registerPreference( "XYHeight", make_property_string( g_layout_globals.nXYHeight ) ); - GlobalPreferenceSystem().registerPreference( "XYWidth", make_property_string( g_layout_globals.nXYWidth ) ); - GlobalPreferenceSystem().registerPreference( "CamWidth", make_property_string( g_layout_globals.nCamWidth ) ); - GlobalPreferenceSystem().registerPreference( "CamHeight", make_property_string( g_layout_globals.nCamHeight ) ); - - GlobalPreferenceSystem().registerPreference( "State", make_property_string( g_layout_globals.nState ) ); - GlobalPreferenceSystem().registerPreference( "PositionX", make_property_string( g_layout_globals.m_position.x ) ); - GlobalPreferenceSystem().registerPreference( "PositionY", make_property_string( g_layout_globals.m_position.y ) ); - GlobalPreferenceSystem().registerPreference( "Width", make_property_string( g_layout_globals.m_position.w ) ); - GlobalPreferenceSystem().registerPreference( "Height", make_property_string( g_layout_globals.m_position.h ) ); - - GlobalPreferenceSystem().registerPreference( "CamWnd", make_property(g_posCamWnd) ); - GlobalPreferenceSystem().registerPreference( "XYWnd", make_property(g_posXYWnd) ); - GlobalPreferenceSystem().registerPreference( "YZWnd", make_property(g_posYZWnd) ); - GlobalPreferenceSystem().registerPreference( "XZWnd", make_property(g_posXZWnd) ); - - { - const char* ENGINEPATH_ATTRIBUTE = +void MainFrame_Construct() +{ + GlobalCommands_insert("OpenManual", makeCallbackF(OpenHelpURL), Accelerator(GDK_KEY_F1)); + + GlobalCommands_insert("Sleep", makeCallbackF(thunk_OnSleep), + Accelerator('P', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("NewMap", makeCallbackF(NewMap)); + GlobalCommands_insert("OpenMap", makeCallbackF(OpenMap), Accelerator('O', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("ImportMap", makeCallbackF(ImportMap)); + GlobalCommands_insert("SaveMap", makeCallbackF(SaveMap), Accelerator('S', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("SaveMapAs", makeCallbackF(SaveMapAs)); + GlobalCommands_insert("ExportSelected", makeCallbackF(ExportMap)); + GlobalCommands_insert("SaveRegion", makeCallbackF(SaveRegion)); + GlobalCommands_insert("RefreshReferences", makeCallbackF(VFS_Refresh)); + GlobalCommands_insert("ProjectSettings", makeCallbackF(DoProjectSettings)); + GlobalCommands_insert("Exit", makeCallbackF(Exit)); + + GlobalCommands_insert("Undo", makeCallbackF(Undo), Accelerator('Z', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("Redo", makeCallbackF(Redo), Accelerator('Y', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("Copy", makeCallbackF(Copy), Accelerator('C', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("Paste", makeCallbackF(Paste), Accelerator('V', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("PasteToCamera", makeCallbackF(PasteToCamera), + Accelerator('V', (GdkModifierType) GDK_MOD1_MASK)); + GlobalCommands_insert("CloneSelection", makeCallbackF(Selection_Clone), Accelerator(GDK_KEY_space)); + GlobalCommands_insert("CloneSelectionAndMakeUnique", makeCallbackF(Selection_Clone_MakeUnique), + Accelerator(GDK_KEY_space, (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("DeleteSelection", makeCallbackF(deleteSelection), Accelerator(GDK_KEY_BackSpace)); + GlobalCommands_insert("ParentSelection", makeCallbackF(Scene_parentSelected)); + GlobalCommands_insert("UnSelectSelection", makeCallbackF(Selection_Deselect), Accelerator(GDK_KEY_Escape)); + GlobalCommands_insert("InvertSelection", makeCallbackF(Select_Invert), Accelerator('I')); + GlobalCommands_insert("SelectInside", makeCallbackF(Select_Inside)); + GlobalCommands_insert("SelectTouching", makeCallbackF(Select_Touching)); + GlobalCommands_insert("ExpandSelectionToEntities", makeCallbackF(Scene_ExpandSelectionToEntities), + Accelerator('E', (GdkModifierType) (GDK_MOD1_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("Preferences", makeCallbackF(PreferencesDialog_showDialog), Accelerator('P')); + + GlobalCommands_insert("ToggleConsole", makeCallbackF(Console_ToggleShow), Accelerator('O')); + GlobalCommands_insert("ToggleEntityInspector", makeCallbackF(EntityInspector_ToggleShow), Accelerator('N')); + GlobalCommands_insert("EntityList", makeCallbackF(EntityList_toggleShown), Accelerator('L')); + + GlobalCommands_insert("ShowHidden", makeCallbackF(Select_ShowAllHidden), + Accelerator('H', (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("HideSelected", makeCallbackF(HideSelected), Accelerator('H')); + + GlobalToggles_insert("DragVertices", makeCallbackF(SelectVertexMode), + ToggleItem::AddCallbackCaller(g_vertexMode_button), Accelerator('V')); + GlobalToggles_insert("DragEdges", makeCallbackF(SelectEdgeMode), ToggleItem::AddCallbackCaller(g_edgeMode_button), + Accelerator('E')); + GlobalToggles_insert("DragFaces", makeCallbackF(SelectFaceMode), ToggleItem::AddCallbackCaller(g_faceMode_button), + Accelerator('F')); + + GlobalCommands_insert("MirrorSelectionX", makeCallbackF(Selection_Flipx)); + GlobalCommands_insert("RotateSelectionX", makeCallbackF(Selection_Rotatex)); + GlobalCommands_insert("MirrorSelectionY", makeCallbackF(Selection_Flipy)); + GlobalCommands_insert("RotateSelectionY", makeCallbackF(Selection_Rotatey)); + GlobalCommands_insert("MirrorSelectionZ", makeCallbackF(Selection_Flipz)); + GlobalCommands_insert("RotateSelectionZ", makeCallbackF(Selection_Rotatez)); + + GlobalCommands_insert("ArbitraryRotation", makeCallbackF(DoRotateDlg)); + GlobalCommands_insert("ArbitraryScale", makeCallbackF(DoScaleDlg)); + + GlobalCommands_insert("BuildMenuCustomize", makeCallbackF(DoBuildMenu)); + + GlobalCommands_insert("FindBrush", makeCallbackF(DoFind)); + + GlobalCommands_insert("MapInfo", makeCallbackF(DoMapInfo), Accelerator('M')); + + + GlobalToggles_insert("ToggleClipper", makeCallbackF(ClipperMode), ToggleItem::AddCallbackCaller(g_clipper_button), + Accelerator('X')); + + GlobalToggles_insert("MouseTranslate", makeCallbackF(TranslateMode), + ToggleItem::AddCallbackCaller(g_translatemode_button), Accelerator('W')); + GlobalToggles_insert("MouseRotate", makeCallbackF(RotateMode), ToggleItem::AddCallbackCaller(g_rotatemode_button), + Accelerator('R')); + GlobalToggles_insert("MouseScale", makeCallbackF(ScaleMode), ToggleItem::AddCallbackCaller(g_scalemode_button)); + GlobalToggles_insert("MouseDrag", makeCallbackF(DragMode), ToggleItem::AddCallbackCaller(g_dragmode_button), + Accelerator('Q')); + + GlobalCommands_insert("ColorSchemeOriginal", makeCallbackF(ColorScheme_Original)); + GlobalCommands_insert("ColorSchemeQER", makeCallbackF(ColorScheme_QER)); + GlobalCommands_insert("ColorSchemeBlackAndGreen", makeCallbackF(ColorScheme_Black)); + GlobalCommands_insert("ColorSchemeYdnar", makeCallbackF(ColorScheme_Ydnar)); + GlobalCommands_insert("ChooseTextureBackgroundColor", makeCallback(g_ColoursMenu.m_textureback)); + GlobalCommands_insert("ChooseGridBackgroundColor", makeCallback(g_ColoursMenu.m_xyback)); + GlobalCommands_insert("ChooseGridMajorColor", makeCallback(g_ColoursMenu.m_gridmajor)); + GlobalCommands_insert("ChooseGridMinorColor", makeCallback(g_ColoursMenu.m_gridminor)); + GlobalCommands_insert("ChooseSmallGridMajorColor", makeCallback(g_ColoursMenu.m_gridmajor_alt)); + GlobalCommands_insert("ChooseSmallGridMinorColor", makeCallback(g_ColoursMenu.m_gridminor_alt)); + GlobalCommands_insert("ChooseGridTextColor", makeCallback(g_ColoursMenu.m_gridtext)); + GlobalCommands_insert("ChooseGridBlockColor", makeCallback(g_ColoursMenu.m_gridblock)); + GlobalCommands_insert("ChooseBrushColor", makeCallback(g_ColoursMenu.m_brush)); + GlobalCommands_insert("ChooseCameraBackgroundColor", makeCallback(g_ColoursMenu.m_cameraback)); + GlobalCommands_insert("ChooseSelectedBrushColor", makeCallback(g_ColoursMenu.m_selectedbrush)); + GlobalCommands_insert("ChooseCameraSelectedBrushColor", makeCallback(g_ColoursMenu.m_selectedbrush3d)); + GlobalCommands_insert("ChooseClipperColor", makeCallback(g_ColoursMenu.m_clipper)); + GlobalCommands_insert("ChooseOrthoViewNameColor", makeCallback(g_ColoursMenu.m_viewname)); + + + GlobalCommands_insert("CSGSubtract", makeCallbackF(CSG_Subtract), + Accelerator('U', (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("CSGMerge", makeCallbackF(CSG_Merge), Accelerator('U', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("CSGHollow", makeCallbackF(CSG_MakeHollow)); + + Grid_registerCommands(); + + GlobalCommands_insert("SnapToGrid", makeCallbackF(Selection_SnapToGrid), + Accelerator('G', (GdkModifierType) GDK_CONTROL_MASK)); + + GlobalCommands_insert("SelectAllOfType", makeCallbackF(Select_AllOfType), + Accelerator('A', (GdkModifierType) GDK_SHIFT_MASK)); + + GlobalCommands_insert("TexRotateClock", makeCallbackF(Texdef_RotateClockwise), + Accelerator(GDK_KEY_Next, (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("TexRotateCounter", makeCallbackF(Texdef_RotateAntiClockwise), + Accelerator(GDK_KEY_Prior, (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("TexScaleUp", makeCallbackF(Texdef_ScaleUp), + Accelerator(GDK_KEY_Up, (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("TexScaleDown", makeCallbackF(Texdef_ScaleDown), + Accelerator(GDK_KEY_Down, (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("TexScaleLeft", makeCallbackF(Texdef_ScaleLeft), + Accelerator(GDK_KEY_Left, (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("TexScaleRight", makeCallbackF(Texdef_ScaleRight), + Accelerator(GDK_KEY_Right, (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("TexShiftUp", makeCallbackF(Texdef_ShiftUp), + Accelerator(GDK_KEY_Up, (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("TexShiftDown", makeCallbackF(Texdef_ShiftDown), + Accelerator(GDK_KEY_Down, (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("TexShiftLeft", makeCallbackF(Texdef_ShiftLeft), + Accelerator(GDK_KEY_Left, (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("TexShiftRight", makeCallbackF(Texdef_ShiftRight), + Accelerator(GDK_KEY_Right, (GdkModifierType) GDK_SHIFT_MASK)); + + GlobalCommands_insert("MoveSelectionDOWN", makeCallbackF(Selection_MoveDown), Accelerator(GDK_KEY_KP_Subtract)); + GlobalCommands_insert("MoveSelectionUP", makeCallbackF(Selection_MoveUp), Accelerator(GDK_KEY_KP_Add)); + + GlobalCommands_insert("SelectNudgeLeft", makeCallbackF(Selection_NudgeLeft), + Accelerator(GDK_KEY_Left, (GdkModifierType) GDK_MOD1_MASK)); + GlobalCommands_insert("SelectNudgeRight", makeCallbackF(Selection_NudgeRight), + Accelerator(GDK_KEY_Right, (GdkModifierType) GDK_MOD1_MASK)); + GlobalCommands_insert("SelectNudgeUp", makeCallbackF(Selection_NudgeUp), + Accelerator(GDK_KEY_Up, (GdkModifierType) GDK_MOD1_MASK)); + GlobalCommands_insert("SelectNudgeDown", makeCallbackF(Selection_NudgeDown), + Accelerator(GDK_KEY_Down, (GdkModifierType) GDK_MOD1_MASK)); + + Patch_registerCommands(); + XYShow_registerCommands(); + + typedef FreeCaller ComponentModeSelectionChangedCaller; + GlobalSelectionSystem().addSelectionChangeCallback(ComponentModeSelectionChangedCaller()); + + GlobalPreferenceSystem().registerPreference("DetachableMenus", + make_property_string(g_Layout_enableDetachableMenus.m_latched)); + GlobalPreferenceSystem().registerPreference("PatchToolBar", + make_property_string(g_Layout_enablePatchToolbar.m_latched)); + GlobalPreferenceSystem().registerPreference("PluginToolBar", + make_property_string(g_Layout_enablePluginToolbar.m_latched)); + GlobalPreferenceSystem().registerPreference("QE4StyleWindows", make_property_string(g_Layout_viewStyle.m_latched)); + GlobalPreferenceSystem().registerPreference("XYHeight", make_property_string(g_layout_globals.nXYHeight)); + GlobalPreferenceSystem().registerPreference("XYWidth", make_property_string(g_layout_globals.nXYWidth)); + GlobalPreferenceSystem().registerPreference("CamWidth", make_property_string(g_layout_globals.nCamWidth)); + GlobalPreferenceSystem().registerPreference("CamHeight", make_property_string(g_layout_globals.nCamHeight)); + + GlobalPreferenceSystem().registerPreference("State", make_property_string(g_layout_globals.nState)); + GlobalPreferenceSystem().registerPreference("PositionX", make_property_string(g_layout_globals.m_position.x)); + GlobalPreferenceSystem().registerPreference("PositionY", make_property_string(g_layout_globals.m_position.y)); + GlobalPreferenceSystem().registerPreference("Width", make_property_string(g_layout_globals.m_position.w)); + GlobalPreferenceSystem().registerPreference("Height", make_property_string(g_layout_globals.m_position.h)); + + GlobalPreferenceSystem().registerPreference("CamWnd", make_property(g_posCamWnd)); + GlobalPreferenceSystem().registerPreference("XYWnd", make_property(g_posXYWnd)); + GlobalPreferenceSystem().registerPreference("YZWnd", make_property(g_posYZWnd)); + GlobalPreferenceSystem().registerPreference("XZWnd", make_property(g_posXZWnd)); + + { + const char *ENGINEPATH_ATTRIBUTE = #if GDEF_OS_WINDOWS - "enginepath_win32" + "enginepath_win32" #elif GDEF_OS_MACOS - "enginepath_macos" + "enginepath_macos" #elif GDEF_OS_LINUX || GDEF_OS_BSD - "enginepath_linux" + "enginepath_linux" #else #error "unknown platform" #endif - ; - StringOutputStream path( 256 ); - path << DirectoryCleaned( g_pGameDescription->getRequiredKeyValue( ENGINEPATH_ATTRIBUTE ) ); - g_strEnginePath = path.c_str(); - } + ; + StringOutputStream path(256); + path << DirectoryCleaned(g_pGameDescription->getRequiredKeyValue(ENGINEPATH_ATTRIBUTE)); + g_strEnginePath = path.c_str(); + } - GlobalPreferenceSystem().registerPreference( "EnginePath", make_property_string( g_strEnginePath ) ); + GlobalPreferenceSystem().registerPreference("EnginePath", make_property_string(g_strEnginePath)); - GlobalPreferenceSystem().registerPreference( "DisableEnginePath", make_property_string( g_disableEnginePath ) ); - GlobalPreferenceSystem().registerPreference( "DisableHomePath", make_property_string( g_disableHomePath ) ); + GlobalPreferenceSystem().registerPreference("DisableEnginePath", make_property_string(g_disableEnginePath)); + GlobalPreferenceSystem().registerPreference("DisableHomePath", make_property_string(g_disableHomePath)); - for ( int i = 0; i < g_pakPathCount; i++ ) { - std::string label = "PakPath" + std::to_string(i); - GlobalPreferenceSystem().registerPreference( label.c_str(), make_property_string( g_strPakPath[i] ) ); - } + for (int i = 0; i < g_pakPathCount; i++) { + std::string label = "PakPath" + std::to_string(i); + GlobalPreferenceSystem().registerPreference(label.c_str(), make_property_string(g_strPakPath[i])); + } - g_Layout_viewStyle.useLatched(); - g_Layout_enableDetachableMenus.useLatched(); - g_Layout_enablePatchToolbar.useLatched(); - g_Layout_enablePluginToolbar.useLatched(); + g_Layout_viewStyle.useLatched(); + g_Layout_enableDetachableMenus.useLatched(); + g_Layout_enablePatchToolbar.useLatched(); + g_Layout_enablePluginToolbar.useLatched(); - Layout_registerPreferencesPage(); - Paths_registerPreferencesPage(); + Layout_registerPreferencesPage(); + Paths_registerPreferencesPage(); - g_brushCount.setCountChangedCallback( makeCallbackF(QE_brushCountChanged) ); - g_entityCount.setCountChangedCallback( makeCallbackF(QE_entityCountChanged) ); - GlobalEntityCreator().setCounter( &g_entityCount ); + g_brushCount.setCountChangedCallback(makeCallbackF(QE_brushCountChanged)); + g_entityCount.setCountChangedCallback(makeCallbackF(QE_entityCountChanged)); + GlobalEntityCreator().setCounter(&g_entityCount); - GLWidget_sharedContextCreated = GlobalGL_sharedContextCreated; - GLWidget_sharedContextDestroyed = GlobalGL_sharedContextDestroyed; + GLWidget_sharedContextCreated = GlobalGL_sharedContextCreated; + GLWidget_sharedContextDestroyed = GlobalGL_sharedContextDestroyed; - GlobalEntityClassManager().attach( g_WorldspawnColourEntityClassObserver ); + GlobalEntityClassManager().attach(g_WorldspawnColourEntityClassObserver); } -void MainFrame_Destroy(){ - GlobalEntityClassManager().detach( g_WorldspawnColourEntityClassObserver ); +void MainFrame_Destroy() +{ + GlobalEntityClassManager().detach(g_WorldspawnColourEntityClassObserver); - GlobalEntityCreator().setCounter( 0 ); - g_entityCount.setCountChangedCallback( Callback() ); - g_brushCount.setCountChangedCallback( Callback() ); + GlobalEntityCreator().setCounter(0); + g_entityCount.setCountChangedCallback(Callback()); + g_brushCount.setCountChangedCallback(Callback()); } -void GLWindow_Construct(){ - GlobalPreferenceSystem().registerPreference( "MouseButtons", make_property_string( g_glwindow_globals.m_nMouseType ) ); +void GLWindow_Construct() +{ + GlobalPreferenceSystem().registerPreference("MouseButtons", make_property_string(g_glwindow_globals.m_nMouseType)); } -void GLWindow_Destroy(){ +void GLWindow_Destroy() +{ } diff --git a/radiant/mainframe.h b/radiant/mainframe.h index 85e60f47..6ff808da 100644 --- a/radiant/mainframe.h +++ b/radiant/mainframe.h @@ -31,10 +31,13 @@ #include "qerplugin.h" class IPlugIn; + class IToolbarButton; class XYWnd; + class CamWnd; + class ZWnd; @@ -45,194 +48,236 @@ const int c_texture_status = 3; const int c_grid_status = 4; const int c_count_status = 5; -class MainFrame -{ +class MainFrame { public: -enum EViewStyle -{ - eRegular = 0, - eFloating = 1, - eSplit = 2, - eRegularLeft = 3, -}; + enum EViewStyle { + eRegular = 0, + eFloating = 1, + eSplit = 2, + eRegularLeft = 3, + }; + + MainFrame(); -MainFrame(); -~MainFrame(); + ~MainFrame(); -ui::Window m_window{ui::null}; + ui::Window m_window{ui::null}; -CopiedString m_command_status; -CopiedString m_position_status; -CopiedString m_brushcount_status; -CopiedString m_texture_status; -CopiedString m_grid_status; + 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(); + void Create(); -ui::Widget m_vSplit{ui::null}; -ui::Widget m_hSplit{ui::null}; -ui::Widget m_vSplit2{ui::null}; + void SaveWindowInfo(); -XYWnd* m_pXYWnd; -XYWnd* m_pYZWnd; -XYWnd* m_pXZWnd; -CamWnd* m_pCamWnd; -ZWnd* m_pZWnd; -XYWnd* m_pActiveXY; + void Shutdown(); -bool m_bSleeping; + ui::Widget m_vSplit{ui::null}; + ui::Widget m_hSplit{ui::null}; + ui::Widget m_vSplit2{ui::null}; -void *m_pStatusLabel[c_count_status]; + XYWnd *m_pXYWnd; + XYWnd *m_pYZWnd; + XYWnd *m_pXZWnd; + CamWnd *m_pCamWnd; + ZWnd *m_pZWnd; + XYWnd *m_pActiveXY; + bool m_bSleeping; -EViewStyle m_nCurrentStyle; -WindowPositionTracker m_position_tracker; + void *m_pStatusLabel[c_count_status]; -IdleDraw m_idleRedrawStatusText; + + EViewStyle m_nCurrentStyle; + WindowPositionTracker m_position_tracker; + + IdleDraw m_idleRedrawStatusText; public: -bool IsSleeping(){ - return m_bSleeping; -} -void OnSleep(); + bool IsSleeping() + { + return m_bSleeping; + } -void SetStatusText( CopiedString& status_text, const char* pText ); -void UpdateStatusText(); -void RedrawStatusText(); -typedef MemberCaller RedrawStatusTextCaller; + void OnSleep(); -void SetGridStatus(); -typedef MemberCaller SetGridStatusCaller; + void SetStatusText(CopiedString &status_text, const char *pText); -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; -}; + void UpdateStatusText(); + + void RedrawStatusText(); + + typedef MemberCaller RedrawStatusTextCaller; + + void SetGridStatus(); + + typedef MemberCaller 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; +extern MainFrame *g_pParentWnd; ui::Window MainFrame_getWindow(); -enum EMouseButtonMode -{ - ETwoButton = 0, - EThreeButton = 1, +enum EMouseButtonMode { + ETwoButton = 0, + EThreeButton = 1, }; -struct glwindow_globals_t -{ - int m_nMouseType; +struct glwindow_globals_t { + int m_nMouseType; - glwindow_globals_t() : - m_nMouseType( EThreeButton ){ - } + glwindow_globals_t() : + m_nMouseType(EThreeButton) + { + } }; void GLWindow_Construct(); + void GLWindow_Destroy(); extern glwindow_globals_t g_glwindow_globals; + template class LatchedValue; + extern LatchedValue g_Layout_enableDetachableMenus; void deleteSelection(); -void Sys_Status( const char* status ); +void Sys_Status(const char *status); + +void ScreenUpdates_Disable(const char *message, const char *title); -void ScreenUpdates_Disable( const char* message, const char* title ); void ScreenUpdates_Enable(); + bool ScreenUpdates_Enabled(); + void ScreenUpdates_process(); -class ScopeDisableScreenUpdates -{ +class ScopeDisableScreenUpdates { public: -ScopeDisableScreenUpdates( const char* message, const char* title ){ - ScreenUpdates_Disable( message, title ); -} -~ScopeDisableScreenUpdates(){ - ScreenUpdates_Enable(); -} + 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_attachEnginePathObserver(ModuleObserver &observer); + +void Radiant_detachEnginePathObserver(ModuleObserver &observer); -void Radiant_attachGameToolsPathObserver( ModuleObserver& observer ); -void Radiant_detachGameToolsPathObserver( 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(); + +const char *EnginePath_get(); + +const char *QERApp_GetGamePath(); extern bool g_disableEnginePath; extern bool g_disableHomePath; const int g_pakPathCount = 5; extern CopiedString g_strPakPath[g_pakPathCount]; -const char* PakPath_get( int num ); + +const char *PakPath_get(int num); extern CopiedString g_strAppPath; -const char* AppPath_get(); + +const char *AppPath_get(); extern CopiedString g_strSettingsPath; -const char* SettingsPath_get(); -const char* LocalRcPath_get( void ); +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 +const char *LocalRcPath_get(void); + +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(); + +const char *GameToolsPath_get(); void Radiant_Initialise(); + void Radiant_Shutdown(); void SaveMapAs(); void XY_UpdateAllWindows(); + void UpdateAllWindows(); @@ -240,41 +285,63 @@ 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 ); +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_Refresh(); + void VFS_Restart(); + void VFS_Construct(); + void VFS_Destroy(); void HomePaths_Construct(); + void HomePaths_Destroy(); -void Radiant_attachHomePathsObserver( ModuleObserver& observer ); -void Radiant_detachHomePathsObserver( ModuleObserver& observer ); + +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(); -SignalHandlerId XYWindowDestroyed_connect( const SignalHandler& handler ); -void XYWindowDestroyed_disconnect( SignalHandlerId id ); -MouseEventHandlerId XYWindowMouseDown_connect( const MouseEventHandler& handler ); -void XYWindowMouseDown_disconnect( MouseEventHandlerId id ); +SignalHandlerId XYWindowDestroyed_connect(const SignalHandler &handler); + +void XYWindowDestroyed_disconnect(SignalHandlerId id); + +MouseEventHandlerId XYWindowMouseDown_connect(const MouseEventHandler &handler); + +void XYWindowMouseDown_disconnect(MouseEventHandlerId id); extern ui::Widget g_page_entity; diff --git a/radiant/map.cpp b/radiant/map.cpp index 5c91dfad..adf69f46 100644 --- a/radiant/map.cpp +++ b/radiant/map.cpp @@ -26,7 +26,9 @@ #include "debugging/debugging.h" #include "imap.h" -MapModules& ReferenceAPI_getMapModules(); + +MapModules &ReferenceAPI_getMapModules(); + #include "iselection.h" #include "iundo.h" #include "ibrush.h" @@ -84,312 +86,355 @@ MapModules& ReferenceAPI_getMapModules(); #include "brushmodule.h" #include "brush.h" -class NameObserver -{ -UniqueNames& m_names; -CopiedString m_name; +class NameObserver { + UniqueNames &m_names; + CopiedString m_name; -void construct(){ - if ( !empty() ) { - //globalOutputStream() << "construct " << makeQuoted(c_str()) << "\n"; - m_names.insert( name_read( c_str() ) ); - } -} -void destroy(){ - if ( !empty() ) { - //globalOutputStream() << "destroy " << makeQuoted(c_str()) << "\n"; - m_names.erase( name_read( c_str() ) ); - } -} + void construct() + { + if (!empty()) { + //globalOutputStream() << "construct " << makeQuoted(c_str()) << "\n"; + m_names.insert(name_read(c_str())); + } + } + + void destroy() + { + if (!empty()) { + //globalOutputStream() << "destroy " << makeQuoted(c_str()) << "\n"; + m_names.erase(name_read(c_str())); + } + } + + NameObserver &operator=(const NameObserver &other); -NameObserver& operator=( const NameObserver& other ); public: -NameObserver( UniqueNames& names ) : m_names( names ){ - construct(); -} -NameObserver( const NameObserver& other ) : m_names( other.m_names ), m_name( other.m_name ){ - construct(); -} -~NameObserver(){ - destroy(); -} -bool empty() const { - return string_empty( c_str() ); -} -const char* c_str() const { - return m_name.c_str(); -} -void nameChanged( const char* name ){ - destroy(); - m_name = name; - construct(); -} -typedef MemberCaller NameChangedCaller; + NameObserver(UniqueNames &names) : m_names(names) + { + construct(); + } + + NameObserver(const NameObserver &other) : m_names(other.m_names), m_name(other.m_name) + { + construct(); + } + + ~NameObserver() + { + destroy(); + } + + bool empty() const + { + return string_empty(c_str()); + } + + const char *c_str() const + { + return m_name.c_str(); + } + + void nameChanged(const char *name) + { + destroy(); + m_name = name; + construct(); + } + + typedef MemberCaller NameChangedCaller; }; -class BasicNamespace : public Namespace -{ -typedef std::map Names; -Names m_names; -UniqueNames m_uniqueNames; +class BasicNamespace : public Namespace { + typedef std::map Names; + Names m_names; + UniqueNames m_uniqueNames; public: -~BasicNamespace(){ - ASSERT_MESSAGE( m_names.empty(), "namespace: names still registered at shutdown" ); -} -void attach( const NameCallback& setName, const NameCallbackCallback& attachObserver ){ - std::pair result = m_names.insert( Names::value_type( setName, m_uniqueNames ) ); - ASSERT_MESSAGE( result.second, "cannot attach name" ); - attachObserver( NameObserver::NameChangedCaller( ( *result.first ).second ) ); - //globalOutputStream() << "attach: " << reinterpret_cast(setName) << "\n"; -} -void detach( const NameCallback& setName, const NameCallbackCallback& detachObserver ){ - Names::iterator i = m_names.find( setName ); - ASSERT_MESSAGE( i != m_names.end(), "cannot detach name" ); - //globalOutputStream() << "detach: " << reinterpret_cast(setName) << "\n"; - detachObserver( NameObserver::NameChangedCaller( ( *i ).second ) ); - m_names.erase( i ); -} - -void makeUnique( const char* name, const NameCallback& setName ) const { - char buffer[1024]; - name_write( buffer, m_uniqueNames.make_unique( name_read( name ) ) ); - setName( buffer ); -} - -void mergeNames( const BasicNamespace& other ) const { - typedef std::list SetNameCallbacks; - typedef std::map NameGroups; - NameGroups groups; - - UniqueNames uniqueNames( other.m_uniqueNames ); - - for ( Names::const_iterator i = m_names.begin(); i != m_names.end(); ++i ) - { - groups[( *i ).second.c_str()].push_back( ( *i ).first ); - } - - for ( NameGroups::iterator i = groups.begin(); i != groups.end(); ++i ) - { - name_t uniqueName( uniqueNames.make_unique( name_read( ( *i ).first.c_str() ) ) ); - uniqueNames.insert( uniqueName ); - - char buffer[1024]; - name_write( buffer, uniqueName ); - - //globalOutputStream() << "renaming " << makeQuoted((*i).first.c_str()) << " to " << makeQuoted(buffer) << "\n"; - - SetNameCallbacks& setNameCallbacks = ( *i ).second; - - for ( SetNameCallbacks::const_iterator j = setNameCallbacks.begin(); j != setNameCallbacks.end(); ++j ) - { - ( *j )( buffer ); - } - } -} + ~BasicNamespace() + { + ASSERT_MESSAGE(m_names.empty(), "namespace: names still registered at shutdown"); + } + + void attach(const NameCallback &setName, const NameCallbackCallback &attachObserver) + { + std::pair result = m_names.insert(Names::value_type(setName, m_uniqueNames)); + ASSERT_MESSAGE(result.second, "cannot attach name"); + attachObserver(NameObserver::NameChangedCaller((*result.first).second)); + //globalOutputStream() << "attach: " << reinterpret_cast(setName) << "\n"; + } + + void detach(const NameCallback &setName, const NameCallbackCallback &detachObserver) + { + Names::iterator i = m_names.find(setName); + ASSERT_MESSAGE(i != m_names.end(), "cannot detach name"); + //globalOutputStream() << "detach: " << reinterpret_cast(setName) << "\n"; + detachObserver(NameObserver::NameChangedCaller((*i).second)); + m_names.erase(i); + } + + void makeUnique(const char *name, const NameCallback &setName) const + { + char buffer[1024]; + name_write(buffer, m_uniqueNames.make_unique(name_read(name))); + setName(buffer); + } + + void mergeNames(const BasicNamespace &other) const + { + typedef std::list SetNameCallbacks; + typedef std::map NameGroups; + NameGroups groups; + + UniqueNames uniqueNames(other.m_uniqueNames); + + for (Names::const_iterator i = m_names.begin(); i != m_names.end(); ++i) { + groups[(*i).second.c_str()].push_back((*i).first); + } + + for (NameGroups::iterator i = groups.begin(); i != groups.end(); ++i) { + name_t uniqueName(uniqueNames.make_unique(name_read((*i).first.c_str()))); + uniqueNames.insert(uniqueName); + + char buffer[1024]; + name_write(buffer, uniqueName); + + //globalOutputStream() << "renaming " << makeQuoted((*i).first.c_str()) << " to " << makeQuoted(buffer) << "\n"; + + SetNameCallbacks &setNameCallbacks = (*i).second; + + for (SetNameCallbacks::const_iterator j = setNameCallbacks.begin(); j != setNameCallbacks.end(); ++j) { + (*j)(buffer); + } + } + } }; BasicNamespace g_defaultNamespace; BasicNamespace g_cloneNamespace; -class NamespaceAPI -{ -Namespace* m_namespace; +class NamespaceAPI { + Namespace *m_namespace; public: -typedef Namespace Type; -STRING_CONSTANT( Name, "*" ); + typedef Namespace Type; -NamespaceAPI(){ - m_namespace = &g_defaultNamespace; -} -Namespace* getTable(){ - return m_namespace; -} + STRING_CONSTANT(Name, "*"); + + NamespaceAPI() + { + m_namespace = &g_defaultNamespace; + } + + Namespace *getTable() + { + return m_namespace; + } }; typedef SingletonModule NamespaceModule; typedef Static StaticNamespaceModule; -StaticRegisterModule staticRegisterDefaultNamespace( StaticNamespaceModule::instance() ); +StaticRegisterModule staticRegisterDefaultNamespace(StaticNamespaceModule::instance()); -std::list g_cloned; +std::list g_cloned; -inline Namespaced* Node_getNamespaced( scene::Node& node ){ - return NodeTypeCast::cast( node ); +inline Namespaced *Node_getNamespaced(scene::Node &node) +{ + return NodeTypeCast::cast(node); } -void Node_gatherNamespaced( scene::Node& node ){ - Namespaced* namespaced = Node_getNamespaced( node ); - if ( namespaced != 0 ) { - g_cloned.push_back( namespaced ); - } +void Node_gatherNamespaced(scene::Node &node) +{ + Namespaced *namespaced = Node_getNamespaced(node); + if (namespaced != 0) { + g_cloned.push_back(namespaced); + } } -class GatherNamespaced : public scene::Traversable::Walker -{ +class GatherNamespaced : public scene::Traversable::Walker { public: -bool pre( scene::Node& node ) const { - Node_gatherNamespaced( node ); - return true; -} + bool pre(scene::Node &node) const + { + Node_gatherNamespaced(node); + return true; + } }; -void Map_gatherNamespaced( scene::Node& root ){ - Node_traverseSubgraph( root, GatherNamespaced() ); +void Map_gatherNamespaced(scene::Node &root) +{ + Node_traverseSubgraph(root, GatherNamespaced()); } -void Map_mergeClonedNames(){ - for ( std::list::const_iterator i = g_cloned.begin(); i != g_cloned.end(); ++i ) - { - ( *i )->setNamespace( g_cloneNamespace ); - } - g_cloneNamespace.mergeNames( g_defaultNamespace ); - for ( std::list::const_iterator i = g_cloned.begin(); i != g_cloned.end(); ++i ) - { - ( *i )->setNamespace( g_defaultNamespace ); - } +void Map_mergeClonedNames() +{ + for (std::list::const_iterator i = g_cloned.begin(); i != g_cloned.end(); ++i) { + (*i)->setNamespace(g_cloneNamespace); + } + g_cloneNamespace.mergeNames(g_defaultNamespace); + for (std::list::const_iterator i = g_cloned.begin(); i != g_cloned.end(); ++i) { + (*i)->setNamespace(g_defaultNamespace); + } - g_cloned.clear(); + g_cloned.clear(); } -class WorldNode -{ -scene::Node* m_node; +class WorldNode { + scene::Node *m_node; public: -WorldNode() - : m_node( 0 ){ -} -void set( scene::Node* node ){ - if ( m_node != 0 ) { - m_node->DecRef(); - } - m_node = node; - if ( m_node != 0 ) { - m_node->IncRef(); - } -} -scene::Node* get() const { - return m_node; -} + WorldNode() + : m_node(0) + { + } + + void set(scene::Node *node) + { + if (m_node != 0) { + m_node->DecRef(); + } + m_node = node; + if (m_node != 0) { + m_node->IncRef(); + } + } + + scene::Node *get() const + { + return m_node; + } }; class Map; -void Map_SetValid( Map& map, bool valid ); -void Map_UpdateTitle( const Map& map ); -void Map_SetWorldspawn( Map& map, scene::Node* node ); +void Map_SetValid(Map &map, bool valid); -class Map : public ModuleObserver -{ +void Map_UpdateTitle(const Map &map); + +void Map_SetWorldspawn(Map &map, scene::Node *node); + + +class Map : public ModuleObserver { public: -CopiedString m_name; -Resource* m_resource; -bool m_valid; + CopiedString m_name; + Resource *m_resource; + bool m_valid; -bool m_modified; -void ( *m_modified_changed )( const Map& ); + bool m_modified; -Signal0 m_mapValidCallbacks; + void ( *m_modified_changed )(const Map &); -WorldNode m_world_node; // "classname" "worldspawn" ! + Signal0 m_mapValidCallbacks; -Map() : m_resource( 0 ), m_valid( false ), m_modified_changed( Map_UpdateTitle ){ -} + WorldNode m_world_node; // "classname" "worldspawn" ! -void realise(){ - if ( m_resource != 0 ) { - if ( Map_Unnamed( *this ) ) { - g_map.m_resource->setNode( NewMapRoot( "" ).get_pointer() ); - MapFile* map = Node_getMapFile( *g_map.m_resource->getNode() ); - if ( map != 0 ) { - map->save(); - } - } - else - { - m_resource->load(); - } + Map() : m_resource(0), m_valid(false), m_modified_changed(Map_UpdateTitle) + { + } - GlobalSceneGraph().insert_root( *m_resource->getNode() ); + void realise() + { + if (m_resource != 0) { + if (Map_Unnamed(*this)) { + g_map.m_resource->setNode(NewMapRoot("").get_pointer()); + MapFile *map = Node_getMapFile(*g_map.m_resource->getNode()); + if (map != 0) { + map->save(); + } + } else { + m_resource->load(); + } - AutoSave_clear(); + GlobalSceneGraph().insert_root(*m_resource->getNode()); - Map_SetValid( g_map, true ); - } -} -void unrealise(){ - if ( m_resource != 0 ) { - Map_SetValid( g_map, false ); - Map_SetWorldspawn( g_map, 0 ); + AutoSave_clear(); + Map_SetValid(g_map, true); + } + } - GlobalUndoSystem().clear(); + void unrealise() + { + if (m_resource != 0) { + Map_SetValid(g_map, false); + Map_SetWorldspawn(g_map, 0); - GlobalSceneGraph().erase_root(); - } -} + + GlobalUndoSystem().clear(); + + GlobalSceneGraph().erase_root(); + } + } }; Map g_map; -Map* g_currentMap = 0; +Map *g_currentMap = 0; -void Map_addValidCallback( Map& map, const SignalHandler& handler ){ - map.m_mapValidCallbacks.connectLast( handler ); +void Map_addValidCallback(Map &map, const SignalHandler &handler) +{ + map.m_mapValidCallbacks.connectLast(handler); } -bool Map_Valid( const Map& map ){ - return map.m_valid; +bool Map_Valid(const Map &map) +{ + return map.m_valid; } -void Map_SetValid( Map& map, bool valid ){ - map.m_valid = valid; - map.m_mapValidCallbacks(); +void Map_SetValid(Map &map, bool valid) +{ + map.m_valid = valid; + map.m_mapValidCallbacks(); } -const char* Map_Name( const Map& map ){ - return map.m_name.c_str(); +const char *Map_Name(const Map &map) +{ + return map.m_name.c_str(); } -bool Map_Unnamed( const Map& map ){ - return string_equal( Map_Name( map ), "unnamed.map" ); +bool Map_Unnamed(const Map &map) +{ + return string_equal(Map_Name(map), "unnamed.map"); } -inline const MapFormat& MapFormat_forFile( const char* filename ){ - const char* moduleName = findModuleName( GetFileTypeRegistry(), MapFormat::Name(), path_get_extension( filename ) ); - MapFormat* format = Radiant_getMapModules().findModule( moduleName ); - ASSERT_MESSAGE( format != 0, "map format not found for file " << makeQuoted( filename ) ); - return *format; +inline const MapFormat &MapFormat_forFile(const char *filename) +{ + const char *moduleName = findModuleName(GetFileTypeRegistry(), MapFormat::Name(), path_get_extension(filename)); + MapFormat *format = Radiant_getMapModules().findModule(moduleName); + ASSERT_MESSAGE(format != 0, "map format not found for file " << makeQuoted(filename)); + return *format; } -const MapFormat& Map_getFormat( const Map& map ){ - return MapFormat_forFile( Map_Name( map ) ); +const MapFormat &Map_getFormat(const Map &map) +{ + return MapFormat_forFile(Map_Name(map)); } -bool Map_Modified( const Map& map ){ - return map.m_modified; +bool Map_Modified(const Map &map) +{ + return map.m_modified; } -void Map_SetModified( Map& map, bool modified ){ - if ( map.m_modified ^ modified ) { - map.m_modified = modified; +void Map_SetModified(Map &map, bool modified) +{ + if (map.m_modified ^ modified) { + map.m_modified = modified; - map.m_modified_changed( map ); - } + map.m_modified_changed(map); + } } -void Map_UpdateTitle( const Map& map ){ - Sys_SetTitle( map.m_name.c_str(), Map_Modified( map ) ); +void Map_UpdateTitle(const Map &map) +{ + Sys_SetTitle(map.m_name.c_str(), Map_Modified(map)); } - -scene::Node* Map_GetWorldspawn( const Map& map ){ - return map.m_world_node.get(); +scene::Node *Map_GetWorldspawn(const Map &map) +{ + return map.m_world_node.get(); } -void Map_SetWorldspawn( Map& map, scene::Node* node ){ - map.m_world_node.set( node ); +void Map_SetWorldspawn(Map &map, scene::Node *node) +{ + map.m_world_node.set(node); } @@ -398,9 +443,9 @@ void Map_SetWorldspawn( Map& map, scene::Node* node ){ float g_MaxWorldCoord = 64 * 1024; float g_MinWorldCoord = -64 * 1024; -void AddRegionBrushes( void ); -void RemoveRegionBrushes( void ); +void AddRegionBrushes(void); +void RemoveRegionBrushes(void); /* @@ -409,64 +454,68 @@ void RemoveRegionBrushes( void ); free all map elements, reinitialize the structures that depend on them ================ */ -void Map_Free(){ - Pointfile_Clear(); +void Map_Free() +{ + Pointfile_Clear(); - g_map.m_resource->detach( g_map ); - GlobalReferenceCache().release( g_map.m_name.c_str() ); - g_map.m_resource = 0; + g_map.m_resource->detach(g_map); + GlobalReferenceCache().release(g_map.m_name.c_str()); + g_map.m_resource = 0; - FlushReferences(); + FlushReferences(); - g_currentMap = 0; - Brush_unlatchPreferences(); + g_currentMap = 0; + Brush_unlatchPreferences(); } -class EntityFindByClassname : public scene::Graph::Walker -{ -const char* m_name; -Entity*& m_entity; +class EntityFindByClassname : public scene::Graph::Walker { + const char *m_name; + Entity *&m_entity; public: -EntityFindByClassname( const char* name, Entity*& entity ) : m_name( name ), m_entity( entity ){ - m_entity = 0; -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( m_entity == 0 ) { - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 - && string_equal( m_name, entity->getKeyValue( "classname" ) ) ) { - m_entity = entity; - } - } - return true; -} + EntityFindByClassname(const char *name, Entity *&entity) : m_name(name), m_entity(entity) + { + m_entity = 0; + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (m_entity == 0) { + Entity *entity = Node_getEntity(path.top()); + if (entity != 0 + && string_equal(m_name, entity->getKeyValue("classname"))) { + m_entity = entity; + } + } + return true; + } }; -Entity* Scene_FindEntityByClass( const char* name ){ - Entity* entity; - GlobalSceneGraph().traverse( EntityFindByClassname( name, entity ) ); - return entity; -} - -Entity *Scene_FindPlayerStart(){ - typedef const char* StaticString; - StaticString strings[] = { - "info_player_start", - "info_player_deathmatch", - "team_CTF_redplayer", - "team_CTF_blueplayer", - "team_CTF_redspawn", - "team_CTF_bluespawn", - }; - typedef const StaticString* StaticStringIterator; - for ( StaticStringIterator i = strings, end = strings + ( sizeof( strings ) / sizeof( StaticString ) ); i != end; ++i ) - { - Entity* entity = Scene_FindEntityByClass( *i ); - if ( entity != 0 ) { - return entity; - } - } - return 0; +Entity *Scene_FindEntityByClass(const char *name) +{ + Entity *entity; + GlobalSceneGraph().traverse(EntityFindByClassname(name, entity)); + return entity; +} + +Entity *Scene_FindPlayerStart() +{ + typedef const char *StaticString; + StaticString strings[] = { + "info_player_start", + "info_player_deathmatch", + "team_CTF_redplayer", + "team_CTF_blueplayer", + "team_CTF_redspawn", + "team_CTF_bluespawn", + }; + typedef const StaticString *StaticStringIterator; + for (StaticStringIterator i = strings, end = strings + (sizeof(strings) / sizeof(StaticString)); i != end; ++i) { + Entity *entity = Scene_FindEntityByClass(*i); + if (entity != 0) { + return entity; + } + } + return 0; } // @@ -474,438 +523,469 @@ Entity *Scene_FindPlayerStart(){ // -void FocusViews( const Vector3& point, float angle ){ - CamWnd& camwnd = *g_pParentWnd->GetCamWnd(); - Camera_setOrigin( camwnd, point ); - Vector3 angles( Camera_getAngles( camwnd ) ); - angles[CAMERA_PITCH] = 0; - angles[CAMERA_YAW] = angle; - Camera_setAngles( camwnd, angles ); +void FocusViews(const Vector3 &point, float angle) +{ + CamWnd &camwnd = *g_pParentWnd->GetCamWnd(); + Camera_setOrigin(camwnd, point); + Vector3 angles(Camera_getAngles(camwnd)); + angles[CAMERA_PITCH] = 0; + angles[CAMERA_YAW] = angle; + Camera_setAngles(camwnd, angles); - XYWnd* xywnd = g_pParentWnd->GetXYWnd(); - xywnd->SetOrigin( point ); + XYWnd *xywnd = g_pParentWnd->GetXYWnd(); + xywnd->SetOrigin(point); } #include "stringio.h" -void Map_StartPosition(){ - Entity* entity = Scene_FindPlayerStart(); +void Map_StartPosition() +{ + Entity *entity = Scene_FindPlayerStart(); - if ( entity ) { - Vector3 origin; - string_parse_vector3( entity->getKeyValue( "origin" ), origin ); - FocusViews( origin, string_read_float( entity->getKeyValue( "angle" ) ) ); - } - else - { - FocusViews( g_vector3_identity, 0 ); - } + if (entity) { + Vector3 origin; + string_parse_vector3(entity->getKeyValue("origin"), origin); + FocusViews(origin, string_read_float(entity->getKeyValue("angle"))); + } else { + FocusViews(g_vector3_identity, 0); + } } -inline bool node_is_worldspawn( scene::Node& node ){ - Entity* entity = Node_getEntity( node ); - return entity != 0 && string_equal( entity->getKeyValue( "classname" ), "worldspawn" ); +inline bool node_is_worldspawn(scene::Node &node) +{ + Entity *entity = Node_getEntity(node); + return entity != 0 && string_equal(entity->getKeyValue("classname"), "worldspawn"); } // use first worldspawn -class entity_updateworldspawn : public scene::Traversable::Walker -{ +class entity_updateworldspawn : public scene::Traversable::Walker { public: -bool pre( scene::Node& node ) const { - if ( node_is_worldspawn( node ) ) { - if ( Map_GetWorldspawn( g_map ) == 0 ) { - Map_SetWorldspawn( g_map, &node ); - } - } - return false; -} + bool pre(scene::Node &node) const + { + if (node_is_worldspawn(node)) { + if (Map_GetWorldspawn(g_map) == 0) { + Map_SetWorldspawn(g_map, &node); + } + } + return false; + } }; -scene::Node* Map_FindWorldspawn( Map& map ){ - Map_SetWorldspawn( map, 0 ); +scene::Node *Map_FindWorldspawn(Map &map) +{ + Map_SetWorldspawn(map, 0); - Node_getTraversable( GlobalSceneGraph().root() )->traverse( entity_updateworldspawn() ); + Node_getTraversable(GlobalSceneGraph().root())->traverse(entity_updateworldspawn()); - return Map_GetWorldspawn( map ); + return Map_GetWorldspawn(map); } -class CollectAllWalker : public scene::Traversable::Walker -{ -scene::Node& m_root; -UnsortedNodeSet& m_nodes; +class CollectAllWalker : public scene::Traversable::Walker { + scene::Node &m_root; + UnsortedNodeSet &m_nodes; public: -CollectAllWalker( scene::Node& root, UnsortedNodeSet& nodes ) : m_root( root ), m_nodes( nodes ){ -} -bool pre( scene::Node& node ) const { - m_nodes.insert( NodeSmartReference( node ) ); - Node_getTraversable( m_root )->erase( node ); - return false; -} + CollectAllWalker(scene::Node &root, UnsortedNodeSet &nodes) : m_root(root), m_nodes(nodes) + { + } + + bool pre(scene::Node &node) const + { + m_nodes.insert(NodeSmartReference(node)); + Node_getTraversable(m_root)->erase(node); + return false; + } }; -void Node_insertChildFirst( scene::Node& parent, scene::Node& child ){ - UnsortedNodeSet nodes; - Node_getTraversable( parent )->traverse( CollectAllWalker( parent, nodes ) ); - Node_getTraversable( parent )->insert( child ); +void Node_insertChildFirst(scene::Node &parent, scene::Node &child) +{ + UnsortedNodeSet nodes; + Node_getTraversable(parent)->traverse(CollectAllWalker(parent, nodes)); + Node_getTraversable(parent)->insert(child); - for ( UnsortedNodeSet::iterator i = nodes.begin(); i != nodes.end(); ++i ) - { - Node_getTraversable( parent )->insert( ( *i ) ); - } + for (UnsortedNodeSet::iterator i = nodes.begin(); i != nodes.end(); ++i) { + Node_getTraversable(parent)->insert((*i)); + } } -scene::Node& createWorldspawn(){ - NodeSmartReference worldspawn( GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( "worldspawn", true ) ) ); - Node_insertChildFirst( GlobalSceneGraph().root(), worldspawn ); - return worldspawn; +scene::Node &createWorldspawn() +{ + NodeSmartReference worldspawn( + GlobalEntityCreator().createEntity(GlobalEntityClassManager().findOrInsert("worldspawn", true))); + Node_insertChildFirst(GlobalSceneGraph().root(), worldspawn); + return worldspawn; } -void Map_UpdateWorldspawn( Map& map ){ - if ( Map_FindWorldspawn( map ) == 0 ) { - Map_SetWorldspawn( map, &createWorldspawn() ); - } +void Map_UpdateWorldspawn(Map &map) +{ + if (Map_FindWorldspawn(map) == 0) { + Map_SetWorldspawn(map, &createWorldspawn()); + } } -scene::Node& Map_FindOrInsertWorldspawn( Map& map ){ - Map_UpdateWorldspawn( map ); - return *Map_GetWorldspawn( map ); +scene::Node &Map_FindOrInsertWorldspawn(Map &map) +{ + Map_UpdateWorldspawn(map); + return *Map_GetWorldspawn(map); } -class MapMergeAll : public scene::Traversable::Walker -{ -mutable scene::Path m_path; +class MapMergeAll : public scene::Traversable::Walker { + mutable scene::Path m_path; public: -MapMergeAll( const scene::Path& root ) - : m_path( root ){ -} -bool pre( scene::Node& node ) const { - Node_getTraversable( m_path.top() )->insert( node ); - m_path.push( makeReference( node ) ); - selectPath( m_path, true ); - return false; -} -void post( scene::Node& node ) const { - m_path.pop(); -} + MapMergeAll(const scene::Path &root) + : m_path(root) + { + } + + bool pre(scene::Node &node) const + { + Node_getTraversable(m_path.top())->insert(node); + m_path.push(makeReference(node)); + selectPath(m_path, true); + return false; + } + + void post(scene::Node &node) const + { + m_path.pop(); + } }; -class MapMergeEntities : public scene::Traversable::Walker -{ -mutable scene::Path m_path; +class MapMergeEntities : public scene::Traversable::Walker { + mutable scene::Path m_path; public: -MapMergeEntities( const scene::Path& root ) - : m_path( root ){ -} -bool pre( scene::Node& node ) const { - if ( node_is_worldspawn( node ) ) { - scene::Node* world_node = Map_FindWorldspawn( g_map ); - if ( world_node == 0 ) { - Map_SetWorldspawn( g_map, &node ); - Node_getTraversable( m_path.top().get() )->insert( node ); - m_path.push( makeReference( node ) ); - Node_getTraversable( node )->traverse( SelectChildren( m_path ) ); - } - else - { - m_path.push( makeReference( *world_node ) ); - Node_getTraversable( node )->traverse( MapMergeAll( m_path ) ); - } - } - else - { - Node_getTraversable( m_path.top() )->insert( node ); - m_path.push( makeReference( node ) ); - if ( node_is_group( node ) ) { - Node_getTraversable( node )->traverse( SelectChildren( m_path ) ); - } - else - { - selectPath( m_path, true ); - } - } - return false; -} -void post( scene::Node& node ) const { - m_path.pop(); -} + MapMergeEntities(const scene::Path &root) + : m_path(root) + { + } + + bool pre(scene::Node &node) const + { + if (node_is_worldspawn(node)) { + scene::Node *world_node = Map_FindWorldspawn(g_map); + if (world_node == 0) { + Map_SetWorldspawn(g_map, &node); + Node_getTraversable(m_path.top().get())->insert(node); + m_path.push(makeReference(node)); + Node_getTraversable(node)->traverse(SelectChildren(m_path)); + } else { + m_path.push(makeReference(*world_node)); + Node_getTraversable(node)->traverse(MapMergeAll(m_path)); + } + } else { + Node_getTraversable(m_path.top())->insert(node); + m_path.push(makeReference(node)); + if (node_is_group(node)) { + Node_getTraversable(node)->traverse(SelectChildren(m_path)); + } else { + selectPath(m_path, true); + } + } + return false; + } + + void post(scene::Node &node) const + { + m_path.pop(); + } }; -class BasicContainer : public scene::Node::Symbiot -{ -class TypeCasts -{ -NodeTypeCastTable m_casts; +class BasicContainer : public scene::Node::Symbiot { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeContainedCast::install(m_casts); + } + + NodeTypeCastTable &get() + { + return m_casts; + } + }; + + scene::Node m_node; + TraversableNodeSet m_traverse; public: -TypeCasts(){ - NodeContainedCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} -}; -scene::Node m_node; -TraversableNodeSet m_traverse; -public: + typedef LazyStatic StaticTypeCasts; -typedef LazyStatic StaticTypeCasts; + scene::Traversable &get(NullType) + { + return m_traverse; + } -scene::Traversable& get( NullType){ - return m_traverse; -} + BasicContainer() : m_node(this, this, StaticTypeCasts::instance().get()) + { + } -BasicContainer() : m_node( this, this, StaticTypeCasts::instance().get() ){ -} -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } }; /// Merges the map graph rooted at \p node into the global scene-graph. -void MergeMap( scene::Node& node ){ - Node_getTraversable( node )->traverse( MapMergeEntities( scene::Path( makeReference( GlobalSceneGraph().root() ) ) ) ); -} -void Map_ImportSelected( TextInputStream& in, const MapFormat& format ){ - NodeSmartReference node( ( new BasicContainer )->node() ); - format.readGraph( node, in, GlobalEntityCreator() ); - Map_gatherNamespaced( node ); - Map_mergeClonedNames(); - MergeMap( node ); -} - -inline scene::Cloneable* Node_getCloneable( scene::Node& node ){ - return NodeTypeCast::cast( node ); +void MergeMap(scene::Node &node) +{ + Node_getTraversable(node)->traverse(MapMergeEntities(scene::Path(makeReference(GlobalSceneGraph().root())))); } -inline scene::Node& node_clone( scene::Node& node ){ - scene::Cloneable* cloneable = Node_getCloneable( node ); - if ( cloneable != 0 ) { - return cloneable->clone(); - } - - return ( new scene::NullNode )->node(); +void Map_ImportSelected(TextInputStream &in, const MapFormat &format) +{ + NodeSmartReference node((new BasicContainer)->node()); + format.readGraph(node, in, GlobalEntityCreator()); + Map_gatherNamespaced(node); + Map_mergeClonedNames(); + MergeMap(node); } -class CloneAll : public scene::Traversable::Walker +inline scene::Cloneable *Node_getCloneable(scene::Node &node) { -mutable scene::Path m_path; -public: -CloneAll( scene::Node& root ) - : m_path( makeReference( root ) ){ + return NodeTypeCast::cast(node); } -bool pre( scene::Node& node ) const { - if ( node.isRoot() ) { - return false; - } - m_path.push( makeReference( node_clone( node ) ) ); - m_path.top().get().IncRef(); +inline scene::Node &node_clone(scene::Node &node) +{ + scene::Cloneable *cloneable = Node_getCloneable(node); + if (cloneable != 0) { + return cloneable->clone(); + } - return true; + return (new scene::NullNode)->node(); } -void post( scene::Node& node ) const { - if ( node.isRoot() ) { - return; - } - Node_getTraversable( m_path.parent() )->insert( m_path.top() ); - - m_path.top().get().DecRef(); - m_path.pop(); -} +class CloneAll : public scene::Traversable::Walker { + mutable scene::Path m_path; +public: + CloneAll(scene::Node &root) + : m_path(makeReference(root)) + { + } + + bool pre(scene::Node &node) const + { + if (node.isRoot()) { + return false; + } + + m_path.push(makeReference(node_clone(node))); + m_path.top().get().IncRef(); + + return true; + } + + void post(scene::Node &node) const + { + if (node.isRoot()) { + return; + } + + Node_getTraversable(m_path.parent())->insert(m_path.top()); + + m_path.top().get().DecRef(); + m_path.pop(); + } }; -scene::Node& Node_Clone( scene::Node& node ){ - scene::Node& clone = node_clone( node ); - scene::Traversable* traversable = Node_getTraversable( node ); - if ( traversable != 0 ) { - traversable->traverse( CloneAll( clone ) ); - } - return clone; +scene::Node &Node_Clone(scene::Node &node) +{ + scene::Node &clone = node_clone(node); + scene::Traversable *traversable = Node_getTraversable(node); + if (traversable != 0) { + traversable->traverse(CloneAll(clone)); + } + return clone; } typedef std::map EntityBreakdown; -class EntityBreakdownWalker : public scene::Graph::Walker -{ -EntityBreakdown& m_entitymap; +class EntityBreakdownWalker : public scene::Graph::Walker { + EntityBreakdown &m_entitymap; public: -EntityBreakdownWalker( EntityBreakdown& entitymap ) - : m_entitymap( entitymap ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 ) { - const EntityClass& eclass = entity->getEntityClass(); - if ( m_entitymap.find( eclass.name() ) == m_entitymap.end() ) { - m_entitymap[eclass.name()] = 1; - } - else{ ++m_entitymap[eclass.name()]; } - } - return true; -} + EntityBreakdownWalker(EntityBreakdown &entitymap) + : m_entitymap(entitymap) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Entity *entity = Node_getEntity(path.top()); + if (entity != 0) { + const EntityClass &eclass = entity->getEntityClass(); + if (m_entitymap.find(eclass.name()) == m_entitymap.end()) { + m_entitymap[eclass.name()] = 1; + } else { ++m_entitymap[eclass.name()]; } + } + return true; + } }; -void Scene_EntityBreakdown( EntityBreakdown& entitymap ){ - GlobalSceneGraph().traverse( EntityBreakdownWalker( entitymap ) ); +void Scene_EntityBreakdown(EntityBreakdown &entitymap) +{ + GlobalSceneGraph().traverse(EntityBreakdownWalker(entitymap)); } -WindowPosition g_posMapInfoWnd( c_default_window_pos ); +WindowPosition g_posMapInfoWnd(c_default_window_pos); -void DoMapInfo(){ - ModalDialog dialog; - ui::Entry brushes_entry{ui::null}; - ui::Entry entities_entry{ui::null}; - ui::ListStore EntityBreakdownWalker{ui::null}; +void DoMapInfo() +{ + ModalDialog dialog; + ui::Entry brushes_entry{ui::null}; + ui::Entry entities_entry{ui::null}; + ui::ListStore EntityBreakdownWalker{ui::null}; - ui::Window window = MainFrame_getWindow().create_dialog_window("Map Info", G_CALLBACK(dialog_delete_callback ), &dialog ); + ui::Window window = MainFrame_getWindow().create_dialog_window("Map Info", G_CALLBACK(dialog_delete_callback), + &dialog); - window_set_position( window, g_posMapInfoWnd ); + window_set_position(window, g_posMapInfoWnd); - { - auto vbox = create_dialog_vbox( 4, 4 ); - window.add(vbox); + { + auto vbox = create_dialog_vbox(4, 4); + window.add(vbox); - { - auto hbox = create_dialog_hbox( 4 ); - vbox.pack_start( hbox, FALSE, TRUE, 0 ); + { + auto hbox = create_dialog_hbox(4); + vbox.pack_start(hbox, FALSE, TRUE, 0); - { - auto table = create_dialog_table( 2, 2, 4, 4 ); - hbox.pack_start( table, TRUE, TRUE, 0 ); + { + auto table = create_dialog_table(2, 2, 4, 4); + hbox.pack_start(table, TRUE, TRUE, 0); - { - auto entry = ui::Entry(ui::New); - entry.show(); + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_editable_set_editable( GTK_EDITABLE(entry), FALSE ); + gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE); - brushes_entry = entry; - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + brushes_entry = entry; + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_editable_set_editable( GTK_EDITABLE(entry), FALSE ); + gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE); - entities_entry = entry; - } - { - ui::Widget label = ui::Label( "Total Brushes" ); - label.show(); + entities_entry = entry; + } + { + ui::Widget label = ui::Label("Total Brushes"); + label.show(); table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - ui::Widget label = ui::Label( "Total Entities" ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + ui::Widget label = ui::Label("Total Entities"); + label.show(); table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - } - { - auto vbox2 = create_dialog_vbox( 4 ); - hbox.pack_start( vbox2, FALSE, FALSE, 0 ); - - { - auto button = create_dialog_button( "Close", G_CALLBACK( dialog_button_ok ), &dialog ); - vbox2.pack_start( button, FALSE, FALSE, 0 ); - } - } - } - { - ui::Widget label = ui::Label( "Entity breakdown" ); - label.show(); - vbox.pack_start( label, FALSE, TRUE, 0 ); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto scr = create_scrolled_window( ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4 ); - vbox.pack_start( scr, TRUE, TRUE, 0 ); - - { - auto store = ui::ListStore::from(gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_STRING )); - - auto view = ui::TreeView(ui::TreeModel::from(store._handle)); - gtk_tree_view_set_headers_clickable(view, TRUE ); - - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn( "Entity", renderer, {{"text", 0}} ); - gtk_tree_view_append_column(view, column ); - gtk_tree_view_column_set_sort_column_id( column, 0 ); - } - - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn( "Count", renderer, {{"text", 1}} ); - gtk_tree_view_append_column(view, column ); - gtk_tree_view_column_set_sort_column_id( column, 1 ); - } - - view.show(); - - scr.add(view); - - EntityBreakdownWalker = store; - } - } - } - - // Initialize fields - - { - EntityBreakdown entitymap; - Scene_EntityBreakdown( entitymap ); - - for ( EntityBreakdown::iterator i = entitymap.begin(); i != entitymap.end(); ++i ) - { - char tmp[16]; - sprintf( tmp, "%u", Unsigned( ( *i ).second ) ); - EntityBreakdownWalker.append(0, (*i).first.c_str(), 1, tmp); - } - } - - EntityBreakdownWalker.unref(); - - char tmp[16]; - sprintf( tmp, "%u", Unsigned( g_brushCount.get() ) ); - brushes_entry.text(tmp); - sprintf( tmp, "%u", Unsigned( g_entityCount.get() ) ); - entities_entry.text(tmp); - - modal_dialog_show( window, dialog ); - - // save before exit - window_get_position( window, g_posMapInfoWnd ); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + } + { + auto vbox2 = create_dialog_vbox(4); + hbox.pack_start(vbox2, FALSE, FALSE, 0); + + { + auto button = create_dialog_button("Close", G_CALLBACK(dialog_button_ok), &dialog); + vbox2.pack_start(button, FALSE, FALSE, 0); + } + } + } + { + ui::Widget label = ui::Label("Entity breakdown"); + label.show(); + vbox.pack_start(label, FALSE, TRUE, 0); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto scr = create_scrolled_window(ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4); + vbox.pack_start(scr, TRUE, TRUE, 0); + + { + auto store = ui::ListStore::from(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING)); + + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_headers_clickable(view, TRUE); + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("Entity", renderer, {{"text", 0}}); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_sort_column_id(column, 0); + } + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("Count", renderer, {{"text", 1}}); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_sort_column_id(column, 1); + } + + view.show(); + + scr.add(view); + + EntityBreakdownWalker = store; + } + } + } + + // Initialize fields + + { + EntityBreakdown entitymap; + Scene_EntityBreakdown(entitymap); + + for (EntityBreakdown::iterator i = entitymap.begin(); i != entitymap.end(); ++i) { + char tmp[16]; + sprintf(tmp, "%u", Unsigned((*i).second)); + EntityBreakdownWalker.append(0, (*i).first.c_str(), 1, tmp); + } + } + + EntityBreakdownWalker.unref(); + + char tmp[16]; + sprintf(tmp, "%u", Unsigned(g_brushCount.get())); + brushes_entry.text(tmp); + sprintf(tmp, "%u", Unsigned(g_entityCount.get())); + entities_entry.text(tmp); + + modal_dialog_show(window, dialog); + + // save before exit + window_get_position(window, g_posMapInfoWnd); window.destroy(); } - -class ScopeTimer -{ -Timer m_timer; -const char* m_message; +class ScopeTimer { + Timer m_timer; + const char *m_message; public: -ScopeTimer( const char* message ) - : m_message( message ){ - m_timer.start(); -} -~ScopeTimer(){ - double elapsed_time = m_timer.elapsed_msec() / 1000.f; - globalOutputStream() << m_message << " timer: " << FloatFormat( elapsed_time, 5, 2 ) << " second(s) elapsed\n"; -} + ScopeTimer(const char *message) + : m_message(message) + { + m_timer.start(); + } + + ~ScopeTimer() + { + double elapsed_time = m_timer.elapsed_msec() / 1000.f; + globalOutputStream() << m_message << " timer: " << FloatFormat(elapsed_time, 5, 2) << " second(s) elapsed\n"; + } }; CopiedString g_strLastFolder = ""; @@ -916,296 +996,309 @@ CopiedString g_strLastFolder = ""; ================ */ -void Map_LoadFile( const char *filename ){ - globalOutputStream() << "Loading map from " << filename << "\n"; - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Map" ); - - MRU_AddFile( filename ); - g_strLastFolder = g_path_get_dirname( filename ); - - { - ScopeTimer timer( "map load" ); - - const MapFormat* format = NULL; - const char* moduleName = findModuleName( &GlobalFiletypes(), MapFormat::Name(), path_get_extension( filename ) ); - if ( string_not_empty( moduleName ) ) { - format = ReferenceAPI_getMapModules().findModule( moduleName ); - } - - for ( int i = 0; i < Brush_toggleFormatCount(); ++i ) - { - if ( i ) { - Map_Free(); - } - Brush_toggleFormat( i ); - g_map.m_name = filename; - Map_UpdateTitle( g_map ); - g_map.m_resource = GlobalReferenceCache().capture( g_map.m_name.c_str() ); - if ( format ) { - format->wrongFormat = false; - } - g_map.m_resource->attach( g_map ); - if ( format ) { - if ( !format->wrongFormat ) { - break; - } - } - } - - Node_getTraversable( GlobalSceneGraph().root() )->traverse( entity_updateworldspawn() ); - } - - globalOutputStream() << "--- LoadMapFile ---\n"; - globalOutputStream() << g_map.m_name.c_str() << "\n"; - - globalOutputStream() << Unsigned( g_brushCount.get() ) << " primitive\n"; - globalOutputStream() << Unsigned( g_entityCount.get() ) << " entities\n"; - - //GlobalEntityCreator().printStatistics(); - - // - // move the view to a start position - // - Map_StartPosition(); - - g_currentMap = &g_map; - - // restart VFS to apply new pak filtering based on mapname - // needed for daemon DPK VFS - VFS_Restart(); -} - -class Excluder +void Map_LoadFile(const char *filename) { + globalOutputStream() << "Loading map from " << filename << "\n"; + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Loading Map"); + + MRU_AddFile(filename); + g_strLastFolder = g_path_get_dirname(filename); + + { + ScopeTimer timer("map load"); + + const MapFormat *format = NULL; + const char *moduleName = findModuleName(&GlobalFiletypes(), MapFormat::Name(), path_get_extension(filename)); + if (string_not_empty(moduleName)) { + format = ReferenceAPI_getMapModules().findModule(moduleName); + } + + for (int i = 0; i < Brush_toggleFormatCount(); ++i) { + if (i) { + Map_Free(); + } + Brush_toggleFormat(i); + g_map.m_name = filename; + Map_UpdateTitle(g_map); + g_map.m_resource = GlobalReferenceCache().capture(g_map.m_name.c_str()); + if (format) { + format->wrongFormat = false; + } + g_map.m_resource->attach(g_map); + if (format) { + if (!format->wrongFormat) { + break; + } + } + } + + Node_getTraversable(GlobalSceneGraph().root())->traverse(entity_updateworldspawn()); + } + + globalOutputStream() << "--- LoadMapFile ---\n"; + globalOutputStream() << g_map.m_name.c_str() << "\n"; + + globalOutputStream() << Unsigned(g_brushCount.get()) << " primitive\n"; + globalOutputStream() << Unsigned(g_entityCount.get()) << " entities\n"; + + //GlobalEntityCreator().printStatistics(); + + // + // move the view to a start position + // + Map_StartPosition(); + + g_currentMap = &g_map; + + // restart VFS to apply new pak filtering based on mapname + // needed for daemon DPK VFS + VFS_Restart(); +} + +class Excluder { public: -virtual bool excluded( scene::Node& node ) const = 0; + virtual bool excluded(scene::Node &node) const = 0; }; -class ExcludeWalker : public scene::Traversable::Walker -{ -const scene::Traversable::Walker& m_walker; -const Excluder* m_exclude; -mutable bool m_skip; +class ExcludeWalker : public scene::Traversable::Walker { + const scene::Traversable::Walker &m_walker; + const Excluder *m_exclude; + mutable bool m_skip; public: -ExcludeWalker( const scene::Traversable::Walker& walker, const Excluder& exclude ) - : m_walker( walker ), m_exclude( &exclude ), m_skip( false ){ -} -bool pre( scene::Node& node ) const { - if ( m_exclude->excluded( node ) || node.isRoot() ) { - m_skip = true; - return false; - } - else - { - m_walker.pre( node ); - } - return true; -} -void post( scene::Node& node ) const { - if ( m_skip ) { - m_skip = false; - } - else - { - m_walker.post( node ); - } -} + ExcludeWalker(const scene::Traversable::Walker &walker, const Excluder &exclude) + : m_walker(walker), m_exclude(&exclude), m_skip(false) + { + } + + bool pre(scene::Node &node) const + { + if (m_exclude->excluded(node) || node.isRoot()) { + m_skip = true; + return false; + } else { + m_walker.pre(node); + } + return true; + } + + void post(scene::Node &node) const + { + if (m_skip) { + m_skip = false; + } else { + m_walker.post(node); + } + } }; -class AnyInstanceSelected : public scene::Instantiable::Visitor -{ -bool& m_selected; +class AnyInstanceSelected : public scene::Instantiable::Visitor { + bool &m_selected; public: -AnyInstanceSelected( bool& selected ) : m_selected( selected ){ - m_selected = false; -} -void visit( scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() ) { - m_selected = true; - } -} + AnyInstanceSelected(bool &selected) : m_selected(selected) + { + m_selected = false; + } + + void visit(scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected()) { + m_selected = true; + } + } }; -bool Node_instanceSelected( scene::Node& node ){ - scene::Instantiable* instantiable = Node_getInstantiable( node ); - ASSERT_NOTNULL( instantiable ); - bool selected; - instantiable->forEachInstance( AnyInstanceSelected( selected ) ); - return selected; -} - -class SelectedDescendantWalker : public scene::Traversable::Walker +bool Node_instanceSelected(scene::Node &node) { -bool& m_selected; -public: -SelectedDescendantWalker( bool& selected ) : m_selected( selected ){ - m_selected = false; + scene::Instantiable *instantiable = Node_getInstantiable(node); + ASSERT_NOTNULL(instantiable); + bool selected; + instantiable->forEachInstance(AnyInstanceSelected(selected)); + return selected; } -bool pre( scene::Node& node ) const { - if ( node.isRoot() ) { - return false; - } - - if ( Node_instanceSelected( node ) ) { - m_selected = true; - } - - return true; -} +class SelectedDescendantWalker : public scene::Traversable::Walker { + bool &m_selected; +public: + SelectedDescendantWalker(bool &selected) : m_selected(selected) + { + m_selected = false; + } + + bool pre(scene::Node &node) const + { + if (node.isRoot()) { + return false; + } + + if (Node_instanceSelected(node)) { + m_selected = true; + } + + return true; + } }; -bool Node_selectedDescendant( scene::Node& node ){ - bool selected; - Node_traverseSubgraph( node, SelectedDescendantWalker( selected ) ); - return selected; +bool Node_selectedDescendant(scene::Node &node) +{ + bool selected; + Node_traverseSubgraph(node, SelectedDescendantWalker(selected)); + return selected; } -class SelectionExcluder : public Excluder -{ +class SelectionExcluder : public Excluder { public: -bool excluded( scene::Node& node ) const { - return !Node_selectedDescendant( node ); -} + bool excluded(scene::Node &node) const + { + return !Node_selectedDescendant(node); + } }; -class IncludeSelectedWalker : public scene::Traversable::Walker -{ -const scene::Traversable::Walker& m_walker; -mutable std::size_t m_selected; -mutable bool m_skip; +class IncludeSelectedWalker : public scene::Traversable::Walker { + const scene::Traversable::Walker &m_walker; + mutable std::size_t m_selected; + mutable bool m_skip; + + bool selectedParent() const + { + return m_selected != 0; + } -bool selectedParent() const { - return m_selected != 0; -} public: -IncludeSelectedWalker( const scene::Traversable::Walker& walker ) - : m_walker( walker ), m_selected( 0 ), m_skip( false ){ -} -bool pre( scene::Node& node ) const { - // include node if: - // node is not a 'root' AND ( node is selected OR any child of node is selected OR any parent of node is selected ) - if ( !node.isRoot() && ( Node_selectedDescendant( node ) || selectedParent() ) ) { - if ( Node_instanceSelected( node ) ) { - ++m_selected; - } - m_walker.pre( node ); - return true; - } - else - { - m_skip = true; - return false; - } -} -void post( scene::Node& node ) const { - if ( m_skip ) { - m_skip = false; - } - else - { - if ( Node_instanceSelected( node ) ) { - --m_selected; - } - m_walker.post( node ); - } -} + IncludeSelectedWalker(const scene::Traversable::Walker &walker) + : m_walker(walker), m_selected(0), m_skip(false) + { + } + + bool pre(scene::Node &node) const + { + // include node if: + // node is not a 'root' AND ( node is selected OR any child of node is selected OR any parent of node is selected ) + if (!node.isRoot() && (Node_selectedDescendant(node) || selectedParent())) { + if (Node_instanceSelected(node)) { + ++m_selected; + } + m_walker.pre(node); + return true; + } else { + m_skip = true; + return false; + } + } + + void post(scene::Node &node) const + { + if (m_skip) { + m_skip = false; + } else { + if (Node_instanceSelected(node)) { + --m_selected; + } + m_walker.post(node); + } + } }; -void Map_Traverse_Selected( scene::Node& root, const scene::Traversable::Walker& walker ){ - scene::Traversable* traversable = Node_getTraversable( root ); - if ( traversable != 0 ) { +void Map_Traverse_Selected(scene::Node &root, const scene::Traversable::Walker &walker) +{ + scene::Traversable *traversable = Node_getTraversable(root); + if (traversable != 0) { #if 0 - traversable->traverse( ExcludeWalker( walker, SelectionExcluder() ) ); + traversable->traverse( ExcludeWalker( walker, SelectionExcluder() ) ); #else - traversable->traverse( IncludeSelectedWalker( walker ) ); + traversable->traverse(IncludeSelectedWalker(walker)); #endif - } + } } -void Map_ExportSelected( TextOutputStream& out, const MapFormat& format ){ - format.writeGraph( GlobalSceneGraph().root(), Map_Traverse_Selected, out ); +void Map_ExportSelected(TextOutputStream &out, const MapFormat &format) +{ + format.writeGraph(GlobalSceneGraph().root(), Map_Traverse_Selected, out); } -void Map_Traverse( scene::Node& root, const scene::Traversable::Walker& walker ){ - scene::Traversable* traversable = Node_getTraversable( root ); - if ( traversable != 0 ) { - traversable->traverse( walker ); - } +void Map_Traverse(scene::Node &root, const scene::Traversable::Walker &walker) +{ + scene::Traversable *traversable = Node_getTraversable(root); + if (traversable != 0) { + traversable->traverse(walker); + } } -class RegionExcluder : public Excluder -{ +class RegionExcluder : public Excluder { public: -bool excluded( scene::Node& node ) const { - return node.excluded(); -} + bool excluded(scene::Node &node) const + { + return node.excluded(); + } }; -void Map_Traverse_Region( scene::Node& root, const scene::Traversable::Walker& walker ){ - scene::Traversable* traversable = Node_getTraversable( root ); - if ( traversable != 0 ) { - traversable->traverse( ExcludeWalker( walker, RegionExcluder() ) ); - } +void Map_Traverse_Region(scene::Node &root, const scene::Traversable::Walker &walker) +{ + scene::Traversable *traversable = Node_getTraversable(root); + if (traversable != 0) { + traversable->traverse(ExcludeWalker(walker, RegionExcluder())); + } } -bool Map_SaveRegion( const char *filename ){ - AddRegionBrushes(); +bool Map_SaveRegion(const char *filename) +{ + AddRegionBrushes(); - bool success = MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse_Region, filename ); + bool success = MapResource_saveFile(MapFormat_forFile(filename), GlobalSceneGraph().root(), Map_Traverse_Region, + filename); - RemoveRegionBrushes(); + RemoveRegionBrushes(); - return success; + return success; } -void Map_RenameAbsolute( const char* absolute ){ - Resource* resource = GlobalReferenceCache().capture( absolute ); - NodeSmartReference clone( NewMapRoot( path_make_relative( absolute, GlobalFileSystem().findRoot( absolute ) ) ) ); - resource->setNode( clone.get_pointer() ); +void Map_RenameAbsolute(const char *absolute) +{ + Resource *resource = GlobalReferenceCache().capture(absolute); + NodeSmartReference clone(NewMapRoot(path_make_relative(absolute, GlobalFileSystem().findRoot(absolute)))); + resource->setNode(clone.get_pointer()); - { - //ScopeTimer timer("clone subgraph"); - Node_getTraversable( GlobalSceneGraph().root() )->traverse( CloneAll( clone ) ); - } + { + //ScopeTimer timer("clone subgraph"); + Node_getTraversable(GlobalSceneGraph().root())->traverse(CloneAll(clone)); + } - g_map.m_resource->detach( g_map ); - GlobalReferenceCache().release( g_map.m_name.c_str() ); + g_map.m_resource->detach(g_map); + GlobalReferenceCache().release(g_map.m_name.c_str()); - g_map.m_resource = resource; + g_map.m_resource = resource; - g_map.m_name = absolute; - Map_UpdateTitle( g_map ); + g_map.m_name = absolute; + Map_UpdateTitle(g_map); - g_map.m_resource->attach( g_map ); - // refresh VFS to apply new pak filtering based on mapname - // needed for daemon DPK VFS - VFS_Refresh(); + g_map.m_resource->attach(g_map); + // refresh VFS to apply new pak filtering based on mapname + // needed for daemon DPK VFS + VFS_Refresh(); } -void Map_Rename( const char* filename ){ - if ( !string_equal( g_map.m_name.c_str(), filename ) ) { - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Saving Map" ); +void Map_Rename(const char *filename) +{ + if (!string_equal(g_map.m_name.c_str(), filename)) { + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Saving Map"); - Map_RenameAbsolute( filename ); + Map_RenameAbsolute(filename); - SceneChangeNotify(); - } - else - { - SaveReferences(); - } + SceneChangeNotify(); + } else { + SaveReferences(); + } } -bool Map_Save(){ - Pointfile_Clear(); +bool Map_Save() +{ + Pointfile_Clear(); - ScopeTimer timer( "map save" ); - SaveReferences(); - return true; // assume success.. + ScopeTimer timer("map save"); + SaveReferences(); + return true; // assume success.. } /* @@ -1214,54 +1307,55 @@ bool Map_Save(){ =========== */ -void Map_New(){ - //globalOutputStream() << "Map_New\n"; +void Map_New() +{ + //globalOutputStream() << "Map_New\n"; - g_map.m_name = "unnamed.map"; - Map_UpdateTitle( g_map ); + g_map.m_name = "unnamed.map"; + Map_UpdateTitle(g_map); - { - g_map.m_resource = GlobalReferenceCache().capture( g_map.m_name.c_str() ); + { + g_map.m_resource = GlobalReferenceCache().capture(g_map.m_name.c_str()); // ASSERT_MESSAGE(g_map.m_resource->getNode() == 0, "bleh"); - g_map.m_resource->attach( g_map ); + g_map.m_resource->attach(g_map); - SceneChangeNotify(); - } + SceneChangeNotify(); + } - FocusViews( g_vector3_identity, 0 ); + FocusViews(g_vector3_identity, 0); - g_currentMap = &g_map; + g_currentMap = &g_map; - // restart VFS to apply new pak filtering based on mapname - // needed for daemon DPK VFS - VFS_Restart(); + // restart VFS to apply new pak filtering based on mapname + // needed for daemon DPK VFS + VFS_Restart(); } -extern void ConstructRegionBrushes( scene::Node * brushes[6], const Vector3 ®ion_mins, const Vector3 ®ion_maxs ); +extern void ConstructRegionBrushes(scene::Node *brushes[6], const Vector3 ®ion_mins, const Vector3 ®ion_maxs); -void ConstructRegionStartpoint( scene::Node* startpoint, const Vector3& region_mins, const Vector3& region_maxs ){ - /*! +void ConstructRegionStartpoint(scene::Node *startpoint, const Vector3 ®ion_mins, const Vector3 ®ion_maxs) +{ + /*! \todo we need to make sure that the player start IS inside the region and bail out if it's not the compiler will refuse to compile a map with a player_start somewhere in empty space.. for now, let's just print an error */ - Vector3 vOrig( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ) ); + Vector3 vOrig(Camera_getOrigin(*g_pParentWnd->GetCamWnd())); - for ( int i = 0 ; i < 3 ; i++ ) - { - if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) { - globalErrorStream() << "Camera is NOT in the region, it's likely that the region won't compile correctly\n"; - break; - } - } + for (int i = 0; i < 3; i++) { + if (vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i]) { + globalErrorStream() << "Camera is NOT in the region, it's likely that the region won't compile correctly\n"; + break; + } + } - // write the info_playerstart - char sTmp[1024]; - sprintf( sTmp, "%d %d %d", (int)vOrig[0], (int)vOrig[1], (int)vOrig[2] ); - Node_getEntity( *startpoint )->setKeyValue( "origin", sTmp ); - sprintf( sTmp, "%d", (int)Camera_getAngles( *g_pParentWnd->GetCamWnd() )[CAMERA_YAW] ); - Node_getEntity( *startpoint )->setKeyValue( "angle", sTmp ); + // write the info_playerstart + char sTmp[1024]; + sprintf(sTmp, "%d %d %d", (int) vOrig[0], (int) vOrig[1], (int) vOrig[2]); + Node_getEntity(*startpoint)->setKeyValue("origin", sTmp); + sprintf(sTmp, "%d", (int) Camera_getAngles(*g_pParentWnd->GetCamWnd())[CAMERA_YAW]); + Node_getEntity(*startpoint)->setKeyValue("angle", sTmp); } /* @@ -1272,11 +1366,11 @@ void ConstructRegionStartpoint( scene::Node* startpoint, const Vector3& region_m =========================================================== */ bool region_active; -Vector3 region_mins( g_MinWorldCoord, g_MinWorldCoord, g_MinWorldCoord ); -Vector3 region_maxs( g_MaxWorldCoord, g_MaxWorldCoord, g_MaxWorldCoord ); +Vector3 region_mins(g_MinWorldCoord, g_MinWorldCoord, g_MinWorldCoord); +Vector3 region_maxs(g_MaxWorldCoord, g_MaxWorldCoord, g_MaxWorldCoord); -scene::Node* region_sides[6]; -scene::Node* region_startpoint = 0; +scene::Node *region_sides[6]; +scene::Node *region_startpoint = 0; /* =========== @@ -1287,103 +1381,116 @@ scene::Node* region_startpoint = 0; with the new implementation we should be able to append them in a temporary manner to the data we pass to the map module =========== */ -void AddRegionBrushes( void ){ - int i; +void AddRegionBrushes(void) +{ + int i; - for ( i = 0; i < 6; i++ ) - { - region_sides[i] = &GlobalBrushCreator().createBrush(); - Node_getTraversable( Map_FindOrInsertWorldspawn( g_map ) )->insert( NodeSmartReference( *region_sides[i] ) ); - } + for (i = 0; i < 6; i++) { + region_sides[i] = &GlobalBrushCreator().createBrush(); + Node_getTraversable(Map_FindOrInsertWorldspawn(g_map))->insert(NodeSmartReference(*region_sides[i])); + } - region_startpoint = &GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( "info_player_start", false ) ); + region_startpoint = &GlobalEntityCreator().createEntity( + GlobalEntityClassManager().findOrInsert("info_player_start", false)); - ConstructRegionBrushes( region_sides, region_mins, region_maxs ); - ConstructRegionStartpoint( region_startpoint, region_mins, region_maxs ); + ConstructRegionBrushes(region_sides, region_mins, region_maxs); + ConstructRegionStartpoint(region_startpoint, region_mins, region_maxs); - Node_getTraversable( GlobalSceneGraph().root() )->insert( NodeSmartReference( *region_startpoint ) ); + Node_getTraversable(GlobalSceneGraph().root())->insert(NodeSmartReference(*region_startpoint)); } -void RemoveRegionBrushes( void ){ - for ( std::size_t i = 0; i < 6; i++ ) - { - Node_getTraversable( *Map_GetWorldspawn( g_map ) )->erase( *region_sides[i] ); - } - Node_getTraversable( GlobalSceneGraph().root() )->erase( *region_startpoint ); +void RemoveRegionBrushes(void) +{ + for (std::size_t i = 0; i < 6; i++) { + Node_getTraversable(*Map_GetWorldspawn(g_map))->erase(*region_sides[i]); + } + Node_getTraversable(GlobalSceneGraph().root())->erase(*region_startpoint); } -inline void exclude_node( scene::Node& node, bool exclude ){ - exclude - ? node.enable( scene::Node::eExcluded ) - : node.disable( scene::Node::eExcluded ); +inline void exclude_node(scene::Node &node, bool exclude) +{ + exclude + ? node.enable(scene::Node::eExcluded) + : node.disable(scene::Node::eExcluded); } -class ExcludeAllWalker : public scene::Graph::Walker -{ -bool m_exclude; +class ExcludeAllWalker : public scene::Graph::Walker { + bool m_exclude; public: -ExcludeAllWalker( bool exclude ) - : m_exclude( exclude ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - exclude_node( path.top(), m_exclude ); + ExcludeAllWalker(bool exclude) + : m_exclude(exclude) + { + } - return true; -} + bool pre(const scene::Path &path, scene::Instance &instance) const + { + exclude_node(path.top(), m_exclude); + + return true; + } }; -void Scene_Exclude_All( bool exclude ){ - GlobalSceneGraph().traverse( ExcludeAllWalker( exclude ) ); +void Scene_Exclude_All(bool exclude) +{ + GlobalSceneGraph().traverse(ExcludeAllWalker(exclude)); } -bool Instance_isSelected( const scene::Instance& instance ){ - const Selectable* selectable = Instance_getSelectable( instance ); - return selectable != 0 && selectable->isSelected(); +bool Instance_isSelected(const scene::Instance &instance) +{ + const Selectable *selectable = Instance_getSelectable(instance); + return selectable != 0 && selectable->isSelected(); } -class ExcludeSelectedWalker : public scene::Graph::Walker -{ -bool m_exclude; +class ExcludeSelectedWalker : public scene::Graph::Walker { + bool m_exclude; public: -ExcludeSelectedWalker( bool exclude ) - : m_exclude( exclude ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - exclude_node( path.top(), ( instance.isSelected() || instance.childSelected() || instance.parentSelected() ) == m_exclude ); - return true; -} + ExcludeSelectedWalker(bool exclude) + : m_exclude(exclude) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + exclude_node(path.top(), + (instance.isSelected() || instance.childSelected() || instance.parentSelected()) == m_exclude); + return true; + } }; -void Scene_Exclude_Selected( bool exclude ){ - GlobalSceneGraph().traverse( ExcludeSelectedWalker( exclude ) ); +void Scene_Exclude_Selected(bool exclude) +{ + GlobalSceneGraph().traverse(ExcludeSelectedWalker(exclude)); } -class ExcludeRegionedWalker : public scene::Graph::Walker -{ -bool m_exclude; +class ExcludeRegionedWalker : public scene::Graph::Walker { + bool m_exclude; public: -ExcludeRegionedWalker( bool exclude ) - : m_exclude( exclude ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - exclude_node( - path.top(), - !( - ( - aabb_intersects_aabb( - instance.worldAABB(), - aabb_for_minmax( region_mins, region_maxs ) - ) != 0 - ) ^ m_exclude - ) - ); - - return true; -} + ExcludeRegionedWalker(bool exclude) + : m_exclude(exclude) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + exclude_node( + path.top(), + !( + ( + aabb_intersects_aabb( + instance.worldAABB(), + aabb_for_minmax(region_mins, region_maxs) + ) != 0 + ) ^ m_exclude + ) + ); + + return true; + } }; -void Scene_Exclude_Region( bool exclude ){ - GlobalSceneGraph().traverse( ExcludeRegionedWalker( exclude ) ); +void Scene_Exclude_Region(bool exclude) +{ + GlobalSceneGraph().traverse(ExcludeRegionedWalker(exclude)); } /* @@ -1393,23 +1500,25 @@ void Scene_Exclude_Region( bool exclude ){ Other filtering options may still be on =========== */ -void Map_RegionOff(){ - region_active = false; +void Map_RegionOff() +{ + region_active = false; - region_maxs[0] = g_MaxWorldCoord - 64; - region_mins[0] = g_MinWorldCoord + 64; - region_maxs[1] = g_MaxWorldCoord - 64; - region_mins[1] = g_MinWorldCoord + 64; - region_maxs[2] = g_MaxWorldCoord - 64; - region_mins[2] = g_MinWorldCoord + 64; + region_maxs[0] = g_MaxWorldCoord - 64; + region_mins[0] = g_MinWorldCoord + 64; + region_maxs[1] = g_MaxWorldCoord - 64; + region_mins[1] = g_MinWorldCoord + 64; + region_maxs[2] = g_MaxWorldCoord - 64; + region_mins[2] = g_MinWorldCoord + 64; - Scene_Exclude_All( false ); + Scene_Exclude_All(false); } -void Map_ApplyRegion( void ){ - region_active = true; +void Map_ApplyRegion(void) +{ + region_active = true; - Scene_Exclude_Region( false ); + Scene_Exclude_Region(false); } @@ -1418,18 +1527,19 @@ void Map_ApplyRegion( void ){ Map_RegionSelectedBrushes ======================== */ -void Map_RegionSelectedBrushes( void ){ - Map_RegionOff(); +void Map_RegionSelectedBrushes(void) +{ + Map_RegionOff(); - if ( GlobalSelectionSystem().countSelected() != 0 - && GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) { - region_active = true; - Select_GetBounds( region_mins, region_maxs ); + if (GlobalSelectionSystem().countSelected() != 0 + && GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) { + region_active = true; + Select_GetBounds(region_mins, region_maxs); - Scene_Exclude_Selected( false ); + Scene_Exclude_Selected(false); - GlobalSelectionSystem().setSelectedAll( false ); - } + GlobalSelectionSystem().setSelectedAll(false); + } } @@ -1438,28 +1548,30 @@ void Map_RegionSelectedBrushes( void ){ Map_RegionXY =========== */ -void Map_RegionXY( float x_min, float y_min, float x_max, float y_max ){ - Map_RegionOff(); +void Map_RegionXY(float x_min, float y_min, float x_max, float y_max) +{ + Map_RegionOff(); - region_mins[0] = x_min; - region_maxs[0] = x_max; - region_mins[1] = y_min; - region_maxs[1] = y_max; - region_mins[2] = g_MinWorldCoord + 64; - region_maxs[2] = g_MaxWorldCoord - 64; + region_mins[0] = x_min; + region_maxs[0] = x_max; + region_mins[1] = y_min; + region_maxs[1] = y_max; + region_mins[2] = g_MinWorldCoord + 64; + region_maxs[2] = g_MaxWorldCoord - 64; - Map_ApplyRegion(); + Map_ApplyRegion(); } -void Map_RegionBounds( const AABB& bounds ){ - Map_RegionOff(); +void Map_RegionBounds(const AABB &bounds) +{ + Map_RegionOff(); - region_mins = vector3_subtracted( bounds.origin, bounds.extents ); - region_maxs = vector3_added( bounds.origin, bounds.extents ); + region_mins = vector3_subtracted(bounds.origin, bounds.extents); + region_maxs = vector3_added(bounds.origin, bounds.extents); - deleteSelection(); + deleteSelection(); - Map_ApplyRegion(); + Map_ApplyRegion(); } /* @@ -1467,11 +1579,12 @@ void Map_RegionBounds( const AABB& bounds ){ Map_RegionBrush =========== */ -void Map_RegionBrush( void ){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); - Map_RegionBounds( instance.worldAABB() ); - } +void Map_RegionBrush(void) +{ + if (GlobalSelectionSystem().countSelected() != 0) { + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); + Map_RegionBounds(instance.worldAABB()); + } } // @@ -1479,125 +1592,127 @@ void Map_RegionBrush( void ){ //Map_ImportFile //================ // -bool Map_ImportFile( const char* filename ){ - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Map" ); - - g_strLastFolder = g_path_get_dirname( filename ); - - bool success = false; - - if ( extension_equal( path_get_extension( filename ), "bsp" ) ) { - goto tryDecompile; - } - - { - const MapFormat* format = NULL; - const char* moduleName = findModuleName( &GlobalFiletypes(), MapFormat::Name(), path_get_extension( filename ) ); - if ( string_not_empty( moduleName ) ) { - format = ReferenceAPI_getMapModules().findModule( moduleName ); - } - - if ( format ) { - format->wrongFormat = false; - } - Resource* resource = GlobalReferenceCache().capture( filename ); - resource->refresh(); // avoid loading old version if map has changed on disk since last import - if ( !resource->load() ) { - GlobalReferenceCache().release( filename ); - goto tryDecompile; - } - if ( format ) { - if ( format->wrongFormat ) { - GlobalReferenceCache().release( filename ); - goto tryDecompile; - } - } - NodeSmartReference clone( NewMapRoot( "" ) ); - Node_getTraversable( *resource->getNode() )->traverse( CloneAll( clone ) ); - Map_gatherNamespaced( clone ); - Map_mergeClonedNames(); - MergeMap( clone ); - success = true; - GlobalReferenceCache().release( filename ); - } - - SceneChangeNotify(); - - return success; - -tryDecompile: - - const char *type = GlobalRadiant().getRequiredGameDescriptionKeyValue( "q3map2_type" ); - int n = string_length( path_get_extension( filename ) ); - if ( n && ( extension_equal( path_get_extension( filename ), "bsp" ) || extension_equal( path_get_extension( filename ), "map" ) ) ) { - StringBuffer output; - output.push_string( AppPath_get() ); - output.push_string( "q3map2." ); - output.push_string( RADIANT_EXECUTABLE ); - output.push_string( " -v -game " ); - output.push_string( ( type && *type ) ? type : "quake3" ); - output.push_string( " -fs_basepath \"" ); - output.push_string( EnginePath_get() ); - output.push_string( "\" -fs_homepath \"" ); - output.push_string( g_qeglobals.m_userEnginePath.c_str() ); - output.push_string( "\"" ); - - // extra pakpaths - for ( int i = 0; i < g_pakPathCount; i++ ) { - if ( g_strcmp0( g_strPakPath[i].c_str(), "") ) { - output.push_string( " -fs_pakpath \"" ); - output.push_string( g_strPakPath[i].c_str() ); - output.push_string( "\"" ); - } - } - - // extra switches - if ( g_disableEnginePath ) { - output.push_string( " -fs_nobasepath " ); - } - - if ( g_disableHomePath ) { - output.push_string( " -fs_nohomepath " ); - } - - output.push_string( " -fs_game " ); - output.push_string( gamename_get() ); - output.push_string( " -convert -format " ); - output.push_string( Brush::m_type == eBrushTypeQuake3BP ? "map_bp" : "map" ); - if ( extension_equal( path_get_extension( filename ), "map" ) ) { - output.push_string( " -readmap " ); - } - output.push_string( " \"" ); - output.push_string( filename ); - output.push_string( "\"" ); - - // run - Q_Exec( NULL, output.c_str(), NULL, false, true ); - - // rebuild filename as "filenamewithoutext_converted.map" - output.clear(); - output.push_range( filename, filename + string_length( filename ) - ( n + 1 ) ); - output.push_string( "_converted.map" ); - filename = output.c_str(); - - // open - Resource* resource = GlobalReferenceCache().capture( filename ); - resource->refresh(); // avoid loading old version if map has changed on disk since last import - if ( !resource->load() ) { - GlobalReferenceCache().release( filename ); - goto tryDecompile; - } - NodeSmartReference clone( NewMapRoot( "" ) ); - Node_getTraversable( *resource->getNode() )->traverse( CloneAll( clone ) ); - Map_gatherNamespaced( clone ); - Map_mergeClonedNames(); - MergeMap( clone ); - success = true; - GlobalReferenceCache().release( filename ); - } - - SceneChangeNotify(); - return success; +bool Map_ImportFile(const char *filename) +{ + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Loading Map"); + + g_strLastFolder = g_path_get_dirname(filename); + + bool success = false; + + if (extension_equal(path_get_extension(filename), "bsp")) { + goto tryDecompile; + } + + { + const MapFormat *format = NULL; + const char *moduleName = findModuleName(&GlobalFiletypes(), MapFormat::Name(), path_get_extension(filename)); + if (string_not_empty(moduleName)) { + format = ReferenceAPI_getMapModules().findModule(moduleName); + } + + if (format) { + format->wrongFormat = false; + } + Resource *resource = GlobalReferenceCache().capture(filename); + resource->refresh(); // avoid loading old version if map has changed on disk since last import + if (!resource->load()) { + GlobalReferenceCache().release(filename); + goto tryDecompile; + } + if (format) { + if (format->wrongFormat) { + GlobalReferenceCache().release(filename); + goto tryDecompile; + } + } + NodeSmartReference clone(NewMapRoot("")); + Node_getTraversable(*resource->getNode())->traverse(CloneAll(clone)); + Map_gatherNamespaced(clone); + Map_mergeClonedNames(); + MergeMap(clone); + success = true; + GlobalReferenceCache().release(filename); + } + + SceneChangeNotify(); + + return success; + + tryDecompile: + + const char *type = GlobalRadiant().getRequiredGameDescriptionKeyValue("q3map2_type"); + int n = string_length(path_get_extension(filename)); + if (n && (extension_equal(path_get_extension(filename), "bsp") || + extension_equal(path_get_extension(filename), "map"))) { + StringBuffer output; + output.push_string(AppPath_get()); + output.push_string("q3map2."); + output.push_string(RADIANT_EXECUTABLE); + output.push_string(" -v -game "); + output.push_string((type && *type) ? type : "quake3"); + output.push_string(" -fs_basepath \""); + output.push_string(EnginePath_get()); + output.push_string("\" -fs_homepath \""); + output.push_string(g_qeglobals.m_userEnginePath.c_str()); + output.push_string("\""); + + // extra pakpaths + for (int i = 0; i < g_pakPathCount; i++) { + if (g_strcmp0(g_strPakPath[i].c_str(), "")) { + output.push_string(" -fs_pakpath \""); + output.push_string(g_strPakPath[i].c_str()); + output.push_string("\""); + } + } + + // extra switches + if (g_disableEnginePath) { + output.push_string(" -fs_nobasepath "); + } + + if (g_disableHomePath) { + output.push_string(" -fs_nohomepath "); + } + + output.push_string(" -fs_game "); + output.push_string(gamename_get()); + output.push_string(" -convert -format "); + output.push_string(Brush::m_type == eBrushTypeQuake3BP ? "map_bp" : "map"); + if (extension_equal(path_get_extension(filename), "map")) { + output.push_string(" -readmap "); + } + output.push_string(" \""); + output.push_string(filename); + output.push_string("\""); + + // run + Q_Exec(NULL, output.c_str(), NULL, false, true); + + // rebuild filename as "filenamewithoutext_converted.map" + output.clear(); + output.push_range(filename, filename + string_length(filename) - (n + 1)); + output.push_string("_converted.map"); + filename = output.c_str(); + + // open + Resource *resource = GlobalReferenceCache().capture(filename); + resource->refresh(); // avoid loading old version if map has changed on disk since last import + if (!resource->load()) { + GlobalReferenceCache().release(filename); + goto tryDecompile; + } + NodeSmartReference clone(NewMapRoot("")); + Node_getTraversable(*resource->getNode())->traverse(CloneAll(clone)); + Map_gatherNamespaced(clone); + Map_mergeClonedNames(); + MergeMap(clone); + success = true; + GlobalReferenceCache().release(filename); + } + + SceneChangeNotify(); + return success; } /* @@ -1605,15 +1720,16 @@ tryDecompile: Map_SaveFile =========== */ -bool Map_SaveFile( const char* filename ){ - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Saving Map" ); - bool success = MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse, filename ); - if ( success ) { - // refresh VFS to apply new pak filtering based on mapname - // needed for daemon DPK VFS - VFS_Refresh(); - } - return success; +bool Map_SaveFile(const char *filename) +{ + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Saving Map"); + bool success = MapResource_saveFile(MapFormat_forFile(filename), GlobalSceneGraph().root(), Map_Traverse, filename); + if (success) { + // refresh VFS to apply new pak filtering based on mapname + // needed for daemon DPK VFS + VFS_Refresh(); + } + return success; } // @@ -1623,556 +1739,615 @@ bool Map_SaveFile( const char* filename ){ // // Saves selected world brushes and whole entities with partial/full selections // -bool Map_SaveSelected( const char* filename ){ - return MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse_Selected, filename ); +bool Map_SaveSelected(const char *filename) +{ + return MapResource_saveFile(MapFormat_forFile(filename), GlobalSceneGraph().root(), Map_Traverse_Selected, + filename); } -class ParentSelectedBrushesToEntityWalker : public scene::Graph::Walker +class ParentSelectedBrushesToEntityWalker : public scene::Graph::Walker { + scene::Node &m_parent; +public: + ParentSelectedBrushesToEntityWalker(scene::Node &parent) : m_parent(parent) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get_pointer() != &m_parent + && Node_isPrimitive(path.top())) { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected() + && path.size() > 1) { + return false; + } + } + return true; + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get_pointer() != &m_parent + && Node_isPrimitive(path.top())) { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected() + && path.size() > 1) { + scene::Node &parent = path.parent(); + if (&parent != &m_parent) { + NodeSmartReference node(path.top().get()); + Node_getTraversable(parent)->erase(node); + Node_getTraversable(m_parent)->insert(node); + } + } + } + } +}; + +void Scene_parentSelectedBrushesToEntity(scene::Graph &graph, scene::Node &parent) { -scene::Node& m_parent; + graph.traverse(ParentSelectedBrushesToEntityWalker(parent)); +} + +class CountSelectedBrushes : public scene::Graph::Walker { + std::size_t &m_count; + mutable std::size_t m_depth; public: -ParentSelectedBrushesToEntityWalker( scene::Node& parent ) : m_parent( parent ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get_pointer() != &m_parent - && Node_isPrimitive( path.top() ) ) { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() - && path.size() > 1 ) { - return false; - } - } - return true; -} -void post( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get_pointer() != &m_parent - && Node_isPrimitive( path.top() ) ) { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() - && path.size() > 1 ) { - scene::Node& parent = path.parent(); - if ( &parent != &m_parent ) { - NodeSmartReference node( path.top().get() ); - Node_getTraversable( parent )->erase( node ); - Node_getTraversable( m_parent )->insert( node ); - } - } - } + CountSelectedBrushes(std::size_t &count) : m_count(count), m_depth(0) + { + m_count = 0; + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (++m_depth != 1 && path.top().get().isRoot()) { + return false; + } + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected() + && Node_isPrimitive(path.top())) { + ++m_count; + } + return true; + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + --m_depth; + } +}; + +std::size_t Scene_countSelectedBrushes(scene::Graph &graph) +{ + std::size_t count; + graph.traverse(CountSelectedBrushes(count)); + return count; } + +enum ENodeType { + eNodeUnknown, + eNodeMap, + eNodeEntity, + eNodePrimitive, }; -void Scene_parentSelectedBrushesToEntity( scene::Graph& graph, scene::Node& parent ){ - graph.traverse( ParentSelectedBrushesToEntityWalker( parent ) ); +const char *nodetype_get_name(ENodeType type) +{ + if (type == eNodeMap) { + return "map"; + } + if (type == eNodeEntity) { + return "entity"; + } + if (type == eNodePrimitive) { + return "primitive"; + } + return "unknown"; +} + +ENodeType node_get_nodetype(scene::Node &node) +{ + if (Node_isEntity(node)) { + return eNodeEntity; + } + if (Node_isPrimitive(node)) { + return eNodePrimitive; + } + return eNodeUnknown; } -class CountSelectedBrushes : public scene::Graph::Walker +bool contains_entity(scene::Node &node) { -std::size_t& m_count; -mutable std::size_t m_depth; -public: -CountSelectedBrushes( std::size_t& count ) : m_count( count ), m_depth( 0 ){ - m_count = 0; -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( ++m_depth != 1 && path.top().get().isRoot() ) { - return false; - } - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() - && Node_isPrimitive( path.top() ) ) { - ++m_count; - } - return true; -} -void post( const scene::Path& path, scene::Instance& instance ) const { - --m_depth; + return Node_getTraversable(node) != 0 && !Node_isBrush(node) && !Node_isPatch(node) && !Node_isEntity(node); } -}; -std::size_t Scene_countSelectedBrushes( scene::Graph& graph ){ - std::size_t count; - graph.traverse( CountSelectedBrushes( count ) ); - return count; +bool contains_primitive(scene::Node &node) +{ + return Node_isEntity(node) && Node_getTraversable(node) != 0 && Node_getEntity(node)->isContainer(); } -enum ENodeType +ENodeType node_get_contains(scene::Node &node) { - eNodeUnknown, - eNodeMap, - eNodeEntity, - eNodePrimitive, -}; + if (contains_entity(node)) { + return eNodeEntity; + } + if (contains_primitive(node)) { + return eNodePrimitive; + } + return eNodeUnknown; +} -const char* nodetype_get_name( ENodeType type ){ - if ( type == eNodeMap ) { - return "map"; - } - if ( type == eNodeEntity ) { - return "entity"; - } - if ( type == eNodePrimitive ) { - return "primitive"; - } - return "unknown"; -} - -ENodeType node_get_nodetype( scene::Node& node ){ - if ( Node_isEntity( node ) ) { - return eNodeEntity; - } - if ( Node_isPrimitive( node ) ) { - return eNodePrimitive; - } - return eNodeUnknown; -} - -bool contains_entity( scene::Node& node ){ - return Node_getTraversable( node ) != 0 && !Node_isBrush( node ) && !Node_isPatch( node ) && !Node_isEntity( node ); -} - -bool contains_primitive( scene::Node& node ){ - return Node_isEntity( node ) && Node_getTraversable( node ) != 0 && Node_getEntity( node )->isContainer(); -} - -ENodeType node_get_contains( scene::Node& node ){ - if ( contains_entity( node ) ) { - return eNodeEntity; - } - if ( contains_primitive( node ) ) { - return eNodePrimitive; - } - return eNodeUnknown; -} - -void Path_parent( const scene::Path& parent, const scene::Path& child ){ - ENodeType contains = node_get_contains( parent.top() ); - ENodeType type = node_get_nodetype( child.top() ); - - if ( contains != eNodeUnknown && contains == type ) { - NodeSmartReference node( child.top().get() ); - Path_deleteTop( child ); - Node_getTraversable( parent.top() )->insert( node ); - SceneChangeNotify(); - } - else - { - globalErrorStream() << "failed - " << nodetype_get_name( type ) << " cannot be parented to " << nodetype_get_name( contains ) << " container.\n"; - } -} - -void Scene_parentSelected(){ - UndoableCommand undo( "parentSelected" ); - - if ( GlobalSelectionSystem().countSelected() > 1 ) { - class ParentSelectedBrushesToEntityWalker : public SelectionSystem::Visitor - { - const scene::Path& m_parent; -public: - ParentSelectedBrushesToEntityWalker( const scene::Path& parent ) : m_parent( parent ){ - } - void visit( scene::Instance& instance ) const { - if ( &m_parent != &instance.path() ) { - Path_parent( m_parent, instance.path() ); - } - } - }; +void Path_parent(const scene::Path &parent, const scene::Path &child) +{ + ENodeType contains = node_get_contains(parent.top()); + ENodeType type = node_get_nodetype(child.top()); - ParentSelectedBrushesToEntityWalker visitor( GlobalSelectionSystem().ultimateSelected().path() ); - GlobalSelectionSystem().foreachSelected( visitor ); - } - else - { - globalOutputStream() << "failed - did not find two selected nodes.\n"; - } + if (contains != eNodeUnknown && contains == type) { + NodeSmartReference node(child.top().get()); + Path_deleteTop(child); + Node_getTraversable(parent.top())->insert(node); + SceneChangeNotify(); + } else { + globalErrorStream() << "failed - " << nodetype_get_name(type) << " cannot be parented to " + << nodetype_get_name(contains) << " container.\n"; + } } +void Scene_parentSelected() +{ + UndoableCommand undo("parentSelected"); + + if (GlobalSelectionSystem().countSelected() > 1) { + class ParentSelectedBrushesToEntityWalker : public SelectionSystem::Visitor { + const scene::Path &m_parent; + public: + ParentSelectedBrushesToEntityWalker(const scene::Path &parent) : m_parent(parent) + { + } + void visit(scene::Instance &instance) const + { + if (&m_parent != &instance.path()) { + Path_parent(m_parent, instance.path()); + } + } + }; -void NewMap(){ - if ( ConfirmModified( "New Map" ) ) { - Map_RegionOff(); - Map_Free(); - Map_New(); - } + ParentSelectedBrushesToEntityWalker visitor(GlobalSelectionSystem().ultimateSelected().path()); + GlobalSelectionSystem().foreachSelected(visitor); + } else { + globalOutputStream() << "failed - did not find two selected nodes.\n"; + } +} + + +void NewMap() +{ + if (ConfirmModified("New Map")) { + Map_RegionOff(); + Map_Free(); + Map_New(); + } } CopiedString g_mapsPath; -const char* getMapsPath(){ - return g_mapsPath.c_str(); +const char *getMapsPath() +{ + return g_mapsPath.c_str(); } -const char* getLastFolderPath(){ - if (g_strLastFolder.empty()) { - GlobalPreferenceSystem().registerPreference( "LastFolder", make_property_string( g_strLastFolder ) ); - if (g_strLastFolder.empty()) { - g_strLastFolder = g_qeglobals.m_userGamePath; - } - } - return g_strLastFolder.c_str(); +const char *getLastFolderPath() +{ + if (g_strLastFolder.empty()) { + GlobalPreferenceSystem().registerPreference("LastFolder", make_property_string(g_strLastFolder)); + if (g_strLastFolder.empty()) { + g_strLastFolder = g_qeglobals.m_userGamePath; + } + } + return g_strLastFolder.c_str(); } -const char* map_open( const char* title ){ - return MainFrame_getWindow().file_dialog( TRUE, title, getLastFolderPath(), MapFormat::Name(), true, false, false ); +const char *map_open(const char *title) +{ + return MainFrame_getWindow().file_dialog(TRUE, title, getLastFolderPath(), MapFormat::Name(), true, false, false); } -const char* map_import( const char* title ){ - return MainFrame_getWindow().file_dialog( TRUE, title, getLastFolderPath(), MapFormat::Name(), false, true, false ); +const char *map_import(const char *title) +{ + return MainFrame_getWindow().file_dialog(TRUE, title, getLastFolderPath(), MapFormat::Name(), false, true, false); } -const char* map_save( const char* title ){ - return MainFrame_getWindow().file_dialog( FALSE, title, getLastFolderPath(), MapFormat::Name(), false, false, true ); +const char *map_save(const char *title) +{ + return MainFrame_getWindow().file_dialog(FALSE, title, getLastFolderPath(), MapFormat::Name(), false, false, true); } -void OpenMap(){ - if ( !ConfirmModified( "Open Map" ) ) { - return; - } +void OpenMap() +{ + if (!ConfirmModified("Open Map")) { + return; + } - const char* filename = map_open( "Open Map" ); + const char *filename = map_open("Open Map"); - if ( filename != NULL ) { - MRU_AddFile( filename ); - Map_RegionOff(); - Map_Free(); - Map_LoadFile( filename ); - } + if (filename != NULL) { + MRU_AddFile(filename); + Map_RegionOff(); + Map_Free(); + Map_LoadFile(filename); + } } -void ImportMap(){ - const char* filename = map_import( "Import Map" ); +void ImportMap() +{ + const char *filename = map_import("Import Map"); - if ( filename != NULL ) { - UndoableCommand undo( "mapImport" ); - Map_ImportFile( filename ); - } + if (filename != NULL) { + UndoableCommand undo("mapImport"); + Map_ImportFile(filename); + } } -bool Map_SaveAs(){ - const char* filename = map_save( "Save Map" ); +bool Map_SaveAs() +{ + const char *filename = map_save("Save Map"); - if ( filename != NULL ) { - g_strLastFolder = g_path_get_dirname( filename ); - MRU_AddFile( filename ); - Map_Rename( filename ); - return Map_Save(); - } - return false; + if (filename != NULL) { + g_strLastFolder = g_path_get_dirname(filename); + MRU_AddFile(filename); + Map_Rename(filename); + return Map_Save(); + } + return false; } -void SaveMapAs(){ - Map_SaveAs(); +void SaveMapAs() +{ + Map_SaveAs(); } -void SaveMap(){ - if ( Map_Unnamed( g_map ) ) { - SaveMapAs(); - } - else if ( Map_Modified( g_map ) ) { - Map_Save(); - } +void SaveMap() +{ + if (Map_Unnamed(g_map)) { + SaveMapAs(); + } else if (Map_Modified(g_map)) { + Map_Save(); + } } -void ExportMap(){ - const char* filename = map_save( "Export Selection" ); +void ExportMap() +{ + const char *filename = map_save("Export Selection"); - if ( filename != NULL ) { - g_strLastFolder = g_path_get_dirname( filename ); - Map_SaveSelected( filename ); - } + if (filename != NULL) { + g_strLastFolder = g_path_get_dirname(filename); + Map_SaveSelected(filename); + } } -void SaveRegion(){ - const char* filename = map_save( "Export Region" ); +void SaveRegion() +{ + const char *filename = map_save("Export Region"); - if ( filename != NULL ) { - g_strLastFolder = g_path_get_dirname( filename ); - Map_SaveRegion( filename ); - } + if (filename != NULL) { + g_strLastFolder = g_path_get_dirname(filename); + Map_SaveRegion(filename); + } } -void RegionOff(){ - Map_RegionOff(); - SceneChangeNotify(); -} - -void RegionXY(){ - Map_RegionXY( - g_pParentWnd->GetXYWnd()->GetOrigin()[0] - 0.5f * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale(), - g_pParentWnd->GetXYWnd()->GetOrigin()[1] - 0.5f * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale(), - g_pParentWnd->GetXYWnd()->GetOrigin()[0] + 0.5f * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale(), - g_pParentWnd->GetXYWnd()->GetOrigin()[1] + 0.5f * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale() - ); - SceneChangeNotify(); +void RegionOff() +{ + Map_RegionOff(); + SceneChangeNotify(); } -void RegionBrush(){ - Map_RegionBrush(); - SceneChangeNotify(); +void RegionXY() +{ + Map_RegionXY( + g_pParentWnd->GetXYWnd()->GetOrigin()[0] - + 0.5f * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale(), + g_pParentWnd->GetXYWnd()->GetOrigin()[1] - + 0.5f * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale(), + g_pParentWnd->GetXYWnd()->GetOrigin()[0] + + 0.5f * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale(), + g_pParentWnd->GetXYWnd()->GetOrigin()[1] + + 0.5f * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale() + ); + SceneChangeNotify(); +} + +void RegionBrush() +{ + Map_RegionBrush(); + SceneChangeNotify(); } -void RegionSelected(){ - Map_RegionSelectedBrushes(); - SceneChangeNotify(); +void RegionSelected() +{ + Map_RegionSelectedBrushes(); + SceneChangeNotify(); } - - - -class BrushFindByIndexWalker : public scene::Traversable::Walker -{ -mutable std::size_t m_index; -scene::Path& m_path; +class BrushFindByIndexWalker : public scene::Traversable::Walker { + mutable std::size_t m_index; + scene::Path &m_path; public: -BrushFindByIndexWalker( std::size_t index, scene::Path& path ) - : m_index( index ), m_path( path ){ -} -bool pre( scene::Node& node ) const { - if ( Node_isPrimitive( node ) && m_index-- == 0 ) { - m_path.push( makeReference( node ) ); - } - return false; -} + BrushFindByIndexWalker(std::size_t index, scene::Path &path) + : m_index(index), m_path(path) + { + } + + bool pre(scene::Node &node) const + { + if (Node_isPrimitive(node) && m_index-- == 0) { + m_path.push(makeReference(node)); + } + return false; + } }; -class EntityFindByIndexWalker : public scene::Traversable::Walker -{ -mutable std::size_t m_index; -scene::Path& m_path; +class EntityFindByIndexWalker : public scene::Traversable::Walker { + mutable std::size_t m_index; + scene::Path &m_path; public: -EntityFindByIndexWalker( std::size_t index, scene::Path& path ) - : m_index( index ), m_path( path ){ -} -bool pre( scene::Node& node ) const { - if ( Node_isEntity( node ) && m_index-- == 0 ) { - m_path.push( makeReference( node ) ); - } - return false; -} + EntityFindByIndexWalker(std::size_t index, scene::Path &path) + : m_index(index), m_path(path) + { + } + + bool pre(scene::Node &node) const + { + if (Node_isEntity(node) && m_index-- == 0) { + m_path.push(makeReference(node)); + } + return false; + } }; -void Scene_FindEntityBrush( std::size_t entity, std::size_t brush, scene::Path& path ){ - path.push( makeReference( GlobalSceneGraph().root() ) ); - { - Node_getTraversable( path.top() )->traverse( EntityFindByIndexWalker( entity, path ) ); - } - if ( path.size() == 2 ) { - scene::Traversable* traversable = Node_getTraversable( path.top() ); - if ( traversable != 0 ) { - traversable->traverse( BrushFindByIndexWalker( brush, path ) ); - } - } -} - -inline bool Node_hasChildren( scene::Node& node ){ - scene::Traversable* traversable = Node_getTraversable( node ); - return traversable != 0 && !traversable->empty(); -} - -void SelectBrush( int entitynum, int brushnum ){ - scene::Path path; - Scene_FindEntityBrush( entitynum, brushnum, path ); - if ( path.size() == 3 || ( path.size() == 2 && !Node_hasChildren( path.top() ) ) ) { - scene::Instance* instance = GlobalSceneGraph().find( path ); - ASSERT_MESSAGE( instance != 0, "SelectBrush: path not found in scenegraph" ); - Selectable* selectable = Instance_getSelectable( *instance ); - ASSERT_MESSAGE( selectable != 0, "SelectBrush: path not selectable" ); - selectable->setSelected( true ); - g_pParentWnd->GetXYWnd()->PositionView( instance->worldAABB().origin ); - } +void Scene_FindEntityBrush(std::size_t entity, std::size_t brush, scene::Path &path) +{ + path.push(makeReference(GlobalSceneGraph().root())); + { + Node_getTraversable(path.top())->traverse(EntityFindByIndexWalker(entity, path)); + } + if (path.size() == 2) { + scene::Traversable *traversable = Node_getTraversable(path.top()); + if (traversable != 0) { + traversable->traverse(BrushFindByIndexWalker(brush, path)); + } + } +} + +inline bool Node_hasChildren(scene::Node &node) +{ + scene::Traversable *traversable = Node_getTraversable(node); + return traversable != 0 && !traversable->empty(); } - -class BrushFindIndexWalker : public scene::Graph::Walker +void SelectBrush(int entitynum, int brushnum) { -mutable const scene::Node* m_node; -std::size_t& m_count; + scene::Path path; + Scene_FindEntityBrush(entitynum, brushnum, path); + if (path.size() == 3 || (path.size() == 2 && !Node_hasChildren(path.top()))) { + scene::Instance *instance = GlobalSceneGraph().find(path); + ASSERT_MESSAGE(instance != 0, "SelectBrush: path not found in scenegraph"); + Selectable *selectable = Instance_getSelectable(*instance); + ASSERT_MESSAGE(selectable != 0, "SelectBrush: path not selectable"); + selectable->setSelected(true); + g_pParentWnd->GetXYWnd()->PositionView(instance->worldAABB().origin); + } +} + + +class BrushFindIndexWalker : public scene::Graph::Walker { + mutable const scene::Node *m_node; + std::size_t &m_count; public: -BrushFindIndexWalker( const scene::Node& node, std::size_t& count ) - : m_node( &node ), m_count( count ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( Node_isPrimitive( path.top() ) ) { - if ( m_node == path.top().get_pointer() ) { - m_node = 0; - } - if ( m_node ) { - ++m_count; - } - } - return true; -} + BrushFindIndexWalker(const scene::Node &node, std::size_t &count) + : m_node(&node), m_count(count) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (Node_isPrimitive(path.top())) { + if (m_node == path.top().get_pointer()) { + m_node = 0; + } + if (m_node) { + ++m_count; + } + } + return true; + } }; -class EntityFindIndexWalker : public scene::Graph::Walker -{ -mutable const scene::Node* m_node; -std::size_t& m_count; +class EntityFindIndexWalker : public scene::Graph::Walker { + mutable const scene::Node *m_node; + std::size_t &m_count; public: -EntityFindIndexWalker( const scene::Node& node, std::size_t& count ) - : m_node( &node ), m_count( count ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( Node_isEntity( path.top() ) ) { - if ( m_node == path.top().get_pointer() ) { - m_node = 0; - } - if ( m_node ) { - ++m_count; - } - } - return true; -} + EntityFindIndexWalker(const scene::Node &node, std::size_t &count) + : m_node(&node), m_count(count) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (Node_isEntity(path.top())) { + if (m_node == path.top().get_pointer()) { + m_node = 0; + } + if (m_node) { + ++m_count; + } + } + return true; + } }; -static void GetSelectionIndex( int *ent, int *brush ){ - std::size_t count_brush = 0; - std::size_t count_entity = 0; - if ( GlobalSelectionSystem().countSelected() != 0 ) { - const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path(); - - GlobalSceneGraph().traverse( BrushFindIndexWalker( path.top(), count_brush ) ); - GlobalSceneGraph().traverse( EntityFindIndexWalker( path.parent(), count_entity ) ); - } - *brush = int(count_brush); - *ent = int(count_entity); -} - -void DoFind(){ - ModalDialog dialog; - ui::Entry entity{ui::null}; - ui::Entry brush{ui::null}; - - ui::Window window = MainFrame_getWindow().create_dialog_window("Find Brush", G_CALLBACK(dialog_delete_callback ), &dialog ); - - auto accel = ui::AccelGroup(ui::New); - window.add_accel_group( accel ); - - { - auto vbox = create_dialog_vbox( 4, 4 ); - window.add(vbox); - { - auto table = create_dialog_table( 2, 2, 4, 4 ); - vbox.pack_start( table, TRUE, TRUE, 0 ); - { - ui::Widget label = ui::Label( "Entity number" ); - label.show(); +static void GetSelectionIndex(int *ent, int *brush) +{ + std::size_t count_brush = 0; + std::size_t count_entity = 0; + if (GlobalSelectionSystem().countSelected() != 0) { + const scene::Path &path = GlobalSelectionSystem().ultimateSelected().path(); + + GlobalSceneGraph().traverse(BrushFindIndexWalker(path.top(), count_brush)); + GlobalSceneGraph().traverse(EntityFindIndexWalker(path.parent(), count_entity)); + } + *brush = int(count_brush); + *ent = int(count_entity); +} + +void DoFind() +{ + ModalDialog dialog; + ui::Entry entity{ui::null}; + ui::Entry brush{ui::null}; + + ui::Window window = MainFrame_getWindow().create_dialog_window("Find Brush", G_CALLBACK(dialog_delete_callback), + &dialog); + + auto accel = ui::AccelGroup(ui::New); + window.add_accel_group(accel); + + { + auto vbox = create_dialog_vbox(4, 4); + window.add(vbox); + { + auto table = create_dialog_table(2, 2, 4, 4); + vbox.pack_start(table, TRUE, TRUE, 0); + { + ui::Widget label = ui::Label("Entity number"); + label.show(); (table).attach(label, {0, 1, 0, 1}, {0, 0}); - } - { - ui::Widget label = ui::Label( "Brush number" ); - label.show(); + } + { + ui::Widget label = ui::Label("Brush number"); + label.show(); (table).attach(label, {0, 1, 1, 2}, {0, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_widget_grab_focus( entry ); - entity = entry; - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + gtk_widget_grab_focus(entry); + entity = entry; + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - brush = entry; - } - } - { - auto hbox = create_dialog_hbox( 4 ); - vbox.pack_start( hbox, TRUE, TRUE, 0 ); - { - auto button = create_dialog_button( "Find", G_CALLBACK( dialog_button_ok ), &dialog ); - hbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - { - auto button = create_dialog_button( "Close", G_CALLBACK( dialog_button_cancel ), &dialog ); - hbox.pack_start( button, FALSE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - } - } - - // Initialize dialog - char buf[16]; - int ent, br; - - GetSelectionIndex( &ent, &br ); - sprintf( buf, "%i", ent ); - entity.text(buf); - sprintf( buf, "%i", br ); - brush.text(buf); - - if ( modal_dialog_show( window, dialog ) == eIDOK ) { - const char *entstr = gtk_entry_get_text( entity ); - const char *brushstr = gtk_entry_get_text( brush ); - SelectBrush( atoi( entstr ), atoi( brushstr ) ); - } + brush = entry; + } + } + { + auto hbox = create_dialog_hbox(4); + vbox.pack_start(hbox, TRUE, TRUE, 0); + { + auto button = create_dialog_button("Find", G_CALLBACK(dialog_button_ok), &dialog); + hbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + { + auto button = create_dialog_button("Close", G_CALLBACK(dialog_button_cancel), &dialog); + hbox.pack_start(button, FALSE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + } + } + + // Initialize dialog + char buf[16]; + int ent, br; + + GetSelectionIndex(&ent, &br); + sprintf(buf, "%i", ent); + entity.text(buf); + sprintf(buf, "%i", br); + brush.text(buf); + + if (modal_dialog_show(window, dialog) == eIDOK) { + const char *entstr = gtk_entry_get_text(entity); + const char *brushstr = gtk_entry_get_text(brush); + SelectBrush(atoi(entstr), atoi(brushstr)); + } window.destroy(); } -void Map_constructPreferences( PreferencesPage& page ){ - page.appendCheckBox( "", "Load last map on open", g_bLoadLastMap ); +void Map_constructPreferences(PreferencesPage &page) +{ + page.appendCheckBox("", "Load last map on open", g_bLoadLastMap); } -class MapEntityClasses : public ModuleObserver -{ -std::size_t m_unrealised; +class MapEntityClasses : public ModuleObserver { + std::size_t m_unrealised; public: -MapEntityClasses() : m_unrealised( 1 ){ -} -void realise(){ - if ( --m_unrealised == 0 ) { - if ( g_map.m_resource != 0 ) { - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Map" ); - g_map.m_resource->realise(); - } - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - if ( g_map.m_resource != 0 ) { - g_map.m_resource->flush(); - g_map.m_resource->unrealise(); - } - } -} + MapEntityClasses() : m_unrealised(1) + { + } + + void realise() + { + if (--m_unrealised == 0) { + if (g_map.m_resource != 0) { + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Loading Map"); + g_map.m_resource->realise(); + } + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + if (g_map.m_resource != 0) { + g_map.m_resource->flush(); + g_map.m_resource->unrealise(); + } + } + } }; MapEntityClasses g_MapEntityClasses; -class MapModuleObserver : public ModuleObserver -{ -std::size_t m_unrealised; +class MapModuleObserver : public ModuleObserver { + std::size_t m_unrealised; public: -MapModuleObserver() : m_unrealised( 1 ){ -} -void realise(){ - if ( --m_unrealised == 0 ) { - ASSERT_MESSAGE( !string_empty( g_qeglobals.m_userGamePath.c_str() ), "maps_directory: user-game-path is empty" ); - StringOutputStream buffer( 256 ); - buffer << g_qeglobals.m_userGamePath.c_str() << "maps/"; - Q_mkdir( buffer.c_str() ); - g_mapsPath = buffer.c_str(); - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - g_mapsPath = ""; - } -} + MapModuleObserver() : m_unrealised(1) + { + } + + void realise() + { + if (--m_unrealised == 0) { + ASSERT_MESSAGE(!string_empty(g_qeglobals.m_userGamePath.c_str()), + "maps_directory: user-game-path is empty"); + StringOutputStream buffer(256); + buffer << g_qeglobals.m_userGamePath.c_str() << "maps/"; + Q_mkdir(buffer.c_str()); + g_mapsPath = buffer.c_str(); + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + g_mapsPath = ""; + } + } }; MapModuleObserver g_MapModuleObserver; @@ -2180,23 +2355,26 @@ MapModuleObserver g_MapModuleObserver; CopiedString g_strLastMap; bool g_bLoadLastMap = false; -void Map_Construct(){ - GlobalCommands_insert( "RegionOff", makeCallbackF(RegionOff) ); - GlobalCommands_insert( "RegionSetXY", makeCallbackF(RegionXY) ); - GlobalCommands_insert( "RegionSetBrush", makeCallbackF(RegionBrush) ); - GlobalCommands_insert( "RegionSetSelection", makeCallbackF(RegionSelected), Accelerator( 'R', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); +void Map_Construct() +{ + GlobalCommands_insert("RegionOff", makeCallbackF(RegionOff)); + GlobalCommands_insert("RegionSetXY", makeCallbackF(RegionXY)); + GlobalCommands_insert("RegionSetBrush", makeCallbackF(RegionBrush)); + GlobalCommands_insert("RegionSetSelection", makeCallbackF(RegionSelected), + Accelerator('R', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); - GlobalPreferenceSystem().registerPreference( "LastMap", make_property_string( g_strLastMap ) ); - GlobalPreferenceSystem().registerPreference( "LoadLastMap", make_property_string( g_bLoadLastMap ) ); - GlobalPreferenceSystem().registerPreference( "MapInfoDlg", make_property( g_posMapInfoWnd ) ); + GlobalPreferenceSystem().registerPreference("LastMap", make_property_string(g_strLastMap)); + GlobalPreferenceSystem().registerPreference("LoadLastMap", make_property_string(g_bLoadLastMap)); + GlobalPreferenceSystem().registerPreference("MapInfoDlg", make_property(g_posMapInfoWnd)); - PreferencesDialog_addSettingsPreferences( makeCallbackF(Map_constructPreferences) ); + PreferencesDialog_addSettingsPreferences(makeCallbackF(Map_constructPreferences)); - GlobalEntityClassManager().attach( g_MapEntityClasses ); - Radiant_attachHomePathsObserver( g_MapModuleObserver ); + GlobalEntityClassManager().attach(g_MapEntityClasses); + Radiant_attachHomePathsObserver(g_MapModuleObserver); } -void Map_Destroy(){ - Radiant_detachHomePathsObserver( g_MapModuleObserver ); - GlobalEntityClassManager().detach( g_MapEntityClasses ); +void Map_Destroy() +{ + Radiant_detachHomePathsObserver(g_MapModuleObserver); + GlobalEntityClassManager().detach(g_MapEntityClasses); } diff --git a/radiant/map.h b/radiant/map.h index c68b0275..62b48047 100644 --- a/radiant/map.h +++ b/radiant/map.h @@ -28,71 +28,82 @@ #include "string/stringfwd.h" class Map; + extern Map g_map; class MapFormat; -void Map_addValidCallback( Map& map, const SignalHandler& handler ); -bool Map_Valid( const Map& map ); +void Map_addValidCallback(Map &map, const SignalHandler &handler); -class DeferredDraw -{ -Callback m_draw; -bool m_defer; -bool m_deferred; +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; -} + 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(); - } +inline void DeferredDraw_onMapValidChanged(DeferredDraw &self) +{ + if (Map_Valid(g_map)) { + self.flush(); + } else { + self.defer(); + } } + typedef ReferenceCaller DeferredDrawOnMapValidChangedCaller; +const char *Map_Name(const Map &map); -const char* Map_Name( const Map& map ); -const MapFormat& Map_getFormat( const Map& map ); -bool Map_Unnamed( const Map& map ); +const MapFormat &Map_getFormat(const Map &map); +bool Map_Unnamed(const Map &map); -namespace scene -{ -class Node; -class Graph; + +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 ); +scene::Node *Map_GetWorldspawn(const Map &map); + +scene::Node *Map_FindWorldspawn(Map &map); + +scene::Node &Map_FindOrInsertWorldspawn(Map &map); + +template +class BasicVector3; -template class BasicVector3; typedef BasicVector3 Vector3; extern Vector3 region_mins, region_maxs; @@ -102,64 +113,79 @@ extern bool region_active; extern float g_MaxWorldCoord; extern float g_MinWorldCoord; -void Map_LoadFile( const char* filename ); -bool Map_SaveFile( const char* filename ); +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 ); +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 ); +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_Modified(const Map &map); + +void Map_SetModified(Map &map, bool modified); bool Map_Save(); + bool Map_SaveAs(); -scene::Node& Node_Clone( scene::Node& node ); +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_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 Map_Traverse(scene::Node &root, const scene::Traversable::Walker &walker); -void SelectBrush( int entitynum, int brushnum ); +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_gatherNamespaced(scene::Node &root); + void Map_mergeClonedNames(); -const char* getMapsPath(); +const char *getMapsPath(); #endif diff --git a/radiant/mru.cpp b/radiant/mru.cpp index 37fd9a17..bcfbdf28 100644 --- a/radiant/mru.cpp +++ b/radiant/mru.cpp @@ -36,197 +36,213 @@ const int 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" }; + 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(); +inline const char *MRU_GetText(std::size_t index) +{ + return MRU_filenames[index].c_str(); } -class EscapedMnemonic -{ -StringBuffer m_buffer; +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; -} + 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 -inline EscapedMnemonic& operator<<( EscapedMnemonic& ostream, const T& t ){ - return ostream_write( ostream, 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 << Unsigned( index + 1 ) << "- " << filename; - gtk_label_set_text_with_mnemonic( GTK_LABEL( gtk_bin_get_child( GTK_BIN( MRU_items[index] ) ) ), mnemonic.c_str() ); +void MRU_updateWidget(std::size_t index, const char *filename) +{ + EscapedMnemonic mnemonic(64); + mnemonic << Unsigned(index + 1) << "- " << 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_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 ); +void MRU_AddFile(const char *str) +{ + std::size_t i; + const char *text; - if ( strcmp( text, str ) == 0 ) { - // reorder menu - for (; i > 0; i-- ) - MRU_SetText( i, MRU_GetText( i - 1 ) ); + // check if file is already in our list + for (i = 0; i < MRU_used; i++) { + text = MRU_GetText(i); - MRU_SetText( 0, str ); + if (strcmp(text, str) == 0) { + // reorder menu + for (; i > 0; i--) { + MRU_SetText(i, MRU_GetText(i - 1)); + } - return; - } - } + MRU_SetText(0, str); - if ( MRU_used < MRU_MAX ) { - MRU_used++; - } + return; + } + } - // move items down - for ( i = MRU_used - 1; i > 0; i-- ) - MRU_SetText( i, MRU_GetText( i - 1 ) ); + if (MRU_used < MRU_MAX) { + MRU_used++; + } - MRU_SetText( 0, str ); - gtk_widget_set_sensitive( ui::MenuItem::from(MRU_items[0]) , TRUE ); - ui::MenuItem::from(MRU_items[MRU_used - 1] ).show(); -} + // move items down + for (i = MRU_used - 1; i > 0; i--) { + MRU_SetText(i, MRU_GetText(i - 1)); + } -void MRU_Init(){ - if ( MRU_used > MRU_MAX ) { - MRU_used = MRU_MAX; - } + MRU_SetText(0, str); + gtk_widget_set_sensitive(ui::MenuItem::from(MRU_items[0]), TRUE); + ui::MenuItem::from(MRU_items[MRU_used - 1]).show(); } -void MRU_AddWidget( ui::MenuItem 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( ui::MenuItem::from(MRU_items[0]) , TRUE ); - ui::MenuItem::from(MRU_items[pos]).show(); - } - } +void MRU_Init() +{ + if (MRU_used > MRU_MAX) { + MRU_used = MRU_MAX; + } } -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 ) { - auto label = ui::Label::from(gtk_bin_get_child(GTK_BIN(MRU_items[0] )) ); - label.text("Recent Files"); - gtk_widget_set_sensitive( ui::MenuItem::from(MRU_items[0]), FALSE ); - } - else - { - ui::MenuItem::from(MRU_items[MRU_used]).hide(); - } - } +void MRU_AddWidget(ui::MenuItem 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(ui::MenuItem::from(MRU_items[0]), TRUE); + ui::MenuItem::from(MRU_items[pos]).show(); + } + } } - -class LoadMRU +void MRU_Activate(std::size_t index) { -std::size_t m_number; + 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) { + auto label = ui::Label::from(gtk_bin_get_child(GTK_BIN(MRU_items[0]))); + label.text("Recent Files"); + gtk_widget_set_sensitive(ui::MenuItem::from(MRU_items[0]), FALSE); + } else { + ui::MenuItem::from(MRU_items[MRU_used]).hide(); + } + } +} + + +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 ); - } -} + LoadMRU(std::size_t number) + : m_number(number) + { + } + + void load() + { + if (ConfirmModified("Open Map")) { + MRU_Activate(m_number - 1); + } + } }; typedef MemberCaller LoadMRUCaller; -LoadMRU g_load_mru1( 1 ); -LoadMRU g_load_mru2( 2 ); -LoadMRU g_load_mru3( 3 ); -LoadMRU g_load_mru4( 4 ); - -void MRU_constructMenu( ui::Menu menu ){ - { - auto item = create_menu_item_with_mnemonic( menu, "_1", LoadMRUCaller( g_load_mru1 ) ); - gtk_widget_set_sensitive( item , FALSE ); - MRU_AddWidget( item, 0 ); - } - { - auto item = create_menu_item_with_mnemonic( menu, "_2", LoadMRUCaller( g_load_mru2 ) ); - item.hide(); - MRU_AddWidget( item, 1 ); - } - { - auto item = create_menu_item_with_mnemonic( menu, "_3", LoadMRUCaller( g_load_mru3 ) ); - item.hide(); - MRU_AddWidget( item, 2 ); - } - { - auto item = create_menu_item_with_mnemonic( menu, "_4", LoadMRUCaller( g_load_mru4 ) ); - item.hide(); - MRU_AddWidget( item, 3 ); - } +LoadMRU g_load_mru1(1); +LoadMRU g_load_mru2(2); +LoadMRU g_load_mru3(3); +LoadMRU g_load_mru4(4); + +void MRU_constructMenu(ui::Menu menu) +{ + { + auto item = create_menu_item_with_mnemonic(menu, "_1", LoadMRUCaller(g_load_mru1)); + gtk_widget_set_sensitive(item, FALSE); + MRU_AddWidget(item, 0); + } + { + auto item = create_menu_item_with_mnemonic(menu, "_2", LoadMRUCaller(g_load_mru2)); + item.hide(); + MRU_AddWidget(item, 1); + } + { + auto item = create_menu_item_with_mnemonic(menu, "_3", LoadMRUCaller(g_load_mru3)); + item.hide(); + MRU_AddWidget(item, 2); + } + { + auto item = create_menu_item_with_mnemonic(menu, "_4", LoadMRUCaller(g_load_mru4)); + item.hide(); + MRU_AddWidget(item, 3); + } } #include "preferencesystem.h" #include "stringio.h" -void MRU_Construct(){ - GlobalPreferenceSystem().registerPreference( "Count", make_property_string( MRU_used ) ); +void MRU_Construct() +{ + GlobalPreferenceSystem().registerPreference("Count", make_property_string(MRU_used)); - for ( std::size_t i = 0; i != MRU_MAX; ++i ) - { - GlobalPreferenceSystem().registerPreference( MRU_keys[i], make_property_string( MRU_filenames[i] ) ); - } + for (std::size_t i = 0; i != MRU_MAX; ++i) { + GlobalPreferenceSystem().registerPreference(MRU_keys[i], make_property_string(MRU_filenames[i])); + } - MRU_Init(); + MRU_Init(); } -void MRU_Destroy(){ + +void MRU_Destroy() +{ } diff --git a/radiant/mru.h b/radiant/mru.h index 33627d80..64d2cd38 100644 --- a/radiant/mru.h +++ b/radiant/mru.h @@ -24,11 +24,12 @@ #if !defined( INCLUDED_MRU_H ) #define INCLUDED_MRU_H -void MRU_AddFile( const char *str ); +void MRU_AddFile(const char *str); -void MRU_constructMenu( ui::Menu menu ); +void MRU_constructMenu(ui::Menu menu); void MRU_Construct(); + void MRU_Destroy(); #endif diff --git a/radiant/multimon.cpp b/radiant/multimon.cpp index 38ed3f30..917821d2 100644 --- a/radiant/multimon.cpp +++ b/radiant/multimon.cpp @@ -29,15 +29,17 @@ multimon_globals_t g_multimon_globals; -LatchedValue g_Multimon_enableSysMenuPopups( false, "Floating windows sysmenu icons" ); - -void MultiMonitor_constructPreferences( PreferencesPage& page ){ - ui::CheckButton primary_monitor = page.appendCheckBox( "Multi Monitor", "Start on Primary Monitor", g_multimon_globals.m_bStartOnPrimMon ); - ui::CheckButton popup = page.appendCheckBox( - "", "Disable system menu on popup windows", - mkImportExportCallback( g_Multimon_enableSysMenuPopups ) - ); - Widget_connectToggleDependency( popup, primary_monitor ); +LatchedValue g_Multimon_enableSysMenuPopups(false, "Floating windows sysmenu icons"); + +void MultiMonitor_constructPreferences(PreferencesPage &page) +{ + ui::CheckButton primary_monitor = page.appendCheckBox("Multi Monitor", "Start on Primary Monitor", + g_multimon_globals.m_bStartOnPrimMon); + ui::CheckButton popup = page.appendCheckBox( + "", "Disable system menu on popup windows", + mkImportExportCallback(g_Multimon_enableSysMenuPopups) + ); + Widget_connectToggleDependency(popup, primary_monitor); } #include "preferencesystem.h" @@ -45,53 +47,58 @@ void MultiMonitor_constructPreferences( PreferencesPage& page ){ #include -namespace -{ -GdkRectangle primaryMonitor; +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 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", make_property_string( g_multimon_globals.m_bStartOnPrimMon ) ); - GlobalPreferenceSystem().registerPreference( "NoSysMenuPopups", make_property_string( g_Multimon_enableSysMenuPopups.m_latched ) ); - - g_Multimon_enableSysMenuPopups.useLatched(); - - PreferencesDialog_addInterfacePreferences( makeCallbackF(MultiMonitor_constructPreferences) ); +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", + make_property_string(g_multimon_globals.m_bStartOnPrimMon)); + GlobalPreferenceSystem().registerPreference("NoSysMenuPopups", + make_property_string(g_Multimon_enableSysMenuPopups.m_latched)); + + g_Multimon_enableSysMenuPopups.useLatched(); + + PreferencesDialog_addInterfacePreferences(makeCallbackF(MultiMonitor_constructPreferences)); } -void MultiMon_Destroy(){ + +void MultiMon_Destroy() +{ } diff --git a/radiant/multimon.h b/radiant/multimon.h index c51bb9d0..e1b3cf4b 100644 --- a/radiant/multimon.h +++ b/radiant/multimon.h @@ -26,15 +26,15 @@ struct WindowPosition; -void PositionWindowOnPrimaryScreen( WindowPosition& position ); +void PositionWindowOnPrimaryScreen(WindowPosition &position); -struct multimon_globals_t -{ - bool m_bStartOnPrimMon; +struct multimon_globals_t { + bool m_bStartOnPrimMon; - multimon_globals_t() : - m_bStartOnPrimMon( false ){ - } + multimon_globals_t() : + m_bStartOnPrimMon(false) + { + } }; extern multimon_globals_t g_multimon_globals; @@ -43,10 +43,15 @@ extern multimon_globals_t g_multimon_globals; void MultiMon_Construct(); void MultiMon_Destroy(); #else -inline void MultiMon_Construct(){ + +inline void MultiMon_Construct() +{ } -inline void MultiMon_Destroy(){ + +inline void MultiMon_Destroy() +{ } + #endif #endif diff --git a/radiant/nullmodel.cpp b/radiant/nullmodel.cpp index e23bb7c0..d80e78ec 100644 --- a/radiant/nullmodel.cpp +++ b/radiant/nullmodel.cpp @@ -40,146 +40,180 @@ #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 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 ); - } -} + 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; +class NullModelInstance : public scene::Instance, public Renderable, public SelectionTestable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + InstanceContainedCast::install(m_casts); + InstanceContainedCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + NullModel &m_nullmodel; public: -TypeCasts(){ - InstanceContainedCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} + + typedef LazyStatic StaticTypeCasts; + + Bounded &get(NullType) + { + return m_nullmodel; + } + + Cullable &get(NullType) + { + 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()); + } }; -NullModel& m_nullmodel; +class NullModelNode : public scene::Node::Symbiot, public scene::Instantiable { + class TypeCasts { + NodeTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + } + + NodeTypeCastTable &get() + { + return m_casts; + } + }; + + + scene::Node m_node; + InstanceSet m_instances; + NullModel m_nullmodel; public: -typedef LazyStatic StaticTypeCasts; - -Bounded& get( NullType){ - return m_nullmodel; -} -Cullable& get( NullType){ - 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() ); -} + typedef LazyStatic 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); + } }; -class NullModelNode : public scene::Node::Symbiot, public scene::Instantiable -{ -class TypeCasts +NodeSmartReference NewNullModel() { -NodeTypeCastTable m_casts; -public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); -} -NodeTypeCastTable& get(){ - return m_casts; -} -}; - - -scene::Node m_node; -InstanceSet m_instances; -NullModel m_nullmodel; -public: - -typedef LazyStatic StaticTypeCasts; - -NullModelNode() : m_node( this, this, StaticTypeCasts::instance().get() ){ - m_node.m_isRoot = true; + return NodeSmartReference((new NullModelNode)->node()); } -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_construct(){ -} -void NullModel_destroy(){ +void NullModel_destroy() +{ } diff --git a/radiant/nullmodel.h b/radiant/nullmodel.h index 39f27cba..76a6c491 100644 --- a/radiant/nullmodel.h +++ b/radiant/nullmodel.h @@ -22,16 +22,18 @@ #if !defined ( INCLUDED_NULLMODEL_H ) #define INCLUDED_NULLMODEL_H -namespace scene -{ -class Node; +namespace scene { + class Node; } #include "generic/referencecounted.h" + typedef SmartReference > NodeSmartReference; + NodeSmartReference NewNullModel(); void NullModel_construct(); + void NullModel_destroy(); #endif diff --git a/radiant/parse.cpp b/radiant/parse.cpp index ac5dd3b2..d5bf5a69 100644 --- a/radiant/parse.cpp +++ b/radiant/parse.cpp @@ -24,21 +24,24 @@ #include "script/scripttokeniser.h" #include "script/scripttokenwriter.h" -class ScriptLibraryAPI -{ -_QERScripLibTable m_scriptlibrary; +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; -} + 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" @@ -46,4 +49,4 @@ _QERScripLibTable* getTable(){ typedef SingletonModule ScriptLibraryModule; typedef Static StaticScriptLibraryModule; -StaticRegisterModule staticRegisterScriptLibrary( StaticScriptLibraryModule::instance() ); +StaticRegisterModule staticRegisterScriptLibrary(StaticScriptLibraryModule::instance()); diff --git a/radiant/patch.cpp b/radiant/patch.cpp index 0d80278d..c48cb44a 100644 --- a/radiant/patch.cpp +++ b/radiant/patch.cpp @@ -29,18 +29,20 @@ Signal0 g_patchTextureChangedCallbacks; -void Patch_addTextureChangedCallback( const SignalHandler& handler ){ - g_patchTextureChangedCallbacks.connectLast( handler ); +void Patch_addTextureChangedCallback(const SignalHandler &handler) +{ + g_patchTextureChangedCallbacks.connectLast(handler); } -void Patch_textureChanged(){ - g_patchTextureChangedCallbacks(); +void Patch_textureChanged() +{ + g_patchTextureChangedCallbacks(); } -Shader* PatchInstance::m_state_selpoint; -Shader* Patch::m_state_ctrl; -Shader* Patch::m_state_lattice; +Shader *PatchInstance::m_state_selpoint; +Shader *Patch::m_state_ctrl; +Shader *Patch::m_state_lattice; EPatchType Patch::m_type; @@ -49,237 +51,238 @@ std::size_t MAX_PATCH_HEIGHT = 0; int g_PatchSubdivideThreshold = 4; -void BezierCurveTree_Delete( BezierCurveTree *pCurve ){ - if ( pCurve ) { - BezierCurveTree_Delete( pCurve->left ); - BezierCurveTree_Delete( pCurve->right ); - delete pCurve; - } +void BezierCurveTree_Delete(BezierCurveTree *pCurve) +{ + if (pCurve) { + BezierCurveTree_Delete(pCurve->left); + BezierCurveTree_Delete(pCurve->right); + delete pCurve; + } } -std::size_t BezierCurveTree_Setup( BezierCurveTree *pCurve, std::size_t index, std::size_t stride ){ - if ( pCurve ) { - if ( pCurve->left && pCurve->right ) { - index = BezierCurveTree_Setup( pCurve->left, index, stride ); - pCurve->index = index * stride; - index++; - index = BezierCurveTree_Setup( pCurve->right, index, stride ); - } - else - { - pCurve->index = BEZIERCURVETREE_MAX_INDEX; - } - } +std::size_t BezierCurveTree_Setup(BezierCurveTree *pCurve, std::size_t index, std::size_t stride) +{ + if (pCurve) { + if (pCurve->left && pCurve->right) { + index = BezierCurveTree_Setup(pCurve->left, index, stride); + pCurve->index = index * stride; + index++; + index = BezierCurveTree_Setup(pCurve->right, index, stride); + } else { + pCurve->index = BEZIERCURVETREE_MAX_INDEX; + } + } - return index; + return index; } -bool BezierCurve_IsCurved( BezierCurve *pCurve ){ - Vector3 vTemp( vector3_subtracted( pCurve->right, pCurve->left ) ); - Vector3 v1( vector3_subtracted( pCurve->crd, pCurve->left ) ); - Vector3 v2( vector3_subtracted( pCurve->right, pCurve->crd ) ); +bool BezierCurve_IsCurved(BezierCurve *pCurve) +{ + Vector3 vTemp(vector3_subtracted(pCurve->right, pCurve->left)); + Vector3 v1(vector3_subtracted(pCurve->crd, pCurve->left)); + Vector3 v2(vector3_subtracted(pCurve->right, pCurve->crd)); - if ( vector3_equal( v1, g_vector3_identity ) || vector3_equal( vTemp, v1 ) ) { // return 0 if 1->2 == 0 or 1->2 == 1->3 - return false; - } + if (vector3_equal(v1, g_vector3_identity) || vector3_equal(vTemp, v1)) { // return 0 if 1->2 == 0 or 1->2 == 1->3 + return false; + } - vector3_normalise( v1 ); - vector3_normalise( v2 ); - if ( vector3_equal( v1, v2 ) ) { - return false; - } + vector3_normalise(v1); + vector3_normalise(v2); + if (vector3_equal(v1, v2)) { + return false; + } - Vector3 v3( vTemp ); - const double width = vector3_length( v3 ); - vector3_scale( v3, 1.0 / width ); + Vector3 v3(vTemp); + const double width = vector3_length(v3); + vector3_scale(v3, 1.0 / width); - if ( vector3_equal( v1, v3 ) && vector3_equal( v2, v3 ) ) { - return false; - } + if (vector3_equal(v1, v3) && vector3_equal(v2, v3)) { + return false; + } - const double angle = acos( vector3_dot( v1, v2 ) ) / c_pi; + const double angle = acos(vector3_dot(v1, v2)) / c_pi; - const double index = width * angle; + const double index = width * angle; - if ( index > static_cast( g_PatchSubdivideThreshold ) ) { - return true; - } - return false; + if (index > static_cast( g_PatchSubdivideThreshold )) { + return true; + } + return false; } -void BezierInterpolate( BezierCurve *pCurve ){ - pCurve->left = vector3_mid( pCurve->left, pCurve->crd ); - pCurve->right = vector3_mid( pCurve->crd, pCurve->right ); - pCurve->crd = vector3_mid( pCurve->left, pCurve->right ); +void BezierInterpolate(BezierCurve *pCurve) +{ + pCurve->left = vector3_mid(pCurve->left, pCurve->crd); + pCurve->right = vector3_mid(pCurve->crd, pCurve->right); + pCurve->crd = vector3_mid(pCurve->left, pCurve->right); } const std::size_t PATCH_MAX_SUBDIVISION_DEPTH = 16; -void BezierCurveTree_FromCurveList( BezierCurveTree *pTree, GSList *pCurveList, std::size_t depth = 0 ){ - GSList *pLeftList = 0; - GSList *pRightList = 0; - BezierCurve *pCurve, *pLeftCurve, *pRightCurve; - bool bSplit = false; - - for ( GSList *l = pCurveList; l; l = l->next ) - { - pCurve = (BezierCurve *)( l->data ); - if ( bSplit || BezierCurve_IsCurved( pCurve ) ) { - bSplit = true; - pLeftCurve = new BezierCurve; - pRightCurve = new BezierCurve; - pLeftCurve->left = pCurve->left; - pRightCurve->right = pCurve->right; - BezierInterpolate( pCurve ); - pLeftCurve->crd = pCurve->left; - pRightCurve->crd = pCurve->right; - pLeftCurve->right = pCurve->crd; - pRightCurve->left = pCurve->crd; - - pLeftList = g_slist_prepend( pLeftList, pLeftCurve ); - pRightList = g_slist_prepend( pRightList, pRightCurve ); - } - } - - if ( pLeftList != 0 && pRightList != 0 && depth != PATCH_MAX_SUBDIVISION_DEPTH ) { - pTree->left = new BezierCurveTree; - pTree->right = new BezierCurveTree; - BezierCurveTree_FromCurveList( pTree->left, pLeftList, depth + 1 ); - BezierCurveTree_FromCurveList( pTree->right, pRightList, depth + 1 ); - - for ( GSList* l = pLeftList; l != 0; l = g_slist_next( l ) ) - { - delete (BezierCurve*)l->data; - } - - for ( GSList* l = pRightList; l != 0; l = g_slist_next( l ) ) - { - delete (BezierCurve*)l->data; - } - - g_slist_free( pLeftList ); - g_slist_free( pRightList ); - } - else - { - pTree->left = 0; - pTree->right = 0; - } +void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, GSList *pCurveList, std::size_t depth = 0) +{ + GSList *pLeftList = 0; + GSList *pRightList = 0; + BezierCurve *pCurve, *pLeftCurve, *pRightCurve; + bool bSplit = false; + + for (GSList *l = pCurveList; l; l = l->next) { + pCurve = (BezierCurve *) (l->data); + if (bSplit || BezierCurve_IsCurved(pCurve)) { + bSplit = true; + pLeftCurve = new BezierCurve; + pRightCurve = new BezierCurve; + pLeftCurve->left = pCurve->left; + pRightCurve->right = pCurve->right; + BezierInterpolate(pCurve); + pLeftCurve->crd = pCurve->left; + pRightCurve->crd = pCurve->right; + pLeftCurve->right = pCurve->crd; + pRightCurve->left = pCurve->crd; + + pLeftList = g_slist_prepend(pLeftList, pLeftCurve); + pRightList = g_slist_prepend(pRightList, pRightCurve); + } + } + + if (pLeftList != 0 && pRightList != 0 && depth != PATCH_MAX_SUBDIVISION_DEPTH) { + pTree->left = new BezierCurveTree; + pTree->right = new BezierCurveTree; + BezierCurveTree_FromCurveList(pTree->left, pLeftList, depth + 1); + BezierCurveTree_FromCurveList(pTree->right, pRightList, depth + 1); + + for (GSList *l = pLeftList; l != 0; l = g_slist_next(l)) { + delete (BezierCurve *) l->data; + } + + for (GSList *l = pRightList; l != 0; l = g_slist_next(l)) { + delete (BezierCurve *) l->data; + } + + g_slist_free(pLeftList); + g_slist_free(pRightList); + } else { + pTree->left = 0; + pTree->right = 0; + } } int Patch::m_CycleCapIndex = 0; -void Patch::setDims( std::size_t w, std::size_t h ){ - if ( ( w % 2 ) == 0 ) { - w -= 1; - } - ASSERT_MESSAGE( w <= MAX_PATCH_WIDTH, "patch too wide" ); - if ( w > MAX_PATCH_WIDTH ) { - w = MAX_PATCH_WIDTH; - } - else if ( w < MIN_PATCH_WIDTH ) { - w = MIN_PATCH_WIDTH; - } - - if ( ( h % 2 ) == 0 ) { - m_height -= 1; - } - ASSERT_MESSAGE( h <= MAX_PATCH_HEIGHT, "patch too tall" ); - if ( h > MAX_PATCH_HEIGHT ) { - h = MAX_PATCH_HEIGHT; - } - else if ( h < MIN_PATCH_HEIGHT ) { - h = MIN_PATCH_HEIGHT; - } - - m_width = w; m_height = h; - - if ( m_width * m_height != m_ctrl.size() ) { - m_ctrl.resize( m_width * m_height ); - onAllocate( m_ctrl.size() ); - } -} - -inline const Colour4b& colour_for_index( std::size_t i, std::size_t width ){ - return ( i % 2 || ( i / width ) % 2 ) ? colour_inside : colour_corner; +void Patch::setDims(std::size_t w, std::size_t h) +{ + if ((w % 2) == 0) { + w -= 1; + } + ASSERT_MESSAGE(w <= MAX_PATCH_WIDTH, "patch too wide"); + if (w > MAX_PATCH_WIDTH) { + w = MAX_PATCH_WIDTH; + } else if (w < MIN_PATCH_WIDTH) { + w = MIN_PATCH_WIDTH; + } + + if ((h % 2) == 0) { + m_height -= 1; + } + ASSERT_MESSAGE(h <= MAX_PATCH_HEIGHT, "patch too tall"); + if (h > MAX_PATCH_HEIGHT) { + h = MAX_PATCH_HEIGHT; + } else if (h < MIN_PATCH_HEIGHT) { + h = MIN_PATCH_HEIGHT; + } + + m_width = w; + m_height = h; + + if (m_width * m_height != m_ctrl.size()) { + m_ctrl.resize(m_width * m_height); + onAllocate(m_ctrl.size()); + } +} + +inline const Colour4b &colour_for_index(std::size_t i, std::size_t width) +{ + return (i % 2 || (i / width) % 2) ? colour_inside : colour_corner; } -inline bool float_valid( float f ){ - return f == f; +inline bool float_valid(float f) +{ + return f == f; } -bool Patch::isValid() const { - if ( !m_width || !m_height ) { - return false; - } - - for ( const_iterator i = m_ctrl.begin(); i != m_ctrl.end(); ++i ) - { - if ( !float_valid( ( *i ).m_vertex.x() ) - || !float_valid( ( *i ).m_vertex.y() ) - || !float_valid( ( *i ).m_vertex.z() ) - || !float_valid( ( *i ).m_texcoord.x() ) - || !float_valid( ( *i ).m_texcoord.y() ) ) { - globalErrorStream() << "patch has invalid control points\n"; - return false; - } - } - return true; -} - -void Patch::UpdateCachedData(){ - m_ctrl_vertices.clear(); - m_lattice_indices.clear(); - - if ( !isValid() ) { - m_tess.m_numStrips = 0; - m_tess.m_lenStrips = 0; - m_tess.m_nArrayHeight = 0; - m_tess.m_nArrayWidth = 0; - m_tess.m_curveTreeU.resize( 0 ); - m_tess.m_curveTreeV.resize( 0 ); - m_tess.m_indices.resize( 0 ); - m_tess.m_vertices.resize( 0 ); - m_tess.m_arrayHeight.resize( 0 ); - m_tess.m_arrayWidth.resize( 0 ); - m_aabb_local = AABB(); - return; - } - - BuildTesselationCurves( ROW ); - BuildTesselationCurves( COL ); - BuildVertexArray(); - AccumulateBBox(); - - IndexBuffer ctrl_indices; - - m_lattice_indices.reserve( ( ( m_width * ( m_height - 1 ) ) + ( m_height * ( m_width - 1 ) ) ) << 1 ); - ctrl_indices.reserve( m_ctrlTransformed.size() ); - { - UniqueVertexBuffer inserter( m_ctrl_vertices ); - for ( iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i ) - { - ctrl_indices.insert( inserter.insert( pointvertex_quantised( PointVertex( reinterpret_cast( ( *i ).m_vertex ), colour_for_index( i - m_ctrlTransformed.begin(), m_width ) ) ) ) ); - } - } - { - for ( IndexBuffer::iterator i = ctrl_indices.begin(); i != ctrl_indices.end(); ++i ) - { - if ( std::size_t( i - ctrl_indices.begin() ) % m_width ) { - m_lattice_indices.insert( *( i - 1 ) ); - m_lattice_indices.insert( *i ); - } - if ( std::size_t( i - ctrl_indices.begin() ) >= m_width ) { - m_lattice_indices.insert( *( i - m_width ) ); - m_lattice_indices.insert( *i ); - } - } - } +bool Patch::isValid() const +{ + if (!m_width || !m_height) { + return false; + } + + for (const_iterator i = m_ctrl.begin(); i != m_ctrl.end(); ++i) { + if (!float_valid((*i).m_vertex.x()) + || !float_valid((*i).m_vertex.y()) + || !float_valid((*i).m_vertex.z()) + || !float_valid((*i).m_texcoord.x()) + || !float_valid((*i).m_texcoord.y())) { + globalErrorStream() << "patch has invalid control points\n"; + return false; + } + } + return true; +} + +void Patch::UpdateCachedData() +{ + m_ctrl_vertices.clear(); + m_lattice_indices.clear(); + + if (!isValid()) { + m_tess.m_numStrips = 0; + m_tess.m_lenStrips = 0; + m_tess.m_nArrayHeight = 0; + m_tess.m_nArrayWidth = 0; + m_tess.m_curveTreeU.resize(0); + m_tess.m_curveTreeV.resize(0); + m_tess.m_indices.resize(0); + m_tess.m_vertices.resize(0); + m_tess.m_arrayHeight.resize(0); + m_tess.m_arrayWidth.resize(0); + m_aabb_local = AABB(); + return; + } + + BuildTesselationCurves(ROW); + BuildTesselationCurves(COL); + BuildVertexArray(); + AccumulateBBox(); + + IndexBuffer ctrl_indices; + + m_lattice_indices.reserve(((m_width * (m_height - 1)) + (m_height * (m_width - 1))) << 1); + ctrl_indices.reserve(m_ctrlTransformed.size()); + { + UniqueVertexBuffer inserter(m_ctrl_vertices); + for (iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i) { + ctrl_indices.insert(inserter.insert(pointvertex_quantised( + PointVertex(reinterpret_cast((*i).m_vertex ), + colour_for_index(i - m_ctrlTransformed.begin(), m_width))))); + } + } + { + for (IndexBuffer::iterator i = ctrl_indices.begin(); i != ctrl_indices.end(); ++i) { + if (std::size_t(i - ctrl_indices.begin()) % m_width) { + m_lattice_indices.insert(*(i - 1)); + m_lattice_indices.insert(*i); + } + if (std::size_t(i - ctrl_indices.begin()) >= m_width) { + m_lattice_indices.insert(*(i - m_width)); + m_lattice_indices.insert(*i); + } + } + } #if 0 - { + { Array::iterator first = m_tess.m_indices.begin(); for ( std::size_t s = 0; s < m_tess.m_numStrips; s++ ) { @@ -302,286 +305,273 @@ void Patch::UpdateCachedData(){ } #endif - SceneChangeNotify(); -} - -void Patch::InvertMatrix(){ - undoSave(); - - PatchControlArray_invert( m_ctrl, m_width, m_height ); - - controlPointsChanged(); + SceneChangeNotify(); } -void Patch::TransposeMatrix(){ - undoSave(); - - { - Array tmp( m_width * m_height ); - copy_ctrl( tmp.data(), m_ctrl.data(), m_ctrl.data() + m_width * m_height ); - - PatchControlIter from = tmp.data(); - for ( std::size_t h = 0; h != m_height; ++h ) - { - PatchControlIter to = m_ctrl.data() + h; - for ( std::size_t w = 0; w != m_width; ++w, ++from, to += m_height ) - { - *to = *from; - } - } - } - - { - std::size_t tmp = m_width; - m_width = m_height; - m_height = tmp; - } - - controlPointsChanged(); -} - -void Patch::Redisperse( EMatrixMajor mt ){ - std::size_t w, h, width, height, row_stride, col_stride; - PatchControl* p1, * p2, * p3; - - undoSave(); - - switch ( mt ) - { - case COL: - width = ( m_width - 1 ) >> 1; - height = m_height; - col_stride = 1; - row_stride = m_width; - break; - case ROW: - width = ( m_height - 1 ) >> 1; - height = m_width; - col_stride = m_width; - row_stride = 1; - break; - default: - ERROR_MESSAGE( "neither row-major nor column-major" ); - return; - } - - for ( h = 0; h < height; h++ ) - { - p1 = m_ctrl.data() + ( h * row_stride ); - for ( w = 0; w < width; w++ ) - { - p2 = p1 + col_stride; - p3 = p2 + col_stride; - p2->m_vertex = vector3_mid( p1->m_vertex, p3->m_vertex ); - p1 = p3; - } - } - - controlPointsChanged(); -} - -void Patch::Smooth( EMatrixMajor mt ){ - std::size_t w, h, width, height, row_stride, col_stride; - bool wrap; - PatchControl* p1, * p2, * p3, * p2b; - - undoSave(); - - switch ( mt ) - { - case COL: - width = ( m_width - 1 ) >> 1; - height = m_height; - col_stride = 1; - row_stride = m_width; - break; - case ROW: - width = ( m_height - 1 ) >> 1; - height = m_width; - col_stride = m_width; - row_stride = 1; - break; - default: - ERROR_MESSAGE( "neither row-major nor column-major" ); - return; - } - - wrap = true; - for ( h = 0; h < height; h++ ) - { - p1 = m_ctrl.data() + ( h * row_stride ); - p2 = p1 + ( 2 * width ) * col_stride; - //globalErrorStream() << "compare " << p1->m_vertex << " and " << p2->m_vertex << "\n"; - if ( vector3_length_squared( vector3_subtracted( p1->m_vertex, p2->m_vertex ) ) > 1.0 ) { - //globalErrorStream() << "too far\n"; - wrap = false; - break; - } - } +void Patch::InvertMatrix() +{ + undoSave(); - for ( h = 0; h < height; h++ ) - { - p1 = m_ctrl.data() + ( h * row_stride ) + col_stride; - for ( w = 0; w < width - 1; w++ ) - { - p2 = p1 + col_stride; - p3 = p2 + col_stride; - p2->m_vertex = vector3_mid( p1->m_vertex, p3->m_vertex ); - p1 = p3; - } - if ( wrap ) { - p1 = m_ctrl.data() + ( h * row_stride ) + ( 2 * width - 1 ) * col_stride; - p2 = m_ctrl.data() + ( h * row_stride ); - p2b = m_ctrl.data() + ( h * row_stride ) + ( 2 * width ) * col_stride; - p3 = m_ctrl.data() + ( h * row_stride ) + col_stride; - p2->m_vertex = p2b->m_vertex = vector3_mid( p1->m_vertex, p3->m_vertex ); - } - } + PatchControlArray_invert(m_ctrl, m_width, m_height); - controlPointsChanged(); + controlPointsChanged(); } -void Patch::InsertRemove( bool bInsert, bool bColumn, bool bFirst ){ - undoSave(); - - if ( bInsert ) { - if ( bColumn && ( m_width + 2 <= MAX_PATCH_WIDTH ) ) { - InsertPoints( COL, bFirst ); - } - else if ( m_height + 2 <= MAX_PATCH_HEIGHT ) { - InsertPoints( ROW, bFirst ); - } - } - else - { - if ( bColumn && ( m_width - 2 >= MIN_PATCH_WIDTH ) ) { - RemovePoints( COL, bFirst ); - } - else if ( m_height - 2 >= MIN_PATCH_HEIGHT ) { - RemovePoints( ROW, bFirst ); - } - } +void Patch::TransposeMatrix() +{ + undoSave(); - controlPointsChanged(); -} - -Patch* Patch::MakeCap( Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirst ){ - std::size_t i, width, height; - - switch ( mt ) - { - case ROW: - width = m_width; - height = m_height; - break; - case COL: - width = m_height; - height = m_width; - break; - default: - ERROR_MESSAGE( "neither row-major nor column-major" ); - return 0; - } + { + Array tmp(m_width * m_height); + copy_ctrl(tmp.data(), m_ctrl.data(), m_ctrl.data() + m_width * m_height); - Array p( width ); + PatchControlIter from = tmp.data(); + for (std::size_t h = 0; h != m_height; ++h) { + PatchControlIter to = m_ctrl.data() + h; + for (std::size_t w = 0; w != m_width; ++w, ++from, to += m_height) { + *to = *from; + } + } + } - std::size_t nIndex = ( bFirst ) ? 0 : height - 1; - if ( mt == ROW ) { - for ( i = 0; i < width; i++ ) - { - p[( bFirst ) ? i : ( width - 1 ) - i] = ctrlAt( nIndex, i ).m_vertex; - } - } - else - { - for ( i = 0; i < width; i++ ) - { - p[( bFirst ) ? i : ( width - 1 ) - i] = ctrlAt( i, nIndex ).m_vertex; - } - } + { + std::size_t tmp = m_width; + m_width = m_height; + m_height = tmp; + } - patch->ConstructSeam( eType, p.data(), width ); - return patch; + controlPointsChanged(); } -void Patch::FlipTexture( int nAxis ){ - undoSave(); +void Patch::Redisperse(EMatrixMajor mt) +{ + std::size_t w, h, width, height, row_stride, col_stride; + PatchControl *p1, *p2, *p3; + + undoSave(); + + switch (mt) { + case COL: + width = (m_width - 1) >> 1; + height = m_height; + col_stride = 1; + row_stride = m_width; + break; + case ROW: + width = (m_height - 1) >> 1; + height = m_width; + col_stride = m_width; + row_stride = 1; + break; + default: + ERROR_MESSAGE("neither row-major nor column-major"); + return; + } + + for (h = 0; h < height; h++) { + p1 = m_ctrl.data() + (h * row_stride); + for (w = 0; w < width; w++) { + p2 = p1 + col_stride; + p3 = p2 + col_stride; + p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex); + p1 = p3; + } + } + + controlPointsChanged(); +} + +void Patch::Smooth(EMatrixMajor mt) +{ + std::size_t w, h, width, height, row_stride, col_stride; + bool wrap; + PatchControl *p1, *p2, *p3, *p2b; + + undoSave(); + + switch (mt) { + case COL: + width = (m_width - 1) >> 1; + height = m_height; + col_stride = 1; + row_stride = m_width; + break; + case ROW: + width = (m_height - 1) >> 1; + height = m_width; + col_stride = m_width; + row_stride = 1; + break; + default: + ERROR_MESSAGE("neither row-major nor column-major"); + return; + } + + wrap = true; + for (h = 0; h < height; h++) { + p1 = m_ctrl.data() + (h * row_stride); + p2 = p1 + (2 * width) * col_stride; + //globalErrorStream() << "compare " << p1->m_vertex << " and " << p2->m_vertex << "\n"; + if (vector3_length_squared(vector3_subtracted(p1->m_vertex, p2->m_vertex)) > 1.0) { + //globalErrorStream() << "too far\n"; + wrap = false; + break; + } + } + + for (h = 0; h < height; h++) { + p1 = m_ctrl.data() + (h * row_stride) + col_stride; + for (w = 0; w < width - 1; w++) { + p2 = p1 + col_stride; + p3 = p2 + col_stride; + p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex); + p1 = p3; + } + if (wrap) { + p1 = m_ctrl.data() + (h * row_stride) + (2 * width - 1) * col_stride; + p2 = m_ctrl.data() + (h * row_stride); + p2b = m_ctrl.data() + (h * row_stride) + (2 * width) * col_stride; + p3 = m_ctrl.data() + (h * row_stride) + col_stride; + p2->m_vertex = p2b->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex); + } + } + + controlPointsChanged(); +} + +void Patch::InsertRemove(bool bInsert, bool bColumn, bool bFirst) +{ + undoSave(); + + if (bInsert) { + if (bColumn && (m_width + 2 <= MAX_PATCH_WIDTH)) { + InsertPoints(COL, bFirst); + } else if (m_height + 2 <= MAX_PATCH_HEIGHT) { + InsertPoints(ROW, bFirst); + } + } else { + if (bColumn && (m_width - 2 >= MIN_PATCH_WIDTH)) { + RemovePoints(COL, bFirst); + } else if (m_height - 2 >= MIN_PATCH_HEIGHT) { + RemovePoints(ROW, bFirst); + } + } + + controlPointsChanged(); +} + +Patch *Patch::MakeCap(Patch *patch, EPatchCap eType, EMatrixMajor mt, bool bFirst) +{ + std::size_t i, width, height; + + switch (mt) { + case ROW: + width = m_width; + height = m_height; + break; + case COL: + width = m_height; + height = m_width; + break; + default: + ERROR_MESSAGE("neither row-major nor column-major"); + return 0; + } + + Array p(width); + + std::size_t nIndex = (bFirst) ? 0 : height - 1; + if (mt == ROW) { + for (i = 0; i < width; i++) { + p[(bFirst) ? i : (width - 1) - i] = ctrlAt(nIndex, i).m_vertex; + } + } else { + for (i = 0; i < width; i++) { + p[(bFirst) ? i : (width - 1) - i] = ctrlAt(i, nIndex).m_vertex; + } + } + + patch->ConstructSeam(eType, p.data(), width); + return patch; +} + +void Patch::FlipTexture(int nAxis) +{ + undoSave(); - for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i ) - { - ( *i ).m_texcoord[nAxis] = -( *i ).m_texcoord[nAxis]; - } + for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) { + (*i).m_texcoord[nAxis] = -(*i).m_texcoord[nAxis]; + } - controlPointsChanged(); + controlPointsChanged(); } -void Patch::TranslateTexture( float s, float t ){ - undoSave(); +void Patch::TranslateTexture(float s, float t) +{ + undoSave(); - s = -1 * s / m_state->getTexture().width; - t = t / m_state->getTexture().height; + s = -1 * s / m_state->getTexture().width; + t = t / m_state->getTexture().height; - for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i ) - { - ( *i ).m_texcoord[0] += s; - ( *i ).m_texcoord[1] += t; - } + for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) { + (*i).m_texcoord[0] += s; + (*i).m_texcoord[1] += t; + } - controlPointsChanged(); + controlPointsChanged(); } -void Patch::ScaleTexture( float s, float t ){ - undoSave(); +void Patch::ScaleTexture(float s, float t) +{ + undoSave(); - for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i ) - { - ( *i ).m_texcoord[0] *= s; - ( *i ).m_texcoord[1] *= t; - } + for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) { + (*i).m_texcoord[0] *= s; + (*i).m_texcoord[1] *= t; + } - controlPointsChanged(); + controlPointsChanged(); } -void Patch::RotateTexture( float angle ){ - undoSave(); +void Patch::RotateTexture(float angle) +{ + undoSave(); - const float s = static_cast( sin( degrees_to_radians( angle ) ) ); - const float c = static_cast( cos( degrees_to_radians( angle ) ) ); + const float s = static_cast( sin(degrees_to_radians(angle))); + const float c = static_cast( cos(degrees_to_radians(angle))); - for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i ) - { - const float x = ( *i ).m_texcoord[0]; - const float y = ( *i ).m_texcoord[1]; - ( *i ).m_texcoord[0] = ( x * c ) - ( y * s ); - ( *i ).m_texcoord[1] = ( y * c ) + ( x * s ); - } + for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) { + const float x = (*i).m_texcoord[0]; + const float y = (*i).m_texcoord[1]; + (*i).m_texcoord[0] = (x * c) - (y * s); + (*i).m_texcoord[1] = (y * c) + (x * s); + } - controlPointsChanged(); + controlPointsChanged(); } -void Patch::SetTextureRepeat( float s, float t ){ - std::size_t w, h; - float si, ti, sc, tc; - PatchControl *pDest; +void Patch::SetTextureRepeat(float s, float t) +{ + std::size_t w, h; + float si, ti, sc, tc; + PatchControl *pDest; - undoSave(); + undoSave(); - si = s / (float)( m_width - 1 ); - ti = t / (float)( m_height - 1 ); + si = s / (float) (m_width - 1); + ti = t / (float) (m_height - 1); - pDest = m_ctrl.data(); - for ( h = 0, tc = 0.0f; h < m_height; h++, tc += ti ) - { - for ( w = 0, sc = 0.0f; w < m_width; w++, sc += si ) - { - pDest->m_texcoord[0] = sc; - pDest->m_texcoord[1] = tc; - pDest++; - } - } + pDest = m_ctrl.data(); + for (h = 0, tc = 0.0f; h < m_height; h++, tc += ti) { + for (w = 0, sc = 0.0f; w < m_width; w++, sc += si) { + pDest->m_texcoord[0] = sc; + pDest->m_texcoord[1] = tc; + pDest++; + } + } - controlPointsChanged(); + controlPointsChanged(); } /* @@ -600,158 +590,159 @@ void Patch::SetTextureRepeat( float s, float t ){ } */ -inline int texture_axis( const Vector3& normal ){ - // axis dominance order: Z, X, Y - return ( normal.x() >= normal.y() ) ? ( normal.x() > normal.z() ) ? 0 : 2 : ( normal.y() > normal.z() ) ? 1 : 2; +inline int texture_axis(const Vector3 &normal) +{ + // axis dominance order: Z, X, Y + return (normal.x() >= normal.y()) ? (normal.x() > normal.z()) ? 0 : 2 : (normal.y() > normal.z()) ? 1 : 2; } -void Patch::CapTexture(){ - const PatchControl& p1 = m_ctrl[m_width]; - const PatchControl& p2 = m_ctrl[m_width * ( m_height - 1 )]; - const PatchControl& p3 = m_ctrl[( m_width * m_height ) - 1]; - - - Vector3 normal( g_vector3_identity ); - - { - Vector3 tmp( vector3_cross( - vector3_subtracted( p2.m_vertex, m_ctrl[0].m_vertex ), - vector3_subtracted( p3.m_vertex, m_ctrl[0].m_vertex ) - ) ); - if ( !vector3_equal( tmp, g_vector3_identity ) ) { - vector3_add( normal, tmp ); - } - } - { - Vector3 tmp( vector3_cross( - vector3_subtracted( p1.m_vertex, p3.m_vertex ), - vector3_subtracted( m_ctrl[0].m_vertex, p3.m_vertex ) - ) ); - if ( !vector3_equal( tmp, g_vector3_identity ) ) { - vector3_add( normal, tmp ); - } - } - - ProjectTexture( texture_axis( normal ) ); +void Patch::CapTexture() +{ + const PatchControl &p1 = m_ctrl[m_width]; + const PatchControl &p2 = m_ctrl[m_width * (m_height - 1)]; + const PatchControl &p3 = m_ctrl[(m_width * m_height) - 1]; + + + Vector3 normal(g_vector3_identity); + + { + Vector3 tmp(vector3_cross( + vector3_subtracted(p2.m_vertex, m_ctrl[0].m_vertex), + vector3_subtracted(p3.m_vertex, m_ctrl[0].m_vertex) + )); + if (!vector3_equal(tmp, g_vector3_identity)) { + vector3_add(normal, tmp); + } + } + { + Vector3 tmp(vector3_cross( + vector3_subtracted(p1.m_vertex, p3.m_vertex), + vector3_subtracted(m_ctrl[0].m_vertex, p3.m_vertex) + )); + if (!vector3_equal(tmp, g_vector3_identity)) { + vector3_add(normal, tmp); + } + } + + ProjectTexture(texture_axis(normal)); } // uses longest parallel chord to calculate texture coords for each row/col -void Patch::NaturalTexture(){ - undoSave(); - - { - float fSize = (float)m_state->getTexture().width * Texdef_getDefaultTextureScale(); - - double texBest = 0; - double tex = 0; - PatchControl* pWidth = m_ctrl.data(); - for ( std::size_t w = 0; w < m_width; w++, pWidth++ ) - { - { - PatchControl* pHeight = pWidth; - for ( std::size_t h = 0; h < m_height; h++, pHeight += m_width ) - pHeight->m_texcoord[0] = static_cast( tex ); - } - - if ( w + 1 == m_width ) { - break; - } - - { - PatchControl* pHeight = pWidth; - for ( std::size_t h = 0; h < m_height; h++, pHeight += m_width ) - { - Vector3 v( vector3_subtracted( pHeight->m_vertex, ( pHeight + 1 )->m_vertex ) ); - double length = tex + ( vector3_length( v ) / fSize ); - if ( fabs( length ) > texBest ) { - texBest = length; - } - } - } - - tex = texBest; - } - } - - { - float fSize = -(float)m_state->getTexture().height * Texdef_getDefaultTextureScale(); - - double texBest = 0; - double tex = 0; - PatchControl* pHeight = m_ctrl.data(); - for ( std::size_t h = 0; h < m_height; h++, pHeight += m_width ) - { - { - PatchControl* pWidth = pHeight; - for ( std::size_t w = 0; w < m_width; w++, pWidth++ ) - pWidth->m_texcoord[1] = static_cast( tex ); - } - - if ( h + 1 == m_height ) { - break; - } - - { - PatchControl* pWidth = pHeight; - for ( std::size_t w = 0; w < m_width; w++, pWidth++ ) - { - Vector3 v( vector3_subtracted( pWidth->m_vertex, ( pWidth + m_width )->m_vertex ) ); - double length = tex + ( vector3_length( v ) / fSize ); - if ( fabs( length ) > texBest ) { - texBest = length; - } - } - } - - tex = texBest; - } - } - - controlPointsChanged(); +void Patch::NaturalTexture() +{ + undoSave(); + + { + float fSize = (float) m_state->getTexture().width * Texdef_getDefaultTextureScale(); + + double texBest = 0; + double tex = 0; + PatchControl *pWidth = m_ctrl.data(); + for (std::size_t w = 0; w < m_width; w++, pWidth++) { + { + PatchControl *pHeight = pWidth; + for (std::size_t h = 0; h < m_height; h++, pHeight += m_width) { + pHeight->m_texcoord[0] = static_cast( tex ); + } + } + + if (w + 1 == m_width) { + break; + } + + { + PatchControl *pHeight = pWidth; + for (std::size_t h = 0; h < m_height; h++, pHeight += m_width) { + Vector3 v(vector3_subtracted(pHeight->m_vertex, (pHeight + 1)->m_vertex)); + double length = tex + (vector3_length(v) / fSize); + if (fabs(length) > texBest) { + texBest = length; + } + } + } + + tex = texBest; + } + } + + { + float fSize = -(float) m_state->getTexture().height * Texdef_getDefaultTextureScale(); + + double texBest = 0; + double tex = 0; + PatchControl *pHeight = m_ctrl.data(); + for (std::size_t h = 0; h < m_height; h++, pHeight += m_width) { + { + PatchControl *pWidth = pHeight; + for (std::size_t w = 0; w < m_width; w++, pWidth++) { + pWidth->m_texcoord[1] = static_cast( tex ); + } + } + + if (h + 1 == m_height) { + break; + } + + { + PatchControl *pWidth = pHeight; + for (std::size_t w = 0; w < m_width; w++, pWidth++) { + Vector3 v(vector3_subtracted(pWidth->m_vertex, (pWidth + m_width)->m_vertex)); + double length = tex + (vector3_length(v) / fSize); + if (fabs(length) > texBest) { + texBest = length; + } + } + } + + tex = texBest; + } + } + + controlPointsChanged(); } // private: -void Patch::AccumulateBBox(){ - m_aabb_local = AABB(); +void Patch::AccumulateBBox() +{ + m_aabb_local = AABB(); - for ( PatchControlArray::iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i ) - { - aabb_extend_by_point_safe( m_aabb_local, ( *i ).m_vertex ); - } + for (PatchControlArray::iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i) { + aabb_extend_by_point_safe(m_aabb_local, (*i).m_vertex); + } - m_boundsChanged(); - m_lightsChanged(); -} - -void Patch::InsertPoints( EMatrixMajor mt, bool bFirst ){ - std::size_t width, height, row_stride, col_stride; - - switch ( mt ) - { - case ROW: - col_stride = 1; - row_stride = m_width; - width = m_width; - height = m_height; - break; - case COL: - col_stride = m_width; - row_stride = 1; - width = m_height; - height = m_width; - break; - default: - ERROR_MESSAGE( "neither row-major nor column-major" ); - return; - } + m_boundsChanged(); + m_lightsChanged(); +} - std::size_t pos = 0; - { - PatchControl* p1 = m_ctrl.data(); - /* +void Patch::InsertPoints(EMatrixMajor mt, bool bFirst) +{ + std::size_t width, height, row_stride, col_stride; + + switch (mt) { + case ROW: + col_stride = 1; + row_stride = m_width; + width = m_width; + height = m_height; + break; + case COL: + col_stride = m_width; + row_stride = 1; + width = m_height; + height = m_width; + break; + default: + ERROR_MESSAGE("neither row-major nor column-major"); + return; + } + + std::size_t pos = 0; + { + PatchControl *p1 = m_ctrl.data(); + /* if(GlobalSelectionSystem().countSelected() != 0) { scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); @@ -759,2057 +750,2009 @@ void Patch::InsertPoints( EMatrixMajor mt, bool bFirst ){ patch->m_selectable.isSelected(); } */ - for ( std::size_t w = 0; w != width; ++w, p1 += col_stride ) - { - { - PatchControl* p2 = p1; - for ( std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride ) - { - if ( 0 ) { //p2->m_selectable.isSelected()) - pos = h; - break; - } - } - if ( pos != 0 ) { - break; - } - } + for (std::size_t w = 0; w != width; ++w, p1 += col_stride) { + { + PatchControl *p2 = p1; + for (std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride) { + if (0) { //p2->m_selectable.isSelected()) + pos = h; + break; + } + } + if (pos != 0) { + break; + } + } + + { + PatchControl *p2 = p1; + for (std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride) { + if (0) { //p2->m_selectable.isSelected()) + pos = h; + break; + } + } + if (pos != 0) { + break; + } + } + } + } + + Array tmp(m_ctrl); + + std::size_t row_stride2, col_stride2; + switch (mt) { + case ROW: + setDims(m_width, m_height + 2); + col_stride2 = 1; + row_stride2 = m_width; + break; + case COL: + setDims(m_width + 2, m_height); + col_stride2 = m_width; + row_stride2 = 1; + break; + default: + ERROR_MESSAGE("neither row-major nor column-major"); + return; + } + if (bFirst) { + pos = height - 1; + } else { + pos = 2; + } + + if (pos >= height) { + if (bFirst) { + pos = height - 1; + } else { + pos = 2; + } + } else if (pos == 0) { + pos = 2; + } else if (pos % 2) { + ++pos; + } + + + for (std::size_t w = 0; w != width; ++w) { + PatchControl *p1 = tmp.data() + (w * col_stride); + PatchControl *p2 = m_ctrl.data() + (w * col_stride2); + for (std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride) { + if (h == pos) { + p2 += 2 * row_stride2; + } + *p2 = *p1; + } + + p1 = tmp.data() + (w * col_stride + pos * row_stride); + p2 = m_ctrl.data() + (w * col_stride2 + pos * row_stride2); + + PatchControl *r2a = (p2 + row_stride2); + PatchControl *r2b = (p2 - row_stride2); + PatchControl *c2a = (p1 - 2 * row_stride); + PatchControl *c2b = (p1 - row_stride); + + // set two new row points + *(p2 + 2 * row_stride2) = *p1; + *r2a = *c2b; + + for (std::size_t i = 0; i != 3; ++i) { + r2a->m_vertex[i] = float_mid(c2b->m_vertex[i], p1->m_vertex[i]); + + r2b->m_vertex[i] = float_mid(c2a->m_vertex[i], c2b->m_vertex[i]); + + p2->m_vertex[i] = float_mid(r2a->m_vertex[i], r2b->m_vertex[i]); + } + for (std::size_t i = 0; i != 2; ++i) { + r2a->m_texcoord[i] = float_mid(c2b->m_texcoord[i], p1->m_texcoord[i]); + + r2b->m_texcoord[i] = float_mid(c2a->m_texcoord[i], c2b->m_texcoord[i]); + + p2->m_texcoord[i] = float_mid(r2a->m_texcoord[i], r2b->m_texcoord[i]); + } + } +} + +void Patch::RemovePoints(EMatrixMajor mt, bool bFirst) +{ + std::size_t width, height, row_stride, col_stride; + + switch (mt) { + case ROW: + col_stride = 1; + row_stride = m_width; + width = m_width; + height = m_height; + break; + case COL: + col_stride = m_width; + row_stride = 1; + width = m_height; + height = m_width; + break; + default: + ERROR_MESSAGE("neither row-major nor column-major"); + return; + } + + std::size_t pos = 0; + { + PatchControl *p1 = m_ctrl.data(); + for (std::size_t w = 0; w != width; ++w, p1 += col_stride) { + { + PatchControl *p2 = p1; + for (std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride) { + if (0) { //p2->m_selectable.isSelected()) + pos = h; + break; + } + } + if (pos != 0) { + break; + } + } + + { + PatchControl *p2 = p1; + for (std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride) { + if (0) { //p2->m_selectable.isSelected()) + pos = h; + break; + } + } + if (pos != 0) { + break; + } + } + } + } + + Array tmp(m_ctrl); + + std::size_t row_stride2, col_stride2; + switch (mt) { + case ROW: + setDims(m_width, m_height - 2); + col_stride2 = 1; + row_stride2 = m_width; + break; + case COL: + setDims(m_width - 2, m_height); + col_stride2 = m_width; + row_stride2 = 1; + break; + default: + ERROR_MESSAGE("neither row-major nor column-major"); + return; + } + if (bFirst) { + pos = height - 3; + } else { + pos = 2; + } + if (pos >= height) { + if (bFirst) { + pos = height - 3; + } else { + pos = 2; + } + } else if (pos == 0) { + pos = 2; + } else if (pos > height - 3) { + pos = height - 3; + } else if (pos % 2) { + ++pos; + } + + for (std::size_t w = 0; w != width; w++) { + PatchControl *p1 = tmp.data() + (w * col_stride); + PatchControl *p2 = m_ctrl.data() + (w * col_stride2); + for (std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride) { + if (h == pos) { + p1 += 2 * row_stride2; + h += 2; + } + *p2 = *p1; + } + + p1 = tmp.data() + (w * col_stride + pos * row_stride); + p2 = m_ctrl.data() + (w * col_stride2 + pos * row_stride2); + + for (std::size_t i = 0; i < 3; i++) { + (p2 - row_stride2)->m_vertex[i] = + ((p1 + 2 * row_stride)->m_vertex[i] + (p1 - 2 * row_stride)->m_vertex[i]) * 0.5f; + + (p2 - row_stride2)->m_vertex[i] = + (p2 - row_stride2)->m_vertex[i] + (2.0f * ((p1)->m_vertex[i] - (p2 - row_stride2)->m_vertex[i])); + } + for (std::size_t i = 0; i < 2; i++) { + (p2 - row_stride2)->m_texcoord[i] = + ((p1 + 2 * row_stride)->m_texcoord[i] + (p1 - 2 * row_stride)->m_texcoord[i]) * 0.5f; + + (p2 - row_stride2)->m_texcoord[i] = (p2 - row_stride2)->m_texcoord[i] + + (2.0f * ((p1)->m_texcoord[i] - (p2 - row_stride2)->m_texcoord[i])); + } + } +} + +void Patch::ConstructSeam(EPatchCap eType, Vector3 *p, std::size_t width) +{ + switch (eType) { + case eCapIBevel: { + setDims(3, 3); + m_ctrl[0].m_vertex = p[0]; + m_ctrl[1].m_vertex = p[1]; + m_ctrl[2].m_vertex = p[1]; + m_ctrl[3].m_vertex = p[1]; + m_ctrl[4].m_vertex = p[1]; + m_ctrl[5].m_vertex = p[1]; + m_ctrl[6].m_vertex = p[2]; + m_ctrl[7].m_vertex = p[1]; + m_ctrl[8].m_vertex = p[1]; + } + break; + case eCapBevel: { + setDims(3, 3); + Vector3 p3(vector3_added(p[2], vector3_subtracted(p[0], p[1]))); + m_ctrl[0].m_vertex = p3; + m_ctrl[1].m_vertex = p3; + m_ctrl[2].m_vertex = p[2]; + m_ctrl[3].m_vertex = p3; + m_ctrl[4].m_vertex = p3; + m_ctrl[5].m_vertex = p[1]; + m_ctrl[6].m_vertex = p3; + m_ctrl[7].m_vertex = p3; + m_ctrl[8].m_vertex = p[0]; + } + break; + case eCapEndCap: { + Vector3 p5(vector3_mid(p[0], p[4])); + + setDims(3, 3); + m_ctrl[0].m_vertex = p[0]; + m_ctrl[1].m_vertex = p5; + m_ctrl[2].m_vertex = p[4]; + m_ctrl[3].m_vertex = p[1]; + m_ctrl[4].m_vertex = p[2]; + m_ctrl[5].m_vertex = p[3]; + m_ctrl[6].m_vertex = p[2]; + m_ctrl[7].m_vertex = p[2]; + m_ctrl[8].m_vertex = p[2]; + } + break; + case eCapIEndCap: { + setDims(5, 3); + m_ctrl[0].m_vertex = p[4]; + m_ctrl[1].m_vertex = p[3]; + m_ctrl[2].m_vertex = p[2]; + m_ctrl[3].m_vertex = p[1]; + m_ctrl[4].m_vertex = p[0]; + m_ctrl[5].m_vertex = p[3]; + m_ctrl[6].m_vertex = p[3]; + m_ctrl[7].m_vertex = p[2]; + m_ctrl[8].m_vertex = p[1]; + m_ctrl[9].m_vertex = p[1]; + m_ctrl[10].m_vertex = p[3]; + m_ctrl[11].m_vertex = p[3]; + m_ctrl[12].m_vertex = p[2]; + m_ctrl[13].m_vertex = p[1]; + m_ctrl[14].m_vertex = p[1]; + } + break; + case eCapCylinder: { + std::size_t mid = (width - 1) >> 1; + + bool degenerate = (mid % 2) != 0; + + std::size_t newHeight = mid + (degenerate ? 2 : 1); + + setDims(3, newHeight); + + if (degenerate) { + ++mid; + for (std::size_t i = width; i != width + 2; ++i) { + p[i] = p[width - 1]; + } + } + + { + PatchControl *pCtrl = m_ctrl.data(); + for (std::size_t i = 0; i != m_height; ++i, pCtrl += m_width) { + pCtrl->m_vertex = p[i]; + } + } + { + PatchControl *pCtrl = m_ctrl.data() + 2; + std::size_t h = m_height - 1; + for (std::size_t i = 0; i != m_height; ++i, pCtrl += m_width) { + pCtrl->m_vertex = p[h + (h - i)]; + } + } + + Redisperse(COL); + } + break; + default: + ERROR_MESSAGE("invalid patch-cap type"); + return; + } + CapTexture(); + controlPointsChanged(); +} + +void Patch::ProjectTexture(int nAxis) +{ + undoSave(); + + int s, t; + + switch (nAxis) { + case 2: + s = 0; + t = 1; + break; + case 0: + s = 1; + t = 2; + break; + case 1: + s = 0; + t = 2; + break; + default: + ERROR_MESSAGE("invalid axis"); + return; + } + + float fWidth = 1 / (m_state->getTexture().width * Texdef_getDefaultTextureScale()); + float fHeight = 1 / (m_state->getTexture().height * -Texdef_getDefaultTextureScale()); + + for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) { + (*i).m_texcoord[0] = (*i).m_vertex[s] * fWidth; + (*i).m_texcoord[1] = (*i).m_vertex[t] * fHeight; + } + + controlPointsChanged(); +} + +void Patch::constructPlane(const AABB &aabb, int axis, std::size_t width, std::size_t height) +{ + setDims(width, height); + + int x, y, z; + switch (axis) { + case 2: + x = 0; + y = 1; + z = 2; + break; + case 1: + x = 0; + y = 2; + z = 1; + break; + case 0: + x = 1; + y = 2; + z = 0; + break; + default: + ERROR_MESSAGE("invalid view-type"); + return; + } + + if (m_width < MIN_PATCH_WIDTH || m_width > MAX_PATCH_WIDTH) { + m_width = 3; + } + if (m_height < MIN_PATCH_HEIGHT || m_height > MAX_PATCH_HEIGHT) { + m_height = 3; + } + + Vector3 vStart; + vStart[x] = aabb.origin[x] - aabb.extents[x]; + vStart[y] = aabb.origin[y] - aabb.extents[y]; + vStart[z] = aabb.origin[z]; + + float xAdj = fabsf((vStart[x] - (aabb.origin[x] + aabb.extents[x])) / (float) (m_width - 1)); + float yAdj = fabsf((vStart[y] - (aabb.origin[y] + aabb.extents[y])) / (float) (m_height - 1)); + + Vector3 vTmp; + vTmp[z] = vStart[z]; + PatchControl *pCtrl = m_ctrl.data(); + + vTmp[y] = vStart[y]; + for (std::size_t h = 0; h < m_height; h++) { + vTmp[x] = vStart[x]; + for (std::size_t w = 0; w < m_width; w++, ++pCtrl) { + pCtrl->m_vertex = vTmp; + vTmp[x] += xAdj; + } + vTmp[y] += yAdj; + } + + NaturalTexture(); +} + +void Patch::ConstructPrefab(const AABB &aabb, EPatchPrefab eType, int axis, std::size_t width, std::size_t height) +{ + Vector3 vPos[3]; + + if (eType != ePlane) { + vPos[0] = vector3_subtracted(aabb.origin, aabb.extents); + vPos[1] = aabb.origin; + vPos[2] = vector3_added(aabb.origin, aabb.extents); + } + + if (eType == ePlane) { + constructPlane(aabb, axis, width, height); + } else if (eType == eSqCylinder + || eType == eCylinder + || eType == eDenseCylinder + || eType == eVeryDenseCylinder + || eType == eCone + || eType == eSphere) { + unsigned char *pIndex; + unsigned char pCylIndex[] = + { + 0, 0, + 1, 0, + 2, 0, + 2, 1, + 2, 2, + 1, 2, + 0, 2, + 0, 1, + 0, 0 + }; + + + PatchControl *pStart; + switch (eType) { + case eSqCylinder: + setDims(9, 3); + pStart = m_ctrl.data(); + break; + case eDenseCylinder: + case eVeryDenseCylinder: + case eCylinder: + setDims(9, 3); + pStart = m_ctrl.data() + 1; + break; + case eCone: + setDims(9, 3); + pStart = m_ctrl.data() + 1; + break; + case eSphere: + setDims(9, 5); + pStart = m_ctrl.data() + (9 + 1); + break; + default: + ERROR_MESSAGE("this should be unreachable"); + return; + } + + for (std::size_t h = 0; h < 3; h++, pStart += 9) { + pIndex = pCylIndex; + PatchControl *pCtrl = pStart; + for (std::size_t w = 0; w < 8; w++, pCtrl++) { + pCtrl->m_vertex[0] = vPos[pIndex[0]][0]; + pCtrl->m_vertex[1] = vPos[pIndex[1]][1]; + pCtrl->m_vertex[2] = vPos[h][2]; + pIndex += 2; + } + } + + switch (eType) { + case eSqCylinder: { + PatchControl *pCtrl = m_ctrl.data(); + for (std::size_t h = 0; h < 3; h++, pCtrl += 9) { + pCtrl[8].m_vertex = pCtrl[0].m_vertex; + } + } + break; + case eDenseCylinder: + case eVeryDenseCylinder: + case eCylinder: { + PatchControl *pCtrl = m_ctrl.data(); + for (std::size_t h = 0; h < 3; h++, pCtrl += 9) { + pCtrl[0].m_vertex = pCtrl[8].m_vertex; + } + } + break; + case eCone: { + PatchControl *pCtrl = m_ctrl.data(); + for (std::size_t h = 0; h < 2; h++, pCtrl += 9) { + pCtrl[0].m_vertex = pCtrl[8].m_vertex; + } + } + { + PatchControl *pCtrl = m_ctrl.data() + 9 * 2; + for (std::size_t w = 0; w < 9; w++, pCtrl++) { + pCtrl->m_vertex[0] = vPos[1][0]; + pCtrl->m_vertex[1] = vPos[1][1]; + pCtrl->m_vertex[2] = vPos[2][2]; + } + } + break; + case eSphere: { + PatchControl *pCtrl = m_ctrl.data() + 9; + for (std::size_t h = 0; h < 3; h++, pCtrl += 9) { + pCtrl[0].m_vertex = pCtrl[8].m_vertex; + } + } + { + PatchControl *pCtrl = m_ctrl.data(); + for (std::size_t w = 0; w < 9; w++, pCtrl++) { + pCtrl->m_vertex[0] = vPos[1][0]; + pCtrl->m_vertex[1] = vPos[1][1]; + pCtrl->m_vertex[2] = vPos[0][2]; + } + } + { + PatchControl *pCtrl = m_ctrl.data() + (9 * 4); + for (std::size_t w = 0; w < 9; w++, pCtrl++) { + pCtrl->m_vertex[0] = vPos[1][0]; + pCtrl->m_vertex[1] = vPos[1][1]; + pCtrl->m_vertex[2] = vPos[2][2]; + } + } + break; + default: + ERROR_MESSAGE("this should be unreachable"); + return; + } + } else if (eType == eXactCylinder) { + int n = (width - 1) / 2; // n = number of segments + setDims(width, height); + + // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents); + // vPos[1] = aabb.origin; + // vPos[2] = vector3_added(aabb.origin, aabb.extents); + + float f = 1 / cos(M_PI / n); + for (std::size_t i = 0; i < width; ++i) { + float angle = (M_PI * i) / n; // 0 to 2pi + float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) * cos(angle) * ((i & 1) ? f : 1.0f); + float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) * sin(angle) * ((i & 1) ? f : 1.0f); + for (std::size_t j = 0; j < height; ++j) { + float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float) (height - 1)); + PatchControl *v; + v = &m_ctrl.data()[j * width + i]; + v->m_vertex[0] = x; + v->m_vertex[1] = y; + v->m_vertex[2] = z; + } + } + } else if (eType == eXactCone) { + int n = (width - 1) / 2; // n = number of segments + setDims(width, height); + + // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents); + // vPos[1] = aabb.origin; + // vPos[2] = vector3_added(aabb.origin, aabb.extents); + + float f = 1 / cos(M_PI / n); + for (std::size_t i = 0; i < width; ++i) { + float angle = (M_PI * i) / n; + for (std::size_t j = 0; j < height; ++j) { + float x = vPos[1][0] + (1.0f - (j / (float) (height - 1))) * (vPos[2][0] - vPos[1][0]) * cos(angle) * + ((i & 1) ? f : 1.0f); + float y = vPos[1][1] + (1.0f - (j / (float) (height - 1))) * (vPos[2][1] - vPos[1][1]) * sin(angle) * + ((i & 1) ? f : 1.0f); + float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float) (height - 1)); + PatchControl *v; + v = &m_ctrl.data()[j * width + i]; + v->m_vertex[0] = x; + v->m_vertex[1] = y; + v->m_vertex[2] = z; + } + } + } else if (eType == eXactSphere) { + int n = (width - 1) / 2; // n = number of segments (yaw) + int m = (height - 1) / 2; // m = number of segments (pitch) + setDims(width, height); + + // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents); + // vPos[1] = aabb.origin; + // vPos[2] = vector3_added(aabb.origin, aabb.extents); + + float f = 1 / cos(M_PI / n); + float g = 1 / cos(M_PI / (2 * m)); + for (std::size_t i = 0; i < width; ++i) { + float angle = (M_PI * i) / n; + for (std::size_t j = 0; j < height; ++j) { + float angle2 = (M_PI * j) / (2 * m); + float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) * sin(angle2) * ((j & 1) ? g : 1.0f) * cos(angle) * + ((i & 1) ? f : 1.0f); + float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) * sin(angle2) * ((j & 1) ? g : 1.0f) * sin(angle) * + ((i & 1) ? f : 1.0f); + float z = vPos[1][2] + (vPos[2][2] - vPos[1][2]) * -cos(angle2) * ((j & 1) ? g : 1.0f); + PatchControl *v; + v = &m_ctrl.data()[j * width + i]; + v->m_vertex[0] = x; + v->m_vertex[1] = y; + v->m_vertex[2] = z; + } + } + } else if (eType == eBevel) { + unsigned char *pIndex; + unsigned char pBevIndex[] = + { + 0, 0, + 2, 0, + 2, 2, + }; + + setDims(3, 3); + + PatchControl *pCtrl = m_ctrl.data(); + for (std::size_t h = 0; h < 3; h++) { + pIndex = pBevIndex; + for (std::size_t w = 0; w < 3; w++, pIndex += 2, pCtrl++) { + pCtrl->m_vertex[0] = vPos[pIndex[0]][0]; + pCtrl->m_vertex[1] = vPos[pIndex[1]][1]; + pCtrl->m_vertex[2] = vPos[h][2]; + } + } + } else if (eType == eEndCap) { + unsigned char *pIndex; + unsigned char pEndIndex[] = + { + 2, 0, + 2, 2, + 1, 2, + 0, 2, + 0, 0, + }; + + setDims(5, 3); + + PatchControl *pCtrl = m_ctrl.data(); + for (std::size_t h = 0; h < 3; h++) { + pIndex = pEndIndex; + for (std::size_t w = 0; w < 5; w++, pIndex += 2, pCtrl++) { + pCtrl->m_vertex[0] = vPos[pIndex[0]][0]; + pCtrl->m_vertex[1] = vPos[pIndex[1]][1]; + pCtrl->m_vertex[2] = vPos[h][2]; + } + } + } + + if (eType == eDenseCylinder) { + InsertRemove(true, false, true); + } + + if (eType == eVeryDenseCylinder) { + InsertRemove(true, false, false); + InsertRemove(true, false, true); + } + + NaturalTexture(); +} + +void Patch::RenderDebug(RenderStateFlags state) const +{ + for (std::size_t i = 0; i < m_tess.m_numStrips; i++) { + glBegin(GL_QUAD_STRIP); + for (std::size_t j = 0; j < m_tess.m_lenStrips; j++) { + glNormal3fv(normal3f_to_array( + (m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j])->normal)); + glTexCoord2fv(texcoord2f_to_array( + (m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j])->texcoord)); + glVertex3fv(vertex3f_to_array( + (m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j])->vertex)); + } + glEnd(); + } +} + +void RenderablePatchSolid::RenderNormals() const +{ + const std::size_t width = m_tess.m_numStrips + 1; + const std::size_t height = m_tess.m_lenStrips >> 1; + glBegin(GL_LINES); + for (std::size_t i = 0; i < width; i++) { + for (std::size_t j = 0; j < height; j++) { + { + Vector3 vNormal( + vector3_added( + vertex3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->vertex), + vector3_scaled( + normal3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->normal), 8) + ) + ); + glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j * width + i))->vertex)); + glVertex3fv(&vNormal[0]); + } + { + Vector3 vNormal( + vector3_added( + vertex3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->vertex), + vector3_scaled( + normal3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->tangent), 8) + ) + ); + glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j * width + i))->vertex)); + glVertex3fv(&vNormal[0]); + } + { + Vector3 vNormal( + vector3_added( + vertex3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->vertex), + vector3_scaled( + normal3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->bitangent), 8) + ) + ); + glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j * width + i))->vertex)); + glVertex3fv(&vNormal[0]); + } + } + } + glEnd(); +} + +const int DEGEN_0a = 0x01; +const int DEGEN_1a = 0x02; +const int DEGEN_2a = 0x04; +const int DEGEN_0b = 0x08; +const int DEGEN_1b = 0x10; +const int DEGEN_2b = 0x20; +const int SPLIT = 0x40; +const int AVERAGE = 0x80; + + +unsigned int subarray_get_degen(PatchControlIter subarray, std::size_t strideU, std::size_t strideV) +{ + unsigned int nDegen = 0; + const PatchControl *p1; + const PatchControl *p2; + + p1 = subarray; + p2 = p1 + strideU; + if (vector3_equal(p1->m_vertex, p2->m_vertex)) { + nDegen |= DEGEN_0a; + } + p1 = p2; + p2 = p1 + strideU; + if (vector3_equal(p1->m_vertex, p2->m_vertex)) { + nDegen |= DEGEN_0b; + } + + p1 = subarray + strideV; + p2 = p1 + strideU; + if (vector3_equal(p1->m_vertex, p2->m_vertex)) { + nDegen |= DEGEN_1a; + } + p1 = p2; + p2 = p1 + strideU; + if (vector3_equal(p1->m_vertex, p2->m_vertex)) { + nDegen |= DEGEN_1b; + } + + p1 = subarray + (strideV << 1); + p2 = p1 + strideU; + if (vector3_equal(p1->m_vertex, p2->m_vertex)) { + nDegen |= DEGEN_2a; + } + p1 = p2; + p2 = p1 + strideU; + if (vector3_equal(p1->m_vertex, p2->m_vertex)) { + nDegen |= DEGEN_2b; + } + + return nDegen; +} + + +inline void +deCasteljau3(const Vector3 &P0, const Vector3 &P1, const Vector3 &P2, Vector3 &P01, Vector3 &P12, Vector3 &P012) +{ + P01 = vector3_mid(P0, P1); + P12 = vector3_mid(P1, P2); + P012 = vector3_mid(P01, P12); +} - { - PatchControl* p2 = p1; - for ( std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride ) - { - if ( 0 ) { //p2->m_selectable.isSelected()) - pos = h; - break; - } - } - if ( pos != 0 ) { - break; - } - } - } - } +inline void BezierInterpolate3(const Vector3 &start, Vector3 &left, Vector3 &mid, Vector3 &right, const Vector3 &end) +{ + left = vector3_mid(start, mid); + right = vector3_mid(mid, end); + mid = vector3_mid(left, right); +} - Array tmp( m_ctrl ); - - std::size_t row_stride2, col_stride2; - switch ( mt ) - { - case ROW: - setDims( m_width, m_height + 2 ); - col_stride2 = 1; - row_stride2 = m_width; - break; - case COL: - setDims( m_width + 2, m_height ); - col_stride2 = m_width; - row_stride2 = 1; - break; - default: - ERROR_MESSAGE( "neither row-major nor column-major" ); - return; - } - if ( bFirst ) { - pos = height - 1; - } - else - { - pos = 2; - } +inline void BezierInterpolate2(const Vector2 &start, Vector2 &left, Vector2 &mid, Vector2 &right, const Vector2 &end) +{ + left[0] = float_mid(start[0], mid[0]); + left[1] = float_mid(start[1], mid[1]); + right[0] = float_mid(mid[0], end[0]); + right[1] = float_mid(mid[1], end[1]); + mid[0] = float_mid(left[0], right[0]); + mid[1] = float_mid(left[1], right[1]); +} - if ( pos >= height ) { - if ( bFirst ) { - pos = height - 1; - } - else - { - pos = 2; - } - } - else if ( pos == 0 ) { - pos = 2; - } - else if ( pos % 2 ) { - ++pos; - } +inline Vector2 &texcoord_for_index(Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].texcoord ); +} - for ( std::size_t w = 0; w != width; ++w ) - { - PatchControl* p1 = tmp.data() + ( w * col_stride ); - PatchControl* p2 = m_ctrl.data() + ( w * col_stride2 ); - for ( std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride ) - { - if ( h == pos ) { - p2 += 2 * row_stride2; - } - *p2 = *p1; - } +inline Vector3 &vertex_for_index(Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].vertex ); +} - p1 = tmp.data() + ( w * col_stride + pos * row_stride ); - p2 = m_ctrl.data() + ( w * col_stride2 + pos * row_stride2 ); +inline Vector3 &normal_for_index(Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].normal ); +} - PatchControl* r2a = ( p2 + row_stride2 ); - PatchControl* r2b = ( p2 - row_stride2 ); - PatchControl* c2a = ( p1 - 2 * row_stride ); - PatchControl* c2b = ( p1 - row_stride ); +inline Vector3 &tangent_for_index(Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].tangent ); +} - // set two new row points - *( p2 + 2 * row_stride2 ) = *p1; - *r2a = *c2b; +inline Vector3 &bitangent_for_index(Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].bitangent ); +} - for ( std::size_t i = 0; i != 3; ++i ) - { - r2a->m_vertex[i] = float_mid( c2b->m_vertex[i], p1->m_vertex[i] ); +inline const Vector2 &texcoord_for_index(const Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].texcoord ); +} - r2b->m_vertex[i] = float_mid( c2a->m_vertex[i], c2b->m_vertex[i] ); +inline const Vector3 &vertex_for_index(const Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].vertex ); +} - p2->m_vertex[i] = float_mid( r2a->m_vertex[i], r2b->m_vertex[i] ); - } - for ( std::size_t i = 0; i != 2; ++i ) - { - r2a->m_texcoord[i] = float_mid( c2b->m_texcoord[i], p1->m_texcoord[i] ); +inline const Vector3 &normal_for_index(const Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].normal ); +} - r2b->m_texcoord[i] = float_mid( c2a->m_texcoord[i], c2b->m_texcoord[i] ); +inline const Vector3 &tangent_for_index(const Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].tangent ); +} - p2->m_texcoord[i] = float_mid( r2a->m_texcoord[i], r2b->m_texcoord[i] ); - } - } +inline const Vector3 &bitangent_for_index(const Array &vertices, std::size_t index) +{ + return reinterpret_cast( vertices[index].bitangent ); } -void Patch::RemovePoints( EMatrixMajor mt, bool bFirst ){ - std::size_t width, height, row_stride, col_stride; - - switch ( mt ) - { - case ROW: - col_stride = 1; - row_stride = m_width; - width = m_width; - height = m_height; - break; - case COL: - col_stride = m_width; - row_stride = 1; - width = m_height; - height = m_width; - break; - default: - ERROR_MESSAGE( "neither row-major nor column-major" ); - return; - } +#include "math/curve.h" - std::size_t pos = 0; - { - PatchControl* p1 = m_ctrl.data(); - for ( std::size_t w = 0; w != width; ++w, p1 += col_stride ) - { - { - PatchControl* p2 = p1; - for ( std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride ) - { - if ( 0 ) { //p2->m_selectable.isSelected()) - pos = h; - break; - } - } - if ( pos != 0 ) { - break; - } - } +inline PatchControl QuadraticBezier_evaluate(const PatchControl *firstPoint, double t) +{ + PatchControl result = {Vector3(0, 0, 0), Vector2(0, 0)}; + double denominator = 0; + + { + double weight = BernsteinPolynomial::apply(t); + vector3_add(result.m_vertex, vector3_scaled(firstPoint[0].m_vertex, weight)); + vector2_add(result.m_texcoord, vector2_scaled(firstPoint[0].m_texcoord, weight)); + denominator += weight; + } + { + double weight = BernsteinPolynomial::apply(t); + vector3_add(result.m_vertex, vector3_scaled(firstPoint[1].m_vertex, weight)); + vector2_add(result.m_texcoord, vector2_scaled(firstPoint[1].m_texcoord, weight)); + denominator += weight; + } + { + double weight = BernsteinPolynomial::apply(t); + vector3_add(result.m_vertex, vector3_scaled(firstPoint[2].m_vertex, weight)); + vector2_add(result.m_texcoord, vector2_scaled(firstPoint[2].m_texcoord, weight)); + denominator += weight; + } + + vector3_divide(result.m_vertex, denominator); + vector2_divide(result.m_texcoord, denominator); + return result; +} + +inline Vector3 vector3_linear_interpolated(const Vector3 &a, const Vector3 &b, double t) +{ + return vector3_added(vector3_scaled(a, 1.0 - t), vector3_scaled(b, t)); +} - { - PatchControl* p2 = p1; - for ( std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride ) - { - if ( 0 ) { //p2->m_selectable.isSelected()) - pos = h; - break; - } - } - if ( pos != 0 ) { - break; - } - } - } - } +inline Vector2 vector2_linear_interpolated(const Vector2 &a, const Vector2 &b, double t) +{ + return vector2_added(vector2_scaled(a, 1.0 - t), vector2_scaled(b, t)); +} - Array tmp( m_ctrl ); - - std::size_t row_stride2, col_stride2; - switch ( mt ) - { - case ROW: - setDims( m_width, m_height - 2 ); - col_stride2 = 1; - row_stride2 = m_width; - break; - case COL: - setDims( m_width - 2, m_height ); - col_stride2 = m_width; - row_stride2 = 1; - break; - default: - ERROR_MESSAGE( "neither row-major nor column-major" ); - return; - } - if ( bFirst ) { - pos = height - 3; - } - else - { - pos = 2; - } - if ( pos >= height ) { - if ( bFirst ) { - pos = height - 3; - } - else - { - pos = 2; - } - } - else if ( pos == 0 ) { - pos = 2; - } - else if ( pos > height - 3 ) { - pos = height - 3; - } - else if ( pos % 2 ) { - ++pos; - } +void normalise_safe(Vector3 &normal) +{ + if (!vector3_equal(normal, g_vector3_identity)) { + vector3_normalise(normal); + } +} - for ( std::size_t w = 0; w != width; w++ ) - { - PatchControl* p1 = tmp.data() + ( w * col_stride ); - PatchControl* p2 = m_ctrl.data() + ( w * col_stride2 ); - for ( std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride ) - { - if ( h == pos ) { - p1 += 2 * row_stride2; h += 2; - } - *p2 = *p1; - } +inline void QuadraticBezier_evaluate(const PatchControl &a, const PatchControl &b, const PatchControl &c, double t, + PatchControl &point, PatchControl &left, PatchControl &right) +{ + left.m_vertex = vector3_linear_interpolated(a.m_vertex, b.m_vertex, t); + left.m_texcoord = vector2_linear_interpolated(a.m_texcoord, b.m_texcoord, t); + right.m_vertex = vector3_linear_interpolated(b.m_vertex, c.m_vertex, t); + right.m_texcoord = vector2_linear_interpolated(b.m_texcoord, c.m_texcoord, t); + point.m_vertex = vector3_linear_interpolated(left.m_vertex, right.m_vertex, t); + point.m_texcoord = vector2_linear_interpolated(left.m_texcoord, right.m_texcoord, t); +} - p1 = tmp.data() + ( w * col_stride + pos * row_stride ); - p2 = m_ctrl.data() + ( w * col_stride2 + pos * row_stride2 ); +void Patch::TesselateSubMatrixFixed(ArbitraryMeshVertex *vertices, std::size_t strideX, std::size_t strideY, + unsigned int nFlagsX, unsigned int nFlagsY, PatchControl *subMatrix[3][3]) +{ + double incrementU = 1.0 / m_subdivisions_x; + double incrementV = 1.0 / m_subdivisions_y; + const std::size_t width = m_subdivisions_x + 1; + const std::size_t height = m_subdivisions_y + 1; + + for (std::size_t i = 0; i != width; ++i) { + double tU = (i + 1 == width) ? 1 : i * incrementU; + PatchControl pointX[3]; + PatchControl leftX[3]; + PatchControl rightX[3]; + QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[0][1], *subMatrix[0][2], tU, pointX[0], leftX[0], + rightX[0]); + QuadraticBezier_evaluate(*subMatrix[1][0], *subMatrix[1][1], *subMatrix[1][2], tU, pointX[1], leftX[1], + rightX[1]); + QuadraticBezier_evaluate(*subMatrix[2][0], *subMatrix[2][1], *subMatrix[2][2], tU, pointX[2], leftX[2], + rightX[2]); + + ArbitraryMeshVertex *p = vertices + i * strideX; + for (std::size_t j = 0; j != height; ++j) { + if ((j == 0 || j + 1 == height) && (i == 0 || i + 1 == width)) { + } else { + double tV = (j + 1 == height) ? 1 : j * incrementV; + + PatchControl pointY[3]; + PatchControl leftY[3]; + PatchControl rightY[3]; + QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[1][0], *subMatrix[2][0], tV, pointY[0], leftY[0], + rightY[0]); + QuadraticBezier_evaluate(*subMatrix[0][1], *subMatrix[1][1], *subMatrix[2][1], tV, pointY[1], leftY[1], + rightY[1]); + QuadraticBezier_evaluate(*subMatrix[0][2], *subMatrix[1][2], *subMatrix[2][2], tV, pointY[2], leftY[2], + rightY[2]); + + PatchControl point; + PatchControl left; + PatchControl right; + QuadraticBezier_evaluate(pointX[0], pointX[1], pointX[2], tV, point, left, right); + PatchControl up; + PatchControl down; + QuadraticBezier_evaluate(pointY[0], pointY[1], pointY[2], tU, point, up, down); + + vertex3f_to_vector3(p->vertex) = point.m_vertex; + texcoord2f_to_vector2(p->texcoord) = point.m_texcoord; + + ArbitraryMeshVertex a, b, c; + + a.vertex = vertex3f_for_vector3(left.m_vertex); + a.texcoord = texcoord2f_for_vector2(left.m_texcoord); + b.vertex = vertex3f_for_vector3(right.m_vertex); + b.texcoord = texcoord2f_for_vector2(right.m_texcoord); + + if (i != 0) { + c.vertex = vertex3f_for_vector3(up.m_vertex); + c.texcoord = texcoord2f_for_vector2(up.m_texcoord); + } else { + c.vertex = vertex3f_for_vector3(down.m_vertex); + c.texcoord = texcoord2f_for_vector2(down.m_texcoord); + } + + Vector3 normal = vector3_normalised( + vector3_cross(right.m_vertex - left.m_vertex, up.m_vertex - down.m_vertex)); + + Vector3 tangent, bitangent; + ArbitraryMeshTriangle_calcTangents(a, b, c, tangent, bitangent); + vector3_normalise(tangent); + vector3_normalise(bitangent); + + if (((nFlagsX & AVERAGE) != 0 && i == 0) || ((nFlagsY & AVERAGE) != 0 && j == 0)) { + normal3f_to_vector3(p->normal) = vector3_normalised( + vector3_added(normal3f_to_vector3(p->normal), normal)); + normal3f_to_vector3(p->tangent) = vector3_normalised( + vector3_added(normal3f_to_vector3(p->tangent), tangent)); + normal3f_to_vector3(p->bitangent) = vector3_normalised( + vector3_added(normal3f_to_vector3(p->bitangent), bitangent)); + } else { + normal3f_to_vector3(p->normal) = normal; + normal3f_to_vector3(p->tangent) = tangent; + normal3f_to_vector3(p->bitangent) = bitangent; + } + } + + p += strideY; + } + } +} + +void Patch::TesselateSubMatrix(const BezierCurveTree *BX, const BezierCurveTree *BY, + std::size_t offStartX, std::size_t offStartY, + std::size_t offEndX, std::size_t offEndY, + std::size_t nFlagsX, std::size_t nFlagsY, + Vector3 &left, Vector3 &mid, Vector3 &right, + Vector2 &texLeft, Vector2 &texMid, Vector2 &texRight, + bool bTranspose) +{ + int newFlagsX, newFlagsY; - for ( std::size_t i = 0; i < 3; i++ ) - { - ( p2 - row_stride2 )->m_vertex[i] = ( ( p1 + 2 * row_stride )->m_vertex[i] + ( p1 - 2 * row_stride )->m_vertex[i] ) * 0.5f; + Vector3 tmp; + Vector3 vertex_0_0, vertex_0_1, vertex_1_0, vertex_1_1, vertex_2_0, vertex_2_1; + Vector2 texTmp; + Vector2 texcoord_0_0, texcoord_0_1, texcoord_1_0, texcoord_1_1, texcoord_2_0, texcoord_2_1; - ( p2 - row_stride2 )->m_vertex[i] = ( p2 - row_stride2 )->m_vertex[i] + ( 2.0f * ( ( p1 )->m_vertex[i] - ( p2 - row_stride2 )->m_vertex[i] ) ); - } - for ( std::size_t i = 0; i < 2; i++ ) - { - ( p2 - row_stride2 )->m_texcoord[i] = ( ( p1 + 2 * row_stride )->m_texcoord[i] + ( p1 - 2 * row_stride )->m_texcoord[i] ) * 0.5f; - - ( p2 - row_stride2 )->m_texcoord[i] = ( p2 - row_stride2 )->m_texcoord[i] + ( 2.0f * ( ( p1 )->m_texcoord[i] - ( p2 - row_stride2 )->m_texcoord[i] ) ); - } - } -} - -void Patch::ConstructSeam( EPatchCap eType, Vector3* p, std::size_t width ){ - switch ( eType ) - { - case eCapIBevel: - { - setDims( 3, 3 ); - m_ctrl[0].m_vertex = p[0]; - m_ctrl[1].m_vertex = p[1]; - m_ctrl[2].m_vertex = p[1]; - m_ctrl[3].m_vertex = p[1]; - m_ctrl[4].m_vertex = p[1]; - m_ctrl[5].m_vertex = p[1]; - m_ctrl[6].m_vertex = p[2]; - m_ctrl[7].m_vertex = p[1]; - m_ctrl[8].m_vertex = p[1]; - } - break; - case eCapBevel: - { - setDims( 3, 3 ); - Vector3 p3( vector3_added( p[2], vector3_subtracted( p[0], p[1] ) ) ); - m_ctrl[0].m_vertex = p3; - m_ctrl[1].m_vertex = p3; - m_ctrl[2].m_vertex = p[2]; - m_ctrl[3].m_vertex = p3; - m_ctrl[4].m_vertex = p3; - m_ctrl[5].m_vertex = p[1]; - m_ctrl[6].m_vertex = p3; - m_ctrl[7].m_vertex = p3; - m_ctrl[8].m_vertex = p[0]; - } - break; - case eCapEndCap: - { - Vector3 p5( vector3_mid( p[0], p[4] ) ); - - setDims( 3, 3 ); - m_ctrl[0].m_vertex = p[0]; - m_ctrl[1].m_vertex = p5; - m_ctrl[2].m_vertex = p[4]; - m_ctrl[3].m_vertex = p[1]; - m_ctrl[4].m_vertex = p[2]; - m_ctrl[5].m_vertex = p[3]; - m_ctrl[6].m_vertex = p[2]; - m_ctrl[7].m_vertex = p[2]; - m_ctrl[8].m_vertex = p[2]; - } - break; - case eCapIEndCap: - { - setDims( 5, 3 ); - m_ctrl[0].m_vertex = p[4]; - m_ctrl[1].m_vertex = p[3]; - m_ctrl[2].m_vertex = p[2]; - m_ctrl[3].m_vertex = p[1]; - m_ctrl[4].m_vertex = p[0]; - m_ctrl[5].m_vertex = p[3]; - m_ctrl[6].m_vertex = p[3]; - m_ctrl[7].m_vertex = p[2]; - m_ctrl[8].m_vertex = p[1]; - m_ctrl[9].m_vertex = p[1]; - m_ctrl[10].m_vertex = p[3]; - m_ctrl[11].m_vertex = p[3]; - m_ctrl[12].m_vertex = p[2]; - m_ctrl[13].m_vertex = p[1]; - m_ctrl[14].m_vertex = p[1]; - } - break; - case eCapCylinder: - { - std::size_t mid = ( width - 1 ) >> 1; - - bool degenerate = ( mid % 2 ) != 0; - - std::size_t newHeight = mid + ( degenerate ? 2 : 1 ); - - setDims( 3, newHeight ); - - if ( degenerate ) { - ++mid; - for ( std::size_t i = width; i != width + 2; ++i ) - { - p[i] = p[width - 1]; - } - } - - { - PatchControl* pCtrl = m_ctrl.data(); - for ( std::size_t i = 0; i != m_height; ++i, pCtrl += m_width ) - { - pCtrl->m_vertex = p[i]; - } - } - { - PatchControl* pCtrl = m_ctrl.data() + 2; - std::size_t h = m_height - 1; - for ( std::size_t i = 0; i != m_height; ++i, pCtrl += m_width ) - { - pCtrl->m_vertex = p[h + ( h - i )]; - } - } - - Redisperse( COL ); - } - break; - default: - ERROR_MESSAGE( "invalid patch-cap type" ); - return; - } - CapTexture(); - controlPointsChanged(); -} - -void Patch::ProjectTexture( int nAxis ){ - undoSave(); - - int s, t; - - switch ( nAxis ) - { - case 2: - s = 0; - t = 1; - break; - case 0: - s = 1; - t = 2; - break; - case 1: - s = 0; - t = 2; - break; - default: - ERROR_MESSAGE( "invalid axis" ); - return; - } - - float fWidth = 1 / ( m_state->getTexture().width * Texdef_getDefaultTextureScale() ); - float fHeight = 1 / ( m_state->getTexture().height * -Texdef_getDefaultTextureScale() ); - - for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i ) - { - ( *i ).m_texcoord[0] = ( *i ).m_vertex[s] * fWidth; - ( *i ).m_texcoord[1] = ( *i ).m_vertex[t] * fHeight; - } - - controlPointsChanged(); -} - -void Patch::constructPlane( const AABB& aabb, int axis, std::size_t width, std::size_t height ){ - setDims( width, height ); - - int x, y, z; - switch ( axis ) - { - case 2: x = 0; y = 1; z = 2; break; - case 1: x = 0; y = 2; z = 1; break; - case 0: x = 1; y = 2; z = 0; break; - default: - ERROR_MESSAGE( "invalid view-type" ); - return; - } - - if ( m_width < MIN_PATCH_WIDTH || m_width > MAX_PATCH_WIDTH ) { - m_width = 3; - } - if ( m_height < MIN_PATCH_HEIGHT || m_height > MAX_PATCH_HEIGHT ) { - m_height = 3; - } - - Vector3 vStart; - vStart[x] = aabb.origin[x] - aabb.extents[x]; - vStart[y] = aabb.origin[y] - aabb.extents[y]; - vStart[z] = aabb.origin[z]; - - float xAdj = fabsf( ( vStart[x] - ( aabb.origin[x] + aabb.extents[x] ) ) / (float)( m_width - 1 ) ); - float yAdj = fabsf( ( vStart[y] - ( aabb.origin[y] + aabb.extents[y] ) ) / (float)( m_height - 1 ) ); - - Vector3 vTmp; - vTmp[z] = vStart[z]; - PatchControl* pCtrl = m_ctrl.data(); - - vTmp[y] = vStart[y]; - for ( std::size_t h = 0; h < m_height; h++ ) - { - vTmp[x] = vStart[x]; - for ( std::size_t w = 0; w < m_width; w++, ++pCtrl ) - { - pCtrl->m_vertex = vTmp; - vTmp[x] += xAdj; - } - vTmp[y] += yAdj; - } - - NaturalTexture(); -} - -void Patch::ConstructPrefab( const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width, std::size_t height ){ - Vector3 vPos[3]; - - if ( eType != ePlane ) { - vPos[0] = vector3_subtracted( aabb.origin, aabb.extents ); - vPos[1] = aabb.origin; - vPos[2] = vector3_added( aabb.origin, aabb.extents ); - } - - if ( eType == ePlane ) { - constructPlane( aabb, axis, width, height ); - } - else if ( eType == eSqCylinder - || eType == eCylinder - || eType == eDenseCylinder - || eType == eVeryDenseCylinder - || eType == eCone - || eType == eSphere ) { - unsigned char *pIndex; - unsigned char pCylIndex[] = - { - 0, 0, - 1, 0, - 2, 0, - 2, 1, - 2, 2, - 1, 2, - 0, 2, - 0, 1, - 0, 0 - }; - - - PatchControl *pStart; - switch ( eType ) - { - case eSqCylinder: setDims( 9, 3 ); - pStart = m_ctrl.data(); - break; - case eDenseCylinder: - case eVeryDenseCylinder: - case eCylinder: - setDims( 9, 3 ); - pStart = m_ctrl.data() + 1; - break; - case eCone: setDims( 9, 3 ); - pStart = m_ctrl.data() + 1; - break; - case eSphere: - setDims( 9, 5 ); - pStart = m_ctrl.data() + ( 9 + 1 ); - break; - default: - ERROR_MESSAGE( "this should be unreachable" ); - return; - } - - for ( std::size_t h = 0; h < 3; h++, pStart += 9 ) - { - pIndex = pCylIndex; - PatchControl* pCtrl = pStart; - for ( std::size_t w = 0; w < 8; w++, pCtrl++ ) - { - pCtrl->m_vertex[0] = vPos[pIndex[0]][0]; - pCtrl->m_vertex[1] = vPos[pIndex[1]][1]; - pCtrl->m_vertex[2] = vPos[h][2]; - pIndex += 2; - } - } - - switch ( eType ) - { - case eSqCylinder: - { - PatchControl* pCtrl = m_ctrl.data(); - for ( std::size_t h = 0; h < 3; h++, pCtrl += 9 ) - { - pCtrl[8].m_vertex = pCtrl[0].m_vertex; - } - } - break; - case eDenseCylinder: - case eVeryDenseCylinder: - case eCylinder: - { - PatchControl* pCtrl = m_ctrl.data(); - for ( std::size_t h = 0; h < 3; h++, pCtrl += 9 ) - { - pCtrl[0].m_vertex = pCtrl[8].m_vertex; - } - } - break; - case eCone: - { - PatchControl* pCtrl = m_ctrl.data(); - for ( std::size_t h = 0; h < 2; h++, pCtrl += 9 ) - { - pCtrl[0].m_vertex = pCtrl[8].m_vertex; - } - } - { - PatchControl* pCtrl = m_ctrl.data() + 9 * 2; - for ( std::size_t w = 0; w < 9; w++, pCtrl++ ) - { - pCtrl->m_vertex[0] = vPos[1][0]; - pCtrl->m_vertex[1] = vPos[1][1]; - pCtrl->m_vertex[2] = vPos[2][2]; - } - } - break; - case eSphere: - { - PatchControl* pCtrl = m_ctrl.data() + 9; - for ( std::size_t h = 0; h < 3; h++, pCtrl += 9 ) - { - pCtrl[0].m_vertex = pCtrl[8].m_vertex; - } - } - { - PatchControl* pCtrl = m_ctrl.data(); - for ( std::size_t w = 0; w < 9; w++, pCtrl++ ) - { - pCtrl->m_vertex[0] = vPos[1][0]; - pCtrl->m_vertex[1] = vPos[1][1]; - pCtrl->m_vertex[2] = vPos[0][2]; - } - } - { - PatchControl* pCtrl = m_ctrl.data() + ( 9 * 4 ); - for ( std::size_t w = 0; w < 9; w++, pCtrl++ ) - { - pCtrl->m_vertex[0] = vPos[1][0]; - pCtrl->m_vertex[1] = vPos[1][1]; - pCtrl->m_vertex[2] = vPos[2][2]; - } - } - break; - default: - ERROR_MESSAGE( "this should be unreachable" ); - return; - } - } - else if ( eType == eXactCylinder ) { - int n = ( width - 1 ) / 2; // n = number of segments - setDims( width, height ); - - // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents); - // vPos[1] = aabb.origin; - // vPos[2] = vector3_added(aabb.origin, aabb.extents); - - float f = 1 / cos( M_PI / n ); - for ( std::size_t i = 0; i < width; ++i ) - { - float angle = ( M_PI * i ) / n; // 0 to 2pi - float x = vPos[1][0] + ( vPos[2][0] - vPos[1][0] ) * cos( angle ) * ( ( i & 1 ) ? f : 1.0f ); - float y = vPos[1][1] + ( vPos[2][1] - vPos[1][1] ) * sin( angle ) * ( ( i & 1 ) ? f : 1.0f ); - for ( std::size_t j = 0; j < height; ++j ) - { - float z = vPos[0][2] + ( vPos[2][2] - vPos[0][2] ) * ( j / (float)( height - 1 ) ); - PatchControl *v; - v = &m_ctrl.data()[j * width + i]; - v->m_vertex[0] = x; - v->m_vertex[1] = y; - v->m_vertex[2] = z; - } - } - } - else if ( eType == eXactCone ) { - int n = ( width - 1 ) / 2; // n = number of segments - setDims( width, height ); - - // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents); - // vPos[1] = aabb.origin; - // vPos[2] = vector3_added(aabb.origin, aabb.extents); - - float f = 1 / cos( M_PI / n ); - for ( std::size_t i = 0; i < width; ++i ) - { - float angle = ( M_PI * i ) / n; - for ( std::size_t j = 0; j < height; ++j ) - { - float x = vPos[1][0] + ( 1.0f - ( j / (float)( height - 1 ) ) ) * ( vPos[2][0] - vPos[1][0] ) * cos( angle ) * ( ( i & 1 ) ? f : 1.0f ); - float y = vPos[1][1] + ( 1.0f - ( j / (float)( height - 1 ) ) ) * ( vPos[2][1] - vPos[1][1] ) * sin( angle ) * ( ( i & 1 ) ? f : 1.0f ); - float z = vPos[0][2] + ( vPos[2][2] - vPos[0][2] ) * ( j / (float)( height - 1 ) ); - PatchControl *v; - v = &m_ctrl.data()[j * width + i]; - v->m_vertex[0] = x; - v->m_vertex[1] = y; - v->m_vertex[2] = z; - } - } - } - else if ( eType == eXactSphere ) { - int n = ( width - 1 ) / 2; // n = number of segments (yaw) - int m = ( height - 1 ) / 2; // m = number of segments (pitch) - setDims( width, height ); - - // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents); - // vPos[1] = aabb.origin; - // vPos[2] = vector3_added(aabb.origin, aabb.extents); - - float f = 1 / cos( M_PI / n ); - float g = 1 / cos( M_PI / ( 2 * m ) ); - for ( std::size_t i = 0; i < width; ++i ) - { - float angle = ( M_PI * i ) / n; - for ( std::size_t j = 0; j < height; ++j ) - { - float angle2 = ( M_PI * j ) / ( 2 * m ); - float x = vPos[1][0] + ( vPos[2][0] - vPos[1][0] ) * sin( angle2 ) * ( ( j & 1 ) ? g : 1.0f ) * cos( angle ) * ( ( i & 1 ) ? f : 1.0f ); - float y = vPos[1][1] + ( vPos[2][1] - vPos[1][1] ) * sin( angle2 ) * ( ( j & 1 ) ? g : 1.0f ) * sin( angle ) * ( ( i & 1 ) ? f : 1.0f ); - float z = vPos[1][2] + ( vPos[2][2] - vPos[1][2] ) * -cos( angle2 ) * ( ( j & 1 ) ? g : 1.0f ); - PatchControl *v; - v = &m_ctrl.data()[j * width + i]; - v->m_vertex[0] = x; - v->m_vertex[1] = y; - v->m_vertex[2] = z; - } - } - } - else if ( eType == eBevel ) { - unsigned char *pIndex; - unsigned char pBevIndex[] = - { - 0, 0, - 2, 0, - 2, 2, - }; - - setDims( 3, 3 ); - - PatchControl* pCtrl = m_ctrl.data(); - for ( std::size_t h = 0; h < 3; h++ ) - { - pIndex = pBevIndex; - for ( std::size_t w = 0; w < 3; w++, pIndex += 2, pCtrl++ ) - { - pCtrl->m_vertex[0] = vPos[pIndex[0]][0]; - pCtrl->m_vertex[1] = vPos[pIndex[1]][1]; - pCtrl->m_vertex[2] = vPos[h][2]; - } - } - } - else if ( eType == eEndCap ) { - unsigned char *pIndex; - unsigned char pEndIndex[] = - { - 2, 0, - 2, 2, - 1, 2, - 0, 2, - 0, 0, - }; - - setDims( 5, 3 ); - - PatchControl* pCtrl = m_ctrl.data(); - for ( std::size_t h = 0; h < 3; h++ ) - { - pIndex = pEndIndex; - for ( std::size_t w = 0; w < 5; w++, pIndex += 2, pCtrl++ ) - { - pCtrl->m_vertex[0] = vPos[pIndex[0]][0]; - pCtrl->m_vertex[1] = vPos[pIndex[1]][1]; - pCtrl->m_vertex[2] = vPos[h][2]; - } - } - } - - if ( eType == eDenseCylinder ) { - InsertRemove( true, false, true ); - } - - if ( eType == eVeryDenseCylinder ) { - InsertRemove( true, false, false ); - InsertRemove( true, false, true ); - } - - NaturalTexture(); -} - -void Patch::RenderDebug( RenderStateFlags state ) const { - for ( std::size_t i = 0; i < m_tess.m_numStrips; i++ ) - { - glBegin( GL_QUAD_STRIP ); - for ( std::size_t j = 0; j < m_tess.m_lenStrips; j++ ) - { - glNormal3fv( normal3f_to_array( ( m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j] )->normal ) ); - glTexCoord2fv( texcoord2f_to_array( ( m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j] )->texcoord ) ); - glVertex3fv( vertex3f_to_array( ( m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j] )->vertex ) ); - } - glEnd(); - } -} - -void RenderablePatchSolid::RenderNormals() const { - const std::size_t width = m_tess.m_numStrips + 1; - const std::size_t height = m_tess.m_lenStrips >> 1; - glBegin( GL_LINES ); - for ( std::size_t i = 0; i < width; i++ ) - { - for ( std::size_t j = 0; j < height; j++ ) - { - { - Vector3 vNormal( - vector3_added( - vertex3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ), - vector3_scaled( normal3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->normal ), 8 ) - ) - ); - glVertex3fv( vertex3f_to_array( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ) ); - glVertex3fv( &vNormal[0] ); - } - { - Vector3 vNormal( - vector3_added( - vertex3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ), - vector3_scaled( normal3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->tangent ), 8 ) - ) - ); - glVertex3fv( vertex3f_to_array( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ) ); - glVertex3fv( &vNormal[0] ); - } - { - Vector3 vNormal( - vector3_added( - vertex3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ), - vector3_scaled( normal3f_to_vector3( ( m_tess.m_vertices.data() + ( j * width + i ) )->bitangent ), 8 ) - ) - ); - glVertex3fv( vertex3f_to_array( ( m_tess.m_vertices.data() + ( j * width + i ) )->vertex ) ); - glVertex3fv( &vNormal[0] ); - } - } - } - glEnd(); -} - -const int DEGEN_0a = 0x01; -const int DEGEN_1a = 0x02; -const int DEGEN_2a = 0x04; -const int DEGEN_0b = 0x08; -const int DEGEN_1b = 0x10; -const int DEGEN_2b = 0x20; -const int SPLIT = 0x40; -const int AVERAGE = 0x80; - - -unsigned int subarray_get_degen( PatchControlIter subarray, std::size_t strideU, std::size_t strideV ){ - unsigned int nDegen = 0; - const PatchControl* p1; - const PatchControl* p2; - - p1 = subarray; - p2 = p1 + strideU; - if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) { - nDegen |= DEGEN_0a; - } - p1 = p2; - p2 = p1 + strideU; - if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) { - nDegen |= DEGEN_0b; - } - - p1 = subarray + strideV; - p2 = p1 + strideU; - if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) { - nDegen |= DEGEN_1a; - } - p1 = p2; - p2 = p1 + strideU; - if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) { - nDegen |= DEGEN_1b; - } - - p1 = subarray + ( strideV << 1 ); - p2 = p1 + strideU; - if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) { - nDegen |= DEGEN_2a; - } - p1 = p2; - p2 = p1 + strideU; - if ( vector3_equal( p1->m_vertex, p2->m_vertex ) ) { - nDegen |= DEGEN_2b; - } - - return nDegen; -} - - -inline void deCasteljau3( const Vector3& P0, const Vector3& P1, const Vector3& P2, Vector3& P01, Vector3& P12, Vector3& P012 ){ - P01 = vector3_mid( P0, P1 ); - P12 = vector3_mid( P1, P2 ); - P012 = vector3_mid( P01, P12 ); -} - -inline void BezierInterpolate3( const Vector3& start, Vector3& left, Vector3& mid, Vector3& right, const Vector3& end ){ - left = vector3_mid( start, mid ); - right = vector3_mid( mid, end ); - mid = vector3_mid( left, right ); -} - -inline void BezierInterpolate2( const Vector2& start, Vector2& left, Vector2& mid, Vector2& right, const Vector2& end ){ - left[0] = float_mid( start[0], mid[0] ); - left[1] = float_mid( start[1], mid[1] ); - right[0] = float_mid( mid[0], end[0] ); - right[1] = float_mid( mid[1], end[1] ); - mid[0] = float_mid( left[0], right[0] ); - mid[1] = float_mid( left[1], right[1] ); -} - - -inline Vector2& texcoord_for_index( Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].texcoord ); -} - -inline Vector3& vertex_for_index( Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].vertex ); -} - -inline Vector3& normal_for_index( Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].normal ); -} - -inline Vector3& tangent_for_index( Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].tangent ); -} - -inline Vector3& bitangent_for_index( Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].bitangent ); -} - -inline const Vector2& texcoord_for_index( const Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].texcoord ); -} - -inline const Vector3& vertex_for_index( const Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].vertex ); -} - -inline const Vector3& normal_for_index( const Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].normal ); -} - -inline const Vector3& tangent_for_index( const Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].tangent ); -} - -inline const Vector3& bitangent_for_index( const Array& vertices, std::size_t index ){ - return reinterpret_cast( vertices[index].bitangent ); -} - -#include "math/curve.h" - -inline PatchControl QuadraticBezier_evaluate( const PatchControl* firstPoint, double t ){ - PatchControl result = { Vector3( 0, 0, 0 ), Vector2( 0, 0 ) }; - double denominator = 0; - - { - double weight = BernsteinPolynomial::apply( t ); - vector3_add( result.m_vertex, vector3_scaled( firstPoint[0].m_vertex, weight ) ); - vector2_add( result.m_texcoord, vector2_scaled( firstPoint[0].m_texcoord, weight ) ); - denominator += weight; - } - { - double weight = BernsteinPolynomial::apply( t ); - vector3_add( result.m_vertex, vector3_scaled( firstPoint[1].m_vertex, weight ) ); - vector2_add( result.m_texcoord, vector2_scaled( firstPoint[1].m_texcoord, weight ) ); - denominator += weight; - } - { - double weight = BernsteinPolynomial::apply( t ); - vector3_add( result.m_vertex, vector3_scaled( firstPoint[2].m_vertex, weight ) ); - vector2_add( result.m_texcoord, vector2_scaled( firstPoint[2].m_texcoord, weight ) ); - denominator += weight; - } - - vector3_divide( result.m_vertex, denominator ); - vector2_divide( result.m_texcoord, denominator ); - return result; -} - -inline Vector3 vector3_linear_interpolated( const Vector3& a, const Vector3& b, double t ){ - return vector3_added( vector3_scaled( a, 1.0 - t ), vector3_scaled( b, t ) ); -} - -inline Vector2 vector2_linear_interpolated( const Vector2& a, const Vector2& b, double t ){ - return vector2_added( vector2_scaled( a, 1.0 - t ), vector2_scaled( b, t ) ); -} - -void normalise_safe( Vector3& normal ){ - if ( !vector3_equal( normal, g_vector3_identity ) ) { - vector3_normalise( normal ); - } -} - -inline void QuadraticBezier_evaluate( const PatchControl& a, const PatchControl& b, const PatchControl& c, double t, PatchControl& point, PatchControl& left, PatchControl& right ){ - left.m_vertex = vector3_linear_interpolated( a.m_vertex, b.m_vertex, t ); - left.m_texcoord = vector2_linear_interpolated( a.m_texcoord, b.m_texcoord, t ); - right.m_vertex = vector3_linear_interpolated( b.m_vertex, c.m_vertex, t ); - right.m_texcoord = vector2_linear_interpolated( b.m_texcoord, c.m_texcoord, t ); - point.m_vertex = vector3_linear_interpolated( left.m_vertex, right.m_vertex, t ); - point.m_texcoord = vector2_linear_interpolated( left.m_texcoord, right.m_texcoord, t ); -} - -void Patch::TesselateSubMatrixFixed( ArbitraryMeshVertex* vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl* subMatrix[3][3] ){ - double incrementU = 1.0 / m_subdivisions_x; - double incrementV = 1.0 / m_subdivisions_y; - const std::size_t width = m_subdivisions_x + 1; - const std::size_t height = m_subdivisions_y + 1; - - for ( std::size_t i = 0; i != width; ++i ) - { - double tU = ( i + 1 == width ) ? 1 : i * incrementU; - PatchControl pointX[3]; - PatchControl leftX[3]; - PatchControl rightX[3]; - QuadraticBezier_evaluate( *subMatrix[0][0], *subMatrix[0][1], *subMatrix[0][2], tU, pointX[0], leftX[0], rightX[0] ); - QuadraticBezier_evaluate( *subMatrix[1][0], *subMatrix[1][1], *subMatrix[1][2], tU, pointX[1], leftX[1], rightX[1] ); - QuadraticBezier_evaluate( *subMatrix[2][0], *subMatrix[2][1], *subMatrix[2][2], tU, pointX[2], leftX[2], rightX[2] ); - - ArbitraryMeshVertex* p = vertices + i * strideX; - for ( std::size_t j = 0; j != height; ++j ) - { - if ( ( j == 0 || j + 1 == height ) && ( i == 0 || i + 1 == width ) ) { - } - else - { - double tV = ( j + 1 == height ) ? 1 : j * incrementV; - - PatchControl pointY[3]; - PatchControl leftY[3]; - PatchControl rightY[3]; - QuadraticBezier_evaluate( *subMatrix[0][0], *subMatrix[1][0], *subMatrix[2][0], tV, pointY[0], leftY[0], rightY[0] ); - QuadraticBezier_evaluate( *subMatrix[0][1], *subMatrix[1][1], *subMatrix[2][1], tV, pointY[1], leftY[1], rightY[1] ); - QuadraticBezier_evaluate( *subMatrix[0][2], *subMatrix[1][2], *subMatrix[2][2], tV, pointY[2], leftY[2], rightY[2] ); - - PatchControl point; - PatchControl left; - PatchControl right; - QuadraticBezier_evaluate( pointX[0], pointX[1], pointX[2], tV, point, left, right ); - PatchControl up; - PatchControl down; - QuadraticBezier_evaluate( pointY[0], pointY[1], pointY[2], tU, point, up, down ); - - vertex3f_to_vector3( p->vertex ) = point.m_vertex; - texcoord2f_to_vector2( p->texcoord ) = point.m_texcoord; - - ArbitraryMeshVertex a, b, c; - - a.vertex = vertex3f_for_vector3( left.m_vertex ); - a.texcoord = texcoord2f_for_vector2( left.m_texcoord ); - b.vertex = vertex3f_for_vector3( right.m_vertex ); - b.texcoord = texcoord2f_for_vector2( right.m_texcoord ); - - if ( i != 0 ) { - c.vertex = vertex3f_for_vector3( up.m_vertex ); - c.texcoord = texcoord2f_for_vector2( up.m_texcoord ); - } - else - { - c.vertex = vertex3f_for_vector3( down.m_vertex ); - c.texcoord = texcoord2f_for_vector2( down.m_texcoord ); - } - - Vector3 normal = vector3_normalised( vector3_cross( right.m_vertex - left.m_vertex, up.m_vertex - down.m_vertex ) ); - - Vector3 tangent, bitangent; - ArbitraryMeshTriangle_calcTangents( a, b, c, tangent, bitangent ); - vector3_normalise( tangent ); - vector3_normalise( bitangent ); - - if ( ( ( nFlagsX & AVERAGE ) != 0 && i == 0 ) || ( ( nFlagsY & AVERAGE ) != 0 && j == 0 ) ) { - normal3f_to_vector3( p->normal ) = vector3_normalised( vector3_added( normal3f_to_vector3( p->normal ), normal ) ); - normal3f_to_vector3( p->tangent ) = vector3_normalised( vector3_added( normal3f_to_vector3( p->tangent ), tangent ) ); - normal3f_to_vector3( p->bitangent ) = vector3_normalised( vector3_added( normal3f_to_vector3( p->bitangent ), bitangent ) ); - } - else - { - normal3f_to_vector3( p->normal ) = normal; - normal3f_to_vector3( p->tangent ) = tangent; - normal3f_to_vector3( p->bitangent ) = bitangent; - } - } - - p += strideY; - } - } -} - -void Patch::TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY, - std::size_t offStartX, std::size_t offStartY, - std::size_t offEndX, std::size_t offEndY, - std::size_t nFlagsX, std::size_t nFlagsY, - Vector3& left, Vector3& mid, Vector3& right, - Vector2& texLeft, Vector2& texMid, Vector2& texRight, - bool bTranspose ){ - int newFlagsX, newFlagsY; - - Vector3 tmp; - Vector3 vertex_0_0, vertex_0_1, vertex_1_0, vertex_1_1, vertex_2_0, vertex_2_1; - Vector2 texTmp; - Vector2 texcoord_0_0, texcoord_0_1, texcoord_1_0, texcoord_1_1, texcoord_2_0, texcoord_2_1; - - { - // texcoords - - BezierInterpolate2( texcoord_for_index( m_tess.m_vertices, offStartX + offStartY ), - texcoord_0_0, - texcoord_for_index( m_tess.m_vertices, BX->index + offStartY ), - texcoord_0_1, - texcoord_for_index( m_tess.m_vertices, offEndX + offStartY ) ); - - - BezierInterpolate2( texcoord_for_index( m_tess.m_vertices, offStartX + offEndY ), - texcoord_2_0, - texcoord_for_index( m_tess.m_vertices, BX->index + offEndY ), - texcoord_2_1, - texcoord_for_index( m_tess.m_vertices, offEndX + offEndY ) ); - - texTmp = texMid; - - BezierInterpolate2( texLeft, - texcoord_1_0, - texTmp, - texcoord_1_1, - texRight ); - - if ( !BezierCurveTree_isLeaf( BY ) ) { - texcoord_for_index( m_tess.m_vertices, BX->index + BY->index ) = texTmp; - } - - - if ( !BezierCurveTree_isLeaf( BX->left ) ) { - texcoord_for_index( m_tess.m_vertices, BX->left->index + offStartY ) = texcoord_0_0; - texcoord_for_index( m_tess.m_vertices, BX->left->index + offEndY ) = texcoord_2_0; + { + // texcoords - if ( !BezierCurveTree_isLeaf( BY ) ) { - texcoord_for_index( m_tess.m_vertices, BX->left->index + BY->index ) = texcoord_1_0; - } - } - if ( !BezierCurveTree_isLeaf( BX->right ) ) { - texcoord_for_index( m_tess.m_vertices, BX->right->index + offStartY ) = texcoord_0_1; - texcoord_for_index( m_tess.m_vertices, BX->right->index + offEndY ) = texcoord_2_1; - - if ( !BezierCurveTree_isLeaf( BY ) ) { - texcoord_for_index( m_tess.m_vertices, BX->right->index + BY->index ) = texcoord_1_1; - } - } - - - // verts - - BezierInterpolate3( vertex_for_index( m_tess.m_vertices, offStartX + offStartY ), - vertex_0_0, - vertex_for_index( m_tess.m_vertices, BX->index + offStartY ), - vertex_0_1, - vertex_for_index( m_tess.m_vertices, offEndX + offStartY ) ); - - - BezierInterpolate3( vertex_for_index( m_tess.m_vertices, offStartX + offEndY ), - vertex_2_0, - vertex_for_index( m_tess.m_vertices, BX->index + offEndY ), - vertex_2_1, - vertex_for_index( m_tess.m_vertices, offEndX + offEndY ) ); - - - tmp = mid; - - BezierInterpolate3( left, - vertex_1_0, - tmp, - vertex_1_1, - right ); - - if ( !BezierCurveTree_isLeaf( BY ) ) { - vertex_for_index( m_tess.m_vertices, BX->index + BY->index ) = tmp; - } - - - if ( !BezierCurveTree_isLeaf( BX->left ) ) { - vertex_for_index( m_tess.m_vertices, BX->left->index + offStartY ) = vertex_0_0; - vertex_for_index( m_tess.m_vertices, BX->left->index + offEndY ) = vertex_2_0; - - if ( !BezierCurveTree_isLeaf( BY ) ) { - vertex_for_index( m_tess.m_vertices, BX->left->index + BY->index ) = vertex_1_0; - } - } - if ( !BezierCurveTree_isLeaf( BX->right ) ) { - vertex_for_index( m_tess.m_vertices, BX->right->index + offStartY ) = vertex_0_1; - vertex_for_index( m_tess.m_vertices, BX->right->index + offEndY ) = vertex_2_1; - - if ( !BezierCurveTree_isLeaf( BY ) ) { - vertex_for_index( m_tess.m_vertices, BX->right->index + BY->index ) = vertex_1_1; - } - } - - // normals - - if ( nFlagsX & SPLIT ) { - ArbitraryMeshVertex a, b, c; - Vector3 tangentU; - - if ( !( nFlagsX & DEGEN_0a ) || !( nFlagsX & DEGEN_0b ) ) { - tangentU = vector3_subtracted( vertex_0_1, vertex_0_0 ); - a.vertex = vertex3f_for_vector3( vertex_0_0 ); - a.texcoord = texcoord2f_for_vector2( texcoord_0_0 ); - c.vertex = vertex3f_for_vector3( vertex_0_1 ); - c.texcoord = texcoord2f_for_vector2( texcoord_0_1 ); - } - else if ( !( nFlagsX & DEGEN_1a ) || !( nFlagsX & DEGEN_1b ) ) { - tangentU = vector3_subtracted( vertex_1_1, vertex_1_0 ); - a.vertex = vertex3f_for_vector3( vertex_1_0 ); - a.texcoord = texcoord2f_for_vector2( texcoord_1_0 ); - c.vertex = vertex3f_for_vector3( vertex_1_1 ); - c.texcoord = texcoord2f_for_vector2( texcoord_1_1 ); - } - else - { - tangentU = vector3_subtracted( vertex_2_1, vertex_2_0 ); - a.vertex = vertex3f_for_vector3( vertex_2_0 ); - a.texcoord = texcoord2f_for_vector2( texcoord_2_0 ); - c.vertex = vertex3f_for_vector3( vertex_2_1 ); - c.texcoord = texcoord2f_for_vector2( texcoord_2_1 ); - } - - Vector3 tangentV; - - if ( ( nFlagsY & DEGEN_0a ) && ( nFlagsY & DEGEN_1a ) && ( nFlagsY & DEGEN_2a ) ) { - tangentV = vector3_subtracted( vertex_for_index( m_tess.m_vertices, BX->index + offEndY ), tmp ); - b.vertex = vertex3f_for_vector3( tmp ); //m_tess.m_vertices[BX->index + offEndY].vertex; - b.texcoord = texcoord2f_for_vector2( texTmp ); //m_tess.m_vertices[BX->index + offEndY].texcoord; - } - else - { - tangentV = vector3_subtracted( tmp, vertex_for_index( m_tess.m_vertices, BX->index + offStartY ) ); - b.vertex = vertex3f_for_vector3( tmp ); //m_tess.m_vertices[BX->index + offStartY].vertex; - b.texcoord = texcoord2f_for_vector2( texTmp ); //m_tess.m_vertices[BX->index + offStartY].texcoord; - } - - - Vector3 normal, s, t; - ArbitraryMeshVertex& v = m_tess.m_vertices[offStartY + BX->index]; - Vector3& p = normal3f_to_vector3( v.normal ); - Vector3& ps = normal3f_to_vector3( v.tangent ); - Vector3& pt = normal3f_to_vector3( v.bitangent ); - - if ( bTranspose ) { - normal = vector3_cross( tangentV, tangentU ); - } - else - { - normal = vector3_cross( tangentU, tangentV ); - } - normalise_safe( normal ); - - ArbitraryMeshTriangle_calcTangents( a, b, c, s, t ); - normalise_safe( s ); - normalise_safe( t ); - - if ( nFlagsX & AVERAGE ) { - p = vector3_normalised( vector3_added( p, normal ) ); - ps = vector3_normalised( vector3_added( ps, s ) ); - pt = vector3_normalised( vector3_added( pt, t ) ); - } - else - { - p = normal; - ps = s; - pt = t; - } - } - - { - ArbitraryMeshVertex a, b, c; - Vector3 tangentU; - - if ( !( nFlagsX & DEGEN_2a ) || !( nFlagsX & DEGEN_2b ) ) { - tangentU = vector3_subtracted( vertex_2_1, vertex_2_0 ); - a.vertex = vertex3f_for_vector3( vertex_2_0 ); - a.texcoord = texcoord2f_for_vector2( texcoord_2_0 ); - c.vertex = vertex3f_for_vector3( vertex_2_1 ); - c.texcoord = texcoord2f_for_vector2( texcoord_2_1 ); - } - else if ( !( nFlagsX & DEGEN_1a ) || !( nFlagsX & DEGEN_1b ) ) { - tangentU = vector3_subtracted( vertex_1_1, vertex_1_0 ); - a.vertex = vertex3f_for_vector3( vertex_1_0 ); - a.texcoord = texcoord2f_for_vector2( texcoord_1_0 ); - c.vertex = vertex3f_for_vector3( vertex_1_1 ); - c.texcoord = texcoord2f_for_vector2( texcoord_1_1 ); - } - else - { - tangentU = vector3_subtracted( vertex_0_1, vertex_0_0 ); - a.vertex = vertex3f_for_vector3( vertex_0_0 ); - a.texcoord = texcoord2f_for_vector2( texcoord_0_0 ); - c.vertex = vertex3f_for_vector3( vertex_0_1 ); - c.texcoord = texcoord2f_for_vector2( texcoord_0_1 ); - } - - Vector3 tangentV; - - if ( ( nFlagsY & DEGEN_0b ) && ( nFlagsY & DEGEN_1b ) && ( nFlagsY & DEGEN_2b ) ) { - tangentV = vector3_subtracted( tmp, vertex_for_index( m_tess.m_vertices, BX->index + offStartY ) ); - b.vertex = vertex3f_for_vector3( tmp ); //m_tess.m_vertices[BX->index + offStartY].vertex; - b.texcoord = texcoord2f_for_vector2( texTmp ); //m_tess.m_vertices[BX->index + offStartY].texcoord; - } - else - { - tangentV = vector3_subtracted( vertex_for_index( m_tess.m_vertices, BX->index + offEndY ), tmp ); - b.vertex = vertex3f_for_vector3( tmp ); //m_tess.m_vertices[BX->index + offEndY].vertex; - b.texcoord = texcoord2f_for_vector2( texTmp ); //m_tess.m_vertices[BX->index + offEndY].texcoord; - } - - ArbitraryMeshVertex& v = m_tess.m_vertices[offEndY + BX->index]; - Vector3& p = normal3f_to_vector3( v.normal ); - Vector3& ps = normal3f_to_vector3( v.tangent ); - Vector3& pt = normal3f_to_vector3( v.bitangent ); - - if ( bTranspose ) { - p = vector3_cross( tangentV, tangentU ); - } - else - { - p = vector3_cross( tangentU, tangentV ); - } - normalise_safe( p ); - - ArbitraryMeshTriangle_calcTangents( a, b, c, ps, pt ); - normalise_safe( ps ); - normalise_safe( pt ); - } - } - - - newFlagsX = newFlagsY = 0; - - if ( ( nFlagsX & DEGEN_0a ) && ( nFlagsX & DEGEN_0b ) ) { - newFlagsX |= DEGEN_0a; - newFlagsX |= DEGEN_0b; - } - if ( ( nFlagsX & DEGEN_1a ) && ( nFlagsX & DEGEN_1b ) ) { - newFlagsX |= DEGEN_1a; - newFlagsX |= DEGEN_1b; - } - if ( ( nFlagsX & DEGEN_2a ) && ( nFlagsX & DEGEN_2b ) ) { - newFlagsX |= DEGEN_2a; - newFlagsX |= DEGEN_2b; - } - if ( ( nFlagsY & DEGEN_0a ) && ( nFlagsY & DEGEN_1a ) && ( nFlagsY & DEGEN_2a ) ) { - newFlagsY |= DEGEN_0a; - newFlagsY |= DEGEN_1a; - newFlagsY |= DEGEN_2a; - } - if ( ( nFlagsY & DEGEN_0b ) && ( nFlagsY & DEGEN_1b ) && ( nFlagsY & DEGEN_2b ) ) { - newFlagsY |= DEGEN_0b; - newFlagsY |= DEGEN_1b; - newFlagsY |= DEGEN_2b; - } - - - //if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_2a)) { newFlagsX |= DEGEN_0a; newFlagsX |= DEGEN_1a; newFlagsX |= DEGEN_2a; } - //if((nFlagsX & DEGEN_0b) && (nFlagsX & DEGEN_1b) && (nFlagsX & DEGEN_2b)) { newFlagsX |= DEGEN_0b; newFlagsX |= DEGEN_1b; newFlagsX |= DEGEN_2b; } - - newFlagsX |= ( nFlagsX & SPLIT ); - newFlagsX |= ( nFlagsX & AVERAGE ); - - if ( !BezierCurveTree_isLeaf( BY ) ) { - { - int nTemp = newFlagsY; - - if ( ( nFlagsY & DEGEN_0a ) && ( nFlagsY & DEGEN_0b ) ) { - newFlagsY |= DEGEN_0a; - newFlagsY |= DEGEN_0b; - } - newFlagsY |= ( nFlagsY & SPLIT ); - newFlagsY |= ( nFlagsY & AVERAGE ); - - Vector3& p = vertex_for_index( m_tess.m_vertices, BX->index + BY->index ); - Vector3 vTemp( p ); - - Vector2& p2 = texcoord_for_index( m_tess.m_vertices, BX->index + BY->index ); - Vector2 stTemp( p2 ); - - TesselateSubMatrix( BY, BX->left, - offStartY, offStartX, - offEndY, BX->index, - newFlagsY, newFlagsX, - vertex_0_0, vertex_1_0, vertex_2_0, - texcoord_0_0, texcoord_1_0, texcoord_2_0, - !bTranspose ); - - newFlagsY = nTemp; - p = vTemp; - p2 = stTemp; - } - - if ( ( nFlagsY & DEGEN_2a ) && ( nFlagsY & DEGEN_2b ) ) { - newFlagsY |= DEGEN_2a; newFlagsY |= DEGEN_2b; - } - - TesselateSubMatrix( BY, BX->right, - offStartY, BX->index, - offEndY, offEndX, - newFlagsY, newFlagsX, - vertex_0_1, vertex_1_1, vertex_2_1, - texcoord_0_1, texcoord_1_1, texcoord_2_1, - !bTranspose ); - } - else - { - if ( !BezierCurveTree_isLeaf( BX->left ) ) { - TesselateSubMatrix( BX->left, BY, - offStartX, offStartY, - BX->index, offEndY, - newFlagsX, newFlagsY, - left, vertex_1_0, tmp, - texLeft, texcoord_1_0, texTmp, - bTranspose ); - } - - if ( !BezierCurveTree_isLeaf( BX->right ) ) { - TesselateSubMatrix( BX->right, BY, - BX->index, offStartY, - offEndX, offEndY, - newFlagsX, newFlagsY, - tmp, vertex_1_1, right, - texTmp, texcoord_1_1, texRight, - bTranspose ); - } - } - -} - -void Patch::BuildTesselationCurves( EMatrixMajor major ){ - std::size_t nArrayStride, length, cross, strideU, strideV; - switch ( major ) - { - case ROW: - nArrayStride = 1; - length = ( m_width - 1 ) >> 1; - cross = m_height; - strideU = 1; - strideV = m_width; - - if ( !m_patchDef3 ) { - BezierCurveTreeArray_deleteAll( m_tess.m_curveTreeU ); - } - - break; - case COL: - nArrayStride = m_tess.m_nArrayWidth; - length = ( m_height - 1 ) >> 1; - cross = m_width; - strideU = m_width; - strideV = 1; - - if ( !m_patchDef3 ) { - BezierCurveTreeArray_deleteAll( m_tess.m_curveTreeV ); - } - - break; - default: - ERROR_MESSAGE( "neither row-major nor column-major" ); - return; - } - - Array arrayLength( length ); - Array pCurveTree( length ); - - std::size_t nArrayLength = 1; - - if ( m_patchDef3 ) { - for ( Array::iterator i = arrayLength.begin(); i != arrayLength.end(); ++i ) - { - *i = Array::value_type( ( major == ROW ) ? m_subdivisions_x : m_subdivisions_y ); - nArrayLength += *i; - } - } - else - { - // create a list of the horizontal control curves in each column of sub-patches - // adaptively tesselate each horizontal control curve in the list - // create a binary tree representing the combined tesselation of the list - for ( std::size_t i = 0; i != length; ++i ) - { - PatchControl* p1 = m_ctrlTransformed.data() + ( i * 2 * strideU ); - GSList* pCurveList = 0; - for ( std::size_t j = 0; j < cross; j += 2 ) - { - PatchControl* p2 = p1 + strideV; - PatchControl* p3 = p2 + strideV; - - // directly taken from one row of control points - { - BezierCurve* pCurve = new BezierCurve; - pCurve->crd = ( p1 + strideU )->m_vertex; - pCurve->left = p1->m_vertex; - pCurve->right = ( p1 + ( strideU << 1 ) )->m_vertex; - pCurveList = g_slist_prepend( pCurveList, pCurve ); - } - - if ( j + 2 >= cross ) { - break; - } - - // interpolated from three columns of control points - { - BezierCurve* pCurve = new BezierCurve; - pCurve->crd = vector3_mid( ( p1 + strideU )->m_vertex, ( p3 + strideU )->m_vertex ); - pCurve->left = vector3_mid( p1->m_vertex, p3->m_vertex ); - pCurve->right = vector3_mid( ( p1 + ( strideU << 1 ) )->m_vertex, ( p3 + ( strideU << 1 ) )->m_vertex ); - - pCurve->crd = vector3_mid( pCurve->crd, ( p2 + strideU )->m_vertex ); - pCurve->left = vector3_mid( pCurve->left, p2->m_vertex ); - pCurve->right = vector3_mid( pCurve->right, ( p2 + ( strideU << 1 ) )->m_vertex ); - pCurveList = g_slist_prepend( pCurveList, pCurve ); - } - - p1 = p3; - } - - pCurveTree[i] = new BezierCurveTree; - BezierCurveTree_FromCurveList( pCurveTree[i], pCurveList ); - for ( GSList* l = pCurveList; l != 0; l = g_slist_next( l ) ) - { - delete static_cast( ( *l ).data ); - } - g_slist_free( pCurveList ); - - // set up array indices for binary tree - // accumulate subarray width - arrayLength[i] = Array::value_type( BezierCurveTree_Setup( pCurveTree[i], nArrayLength, nArrayStride ) - ( nArrayLength - 1 ) ); - // accumulate total array width - nArrayLength += arrayLength[i]; - } - } - - switch ( major ) - { - case ROW: - m_tess.m_nArrayWidth = nArrayLength; - std::swap( m_tess.m_arrayWidth, arrayLength ); - - if ( !m_patchDef3 ) { - std::swap( m_tess.m_curveTreeU, pCurveTree ); - } - break; - case COL: - m_tess.m_nArrayHeight = nArrayLength; - std::swap( m_tess.m_arrayHeight, arrayLength ); - - if ( !m_patchDef3 ) { - std::swap( m_tess.m_curveTreeV, pCurveTree ); - } - break; - } -} - -inline void vertex_assign_ctrl( ArbitraryMeshVertex& vertex, const PatchControl& ctrl ){ - vertex.vertex = vertex3f_for_vector3( ctrl.m_vertex ); - vertex.texcoord = texcoord2f_for_vector2( ctrl.m_texcoord ); -} - -inline void vertex_clear_normal( ArbitraryMeshVertex& vertex ){ - vertex.normal = Normal3f( 0, 0, 0 ); - vertex.tangent = Normal3f( 0, 0, 0 ); - vertex.bitangent = Normal3f( 0, 0, 0 ); -} - -inline void tangents_remove_degenerate( Vector3 tangents[6], Vector2 textureTangents[6], unsigned int flags ){ - if ( flags & DEGEN_0a ) { - const std::size_t i = - ( flags & DEGEN_0b ) - ? ( flags & DEGEN_1a ) - ? ( flags & DEGEN_1b ) - ? ( flags & DEGEN_2a ) - ? 5 - : 4 - : 3 - : 2 - : 1; - tangents[0] = tangents[i]; - textureTangents[0] = textureTangents[i]; - } - if ( flags & DEGEN_0b ) { - const std::size_t i = - ( flags & DEGEN_0a ) - ? ( flags & DEGEN_1b ) - ? ( flags & DEGEN_1a ) - ? ( flags & DEGEN_2b ) - ? 4 - : 5 - : 2 - : 3 - : 0; - tangents[1] = tangents[i]; - textureTangents[1] = textureTangents[i]; - } - if ( flags & DEGEN_2a ) { - const std::size_t i = - ( flags & DEGEN_2b ) - ? ( flags & DEGEN_1a ) - ? ( flags & DEGEN_1b ) - ? ( flags & DEGEN_0a ) - ? 1 - : 0 - : 3 - : 2 - : 5; - tangents[4] = tangents[i]; - textureTangents[4] = textureTangents[i]; - } - if ( flags & DEGEN_2b ) { - const std::size_t i = - ( flags & DEGEN_2a ) - ? ( flags & DEGEN_1b ) - ? ( flags & DEGEN_1a ) - ? ( flags & DEGEN_0b ) - ? 0 - : 1 - : 2 - : 3 - : 4; - tangents[5] = tangents[i]; - textureTangents[5] = textureTangents[i]; - } -} - -void bestTangents00( unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1 ){ - if ( fabs( dot + length ) < 0.001 ) { // opposing direction = degenerate - if ( !( degenerateFlags & DEGEN_1a ) ) { // if this tangent is degenerate we cannot use it - index0 = 2; - index1 = 0; - } - else if ( !( degenerateFlags & DEGEN_0b ) ) { - index0 = 0; - index1 = 1; - } - else - { - index0 = 1; - index1 = 0; - } - } - else if ( fabs( dot - length ) < 0.001 ) { // same direction = degenerate - if ( degenerateFlags & DEGEN_0b ) { - index0 = 0; - index1 = 1; - } - else - { - index0 = 1; - index1 = 0; - } - } -} - -void bestTangents01( unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1 ){ - if ( fabs( dot - length ) < 0.001 ) { // same direction = degenerate - if ( !( degenerateFlags & DEGEN_1a ) ) { // if this tangent is degenerate we cannot use it - index0 = 2; - index1 = 1; - } - else if ( !( degenerateFlags & DEGEN_2b ) ) { - index0 = 4; - index1 = 0; - } - else - { - index0 = 5; - index1 = 1; - } - } - else if ( fabs( dot + length ) < 0.001 ) { // opposing direction = degenerate - if ( degenerateFlags & DEGEN_2b ) { - index0 = 4; - index1 = 0; - } - else - { - index0 = 5; - index1 = 1; - } - } -} - -void bestTangents10( unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1 ){ - if ( fabs( dot - length ) < 0.001 ) { // same direction = degenerate - if ( !( degenerateFlags & DEGEN_1b ) ) { // if this tangent is degenerate we cannot use it - index0 = 3; - index1 = 4; - } - else if ( !( degenerateFlags & DEGEN_0a ) ) { - index0 = 1; - index1 = 5; - } - else - { - index0 = 0; - index1 = 4; - } - } - else if ( fabs( dot + length ) < 0.001 ) { // opposing direction = degenerate - if ( degenerateFlags & DEGEN_0a ) { - index0 = 1; - index1 = 5; - } - else - { - index0 = 0; - index1 = 4; - } - } + BezierInterpolate2(texcoord_for_index(m_tess.m_vertices, offStartX + offStartY), + texcoord_0_0, + texcoord_for_index(m_tess.m_vertices, BX->index + offStartY), + texcoord_0_1, + texcoord_for_index(m_tess.m_vertices, offEndX + offStartY)); + + + BezierInterpolate2(texcoord_for_index(m_tess.m_vertices, offStartX + offEndY), + texcoord_2_0, + texcoord_for_index(m_tess.m_vertices, BX->index + offEndY), + texcoord_2_1, + texcoord_for_index(m_tess.m_vertices, offEndX + offEndY)); + + texTmp = texMid; + + BezierInterpolate2(texLeft, + texcoord_1_0, + texTmp, + texcoord_1_1, + texRight); + + if (!BezierCurveTree_isLeaf(BY)) { + texcoord_for_index(m_tess.m_vertices, BX->index + BY->index) = texTmp; + } + + + if (!BezierCurveTree_isLeaf(BX->left)) { + texcoord_for_index(m_tess.m_vertices, BX->left->index + offStartY) = texcoord_0_0; + texcoord_for_index(m_tess.m_vertices, BX->left->index + offEndY) = texcoord_2_0; + + if (!BezierCurveTree_isLeaf(BY)) { + texcoord_for_index(m_tess.m_vertices, BX->left->index + BY->index) = texcoord_1_0; + } + } + if (!BezierCurveTree_isLeaf(BX->right)) { + texcoord_for_index(m_tess.m_vertices, BX->right->index + offStartY) = texcoord_0_1; + texcoord_for_index(m_tess.m_vertices, BX->right->index + offEndY) = texcoord_2_1; + + if (!BezierCurveTree_isLeaf(BY)) { + texcoord_for_index(m_tess.m_vertices, BX->right->index + BY->index) = texcoord_1_1; + } + } + + + // verts + + BezierInterpolate3(vertex_for_index(m_tess.m_vertices, offStartX + offStartY), + vertex_0_0, + vertex_for_index(m_tess.m_vertices, BX->index + offStartY), + vertex_0_1, + vertex_for_index(m_tess.m_vertices, offEndX + offStartY)); + + + BezierInterpolate3(vertex_for_index(m_tess.m_vertices, offStartX + offEndY), + vertex_2_0, + vertex_for_index(m_tess.m_vertices, BX->index + offEndY), + vertex_2_1, + vertex_for_index(m_tess.m_vertices, offEndX + offEndY)); + + + tmp = mid; + + BezierInterpolate3(left, + vertex_1_0, + tmp, + vertex_1_1, + right); + + if (!BezierCurveTree_isLeaf(BY)) { + vertex_for_index(m_tess.m_vertices, BX->index + BY->index) = tmp; + } + + + if (!BezierCurveTree_isLeaf(BX->left)) { + vertex_for_index(m_tess.m_vertices, BX->left->index + offStartY) = vertex_0_0; + vertex_for_index(m_tess.m_vertices, BX->left->index + offEndY) = vertex_2_0; + + if (!BezierCurveTree_isLeaf(BY)) { + vertex_for_index(m_tess.m_vertices, BX->left->index + BY->index) = vertex_1_0; + } + } + if (!BezierCurveTree_isLeaf(BX->right)) { + vertex_for_index(m_tess.m_vertices, BX->right->index + offStartY) = vertex_0_1; + vertex_for_index(m_tess.m_vertices, BX->right->index + offEndY) = vertex_2_1; + + if (!BezierCurveTree_isLeaf(BY)) { + vertex_for_index(m_tess.m_vertices, BX->right->index + BY->index) = vertex_1_1; + } + } + + // normals + + if (nFlagsX & SPLIT) { + ArbitraryMeshVertex a, b, c; + Vector3 tangentU; + + if (!(nFlagsX & DEGEN_0a) || !(nFlagsX & DEGEN_0b)) { + tangentU = vector3_subtracted(vertex_0_1, vertex_0_0); + a.vertex = vertex3f_for_vector3(vertex_0_0); + a.texcoord = texcoord2f_for_vector2(texcoord_0_0); + c.vertex = vertex3f_for_vector3(vertex_0_1); + c.texcoord = texcoord2f_for_vector2(texcoord_0_1); + } else if (!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b)) { + tangentU = vector3_subtracted(vertex_1_1, vertex_1_0); + a.vertex = vertex3f_for_vector3(vertex_1_0); + a.texcoord = texcoord2f_for_vector2(texcoord_1_0); + c.vertex = vertex3f_for_vector3(vertex_1_1); + c.texcoord = texcoord2f_for_vector2(texcoord_1_1); + } else { + tangentU = vector3_subtracted(vertex_2_1, vertex_2_0); + a.vertex = vertex3f_for_vector3(vertex_2_0); + a.texcoord = texcoord2f_for_vector2(texcoord_2_0); + c.vertex = vertex3f_for_vector3(vertex_2_1); + c.texcoord = texcoord2f_for_vector2(texcoord_2_1); + } + + Vector3 tangentV; + + if ((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a)) { + tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp); + b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offEndY].vertex; + b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offEndY].texcoord; + } else { + tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY)); + b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offStartY].vertex; + b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offStartY].texcoord; + } + + + Vector3 normal, s, t; + ArbitraryMeshVertex &v = m_tess.m_vertices[offStartY + BX->index]; + Vector3 &p = normal3f_to_vector3(v.normal); + Vector3 &ps = normal3f_to_vector3(v.tangent); + Vector3 &pt = normal3f_to_vector3(v.bitangent); + + if (bTranspose) { + normal = vector3_cross(tangentV, tangentU); + } else { + normal = vector3_cross(tangentU, tangentV); + } + normalise_safe(normal); + + ArbitraryMeshTriangle_calcTangents(a, b, c, s, t); + normalise_safe(s); + normalise_safe(t); + + if (nFlagsX & AVERAGE) { + p = vector3_normalised(vector3_added(p, normal)); + ps = vector3_normalised(vector3_added(ps, s)); + pt = vector3_normalised(vector3_added(pt, t)); + } else { + p = normal; + ps = s; + pt = t; + } + } + + { + ArbitraryMeshVertex a, b, c; + Vector3 tangentU; + + if (!(nFlagsX & DEGEN_2a) || !(nFlagsX & DEGEN_2b)) { + tangentU = vector3_subtracted(vertex_2_1, vertex_2_0); + a.vertex = vertex3f_for_vector3(vertex_2_0); + a.texcoord = texcoord2f_for_vector2(texcoord_2_0); + c.vertex = vertex3f_for_vector3(vertex_2_1); + c.texcoord = texcoord2f_for_vector2(texcoord_2_1); + } else if (!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b)) { + tangentU = vector3_subtracted(vertex_1_1, vertex_1_0); + a.vertex = vertex3f_for_vector3(vertex_1_0); + a.texcoord = texcoord2f_for_vector2(texcoord_1_0); + c.vertex = vertex3f_for_vector3(vertex_1_1); + c.texcoord = texcoord2f_for_vector2(texcoord_1_1); + } else { + tangentU = vector3_subtracted(vertex_0_1, vertex_0_0); + a.vertex = vertex3f_for_vector3(vertex_0_0); + a.texcoord = texcoord2f_for_vector2(texcoord_0_0); + c.vertex = vertex3f_for_vector3(vertex_0_1); + c.texcoord = texcoord2f_for_vector2(texcoord_0_1); + } + + Vector3 tangentV; + + if ((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b)) { + tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY)); + b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offStartY].vertex; + b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offStartY].texcoord; + } else { + tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp); + b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offEndY].vertex; + b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offEndY].texcoord; + } + + ArbitraryMeshVertex &v = m_tess.m_vertices[offEndY + BX->index]; + Vector3 &p = normal3f_to_vector3(v.normal); + Vector3 &ps = normal3f_to_vector3(v.tangent); + Vector3 &pt = normal3f_to_vector3(v.bitangent); + + if (bTranspose) { + p = vector3_cross(tangentV, tangentU); + } else { + p = vector3_cross(tangentU, tangentV); + } + normalise_safe(p); + + ArbitraryMeshTriangle_calcTangents(a, b, c, ps, pt); + normalise_safe(ps); + normalise_safe(pt); + } + } + + + newFlagsX = newFlagsY = 0; + + if ((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_0b)) { + newFlagsX |= DEGEN_0a; + newFlagsX |= DEGEN_0b; + } + if ((nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_1b)) { + newFlagsX |= DEGEN_1a; + newFlagsX |= DEGEN_1b; + } + if ((nFlagsX & DEGEN_2a) && (nFlagsX & DEGEN_2b)) { + newFlagsX |= DEGEN_2a; + newFlagsX |= DEGEN_2b; + } + if ((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a)) { + newFlagsY |= DEGEN_0a; + newFlagsY |= DEGEN_1a; + newFlagsY |= DEGEN_2a; + } + if ((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b)) { + newFlagsY |= DEGEN_0b; + newFlagsY |= DEGEN_1b; + newFlagsY |= DEGEN_2b; + } + + + //if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_2a)) { newFlagsX |= DEGEN_0a; newFlagsX |= DEGEN_1a; newFlagsX |= DEGEN_2a; } + //if((nFlagsX & DEGEN_0b) && (nFlagsX & DEGEN_1b) && (nFlagsX & DEGEN_2b)) { newFlagsX |= DEGEN_0b; newFlagsX |= DEGEN_1b; newFlagsX |= DEGEN_2b; } + + newFlagsX |= (nFlagsX & SPLIT); + newFlagsX |= (nFlagsX & AVERAGE); + + if (!BezierCurveTree_isLeaf(BY)) { + { + int nTemp = newFlagsY; + + if ((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_0b)) { + newFlagsY |= DEGEN_0a; + newFlagsY |= DEGEN_0b; + } + newFlagsY |= (nFlagsY & SPLIT); + newFlagsY |= (nFlagsY & AVERAGE); + + Vector3 &p = vertex_for_index(m_tess.m_vertices, BX->index + BY->index); + Vector3 vTemp(p); + + Vector2 &p2 = texcoord_for_index(m_tess.m_vertices, BX->index + BY->index); + Vector2 stTemp(p2); + + TesselateSubMatrix(BY, BX->left, + offStartY, offStartX, + offEndY, BX->index, + newFlagsY, newFlagsX, + vertex_0_0, vertex_1_0, vertex_2_0, + texcoord_0_0, texcoord_1_0, texcoord_2_0, + !bTranspose); + + newFlagsY = nTemp; + p = vTemp; + p2 = stTemp; + } + + if ((nFlagsY & DEGEN_2a) && (nFlagsY & DEGEN_2b)) { + newFlagsY |= DEGEN_2a; + newFlagsY |= DEGEN_2b; + } + + TesselateSubMatrix(BY, BX->right, + offStartY, BX->index, + offEndY, offEndX, + newFlagsY, newFlagsX, + vertex_0_1, vertex_1_1, vertex_2_1, + texcoord_0_1, texcoord_1_1, texcoord_2_1, + !bTranspose); + } else { + if (!BezierCurveTree_isLeaf(BX->left)) { + TesselateSubMatrix(BX->left, BY, + offStartX, offStartY, + BX->index, offEndY, + newFlagsX, newFlagsY, + left, vertex_1_0, tmp, + texLeft, texcoord_1_0, texTmp, + bTranspose); + } + + if (!BezierCurveTree_isLeaf(BX->right)) { + TesselateSubMatrix(BX->right, BY, + BX->index, offStartY, + offEndX, offEndY, + newFlagsX, newFlagsY, + tmp, vertex_1_1, right, + texTmp, texcoord_1_1, texRight, + bTranspose); + } + } + +} + +void Patch::BuildTesselationCurves(EMatrixMajor major) +{ + std::size_t nArrayStride, length, cross, strideU, strideV; + switch (major) { + case ROW: + nArrayStride = 1; + length = (m_width - 1) >> 1; + cross = m_height; + strideU = 1; + strideV = m_width; + + if (!m_patchDef3) { + BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeU); + } + + break; + case COL: + nArrayStride = m_tess.m_nArrayWidth; + length = (m_height - 1) >> 1; + cross = m_width; + strideU = m_width; + strideV = 1; + + if (!m_patchDef3) { + BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeV); + } + + break; + default: + ERROR_MESSAGE("neither row-major nor column-major"); + return; + } + + Array arrayLength(length); + Array pCurveTree(length); + + std::size_t nArrayLength = 1; + + if (m_patchDef3) { + for (Array::iterator i = arrayLength.begin(); i != arrayLength.end(); ++i) { + *i = Array::value_type((major == ROW) ? m_subdivisions_x : m_subdivisions_y); + nArrayLength += *i; + } + } else { + // create a list of the horizontal control curves in each column of sub-patches + // adaptively tesselate each horizontal control curve in the list + // create a binary tree representing the combined tesselation of the list + for (std::size_t i = 0; i != length; ++i) { + PatchControl *p1 = m_ctrlTransformed.data() + (i * 2 * strideU); + GSList *pCurveList = 0; + for (std::size_t j = 0; j < cross; j += 2) { + PatchControl *p2 = p1 + strideV; + PatchControl *p3 = p2 + strideV; + + // directly taken from one row of control points + { + BezierCurve *pCurve = new BezierCurve; + pCurve->crd = (p1 + strideU)->m_vertex; + pCurve->left = p1->m_vertex; + pCurve->right = (p1 + (strideU << 1))->m_vertex; + pCurveList = g_slist_prepend(pCurveList, pCurve); + } + + if (j + 2 >= cross) { + break; + } + + // interpolated from three columns of control points + { + BezierCurve *pCurve = new BezierCurve; + pCurve->crd = vector3_mid((p1 + strideU)->m_vertex, (p3 + strideU)->m_vertex); + pCurve->left = vector3_mid(p1->m_vertex, p3->m_vertex); + pCurve->right = vector3_mid((p1 + (strideU << 1))->m_vertex, (p3 + (strideU << 1))->m_vertex); + + pCurve->crd = vector3_mid(pCurve->crd, (p2 + strideU)->m_vertex); + pCurve->left = vector3_mid(pCurve->left, p2->m_vertex); + pCurve->right = vector3_mid(pCurve->right, (p2 + (strideU << 1))->m_vertex); + pCurveList = g_slist_prepend(pCurveList, pCurve); + } + + p1 = p3; + } + + pCurveTree[i] = new BezierCurveTree; + BezierCurveTree_FromCurveList(pCurveTree[i], pCurveList); + for (GSList *l = pCurveList; l != 0; l = g_slist_next(l)) { + delete static_cast((*l).data ); + } + g_slist_free(pCurveList); + + // set up array indices for binary tree + // accumulate subarray width + arrayLength[i] = Array::value_type( + BezierCurveTree_Setup(pCurveTree[i], nArrayLength, nArrayStride) - (nArrayLength - 1)); + // accumulate total array width + nArrayLength += arrayLength[i]; + } + } + + switch (major) { + case ROW: + m_tess.m_nArrayWidth = nArrayLength; + std::swap(m_tess.m_arrayWidth, arrayLength); + + if (!m_patchDef3) { + std::swap(m_tess.m_curveTreeU, pCurveTree); + } + break; + case COL: + m_tess.m_nArrayHeight = nArrayLength; + std::swap(m_tess.m_arrayHeight, arrayLength); + + if (!m_patchDef3) { + std::swap(m_tess.m_curveTreeV, pCurveTree); + } + break; + } +} + +inline void vertex_assign_ctrl(ArbitraryMeshVertex &vertex, const PatchControl &ctrl) +{ + vertex.vertex = vertex3f_for_vector3(ctrl.m_vertex); + vertex.texcoord = texcoord2f_for_vector2(ctrl.m_texcoord); } -void bestTangents11( unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1 ){ - if ( fabs( dot + length ) < 0.001 ) { // opposing direction = degenerate - if ( !( degenerateFlags & DEGEN_1b ) ) { // if this tangent is degenerate we cannot use it - index0 = 3; - index1 = 5; - } - else if ( !( degenerateFlags & DEGEN_2a ) ) { - index0 = 5; - index1 = 4; - } - else - { - index0 = 4; - index1 = 5; - } - } - else if ( fabs( dot - length ) < 0.001 ) { // same direction = degenerate - if ( degenerateFlags & DEGEN_2a ) { - index0 = 5; - index1 = 4; - } - else - { - index0 = 4; - index1 = 5; - } - } +inline void vertex_clear_normal(ArbitraryMeshVertex &vertex) +{ + vertex.normal = Normal3f(0, 0, 0); + vertex.tangent = Normal3f(0, 0, 0); + vertex.bitangent = Normal3f(0, 0, 0); } -void Patch::accumulateVertexTangentSpace( std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], Vector2 tangentT[6], std::size_t index0, std::size_t index1 ){ - { - Vector3 normal( vector3_cross( tangentX[index0], tangentY[index1] ) ); - if ( !vector3_equal( normal, g_vector3_identity ) ) { - vector3_add( normal_for_index( m_tess.m_vertices, index ), vector3_normalised( normal ) ); - } - } - - { - ArbitraryMeshVertex a, b, c; - a.vertex = Vertex3f( 0, 0, 0 ); - a.texcoord = TexCoord2f( 0, 0 ); - b.vertex = vertex3f_for_vector3( tangentX[index0] ); - b.texcoord = texcoord2f_for_vector2( tangentS[index0] ); - c.vertex = vertex3f_for_vector3( tangentY[index1] ); - c.texcoord = texcoord2f_for_vector2( tangentT[index1] ); - - Vector3 s, t; - ArbitraryMeshTriangle_calcTangents( a, b, c, s, t ); - if ( !vector3_equal( s, g_vector3_identity ) ) { - vector3_add( tangent_for_index( m_tess.m_vertices, index ), vector3_normalised( s ) ); - } - if ( !vector3_equal( t, g_vector3_identity ) ) { - vector3_add( bitangent_for_index( m_tess.m_vertices, index ), vector3_normalised( t ) ); - } - } +inline void tangents_remove_degenerate(Vector3 tangents[6], Vector2 textureTangents[6], unsigned int flags) +{ + if (flags & DEGEN_0a) { + const std::size_t i = + (flags & DEGEN_0b) + ? (flags & DEGEN_1a) + ? (flags & DEGEN_1b) + ? (flags & DEGEN_2a) + ? 5 + : 4 + : 3 + : 2 + : 1; + tangents[0] = tangents[i]; + textureTangents[0] = textureTangents[i]; + } + if (flags & DEGEN_0b) { + const std::size_t i = + (flags & DEGEN_0a) + ? (flags & DEGEN_1b) + ? (flags & DEGEN_1a) + ? (flags & DEGEN_2b) + ? 4 + : 5 + : 2 + : 3 + : 0; + tangents[1] = tangents[i]; + textureTangents[1] = textureTangents[i]; + } + if (flags & DEGEN_2a) { + const std::size_t i = + (flags & DEGEN_2b) + ? (flags & DEGEN_1a) + ? (flags & DEGEN_1b) + ? (flags & DEGEN_0a) + ? 1 + : 0 + : 3 + : 2 + : 5; + tangents[4] = tangents[i]; + textureTangents[4] = textureTangents[i]; + } + if (flags & DEGEN_2b) { + const std::size_t i = + (flags & DEGEN_2a) + ? (flags & DEGEN_1b) + ? (flags & DEGEN_1a) + ? (flags & DEGEN_0b) + ? 0 + : 1 + : 2 + : 3 + : 4; + tangents[5] = tangents[i]; + textureTangents[5] = textureTangents[i]; + } +} + +void bestTangents00(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1) +{ + if (fabs(dot + length) < 0.001) { // opposing direction = degenerate + if (!(degenerateFlags & DEGEN_1a)) { // if this tangent is degenerate we cannot use it + index0 = 2; + index1 = 0; + } else if (!(degenerateFlags & DEGEN_0b)) { + index0 = 0; + index1 = 1; + } else { + index0 = 1; + index1 = 0; + } + } else if (fabs(dot - length) < 0.001) { // same direction = degenerate + if (degenerateFlags & DEGEN_0b) { + index0 = 0; + index1 = 1; + } else { + index0 = 1; + index1 = 0; + } + } +} + +void bestTangents01(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1) +{ + if (fabs(dot - length) < 0.001) { // same direction = degenerate + if (!(degenerateFlags & DEGEN_1a)) { // if this tangent is degenerate we cannot use it + index0 = 2; + index1 = 1; + } else if (!(degenerateFlags & DEGEN_2b)) { + index0 = 4; + index1 = 0; + } else { + index0 = 5; + index1 = 1; + } + } else if (fabs(dot + length) < 0.001) { // opposing direction = degenerate + if (degenerateFlags & DEGEN_2b) { + index0 = 4; + index1 = 0; + } else { + index0 = 5; + index1 = 1; + } + } +} + +void bestTangents10(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1) +{ + if (fabs(dot - length) < 0.001) { // same direction = degenerate + if (!(degenerateFlags & DEGEN_1b)) { // if this tangent is degenerate we cannot use it + index0 = 3; + index1 = 4; + } else if (!(degenerateFlags & DEGEN_0a)) { + index0 = 1; + index1 = 5; + } else { + index0 = 0; + index1 = 4; + } + } else if (fabs(dot + length) < 0.001) { // opposing direction = degenerate + if (degenerateFlags & DEGEN_0a) { + index0 = 1; + index1 = 5; + } else { + index0 = 0; + index1 = 4; + } + } +} + +void bestTangents11(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1) +{ + if (fabs(dot + length) < 0.001) { // opposing direction = degenerate + if (!(degenerateFlags & DEGEN_1b)) { // if this tangent is degenerate we cannot use it + index0 = 3; + index1 = 5; + } else if (!(degenerateFlags & DEGEN_2a)) { + index0 = 5; + index1 = 4; + } else { + index0 = 4; + index1 = 5; + } + } else if (fabs(dot - length) < 0.001) { // same direction = degenerate + if (degenerateFlags & DEGEN_2a) { + index0 = 5; + index1 = 4; + } else { + index0 = 4; + index1 = 5; + } + } +} + +void +Patch::accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], + Vector2 tangentT[6], std::size_t index0, std::size_t index1) +{ + { + Vector3 normal(vector3_cross(tangentX[index0], tangentY[index1])); + if (!vector3_equal(normal, g_vector3_identity)) { + vector3_add(normal_for_index(m_tess.m_vertices, index), vector3_normalised(normal)); + } + } + + { + ArbitraryMeshVertex a, b, c; + a.vertex = Vertex3f(0, 0, 0); + a.texcoord = TexCoord2f(0, 0); + b.vertex = vertex3f_for_vector3(tangentX[index0]); + b.texcoord = texcoord2f_for_vector2(tangentS[index0]); + c.vertex = vertex3f_for_vector3(tangentY[index1]); + c.texcoord = texcoord2f_for_vector2(tangentT[index1]); + + Vector3 s, t; + ArbitraryMeshTriangle_calcTangents(a, b, c, s, t); + if (!vector3_equal(s, g_vector3_identity)) { + vector3_add(tangent_for_index(m_tess.m_vertices, index), vector3_normalised(s)); + } + if (!vector3_equal(t, g_vector3_identity)) { + vector3_add(bitangent_for_index(m_tess.m_vertices, index), vector3_normalised(t)); + } + } } const std::size_t PATCH_MAX_VERTEX_ARRAY = 1048576; -void Patch::BuildVertexArray(){ - const std::size_t strideU = 1; - const std::size_t strideV = m_width; - - const std::size_t numElems = m_tess.m_nArrayWidth * m_tess.m_nArrayHeight; // total number of elements in vertex array - - const bool bWidthStrips = ( m_tess.m_nArrayWidth >= m_tess.m_nArrayHeight ); // decide if horizontal strips are longer than vertical - - - // allocate vertex, normal, texcoord and primitive-index arrays - m_tess.m_vertices.resize( numElems ); - m_tess.m_indices.resize( m_tess.m_nArrayWidth * 2 * ( m_tess.m_nArrayHeight - 1 ) ); - - // set up strip indices - if ( bWidthStrips ) { - m_tess.m_numStrips = m_tess.m_nArrayHeight - 1; - m_tess.m_lenStrips = m_tess.m_nArrayWidth * 2; - - for ( std::size_t i = 0; i < m_tess.m_nArrayWidth; i++ ) - { - for ( std::size_t j = 0; j < m_tess.m_numStrips; j++ ) - { - m_tess.m_indices[( j * m_tess.m_lenStrips ) + i * 2] = RenderIndex( j * m_tess.m_nArrayWidth + i ); - m_tess.m_indices[( j * m_tess.m_lenStrips ) + i * 2 + 1] = RenderIndex( ( j + 1 ) * m_tess.m_nArrayWidth + i ); - // reverse because radiant uses CULL_FRONT - //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(j*m_tess.m_nArrayWidth+i); - //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i); - } - } - } - else - { - m_tess.m_numStrips = m_tess.m_nArrayWidth - 1; - m_tess.m_lenStrips = m_tess.m_nArrayHeight * 2; - - for ( std::size_t i = 0; i < m_tess.m_nArrayHeight; i++ ) - { - for ( std::size_t j = 0; j < m_tess.m_numStrips; j++ ) - { - m_tess.m_indices[( j * m_tess.m_lenStrips ) + i * 2] = RenderIndex( ( ( m_tess.m_nArrayHeight - 1 ) - i ) * m_tess.m_nArrayWidth + j ); - m_tess.m_indices[( j * m_tess.m_lenStrips ) + i * 2 + 1] = RenderIndex( ( ( m_tess.m_nArrayHeight - 1 ) - i ) * m_tess.m_nArrayWidth + j + 1 ); - // reverse because radiant uses CULL_FRONT - //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j); - //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j+1); - - } - } - } - - { - PatchControlIter pCtrl = m_ctrlTransformed.data(); - for ( std::size_t j = 0, offStartY = 0; j + 1 < m_height; j += 2, pCtrl += ( strideU + strideV ) ) - { - // set up array offsets for this sub-patch - const bool leafY = ( m_patchDef3 ) ? false : BezierCurveTree_isLeaf( m_tess.m_curveTreeV[j >> 1] ); - const std::size_t offMidY = ( m_patchDef3 ) ? 0 : m_tess.m_curveTreeV[j >> 1]->index; - const std::size_t widthY = m_tess.m_arrayHeight[j >> 1] * m_tess.m_nArrayWidth; - const std::size_t offEndY = offStartY + widthY; - - for ( std::size_t i = 0, offStartX = 0; i + 1 < m_width; i += 2, pCtrl += ( strideU << 1 ) ) - { - const bool leafX = ( m_patchDef3 ) ? false : BezierCurveTree_isLeaf( m_tess.m_curveTreeU[i >> 1] ); - const std::size_t offMidX = ( m_patchDef3 ) ? 0 : m_tess.m_curveTreeU[i >> 1]->index; - const std::size_t widthX = m_tess.m_arrayWidth[i >> 1]; - const std::size_t offEndX = offStartX + widthX; - - PatchControl *subMatrix[3][3]; - subMatrix[0][0] = pCtrl; - subMatrix[0][1] = subMatrix[0][0] + strideU; - subMatrix[0][2] = subMatrix[0][1] + strideU; - subMatrix[1][0] = subMatrix[0][0] + strideV; - subMatrix[1][1] = subMatrix[1][0] + strideU; - subMatrix[1][2] = subMatrix[1][1] + strideU; - subMatrix[2][0] = subMatrix[1][0] + strideV; - subMatrix[2][1] = subMatrix[2][0] + strideU; - subMatrix[2][2] = subMatrix[2][1] + strideU; - - // assign on-patch control points to vertex array - if ( i == 0 && j == 0 ) { - vertex_clear_normal( m_tess.m_vertices[offStartX + offStartY] ); - } - vertex_assign_ctrl( m_tess.m_vertices[offStartX + offStartY], *subMatrix[0][0] ); - if ( j == 0 ) { - vertex_clear_normal( m_tess.m_vertices[offEndX + offStartY] ); - } - vertex_assign_ctrl( m_tess.m_vertices[offEndX + offStartY], *subMatrix[0][2] ); - if ( i == 0 ) { - vertex_clear_normal( m_tess.m_vertices[offStartX + offEndY] ); - } - vertex_assign_ctrl( m_tess.m_vertices[offStartX + offEndY], *subMatrix[2][0] ); - - vertex_clear_normal( m_tess.m_vertices[offEndX + offEndY] ); - vertex_assign_ctrl( m_tess.m_vertices[offEndX + offEndY], *subMatrix[2][2] ); - - if ( !m_patchDef3 ) { - // assign remaining control points to vertex array - if ( !leafX ) { - vertex_assign_ctrl( m_tess.m_vertices[offMidX + offStartY], *subMatrix[0][1] ); - vertex_assign_ctrl( m_tess.m_vertices[offMidX + offEndY], *subMatrix[2][1] ); - } - if ( !leafY ) { - vertex_assign_ctrl( m_tess.m_vertices[offStartX + offMidY], *subMatrix[1][0] ); - vertex_assign_ctrl( m_tess.m_vertices[offEndX + offMidY], *subMatrix[1][2] ); - - if ( !leafX ) { - vertex_assign_ctrl( m_tess.m_vertices[offMidX + offMidY], *subMatrix[1][1] ); - } - } - } - - // test all 12 edges for degeneracy - unsigned int nFlagsX = subarray_get_degen( pCtrl, strideU, strideV ); - unsigned int nFlagsY = subarray_get_degen( pCtrl, strideV, strideU ); - Vector3 tangentX[6], tangentY[6]; - Vector2 tangentS[6], tangentT[6]; - - // set up tangents for each of the 12 edges if they were not degenerate - if ( !( nFlagsX & DEGEN_0a ) ) { - tangentX[0] = vector3_subtracted( subMatrix[0][1]->m_vertex, subMatrix[0][0]->m_vertex ); - tangentS[0] = vector2_subtracted( subMatrix[0][1]->m_texcoord, subMatrix[0][0]->m_texcoord ); - } - if ( !( nFlagsX & DEGEN_0b ) ) { - tangentX[1] = vector3_subtracted( subMatrix[0][2]->m_vertex, subMatrix[0][1]->m_vertex ); - tangentS[1] = vector2_subtracted( subMatrix[0][2]->m_texcoord, subMatrix[0][1]->m_texcoord ); - } - if ( !( nFlagsX & DEGEN_1a ) ) { - tangentX[2] = vector3_subtracted( subMatrix[1][1]->m_vertex, subMatrix[1][0]->m_vertex ); - tangentS[2] = vector2_subtracted( subMatrix[1][1]->m_texcoord, subMatrix[1][0]->m_texcoord ); - } - if ( !( nFlagsX & DEGEN_1b ) ) { - tangentX[3] = vector3_subtracted( subMatrix[1][2]->m_vertex, subMatrix[1][1]->m_vertex ); - tangentS[3] = vector2_subtracted( subMatrix[1][2]->m_texcoord, subMatrix[1][1]->m_texcoord ); - } - if ( !( nFlagsX & DEGEN_2a ) ) { - tangentX[4] = vector3_subtracted( subMatrix[2][1]->m_vertex, subMatrix[2][0]->m_vertex ); - tangentS[4] = vector2_subtracted( subMatrix[2][1]->m_texcoord, subMatrix[2][0]->m_texcoord ); - } - if ( !( nFlagsX & DEGEN_2b ) ) { - tangentX[5] = vector3_subtracted( subMatrix[2][2]->m_vertex, subMatrix[2][1]->m_vertex ); - tangentS[5] = vector2_subtracted( subMatrix[2][2]->m_texcoord, subMatrix[2][1]->m_texcoord ); - } - - if ( !( nFlagsY & DEGEN_0a ) ) { - tangentY[0] = vector3_subtracted( subMatrix[1][0]->m_vertex, subMatrix[0][0]->m_vertex ); - tangentT[0] = vector2_subtracted( subMatrix[1][0]->m_texcoord, subMatrix[0][0]->m_texcoord ); - } - if ( !( nFlagsY & DEGEN_0b ) ) { - tangentY[1] = vector3_subtracted( subMatrix[2][0]->m_vertex, subMatrix[1][0]->m_vertex ); - tangentT[1] = vector2_subtracted( subMatrix[2][0]->m_texcoord, subMatrix[1][0]->m_texcoord ); - } - if ( !( nFlagsY & DEGEN_1a ) ) { - tangentY[2] = vector3_subtracted( subMatrix[1][1]->m_vertex, subMatrix[0][1]->m_vertex ); - tangentT[2] = vector2_subtracted( subMatrix[1][1]->m_texcoord, subMatrix[0][1]->m_texcoord ); - } - if ( !( nFlagsY & DEGEN_1b ) ) { - tangentY[3] = vector3_subtracted( subMatrix[2][1]->m_vertex, subMatrix[1][1]->m_vertex ); - tangentT[3] = vector2_subtracted( subMatrix[2][1]->m_texcoord, subMatrix[1][1]->m_texcoord ); - } - if ( !( nFlagsY & DEGEN_2a ) ) { - tangentY[4] = vector3_subtracted( subMatrix[1][2]->m_vertex, subMatrix[0][2]->m_vertex ); - tangentT[4] = vector2_subtracted( subMatrix[1][2]->m_texcoord, subMatrix[0][2]->m_texcoord ); - } - if ( !( nFlagsY & DEGEN_2b ) ) { - tangentY[5] = vector3_subtracted( subMatrix[2][2]->m_vertex, subMatrix[1][2]->m_vertex ); - tangentT[5] = vector2_subtracted( subMatrix[2][2]->m_texcoord, subMatrix[1][2]->m_texcoord ); - } - - // set up remaining edge tangents by borrowing the tangent from the closest parallel non-degenerate edge - tangents_remove_degenerate( tangentX, tangentS, nFlagsX ); - tangents_remove_degenerate( tangentY, tangentT, nFlagsY ); - - { - // x=0, y=0 - std::size_t index = offStartX + offStartY; - std::size_t index0 = 0; - std::size_t index1 = 0; - - double dot = vector3_dot( tangentX[index0], tangentY[index1] ); - double length = vector3_length( tangentX[index0] ) * vector3_length( tangentY[index1] ); - - bestTangents00( nFlagsX, dot, length, index0, index1 ); - - accumulateVertexTangentSpace( index, tangentX, tangentY, tangentS, tangentT, index0, index1 ); - } - - { - // x=1, y=0 - std::size_t index = offEndX + offStartY; - std::size_t index0 = 1; - std::size_t index1 = 4; - - double dot = vector3_dot( tangentX[index0],tangentY[index1] ); - double length = vector3_length( tangentX[index0] ) * vector3_length( tangentY[index1] ); - - bestTangents10( nFlagsX, dot, length, index0, index1 ); - - accumulateVertexTangentSpace( index, tangentX, tangentY, tangentS, tangentT, index0, index1 ); - } - - { - // x=0, y=1 - std::size_t index = offStartX + offEndY; - std::size_t index0 = 4; - std::size_t index1 = 1; - - double dot = vector3_dot( tangentX[index0], tangentY[index1] ); - double length = vector3_length( tangentX[index1] ) * vector3_length( tangentY[index1] ); - - bestTangents01( nFlagsX, dot, length, index0, index1 ); - - accumulateVertexTangentSpace( index, tangentX, tangentY, tangentS, tangentT, index0, index1 ); - } - - { - // x=1, y=1 - std::size_t index = offEndX + offEndY; - std::size_t index0 = 5; - std::size_t index1 = 5; - - double dot = vector3_dot( tangentX[index0],tangentY[index1] ); - double length = vector3_length( tangentX[index0] ) * vector3_length( tangentY[index1] ); - - bestTangents11( nFlagsX, dot, length, index0, index1 ); - - accumulateVertexTangentSpace( index, tangentX, tangentY, tangentS, tangentT, index0, index1 ); - } - - //normalise normals that won't be accumulated again - if ( i != 0 || j != 0 ) { - normalise_safe( normal_for_index( m_tess.m_vertices, offStartX + offStartY ) ); - normalise_safe( tangent_for_index( m_tess.m_vertices, offStartX + offStartY ) ); - normalise_safe( bitangent_for_index( m_tess.m_vertices, offStartX + offStartY ) ); - } - if ( i + 3 == m_width ) { - normalise_safe( normal_for_index( m_tess.m_vertices, offEndX + offStartY ) ); - normalise_safe( tangent_for_index( m_tess.m_vertices, offEndX + offStartY ) ); - normalise_safe( bitangent_for_index( m_tess.m_vertices, offEndX + offStartY ) ); - } - if ( j + 3 == m_height ) { - normalise_safe( normal_for_index( m_tess.m_vertices, offStartX + offEndY ) ); - normalise_safe( tangent_for_index( m_tess.m_vertices, offStartX + offEndY ) ); - normalise_safe( bitangent_for_index( m_tess.m_vertices, offStartX + offEndY ) ); - } - if ( i + 3 == m_width && j + 3 == m_height ) { - normalise_safe( normal_for_index( m_tess.m_vertices, offEndX + offEndY ) ); - normalise_safe( tangent_for_index( m_tess.m_vertices, offEndX + offEndY ) ); - normalise_safe( bitangent_for_index( m_tess.m_vertices, offEndX + offEndY ) ); - } - - // set flags to average normals between shared edges - if ( j != 0 ) { - nFlagsX |= AVERAGE; - } - if ( i != 0 ) { - nFlagsY |= AVERAGE; - } - // set flags to save evaluating shared edges twice - nFlagsX |= SPLIT; - nFlagsY |= SPLIT; - - // if the patch is curved.. tesselate recursively - // use the relevant control curves for this sub-patch - if ( m_patchDef3 ) { - TesselateSubMatrixFixed( m_tess.m_vertices.data() + offStartX + offStartY, 1, m_tess.m_nArrayWidth, nFlagsX, nFlagsY, subMatrix ); - } - else - { - if ( !leafX ) { - TesselateSubMatrix( m_tess.m_curveTreeU[i >> 1], m_tess.m_curveTreeV[j >> 1], - offStartX, offStartY, offEndX, offEndY, // array offsets - nFlagsX, nFlagsY, - subMatrix[1][0]->m_vertex, subMatrix[1][1]->m_vertex, subMatrix[1][2]->m_vertex, - subMatrix[1][0]->m_texcoord, subMatrix[1][1]->m_texcoord, subMatrix[1][2]->m_texcoord, - false ); - } - else if ( !leafY ) { - TesselateSubMatrix( m_tess.m_curveTreeV[j >> 1], m_tess.m_curveTreeU[i >> 1], - offStartY, offStartX, offEndY, offEndX, // array offsets - nFlagsY, nFlagsX, - subMatrix[0][1]->m_vertex, subMatrix[1][1]->m_vertex, subMatrix[2][1]->m_vertex, - subMatrix[0][1]->m_texcoord, subMatrix[1][1]->m_texcoord, subMatrix[2][1]->m_texcoord, - true ); - } - } - - offStartX = offEndX; - } - offStartY = offEndY; - } - } -} - - - -class PatchFilterWrapper : public Filter +void Patch::BuildVertexArray() { -bool m_active; -bool m_invert; -PatchFilter& m_filter; + const std::size_t strideU = 1; + const std::size_t strideV = m_width; + + const std::size_t numElems = + m_tess.m_nArrayWidth * m_tess.m_nArrayHeight; // total number of elements in vertex array + + const bool bWidthStrips = (m_tess.m_nArrayWidth >= + m_tess.m_nArrayHeight); // decide if horizontal strips are longer than vertical + + + // allocate vertex, normal, texcoord and primitive-index arrays + m_tess.m_vertices.resize(numElems); + m_tess.m_indices.resize(m_tess.m_nArrayWidth * 2 * (m_tess.m_nArrayHeight - 1)); + + // set up strip indices + if (bWidthStrips) { + m_tess.m_numStrips = m_tess.m_nArrayHeight - 1; + m_tess.m_lenStrips = m_tess.m_nArrayWidth * 2; + + for (std::size_t i = 0; i < m_tess.m_nArrayWidth; i++) { + for (std::size_t j = 0; j < m_tess.m_numStrips; j++) { + m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2] = RenderIndex(j * m_tess.m_nArrayWidth + i); + m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2 + 1] = RenderIndex( + (j + 1) * m_tess.m_nArrayWidth + i); + // reverse because radiant uses CULL_FRONT + //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(j*m_tess.m_nArrayWidth+i); + //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i); + } + } + } else { + m_tess.m_numStrips = m_tess.m_nArrayWidth - 1; + m_tess.m_lenStrips = m_tess.m_nArrayHeight * 2; + + for (std::size_t i = 0; i < m_tess.m_nArrayHeight; i++) { + for (std::size_t j = 0; j < m_tess.m_numStrips; j++) { + m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2] = RenderIndex( + ((m_tess.m_nArrayHeight - 1) - i) * m_tess.m_nArrayWidth + j); + m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2 + 1] = RenderIndex( + ((m_tess.m_nArrayHeight - 1) - i) * m_tess.m_nArrayWidth + j + 1); + // reverse because radiant uses CULL_FRONT + //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j); + //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j+1); + + } + } + } + + { + PatchControlIter pCtrl = m_ctrlTransformed.data(); + for (std::size_t j = 0, offStartY = 0; j + 1 < m_height; j += 2, pCtrl += (strideU + strideV)) { + // set up array offsets for this sub-patch + const bool leafY = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeV[j >> 1]); + const std::size_t offMidY = (m_patchDef3) ? 0 : m_tess.m_curveTreeV[j >> 1]->index; + const std::size_t widthY = m_tess.m_arrayHeight[j >> 1] * m_tess.m_nArrayWidth; + const std::size_t offEndY = offStartY + widthY; + + for (std::size_t i = 0, offStartX = 0; i + 1 < m_width; i += 2, pCtrl += (strideU << 1)) { + const bool leafX = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeU[i >> 1]); + const std::size_t offMidX = (m_patchDef3) ? 0 : m_tess.m_curveTreeU[i >> 1]->index; + const std::size_t widthX = m_tess.m_arrayWidth[i >> 1]; + const std::size_t offEndX = offStartX + widthX; + + PatchControl *subMatrix[3][3]; + subMatrix[0][0] = pCtrl; + subMatrix[0][1] = subMatrix[0][0] + strideU; + subMatrix[0][2] = subMatrix[0][1] + strideU; + subMatrix[1][0] = subMatrix[0][0] + strideV; + subMatrix[1][1] = subMatrix[1][0] + strideU; + subMatrix[1][2] = subMatrix[1][1] + strideU; + subMatrix[2][0] = subMatrix[1][0] + strideV; + subMatrix[2][1] = subMatrix[2][0] + strideU; + subMatrix[2][2] = subMatrix[2][1] + strideU; + + // assign on-patch control points to vertex array + if (i == 0 && j == 0) { + vertex_clear_normal(m_tess.m_vertices[offStartX + offStartY]); + } + vertex_assign_ctrl(m_tess.m_vertices[offStartX + offStartY], *subMatrix[0][0]); + if (j == 0) { + vertex_clear_normal(m_tess.m_vertices[offEndX + offStartY]); + } + vertex_assign_ctrl(m_tess.m_vertices[offEndX + offStartY], *subMatrix[0][2]); + if (i == 0) { + vertex_clear_normal(m_tess.m_vertices[offStartX + offEndY]); + } + vertex_assign_ctrl(m_tess.m_vertices[offStartX + offEndY], *subMatrix[2][0]); + + vertex_clear_normal(m_tess.m_vertices[offEndX + offEndY]); + vertex_assign_ctrl(m_tess.m_vertices[offEndX + offEndY], *subMatrix[2][2]); + + if (!m_patchDef3) { + // assign remaining control points to vertex array + if (!leafX) { + vertex_assign_ctrl(m_tess.m_vertices[offMidX + offStartY], *subMatrix[0][1]); + vertex_assign_ctrl(m_tess.m_vertices[offMidX + offEndY], *subMatrix[2][1]); + } + if (!leafY) { + vertex_assign_ctrl(m_tess.m_vertices[offStartX + offMidY], *subMatrix[1][0]); + vertex_assign_ctrl(m_tess.m_vertices[offEndX + offMidY], *subMatrix[1][2]); + + if (!leafX) { + vertex_assign_ctrl(m_tess.m_vertices[offMidX + offMidY], *subMatrix[1][1]); + } + } + } + + // test all 12 edges for degeneracy + unsigned int nFlagsX = subarray_get_degen(pCtrl, strideU, strideV); + unsigned int nFlagsY = subarray_get_degen(pCtrl, strideV, strideU); + Vector3 tangentX[6], tangentY[6]; + Vector2 tangentS[6], tangentT[6]; + + // set up tangents for each of the 12 edges if they were not degenerate + if (!(nFlagsX & DEGEN_0a)) { + tangentX[0] = vector3_subtracted(subMatrix[0][1]->m_vertex, subMatrix[0][0]->m_vertex); + tangentS[0] = vector2_subtracted(subMatrix[0][1]->m_texcoord, subMatrix[0][0]->m_texcoord); + } + if (!(nFlagsX & DEGEN_0b)) { + tangentX[1] = vector3_subtracted(subMatrix[0][2]->m_vertex, subMatrix[0][1]->m_vertex); + tangentS[1] = vector2_subtracted(subMatrix[0][2]->m_texcoord, subMatrix[0][1]->m_texcoord); + } + if (!(nFlagsX & DEGEN_1a)) { + tangentX[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[1][0]->m_vertex); + tangentS[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[1][0]->m_texcoord); + } + if (!(nFlagsX & DEGEN_1b)) { + tangentX[3] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[1][1]->m_vertex); + tangentS[3] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[1][1]->m_texcoord); + } + if (!(nFlagsX & DEGEN_2a)) { + tangentX[4] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[2][0]->m_vertex); + tangentS[4] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[2][0]->m_texcoord); + } + if (!(nFlagsX & DEGEN_2b)) { + tangentX[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[2][1]->m_vertex); + tangentS[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[2][1]->m_texcoord); + } + + if (!(nFlagsY & DEGEN_0a)) { + tangentY[0] = vector3_subtracted(subMatrix[1][0]->m_vertex, subMatrix[0][0]->m_vertex); + tangentT[0] = vector2_subtracted(subMatrix[1][0]->m_texcoord, subMatrix[0][0]->m_texcoord); + } + if (!(nFlagsY & DEGEN_0b)) { + tangentY[1] = vector3_subtracted(subMatrix[2][0]->m_vertex, subMatrix[1][0]->m_vertex); + tangentT[1] = vector2_subtracted(subMatrix[2][0]->m_texcoord, subMatrix[1][0]->m_texcoord); + } + if (!(nFlagsY & DEGEN_1a)) { + tangentY[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[0][1]->m_vertex); + tangentT[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[0][1]->m_texcoord); + } + if (!(nFlagsY & DEGEN_1b)) { + tangentY[3] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[1][1]->m_vertex); + tangentT[3] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[1][1]->m_texcoord); + } + if (!(nFlagsY & DEGEN_2a)) { + tangentY[4] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[0][2]->m_vertex); + tangentT[4] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[0][2]->m_texcoord); + } + if (!(nFlagsY & DEGEN_2b)) { + tangentY[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[1][2]->m_vertex); + tangentT[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[1][2]->m_texcoord); + } + + // set up remaining edge tangents by borrowing the tangent from the closest parallel non-degenerate edge + tangents_remove_degenerate(tangentX, tangentS, nFlagsX); + tangents_remove_degenerate(tangentY, tangentT, nFlagsY); + + { + // x=0, y=0 + std::size_t index = offStartX + offStartY; + std::size_t index0 = 0; + std::size_t index1 = 0; + + double dot = vector3_dot(tangentX[index0], tangentY[index1]); + double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]); + + bestTangents00(nFlagsX, dot, length, index0, index1); + + accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1); + } + + { + // x=1, y=0 + std::size_t index = offEndX + offStartY; + std::size_t index0 = 1; + std::size_t index1 = 4; + + double dot = vector3_dot(tangentX[index0], tangentY[index1]); + double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]); + + bestTangents10(nFlagsX, dot, length, index0, index1); + + accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1); + } + + { + // x=0, y=1 + std::size_t index = offStartX + offEndY; + std::size_t index0 = 4; + std::size_t index1 = 1; + + double dot = vector3_dot(tangentX[index0], tangentY[index1]); + double length = vector3_length(tangentX[index1]) * vector3_length(tangentY[index1]); + + bestTangents01(nFlagsX, dot, length, index0, index1); + + accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1); + } + + { + // x=1, y=1 + std::size_t index = offEndX + offEndY; + std::size_t index0 = 5; + std::size_t index1 = 5; + + double dot = vector3_dot(tangentX[index0], tangentY[index1]); + double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]); + + bestTangents11(nFlagsX, dot, length, index0, index1); + + accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1); + } + + //normalise normals that won't be accumulated again + if (i != 0 || j != 0) { + normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offStartY)); + normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offStartY)); + normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offStartY)); + } + if (i + 3 == m_width) { + normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offStartY)); + normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offStartY)); + normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offStartY)); + } + if (j + 3 == m_height) { + normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offEndY)); + normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offEndY)); + normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offEndY)); + } + if (i + 3 == m_width && j + 3 == m_height) { + normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offEndY)); + normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offEndY)); + normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offEndY)); + } + + // set flags to average normals between shared edges + if (j != 0) { + nFlagsX |= AVERAGE; + } + if (i != 0) { + nFlagsY |= AVERAGE; + } + // set flags to save evaluating shared edges twice + nFlagsX |= SPLIT; + nFlagsY |= SPLIT; + + // if the patch is curved.. tesselate recursively + // use the relevant control curves for this sub-patch + if (m_patchDef3) { + TesselateSubMatrixFixed(m_tess.m_vertices.data() + offStartX + offStartY, 1, m_tess.m_nArrayWidth, + nFlagsX, nFlagsY, subMatrix); + } else { + if (!leafX) { + TesselateSubMatrix(m_tess.m_curveTreeU[i >> 1], m_tess.m_curveTreeV[j >> 1], + offStartX, offStartY, offEndX, offEndY, // array offsets + nFlagsX, nFlagsY, + subMatrix[1][0]->m_vertex, subMatrix[1][1]->m_vertex, + subMatrix[1][2]->m_vertex, + subMatrix[1][0]->m_texcoord, subMatrix[1][1]->m_texcoord, + subMatrix[1][2]->m_texcoord, + false); + } else if (!leafY) { + TesselateSubMatrix(m_tess.m_curveTreeV[j >> 1], m_tess.m_curveTreeU[i >> 1], + offStartY, offStartX, offEndY, offEndX, // array offsets + nFlagsY, nFlagsX, + subMatrix[0][1]->m_vertex, subMatrix[1][1]->m_vertex, + subMatrix[2][1]->m_vertex, + subMatrix[0][1]->m_texcoord, subMatrix[1][1]->m_texcoord, + subMatrix[2][1]->m_texcoord, + true); + } + } + + offStartX = offEndX; + } + offStartY = offEndY; + } + } +} + + +class PatchFilterWrapper : public Filter { + bool m_active; + bool m_invert; + PatchFilter &m_filter; public: -PatchFilterWrapper( PatchFilter& filter, bool invert ) : m_invert( invert ), m_filter( filter ){ -} -void setActive( bool active ){ - m_active = active; -} -bool active(){ - return m_active; -} -bool filter( const Patch& patch ){ - return m_invert ^ m_filter.filter( patch ); -} + PatchFilterWrapper(PatchFilter &filter, bool invert) : m_invert(invert), m_filter(filter) + { + } + + void setActive(bool active) + { + m_active = active; + } + + bool active() + { + return m_active; + } + + bool filter(const Patch &patch) + { + return m_invert ^ m_filter.filter(patch); + } }; typedef std::list PatchFilters; PatchFilters g_patchFilters; -void add_patch_filter( PatchFilter& filter, int mask, bool invert ){ - g_patchFilters.push_back( PatchFilterWrapper( filter, invert ) ); - GlobalFilterSystem().addFilter( g_patchFilters.back(), mask ); +void add_patch_filter(PatchFilter &filter, int mask, bool invert) +{ + g_patchFilters.push_back(PatchFilterWrapper(filter, invert)); + GlobalFilterSystem().addFilter(g_patchFilters.back(), mask); } -bool patch_filtered( Patch& patch ){ - for ( PatchFilters::iterator i = g_patchFilters.begin(); i != g_patchFilters.end(); ++i ) - { - if ( ( *i ).active() && ( *i ).filter( patch ) ) { - return true; - } - } - return false; +bool patch_filtered(Patch &patch) +{ + for (PatchFilters::iterator i = g_patchFilters.begin(); i != g_patchFilters.end(); ++i) { + if ((*i).active() && (*i).filter(patch)) { + return true; + } + } + return false; } diff --git a/radiant/patch.h b/radiant/patch.h index 6e8742b0..3ab56d44 100644 --- a/radiant/patch.h +++ b/radiant/patch.h @@ -64,10 +64,9 @@ #include "xml/ixml.h" #include "dragplanes.h" -enum EPatchType -{ - ePatchTypeQuake3, - ePatchTypeDoom3, +enum EPatchType { + ePatchTypeQuake3, + ePatchTypeDoom3, }; extern int g_PatchSubdivideThreshold; @@ -82,1358 +81,1497 @@ extern std::size_t MAX_PATCH_HEIGHT; #define MAX_PATCH_ROWCTRL ( ( ( MAX_PATCH_WIDTH - 1 ) - 1 ) / 2 ) #define MAX_PATCH_COLCTRL ( ( ( MAX_PATCH_HEIGHT - 1 ) - 1 ) / 2 ) -enum EPatchCap -{ - eCapBevel, - eCapEndCap, - eCapIBevel, - eCapIEndCap, - eCapCylinder, +enum EPatchCap { + eCapBevel, + eCapEndCap, + eCapIBevel, + eCapIEndCap, + eCapCylinder, }; -enum EPatchPrefab -{ - ePlane, - eBevel, - eEndCap, - eCylinder, - eDenseCylinder, - eVeryDenseCylinder, - eSqCylinder, - eCone, - eSphere, - eXactCylinder, - eXactSphere, - eXactCone, +enum EPatchPrefab { + ePlane, + eBevel, + eEndCap, + eCylinder, + eDenseCylinder, + eVeryDenseCylinder, + eSqCylinder, + eCone, + eSphere, + eXactCylinder, + eXactSphere, + eXactCone, }; -enum EMatrixMajor -{ - ROW, COL, +enum EMatrixMajor { + ROW, COL, }; -struct BezierCurve -{ - Vector3 crd; - Vector3 left; - Vector3 right; +struct BezierCurve { + Vector3 crd; + Vector3 left; + Vector3 right; }; -const std::size_t BEZIERCURVETREE_MAX_INDEX = std::size_t( 1 ) << ( std::numeric_limits::digits - 1 ); +const std::size_t BEZIERCURVETREE_MAX_INDEX = std::size_t(1) << (std::numeric_limits::digits - 1); -struct BezierCurveTree -{ - std::size_t index; - BezierCurveTree* left; - BezierCurveTree* right; +struct BezierCurveTree { + std::size_t index; + BezierCurveTree *left; + BezierCurveTree *right; }; -inline bool BezierCurveTree_isLeaf( const BezierCurveTree* node ){ - return node->left == 0 && node->right == 0; +inline bool BezierCurveTree_isLeaf(const BezierCurveTree *node) +{ + return node->left == 0 && node->right == 0; } -void BezierCurveTree_Delete( BezierCurveTree *pCurve ); +void BezierCurveTree_Delete(BezierCurveTree *pCurve); -inline VertexPointer vertexpointer_arbitrarymeshvertex( const ArbitraryMeshVertex* array ){ - return VertexPointer( VertexPointer::pointer( &array->vertex ), sizeof( ArbitraryMeshVertex ) ); +inline VertexPointer vertexpointer_arbitrarymeshvertex(const ArbitraryMeshVertex *array) +{ + return VertexPointer(VertexPointer::pointer(&array->vertex), sizeof(ArbitraryMeshVertex)); } -typedef PatchControl* PatchControlIter; -typedef const PatchControl* PatchControlConstIter; +typedef PatchControl *PatchControlIter; +typedef const PatchControl *PatchControlConstIter; -inline void copy_ctrl( PatchControlIter ctrl, PatchControlConstIter begin, PatchControlConstIter end ){ - std::copy( begin, end, ctrl ); +inline void copy_ctrl(PatchControlIter ctrl, PatchControlConstIter begin, PatchControlConstIter end) +{ + std::copy(begin, end, ctrl); } -const Colour4b colour_corner( 0, 255, 0, 255 ); -const Colour4b colour_inside( 255, 0, 255, 255 ); +const Colour4b colour_corner(0, 255, 0, 255); +const Colour4b colour_inside(255, 0, 255, 255); class Patch; -class PatchFilter -{ +class PatchFilter { public: -virtual bool filter( const Patch& patch ) const = 0; + virtual bool filter(const Patch &patch) const = 0; }; -bool patch_filtered( Patch& patch ); -void add_patch_filter( PatchFilter& filter, int mask, bool invert = false ); +bool patch_filtered(Patch &patch); + +void add_patch_filter(PatchFilter &filter, int mask, bool invert = false); + +void Patch_addTextureChangedCallback(const SignalHandler &handler); -void Patch_addTextureChangedCallback( const SignalHandler& handler ); void Patch_textureChanged(); -inline void BezierCurveTreeArray_deleteAll( Array& curveTrees ){ - for ( Array::iterator i = curveTrees.begin(); i != curveTrees.end(); ++i ) - { - BezierCurveTree_Delete( *i ); - } +inline void BezierCurveTreeArray_deleteAll(Array &curveTrees) +{ + for (Array::iterator i = curveTrees.begin(); i != curveTrees.end(); ++i) { + BezierCurveTree_Delete(*i); + } } -inline void PatchControlArray_invert( Array& ctrl, std::size_t width, std::size_t height ){ - Array tmp( width ); +inline void PatchControlArray_invert(Array &ctrl, std::size_t width, std::size_t height) +{ + Array tmp(width); - PatchControlIter from = ctrl.data() + ( width * ( height - 1 ) ); - PatchControlIter to = ctrl.data(); - for ( std::size_t h = 0; h != ( ( height - 1 ) >> 1 ); ++h, to += width, from -= width ) - { - copy_ctrl( tmp.data(), to, to + width ); - copy_ctrl( to, from, from + width ); - copy_ctrl( from, tmp.data(), tmp.data() + width ); - } + PatchControlIter from = ctrl.data() + (width * (height - 1)); + PatchControlIter to = ctrl.data(); + for (std::size_t h = 0; h != ((height - 1) >> 1); ++h, to += width, from -= width) { + copy_ctrl(tmp.data(), to, to + width); + copy_ctrl(to, from, from + width); + copy_ctrl(from, tmp.data(), tmp.data() + width); + } } -class PatchTesselation -{ +class PatchTesselation { public: -PatchTesselation() - : m_numStrips( 0 ), m_lenStrips( 0 ), m_nArrayWidth( 0 ), m_nArrayHeight( 0 ){ -} -Array m_vertices; -Array m_indices; -std::size_t m_numStrips; -std::size_t m_lenStrips; - -Array m_arrayWidth; -std::size_t m_nArrayWidth; -Array m_arrayHeight; -std::size_t m_nArrayHeight; - -Array m_curveTreeU; -Array m_curveTreeV; + PatchTesselation() + : m_numStrips(0), m_lenStrips(0), m_nArrayWidth(0), m_nArrayHeight(0) + { + } + + Array m_vertices; + Array m_indices; + std::size_t m_numStrips; + std::size_t m_lenStrips; + + Array m_arrayWidth; + std::size_t m_nArrayWidth; + Array m_arrayHeight; + std::size_t m_nArrayHeight; + + Array m_curveTreeU; + Array m_curveTreeV; }; -class RenderablePatchWireframe : public OpenGLRenderable -{ -PatchTesselation& m_tess; +class RenderablePatchWireframe : public OpenGLRenderable { + PatchTesselation &m_tess; public: -RenderablePatchWireframe( PatchTesselation& tess ) : m_tess( tess ){ -} -void render( RenderStateFlags state ) const { - { - #if NV_DRIVER_BUG - glVertexPointer( 3, GL_FLOAT, 0, 0 ); - glDrawArrays( GL_TRIANGLE_FAN, 0, 0 ); - #endif - - std::size_t n = 0; - glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex ); - for ( std::size_t i = 0; i <= m_tess.m_curveTreeV.size(); ++i ) - { - glDrawArrays( GL_LINE_STRIP, GLint( n ), GLsizei( m_tess.m_nArrayWidth ) ); - - if ( i == m_tess.m_curveTreeV.size() ) { - break; - } - - if ( !BezierCurveTree_isLeaf( m_tess.m_curveTreeV[i] ) ) { - glDrawArrays( GL_LINE_STRIP, GLint( m_tess.m_curveTreeV[i]->index ), GLsizei( m_tess.m_nArrayWidth ) ); - } - - n += ( m_tess.m_arrayHeight[i] * m_tess.m_nArrayWidth ); - - } - } - - { - const ArbitraryMeshVertex* p = m_tess.m_vertices.data(); - std::size_t n = m_tess.m_nArrayWidth * sizeof( ArbitraryMeshVertex ); - for ( std::size_t i = 0; i <= m_tess.m_curveTreeU.size(); ++i ) - { - glVertexPointer( 3, GL_FLOAT, GLsizei( n ), &p->vertex ); - glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_tess.m_nArrayHeight ) ); - - if ( i == m_tess.m_curveTreeU.size() ) { - break; - } - - if ( !BezierCurveTree_isLeaf( m_tess.m_curveTreeU[i] ) ) { - glVertexPointer( 3, GL_FLOAT, GLsizei( n ), &( m_tess.m_vertices.data() + ( m_tess.m_curveTreeU[i]->index ) )->vertex ); - glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_tess.m_nArrayHeight ) ); - } + RenderablePatchWireframe(PatchTesselation &tess) : m_tess(tess) + { + } + + void render(RenderStateFlags state) const + { + { +#if NV_DRIVER_BUG + glVertexPointer(3, GL_FLOAT, 0, 0); + glDrawArrays(GL_TRIANGLE_FAN, 0, 0); +#endif - p += m_tess.m_arrayWidth[i]; - } - } -} + std::size_t n = 0; + glVertexPointer(3, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->vertex); + for (std::size_t i = 0; i <= m_tess.m_curveTreeV.size(); ++i) { + glDrawArrays(GL_LINE_STRIP, GLint(n), GLsizei(m_tess.m_nArrayWidth)); + + if (i == m_tess.m_curveTreeV.size()) { + break; + } + + if (!BezierCurveTree_isLeaf(m_tess.m_curveTreeV[i])) { + glDrawArrays(GL_LINE_STRIP, GLint(m_tess.m_curveTreeV[i]->index), GLsizei(m_tess.m_nArrayWidth)); + } + + n += (m_tess.m_arrayHeight[i] * m_tess.m_nArrayWidth); + + } + } + + { + const ArbitraryMeshVertex *p = m_tess.m_vertices.data(); + std::size_t n = m_tess.m_nArrayWidth * sizeof(ArbitraryMeshVertex); + for (std::size_t i = 0; i <= m_tess.m_curveTreeU.size(); ++i) { + glVertexPointer(3, GL_FLOAT, GLsizei(n), &p->vertex); + glDrawArrays(GL_LINE_STRIP, 0, GLsizei(m_tess.m_nArrayHeight)); + + if (i == m_tess.m_curveTreeU.size()) { + break; + } + + if (!BezierCurveTree_isLeaf(m_tess.m_curveTreeU[i])) { + glVertexPointer(3, GL_FLOAT, GLsizei(n), + &(m_tess.m_vertices.data() + (m_tess.m_curveTreeU[i]->index))->vertex); + glDrawArrays(GL_LINE_STRIP, 0, GLsizei(m_tess.m_nArrayHeight)); + } + + p += m_tess.m_arrayWidth[i]; + } + } + } }; -class RenderablePatchFixedWireframe : public OpenGLRenderable -{ -PatchTesselation& m_tess; +class RenderablePatchFixedWireframe : public OpenGLRenderable { + PatchTesselation &m_tess; public: -RenderablePatchFixedWireframe( PatchTesselation& tess ) : m_tess( tess ){ -} -void render( RenderStateFlags state ) const { - glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex ); - const RenderIndex* strip_indices = m_tess.m_indices.data(); - for ( std::size_t i = 0; i < m_tess.m_numStrips; i++, strip_indices += m_tess.m_lenStrips ) - { - glDrawElements( GL_QUAD_STRIP, GLsizei( m_tess.m_lenStrips ), RenderIndexTypeID, strip_indices ); - } -} + RenderablePatchFixedWireframe(PatchTesselation &tess) : m_tess(tess) + { + } + + void render(RenderStateFlags state) const + { + glVertexPointer(3, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->vertex); + const RenderIndex *strip_indices = m_tess.m_indices.data(); + for (std::size_t i = 0; i < m_tess.m_numStrips; i++, strip_indices += m_tess.m_lenStrips) { + glDrawElements(GL_QUAD_STRIP, GLsizei(m_tess.m_lenStrips), RenderIndexTypeID, strip_indices); + } + } }; -class RenderablePatchSolid : public OpenGLRenderable -{ -PatchTesselation& m_tess; +class RenderablePatchSolid : public OpenGLRenderable { + PatchTesselation &m_tess; public: -RenderablePatchSolid( PatchTesselation& tess ) : m_tess( tess ){ -} -void RenderNormals() const; -void render( RenderStateFlags state ) const { + RenderablePatchSolid(PatchTesselation &tess) : m_tess(tess) + { + } + + void RenderNormals() const; + + void render(RenderStateFlags state) const + { #if 0 - if ( ( state & RENDER_FILL ) == 0 ) { + if ( ( state & RENDER_FILL ) == 0 ) { RenderablePatchWireframe( m_tess ).render( state ); } else #endif - { - if ( ( state & RENDER_BUMP ) != 0 ) { - if ( GlobalShaderCache().useShaderLanguage() ) { - glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->normal ); - glVertexAttribPointerARB( c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->texcoord ); - glVertexAttribPointerARB( c_attr_Tangent, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->tangent ); - glVertexAttribPointerARB( c_attr_Binormal, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->bitangent ); - } - else - { - glVertexAttribPointerARB( 11, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->normal ); - glVertexAttribPointerARB( 8, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->texcoord ); - glVertexAttribPointerARB( 9, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->tangent ); - glVertexAttribPointerARB( 10, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->bitangent ); - } - } - else - { - glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->normal ); - glTexCoordPointer( 2, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->texcoord ); - } - glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex ); - const RenderIndex* strip_indices = m_tess.m_indices.data(); - for ( std::size_t i = 0; i < m_tess.m_numStrips; i++, strip_indices += m_tess.m_lenStrips ) - { - glDrawElements( GL_QUAD_STRIP, GLsizei( m_tess.m_lenStrips ), RenderIndexTypeID, strip_indices ); - } - } + { + if ((state & RENDER_BUMP) != 0) { + if (GlobalShaderCache().useShaderLanguage()) { + glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->normal); + glVertexAttribPointerARB(c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_tess.m_vertices.data()->texcoord); + glVertexAttribPointerARB(c_attr_Tangent, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_tess.m_vertices.data()->tangent); + glVertexAttribPointerARB(c_attr_Binormal, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_tess.m_vertices.data()->bitangent); + } else { + glVertexAttribPointerARB(11, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_tess.m_vertices.data()->normal); + glVertexAttribPointerARB(8, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_tess.m_vertices.data()->texcoord); + glVertexAttribPointerARB(9, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_tess.m_vertices.data()->tangent); + glVertexAttribPointerARB(10, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), + &m_tess.m_vertices.data()->bitangent); + } + } else { + glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->normal); + glTexCoordPointer(2, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->texcoord); + } + glVertexPointer(3, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->vertex); + const RenderIndex *strip_indices = m_tess.m_indices.data(); + for (std::size_t i = 0; i < m_tess.m_numStrips; i++, strip_indices += m_tess.m_lenStrips) { + glDrawElements(GL_QUAD_STRIP, GLsizei(m_tess.m_lenStrips), RenderIndexTypeID, strip_indices); + } + } #if GDEF_DEBUG - RenderNormals(); + RenderNormals(); #endif -} + } }; // parametric surface defined by quadratic bezier control curves class Patch : - public XMLImporter, - public XMLExporter, - public TransformNode, - public Bounded, - public Cullable, - public Snappable, - public Undoable, - public Filterable, - public Nameable -{ -class xml_state_t -{ -public: -enum EState -{ - eDefault, - ePatch, - eMatrix, - eShader, -}; -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 ); -} -private: -EState m_state; -StringOutputStream m_content; -}; - -std::vector m_xml_state; - -typedef Array PatchControlArray; - -class SavedState : public UndoMemento -{ -public: -SavedState( - std::size_t width, - std::size_t height, - const PatchControlArray& ctrl, - const char* shader, - bool patchDef3, - std::size_t subdivisions_x, - std::size_t subdivisions_y - ) : - m_width( width ), - m_height( height ), - m_shader( shader ), - m_ctrl( ctrl ), - m_patchDef3( patchDef3 ), - m_subdivisions_x( subdivisions_x ), - m_subdivisions_y( subdivisions_y ){ -} - -void release(){ - delete this; -} + public XMLImporter, + public XMLExporter, + public TransformNode, + public Bounded, + public Cullable, + public Snappable, + public Undoable, + public Filterable, + public Nameable { + class xml_state_t { + public: + enum EState { + eDefault, + ePatch, + eMatrix, + eShader, + }; + + 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); + } + + private: + EState m_state; + StringOutputStream m_content; + }; + + std::vector m_xml_state; + + typedef Array PatchControlArray; + + class SavedState : public UndoMemento { + public: + SavedState( + std::size_t width, + std::size_t height, + const PatchControlArray &ctrl, + const char *shader, + bool patchDef3, + std::size_t subdivisions_x, + std::size_t subdivisions_y + ) : + m_width(width), + m_height(height), + m_shader(shader), + m_ctrl(ctrl), + m_patchDef3(patchDef3), + m_subdivisions_x(subdivisions_x), + m_subdivisions_y(subdivisions_y) + { + } + + void release() + { + delete this; + } + + std::size_t m_width, m_height; + CopiedString m_shader; + PatchControlArray m_ctrl; + bool m_patchDef3; + std::size_t m_subdivisions_x; + std::size_t m_subdivisions_y; + }; -std::size_t m_width, m_height; -CopiedString m_shader; -PatchControlArray m_ctrl; -bool m_patchDef3; -std::size_t m_subdivisions_x; -std::size_t m_subdivisions_y; -}; - -public: -class Observer -{ public: -virtual void allocate( std::size_t size ) = 0; -}; + class Observer { + public: + virtual void allocate(std::size_t size) = 0; + }; private: -typedef UniqueSet Observers; -Observers m_observers; + typedef UniqueSet Observers; + Observers m_observers; -scene::Node* m_node; + scene::Node *m_node; -AABB m_aabb_local; // local bbox + AABB m_aabb_local; // local bbox -CopiedString m_shader; -Shader* m_state; + CopiedString m_shader; + Shader *m_state; -std::size_t m_width; -std::size_t m_height; + std::size_t m_width; + std::size_t m_height; public: -bool m_patchDef3; -std::size_t m_subdivisions_x; -std::size_t m_subdivisions_y; + bool m_patchDef3; + std::size_t m_subdivisions_x; + std::size_t m_subdivisions_y; private: -UndoObserver* m_undoable_observer; -MapFile* m_map; + UndoObserver *m_undoable_observer; + MapFile *m_map; // dynamically allocated array of control points, size is m_width*m_height -PatchControlArray m_ctrl; -PatchControlArray m_ctrlTransformed; + PatchControlArray m_ctrl; + PatchControlArray m_ctrlTransformed; -PatchTesselation m_tess; -RenderablePatchSolid m_render_solid; -RenderablePatchWireframe m_render_wireframe; -RenderablePatchFixedWireframe m_render_wireframe_fixed; + PatchTesselation m_tess; + RenderablePatchSolid m_render_solid; + RenderablePatchWireframe m_render_wireframe; + RenderablePatchFixedWireframe m_render_wireframe_fixed; -static Shader* m_state_ctrl; -static Shader* m_state_lattice; -VertexBuffer m_ctrl_vertices; -RenderableVertexBuffer m_render_ctrl; -IndexBuffer m_lattice_indices; -RenderableIndexBuffer m_render_lattice; + static Shader *m_state_ctrl; + static Shader *m_state_lattice; + VertexBuffer m_ctrl_vertices; + RenderableVertexBuffer m_render_ctrl; + IndexBuffer m_lattice_indices; + RenderableIndexBuffer m_render_lattice; -bool m_bOverlay; + bool m_bOverlay; -bool m_transformChanged; -Callback m_evaluateTransform; -Callback m_boundsChanged; + bool m_transformChanged; + Callback m_evaluateTransform; + Callback m_boundsChanged; -void construct(){ - m_bOverlay = false; - m_width = m_height = 0; + void construct() + { + m_bOverlay = false; + m_width = m_height = 0; - m_patchDef3 = false; - m_subdivisions_x = 0; - m_subdivisions_y = 0; + m_patchDef3 = false; + m_subdivisions_x = 0; + m_subdivisions_y = 0; - check_shader(); - captureShader(); + check_shader(); + captureShader(); - m_xml_state.push_back( xml_state_t::eDefault ); -} + m_xml_state.push_back(xml_state_t::eDefault); + } public: -Callback m_lightsChanged; - -static int m_CycleCapIndex; // = 0; -static EPatchType m_type; - -STRING_CONSTANT( Name, "Patch" ); - -Patch( scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) : - m_node( &node ), - m_shader( texdef_name_default() ), - m_state( 0 ), - m_undoable_observer( 0 ), - m_map( 0 ), - m_render_solid( m_tess ), - m_render_wireframe( m_tess ), - m_render_wireframe_fixed( m_tess ), - m_render_ctrl( GL_POINTS, m_ctrl_vertices ), - m_render_lattice( GL_LINES, m_lattice_indices, m_ctrl_vertices ), - m_transformChanged( false ), - m_evaluateTransform( evaluateTransform ), - m_boundsChanged( boundsChanged ){ - construct(); -} -Patch( const Patch& other, scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) : - m_node( &node ), - m_shader( texdef_name_default() ), - m_state( 0 ), - m_undoable_observer( 0 ), - m_map( 0 ), - m_render_solid( m_tess ), - m_render_wireframe( m_tess ), - m_render_wireframe_fixed( m_tess ), - m_render_ctrl( GL_POINTS, m_ctrl_vertices ), - m_render_lattice( GL_LINES, m_lattice_indices, m_ctrl_vertices ), - m_transformChanged( false ), - m_evaluateTransform( evaluateTransform ), - m_boundsChanged( boundsChanged ){ - construct(); - - m_patchDef3 = other.m_patchDef3; - m_subdivisions_x = other.m_subdivisions_x; - m_subdivisions_y = other.m_subdivisions_y; - setDims( other.m_width, other.m_height ); - copy_ctrl( m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data() + ( m_width * m_height ) ); - SetShader( other.m_shader.c_str() ); - controlPointsChanged(); -} + Callback m_lightsChanged; + + static int m_CycleCapIndex; // = 0; + static EPatchType m_type; + + STRING_CONSTANT(Name, "Patch"); + + Patch(scene::Node &node, const Callback &evaluateTransform, const Callback &boundsChanged) : + m_node(&node), + m_shader(texdef_name_default()), + m_state(0), + m_undoable_observer(0), + m_map(0), + m_render_solid(m_tess), + m_render_wireframe(m_tess), + m_render_wireframe_fixed(m_tess), + m_render_ctrl(GL_POINTS, m_ctrl_vertices), + m_render_lattice(GL_LINES, m_lattice_indices, m_ctrl_vertices), + m_transformChanged(false), + m_evaluateTransform(evaluateTransform), + m_boundsChanged(boundsChanged) + { + construct(); + } + + Patch(const Patch &other, scene::Node &node, const Callback &evaluateTransform, + const Callback &boundsChanged) : + m_node(&node), + m_shader(texdef_name_default()), + m_state(0), + m_undoable_observer(0), + m_map(0), + m_render_solid(m_tess), + m_render_wireframe(m_tess), + m_render_wireframe_fixed(m_tess), + m_render_ctrl(GL_POINTS, m_ctrl_vertices), + m_render_lattice(GL_LINES, m_lattice_indices, m_ctrl_vertices), + m_transformChanged(false), + m_evaluateTransform(evaluateTransform), + m_boundsChanged(boundsChanged) + { + construct(); + + m_patchDef3 = other.m_patchDef3; + m_subdivisions_x = other.m_subdivisions_x; + m_subdivisions_y = other.m_subdivisions_y; + setDims(other.m_width, other.m_height); + copy_ctrl(m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data() + (m_width * m_height)); + SetShader(other.m_shader.c_str()); + controlPointsChanged(); + } + + Patch(const Patch &other) : + XMLImporter(other), + XMLExporter(other), + TransformNode(other), + Bounded(other), + Cullable(other), + Snappable(), + Undoable(other), + Filterable(other), + Nameable(other), + m_state(0), + m_undoable_observer(0), + m_map(0), + m_render_solid(m_tess), + m_render_wireframe(m_tess), + m_render_wireframe_fixed(m_tess), + m_render_ctrl(GL_POINTS, m_ctrl_vertices), + m_render_lattice(GL_LINES, m_lattice_indices, m_ctrl_vertices), + m_transformChanged(false), + m_evaluateTransform(other.m_evaluateTransform), + m_boundsChanged(other.m_boundsChanged) + { + m_bOverlay = false; + + m_patchDef3 = other.m_patchDef3; + m_subdivisions_x = other.m_subdivisions_x; + m_subdivisions_y = other.m_subdivisions_y; + setDims(other.m_width, other.m_height); + copy_ctrl(m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data() + (m_width * m_height)); + SetShader(other.m_shader.c_str()); + controlPointsChanged(); + } + + ~Patch() + { + BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeU); + BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeV); + + releaseShader(); + + ASSERT_MESSAGE(m_observers.empty(), "Patch::~Patch: observers still attached"); + } + + InstanceCounter m_instanceCounter; + + void instanceAttach(const scene::Path &path) + { + if (++m_instanceCounter.m_count == 1) { + m_state->incrementUsed(); + m_map = path_find_mapfile(path.begin(), path.end()); + m_undoable_observer = GlobalUndoSystem().observer(this); + GlobalFilterSystem().registerFilterable(*this); + } else { + ASSERT_MESSAGE(path_find_mapfile(path.begin(), path.end()) == m_map, + "node is instanced across more than one file"); + } + } + + void instanceDetach(const scene::Path &path) + { + if (--m_instanceCounter.m_count == 0) { + m_map = 0; + m_undoable_observer = 0; + GlobalUndoSystem().release(this); + GlobalFilterSystem().unregisterFilterable(*this); + m_state->decrementUsed(); + } + } + + const char *name() const + { + return "patch"; + } + + void attach(const NameCallback &callback) + { + } + + void detach(const NameCallback &callback) + { + } + + void attach(Observer *observer) + { + observer->allocate(m_width * m_height); + + m_observers.insert(observer); + } + + void detach(Observer *observer) + { + m_observers.erase(observer); + } + + void updateFiltered() + { + if (m_node != 0) { + if (patch_filtered(*this)) { + m_node->enable(scene::Node::eFiltered); + } else { + m_node->disable(scene::Node::eFiltered); + } + } + } + + void onAllocate(std::size_t size) + { + for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { + (*i)->allocate(size); + } + } + + const Matrix4 &localToParent() const + { + return g_matrix4_identity; + } + + const AABB &localAABB() const + { + return m_aabb_local; + } + + VolumeIntersectionValue intersectVolume(const VolumeTest &test, const Matrix4 &localToWorld) const + { + return test.TestAABB(m_aabb_local, localToWorld); + } + + void render_solid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + renderer.SetState(m_state, Renderer::eFullMaterials); + renderer.addRenderable(m_render_solid, localToWorld); + } + + void render_wireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + renderer.SetState(m_state, Renderer::eFullMaterials); + if (m_patchDef3) { + renderer.addRenderable(m_render_wireframe_fixed, localToWorld); + } else { + renderer.addRenderable(m_render_wireframe, localToWorld); + } + } + + void render_component(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const + { + renderer.SetState(m_state_lattice, Renderer::eWireframeOnly); + renderer.SetState(m_state_lattice, Renderer::eFullMaterials); + renderer.addRenderable(m_render_lattice, localToWorld); + + renderer.SetState(m_state_ctrl, Renderer::eWireframeOnly); + renderer.SetState(m_state_ctrl, Renderer::eFullMaterials); + renderer.addRenderable(m_render_ctrl, localToWorld); + } + + void testSelect(Selector &selector, SelectionTest &test) + { + SelectionIntersection best; + IndexPointer::index_type *pIndex = m_tess.m_indices.data(); + for (std::size_t s = 0; s < m_tess.m_numStrips; s++) { + test.TestQuadStrip(vertexpointer_arbitrarymeshvertex(m_tess.m_vertices.data()), + IndexPointer(pIndex, m_tess.m_lenStrips), best); + pIndex += m_tess.m_lenStrips; + } + if (best.valid()) { + selector.addIntersection(best); + } + } + + void transform(const Matrix4 &matrix) + { + for (PatchControlIter i = m_ctrlTransformed.data(); + i != m_ctrlTransformed.data() + m_ctrlTransformed.size(); ++i) { + matrix4_transform_point(matrix, (*i).m_vertex); + } + + if (matrix4_handedness(matrix) == MATRIX4_LEFTHANDED) { + PatchControlArray_invert(m_ctrlTransformed, m_width, m_height); + } + UpdateCachedData(); + } + + void transformChanged() + { + m_transformChanged = true; + m_lightsChanged(); + SceneChangeNotify(); + } + + typedef MemberCaller TransformChangedCaller; + + void evaluateTransform() + { + if (m_transformChanged) { + m_transformChanged = false; + revertTransform(); + m_evaluateTransform(); + } + } + + void revertTransform() + { + m_ctrlTransformed = m_ctrl; + } + + void freezeTransform() + { + undoSave(); + evaluateTransform(); + ASSERT_MESSAGE(m_ctrlTransformed.size() == m_ctrl.size(), "Patch::freeze: size mismatch"); + std::copy(m_ctrlTransformed.begin(), m_ctrlTransformed.end(), m_ctrl.begin()); + } + + void controlPointsChanged() + { + transformChanged(); + evaluateTransform(); + UpdateCachedData(); + } + + bool isValid() const; + + void snapto(float snap) + { + undoSave(); + + for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) { + vector3_snap((*i).m_vertex, snap); + } + + controlPointsChanged(); + } + + + void RenderDebug(RenderStateFlags state) const; + + void RenderNormals(RenderStateFlags state) const; + + void pushElement(const XMLElement &element) + { + switch (m_xml_state.back().state()) { + case xml_state_t::eDefault: + ASSERT_MESSAGE(string_equal(element.name(), "patch"), "parse error"); + m_xml_state.push_back(xml_state_t::ePatch); + break; + case xml_state_t::ePatch: + if (string_equal(element.name(), "matrix")) { + setDims(atoi(element.attribute("width")), atoi(element.attribute("height"))); + m_xml_state.push_back(xml_state_t::eMatrix); + } else if (string_equal(element.name(), "shader")) { + m_xml_state.push_back(xml_state_t::eShader); + } + break; + default: + ERROR_MESSAGE("parse error"); + } + + } + + void popElement(const char *name) + { + switch (m_xml_state.back().state()) { + case xml_state_t::eDefault: + ERROR_MESSAGE("parse error"); + break; + case xml_state_t::ePatch: + break; + case xml_state_t::eMatrix: { + StringTokeniser content(m_xml_state.back().content()); + + for (PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i) { + (*i).m_vertex[0] = string_read_float(content.getToken()); + (*i).m_vertex[1] = string_read_float(content.getToken()); + (*i).m_vertex[2] = string_read_float(content.getToken()); + (*i).m_texcoord[0] = string_read_float(content.getToken()); + (*i).m_texcoord[1] = string_read_float(content.getToken()); + } + controlPointsChanged(); + } + break; + case xml_state_t::eShader: { + SetShader(m_xml_state.back().content()); + } + break; + default: + ERROR_MESSAGE("parse error"); + } + + ASSERT_MESSAGE(!m_xml_state.empty(), "popping empty stack"); + m_xml_state.pop_back(); + } + + std::size_t write(const char *buffer, std::size_t length) + { + switch (m_xml_state.back().state()) { + case xml_state_t::eDefault: + break; + case xml_state_t::ePatch: + break; + case xml_state_t::eMatrix: + case xml_state_t::eShader: + return m_xml_state.back().write(buffer, length); + break; + default: + ERROR_MESSAGE("parse error"); + } + return length; + } + + void exportXML(XMLImporter &importer) + { + StaticElement patchElement("patch"); + importer.pushElement(patchElement); + + { + const StaticElement element("shader"); + importer.pushElement(element); + importer.write(m_shader.c_str(), strlen(m_shader.c_str())); + importer.popElement(element.name()); + } + + { + char width[16], height[16]; + sprintf(width, "%u", Unsigned(m_width)); + sprintf(height, "%u", Unsigned(m_height)); + StaticElement element("matrix"); + element.insertAttribute("width", width); + element.insertAttribute("height", height); + + importer.pushElement(element); + { + for (PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i) { + importer << (*i).m_vertex[0] + << ' ' << (*i).m_vertex[1] + << ' ' << (*i).m_vertex[2] + << ' ' << (*i).m_texcoord[0] + << ' ' << (*i).m_texcoord[1]; + } + } + importer.popElement(element.name()); + } + + importer.popElement(patchElement.name()); + } + + void UpdateCachedData(); + + const char *GetShader() const + { + return m_shader.c_str(); + } + + void SetShader(const char *name) + { + ASSERT_NOTNULL(name); + + if (shader_equal(m_shader.c_str(), name)) { + return; + } + + undoSave(); + + if (m_instanceCounter.m_count != 0) { + m_state->decrementUsed(); + } + releaseShader(); + m_shader = name; + captureShader(); + if (m_instanceCounter.m_count != 0) { + m_state->incrementUsed(); + } + + check_shader(); + Patch_textureChanged(); + } + + int getShaderFlags() const + { + if (m_state != 0) { + return m_state->getFlags(); + } + return 0; + } + + typedef PatchControl *iterator; + typedef const PatchControl *const_iterator; + + iterator begin() + { + return m_ctrl.data(); + } + + const_iterator begin() const + { + return m_ctrl.data(); + } + + iterator end() + { + return m_ctrl.data() + m_ctrl.size(); + } + + const_iterator end() const + { + return m_ctrl.data() + m_ctrl.size(); + } + + PatchControlArray &getControlPoints() + { + return m_ctrl; + } + + PatchControlArray &getControlPointsTransformed() + { + return m_ctrlTransformed; + } + + void setDims(std::size_t w, std::size_t h); + + std::size_t getWidth() const + { + return m_width; + } + + std::size_t getHeight() const + { + return m_height; + } -Patch( const Patch& other ) : - XMLImporter( other ), - XMLExporter( other ), - TransformNode( other ), - Bounded( other ), - Cullable( other ), - Snappable(), - Undoable( other ), - Filterable( other ), - Nameable( other ), - m_state( 0 ), - m_undoable_observer( 0 ), - m_map( 0 ), - m_render_solid( m_tess ), - m_render_wireframe( m_tess ), - m_render_wireframe_fixed( m_tess ), - m_render_ctrl( GL_POINTS, m_ctrl_vertices ), - m_render_lattice( GL_LINES, m_lattice_indices, m_ctrl_vertices ), - m_transformChanged( false ), - m_evaluateTransform( other.m_evaluateTransform ), - m_boundsChanged( other.m_boundsChanged ){ - m_bOverlay = false; - - m_patchDef3 = other.m_patchDef3; - m_subdivisions_x = other.m_subdivisions_x; - m_subdivisions_y = other.m_subdivisions_y; - setDims( other.m_width, other.m_height ); - copy_ctrl( m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data() + ( m_width * m_height ) ); - SetShader( other.m_shader.c_str() ); - controlPointsChanged(); -} + PatchControl &ctrlAt(std::size_t row, std::size_t col) + { + return m_ctrl[row * m_width + col]; + } -~Patch(){ - BezierCurveTreeArray_deleteAll( m_tess.m_curveTreeU ); - BezierCurveTreeArray_deleteAll( m_tess.m_curveTreeV ); + const PatchControl &ctrlAt(std::size_t row, std::size_t col) const + { + return m_ctrl[row * m_width + col]; + } - releaseShader(); + void ConstructPrefab(const AABB &aabb, EPatchPrefab eType, int axis, std::size_t width = 3, std::size_t height = 3); - ASSERT_MESSAGE( m_observers.empty(), "Patch::~Patch: observers still attached" ); -} + void constructPlane(const AABB &aabb, int axis, std::size_t width, std::size_t height); -InstanceCounter m_instanceCounter; -void instanceAttach( const scene::Path& path ){ - if ( ++m_instanceCounter.m_count == 1 ) { - m_state->incrementUsed(); - m_map = path_find_mapfile( path.begin(), path.end() ); - m_undoable_observer = GlobalUndoSystem().observer( this ); - GlobalFilterSystem().registerFilterable( *this ); - } - else - { - ASSERT_MESSAGE( path_find_mapfile( path.begin(), path.end() ) == m_map, "node is instanced across more than one file" ); - } -} -void instanceDetach( const scene::Path& path ){ - if ( --m_instanceCounter.m_count == 0 ) { - m_map = 0; - m_undoable_observer = 0; - GlobalUndoSystem().release( this ); - GlobalFilterSystem().unregisterFilterable( *this ); - m_state->decrementUsed(); - } -} + void InvertMatrix(); -const char* name() const { - return "patch"; -} -void attach( const NameCallback& callback ){ -} -void detach( const NameCallback& callback ){ -} + void TransposeMatrix(); -void attach( Observer* observer ){ - observer->allocate( m_width * m_height ); + void Redisperse(EMatrixMajor mt); - m_observers.insert( observer ); -} -void detach( Observer* observer ){ - m_observers.erase( observer ); -} + void Smooth(EMatrixMajor mt); -void updateFiltered(){ - if ( m_node != 0 ) { - if ( patch_filtered( *this ) ) { - m_node->enable( scene::Node::eFiltered ); - } - else - { - m_node->disable( scene::Node::eFiltered ); - } - } -} + void InsertRemove(bool bInsert, bool bColumn, bool bFirst); -void onAllocate( std::size_t size ){ - for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) - { - ( *i )->allocate( size ); - } -} + Patch *MakeCap(Patch *patch, EPatchCap eType, EMatrixMajor mt, bool bFirst); -const Matrix4& localToParent() const { - return g_matrix4_identity; -} -const AABB& localAABB() const { - return m_aabb_local; -} -VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const { - return test.TestAABB( m_aabb_local, localToWorld ); -} -void render_solid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - renderer.SetState( m_state, Renderer::eFullMaterials ); - renderer.addRenderable( m_render_solid, localToWorld ); -} -void render_wireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - renderer.SetState( m_state, Renderer::eFullMaterials ); - if ( m_patchDef3 ) { - renderer.addRenderable( m_render_wireframe_fixed, localToWorld ); - } - else - { - renderer.addRenderable( m_render_wireframe, localToWorld ); - } -} + void ConstructSeam(EPatchCap eType, Vector3 *p, std::size_t width); -void render_component( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { - renderer.SetState( m_state_lattice, Renderer::eWireframeOnly ); - renderer.SetState( m_state_lattice, Renderer::eFullMaterials ); - renderer.addRenderable( m_render_lattice, localToWorld ); + void FlipTexture(int nAxis); - renderer.SetState( m_state_ctrl, Renderer::eWireframeOnly ); - renderer.SetState( m_state_ctrl, Renderer::eFullMaterials ); - renderer.addRenderable( m_render_ctrl, localToWorld ); -} -void testSelect( Selector& selector, SelectionTest& test ){ - SelectionIntersection best; - IndexPointer::index_type* pIndex = m_tess.m_indices.data(); - for ( std::size_t s = 0; s < m_tess.m_numStrips; s++ ) - { - test.TestQuadStrip( vertexpointer_arbitrarymeshvertex( m_tess.m_vertices.data() ), IndexPointer( pIndex, m_tess.m_lenStrips ), best ); - pIndex += m_tess.m_lenStrips; - } - if ( best.valid() ) { - selector.addIntersection( best ); - } -} -void transform( const Matrix4& matrix ){ - for ( PatchControlIter i = m_ctrlTransformed.data(); i != m_ctrlTransformed.data() + m_ctrlTransformed.size(); ++i ) - { - matrix4_transform_point( matrix, ( *i ).m_vertex ); - } - - if ( matrix4_handedness( matrix ) == MATRIX4_LEFTHANDED ) { - PatchControlArray_invert( m_ctrlTransformed, m_width, m_height ); - } - UpdateCachedData(); -} -void transformChanged(){ - m_transformChanged = true; - m_lightsChanged(); - SceneChangeNotify(); -} -typedef MemberCaller TransformChangedCaller; - -void evaluateTransform(){ - if ( m_transformChanged ) { - m_transformChanged = false; - revertTransform(); - m_evaluateTransform(); - } -} - -void revertTransform(){ - m_ctrlTransformed = m_ctrl; -} -void freezeTransform(){ - undoSave(); - evaluateTransform(); - ASSERT_MESSAGE( m_ctrlTransformed.size() == m_ctrl.size(), "Patch::freeze: size mismatch" ); - std::copy( m_ctrlTransformed.begin(), m_ctrlTransformed.end(), m_ctrl.begin() ); -} - -void controlPointsChanged(){ - transformChanged(); - evaluateTransform(); - UpdateCachedData(); -} -bool isValid() const; + void TranslateTexture(float s, float t); -void snapto( float snap ){ - undoSave(); + void ScaleTexture(float s, float t); - for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i ) - { - vector3_snap( ( *i ).m_vertex, snap ); - } - - controlPointsChanged(); -} - - - - -void RenderDebug( RenderStateFlags state ) const; -void RenderNormals( RenderStateFlags state ) const; - -void pushElement( const XMLElement& element ){ - switch ( m_xml_state.back().state() ) - { - case xml_state_t::eDefault: - ASSERT_MESSAGE( string_equal( element.name(), "patch" ), "parse error" ); - m_xml_state.push_back( xml_state_t::ePatch ); - break; - case xml_state_t::ePatch: - if ( string_equal( element.name(), "matrix" ) ) { - setDims( atoi( element.attribute( "width" ) ), atoi( element.attribute( "height" ) ) ); - m_xml_state.push_back( xml_state_t::eMatrix ); - } - else if ( string_equal( element.name(), "shader" ) ) { - m_xml_state.push_back( xml_state_t::eShader ); - } - break; - default: - ERROR_MESSAGE( "parse error" ); - } - -} -void popElement( const char* name ){ - switch ( m_xml_state.back().state() ) - { - case xml_state_t::eDefault: - ERROR_MESSAGE( "parse error" ); - break; - case xml_state_t::ePatch: - break; - case xml_state_t::eMatrix: - { - StringTokeniser content( m_xml_state.back().content() ); - - for ( PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i ) - { - ( *i ).m_vertex[0] = string_read_float( content.getToken() ); - ( *i ).m_vertex[1] = string_read_float( content.getToken() ); - ( *i ).m_vertex[2] = string_read_float( content.getToken() ); - ( *i ).m_texcoord[0] = string_read_float( content.getToken() ); - ( *i ).m_texcoord[1] = string_read_float( content.getToken() ); - } - controlPointsChanged(); - } - break; - case xml_state_t::eShader: - { - SetShader( m_xml_state.back().content() ); - } - break; - default: - ERROR_MESSAGE( "parse error" ); - } + void RotateTexture(float angle); - ASSERT_MESSAGE( !m_xml_state.empty(), "popping empty stack" ); - m_xml_state.pop_back(); -} -std::size_t write( const char* buffer, std::size_t length ){ - switch ( m_xml_state.back().state() ) - { - case xml_state_t::eDefault: - break; - case xml_state_t::ePatch: - break; - case xml_state_t::eMatrix: - case xml_state_t::eShader: - return m_xml_state.back().write( buffer, length ); - break; - default: - ERROR_MESSAGE( "parse error" ); - } - return length; -} + void SetTextureRepeat(float s, float t); // call with s=1 t=1 for FIT + void CapTexture(); -void exportXML( XMLImporter& importer ){ - StaticElement patchElement( "patch" ); - importer.pushElement( patchElement ); + void NaturalTexture(); - { - const StaticElement element( "shader" ); - importer.pushElement( element ); - importer.write( m_shader.c_str(), strlen( m_shader.c_str() ) ); - importer.popElement( element.name() ); - } + void ProjectTexture(int nAxis); - { - char width[16], height[16]; - sprintf( width, "%u", Unsigned( m_width ) ); - sprintf( height, "%u", Unsigned( m_height ) ); - StaticElement element( "matrix" ); - element.insertAttribute( "width", width ); - element.insertAttribute( "height", height ); - - importer.pushElement( element ); - { - for ( PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i ) - { - importer << ( *i ).m_vertex[0] - << ' ' << ( *i ).m_vertex[1] - << ' ' << ( *i ).m_vertex[2] - << ' ' << ( *i ).m_texcoord[0] - << ' ' << ( *i ).m_texcoord[1]; - } - } - importer.popElement( element.name() ); - } + void undoSave() + { + if (m_map != 0) { + m_map->changed(); + } + if (m_undoable_observer != 0) { + m_undoable_observer->save(this); + } + } - importer.popElement( patchElement.name() ); -} + UndoMemento *exportState() const + { + return new SavedState(m_width, m_height, m_ctrl, m_shader.c_str(), m_patchDef3, m_subdivisions_x, + m_subdivisions_y); + } -void UpdateCachedData(); + void importState(const UndoMemento *state) + { + undoSave(); -const char *GetShader() const { - return m_shader.c_str(); -} -void SetShader( const char* name ){ - ASSERT_NOTNULL( name ); + const SavedState &other = *(static_cast( state )); - if ( shader_equal( m_shader.c_str(), name ) ) { - return; - } + // begin duplicate of SavedState copy constructor, needs refactoring - undoSave(); + // copy construct + { + m_width = other.m_width; + m_height = other.m_height; + SetShader(other.m_shader.c_str()); + m_ctrl = other.m_ctrl; + onAllocate(m_ctrl.size()); + m_patchDef3 = other.m_patchDef3; + m_subdivisions_x = other.m_subdivisions_x; + m_subdivisions_y = other.m_subdivisions_y; + } - if ( m_instanceCounter.m_count != 0 ) { - m_state->decrementUsed(); - } - releaseShader(); - m_shader = name; - captureShader(); - if ( m_instanceCounter.m_count != 0 ) { - m_state->incrementUsed(); - } + // end duplicate code - check_shader(); - Patch_textureChanged(); -} -int getShaderFlags() const { - if ( m_state != 0 ) { - return m_state->getFlags(); - } - return 0; -} + Patch_textureChanged(); -typedef PatchControl* iterator; -typedef const PatchControl* const_iterator; + controlPointsChanged(); + } -iterator begin(){ - return m_ctrl.data(); -} -const_iterator begin() const { - return m_ctrl.data(); -} -iterator end(){ - return m_ctrl.data() + m_ctrl.size(); -} -const_iterator end() const { - return m_ctrl.data() + m_ctrl.size(); -} + static void constructStatic(EPatchType type) + { + Patch::m_type = type; + Patch::m_state_ctrl = GlobalShaderCache().capture("$POINT"); + Patch::m_state_lattice = GlobalShaderCache().capture("$LATTICE"); + } -PatchControlArray& getControlPoints(){ - return m_ctrl; -} -PatchControlArray& getControlPointsTransformed(){ - return m_ctrlTransformed; -} + static void destroyStatic() + { + GlobalShaderCache().release("$LATTICE"); + GlobalShaderCache().release("$POINT"); + } -void setDims( std::size_t w, std::size_t h ); -std::size_t getWidth() const { - return m_width; -} -std::size_t getHeight() const { - return m_height; -} -PatchControl& ctrlAt( std::size_t row, std::size_t col ){ - return m_ctrl[row * m_width + col]; -} -const PatchControl& ctrlAt( std::size_t row, std::size_t col ) const { - return m_ctrl[row * m_width + col]; -} - -void ConstructPrefab( const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width = 3, std::size_t height = 3 ); -void constructPlane( const AABB& aabb, int axis, std::size_t width, std::size_t height ); -void InvertMatrix(); -void TransposeMatrix(); -void Redisperse( EMatrixMajor mt ); -void Smooth( EMatrixMajor mt ); -void InsertRemove( bool bInsert, bool bColumn, bool bFirst ); -Patch* MakeCap( Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirst ); -void ConstructSeam( EPatchCap eType, Vector3* p, std::size_t width ); - -void FlipTexture( int nAxis ); -void TranslateTexture( float s, float t ); -void ScaleTexture( float s, float t ); -void RotateTexture( float angle ); -void SetTextureRepeat( float s, float t ); // call with s=1 t=1 for FIT -void CapTexture(); -void NaturalTexture(); -void ProjectTexture( int nAxis ); - -void undoSave(){ - if ( m_map != 0 ) { - m_map->changed(); - } - if ( m_undoable_observer != 0 ) { - m_undoable_observer->save( this ); - } -} - -UndoMemento* exportState() const { - return new SavedState( m_width, m_height, m_ctrl, m_shader.c_str(), m_patchDef3, m_subdivisions_x, m_subdivisions_y ); -} -void importState( const UndoMemento* state ){ - undoSave(); - - const SavedState& other = *( static_cast( state ) ); - - // begin duplicate of SavedState copy constructor, needs refactoring - - // copy construct - { - m_width = other.m_width; - m_height = other.m_height; - SetShader( other.m_shader.c_str() ); - m_ctrl = other.m_ctrl; - onAllocate( m_ctrl.size() ); - m_patchDef3 = other.m_patchDef3; - m_subdivisions_x = other.m_subdivisions_x; - m_subdivisions_y = other.m_subdivisions_y; - } - - // end duplicate code - - Patch_textureChanged(); - - controlPointsChanged(); -} - -static void constructStatic( EPatchType type ){ - Patch::m_type = type; - Patch::m_state_ctrl = GlobalShaderCache().capture( "$POINT" ); - Patch::m_state_lattice = GlobalShaderCache().capture( "$LATTICE" ); -} - -static void destroyStatic(){ - GlobalShaderCache().release( "$LATTICE" ); - GlobalShaderCache().release( "$POINT" ); -} private: -void captureShader(){ - m_state = GlobalShaderCache().capture( m_shader.c_str() ); -} + void captureShader() + { + m_state = GlobalShaderCache().capture(m_shader.c_str()); + } -void releaseShader(){ - GlobalShaderCache().release( m_shader.c_str() ); -} + void releaseShader() + { + GlobalShaderCache().release(m_shader.c_str()); + } -void check_shader(){ - if ( !shader_valid( GetShader() ) ) { - globalErrorStream() << "patch has invalid texture name: '" << GetShader() << "'\n"; - } -} + void check_shader() + { + if (!shader_valid(GetShader())) { + globalErrorStream() << "patch has invalid texture name: '" << GetShader() << "'\n"; + } + } + + void InsertPoints(EMatrixMajor mt, bool bFirst); -void InsertPoints( EMatrixMajor mt, bool bFirst ); -void RemovePoints( EMatrixMajor mt, bool bFirst ); + void RemovePoints(EMatrixMajor mt, bool bFirst); -void AccumulateBBox(); + void AccumulateBBox(); -void TesselateSubMatrixFixed( ArbitraryMeshVertex * vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl * subMatrix[3][3] ); + void TesselateSubMatrixFixed(ArbitraryMeshVertex *vertices, std::size_t strideX, std::size_t strideY, + unsigned int nFlagsX, unsigned int nFlagsY, PatchControl *subMatrix[3][3]); // uses binary trees representing bezier curves to recursively tesselate a bezier sub-patch -void TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY, - std::size_t offStartX, std::size_t offStartY, - std::size_t offEndX, std::size_t offEndY, - std::size_t nFlagsX, std::size_t nFlagsY, - Vector3& left, Vector3& mid, Vector3& right, - Vector2& texLeft, Vector2& texMid, Vector2& texRight, - bool bTranspose ); + void TesselateSubMatrix(const BezierCurveTree *BX, const BezierCurveTree *BY, + std::size_t offStartX, std::size_t offStartY, + std::size_t offEndX, std::size_t offEndY, + std::size_t nFlagsX, std::size_t nFlagsY, + Vector3 &left, Vector3 &mid, Vector3 &right, + Vector2 &texLeft, Vector2 &texMid, Vector2 &texRight, + bool bTranspose); // tesselates the entire surface -void BuildTesselationCurves( EMatrixMajor major ); -void accumulateVertexTangentSpace( std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], Vector2 tangentT[6], std::size_t index0, std::size_t index1 ); -void BuildVertexArray(); -}; + void BuildTesselationCurves(EMatrixMajor major); -inline bool Patch_importHeader( Patch& patch, Tokeniser& tokeniser ){ - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) ); - return true; -} + void accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], + Vector2 tangentT[6], std::size_t index0, std::size_t index1); -inline bool Patch_importShader( Patch& patch, Tokeniser& tokeniser ){ - // parse shader name - tokeniser.nextLine(); - const char* texture = tokeniser.getToken(); - if ( texture == 0 ) { - Tokeniser_unexpectedError( tokeniser, texture, "#texture-name" ); - return false; - } - if ( string_equal( texture, "NULL" ) ) { - patch.SetShader( texdef_name_default() ); - } - else - { - StringOutputStream shader( string_length( GlobalTexturePrefix_get() ) + string_length( texture ) ); - shader << GlobalTexturePrefix_get() << texture; - patch.SetShader( shader.c_str() ); - } - return true; -} + void BuildVertexArray(); +}; -inline bool PatchDoom3_importShader( Patch& patch, Tokeniser& tokeniser ){ - // parse shader name - tokeniser.nextLine(); - 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(); - } - patch.SetShader( shader ); - return true; +inline bool Patch_importHeader(Patch &patch, Tokeniser &tokeniser) +{ + tokeniser.nextLine(); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "{")); + return true; } -inline bool Patch_importParams( Patch& patch, Tokeniser& tokeniser ){ - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); +inline bool Patch_importShader(Patch &patch, Tokeniser &tokeniser) +{ + // parse shader name + tokeniser.nextLine(); + const char *texture = tokeniser.getToken(); + if (texture == 0) { + Tokeniser_unexpectedError(tokeniser, texture, "#texture-name"); + return false; + } + if (string_equal(texture, "NULL")) { + patch.SetShader(texdef_name_default()); + } else { + StringOutputStream shader(string_length(GlobalTexturePrefix_get()) + string_length(texture)); + shader << GlobalTexturePrefix_get() << texture; + patch.SetShader(shader.c_str()); + } + return true; +} + +inline bool PatchDoom3_importShader(Patch &patch, Tokeniser &tokeniser) +{ + // parse shader name + tokeniser.nextLine(); + 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(); + } + patch.SetShader(shader); + return true; +} + +inline bool Patch_importParams(Patch &patch, Tokeniser &tokeniser) +{ + tokeniser.nextLine(); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); - // parse matrix dimensions - { - std::size_t c, r; - RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, c ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, r ) ); + // parse matrix dimensions + { + std::size_t c, r; + RETURN_FALSE_IF_FAIL(Tokeniser_getSize(tokeniser, c)); + RETURN_FALSE_IF_FAIL(Tokeniser_getSize(tokeniser, r)); - patch.setDims( c, r ); - } + patch.setDims(c, r); + } - if ( patch.m_patchDef3 ) { - RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, patch.m_subdivisions_x ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, patch.m_subdivisions_y ) ); - } + if (patch.m_patchDef3) { + RETURN_FALSE_IF_FAIL(Tokeniser_getSize(tokeniser, patch.m_subdivisions_x)); + RETURN_FALSE_IF_FAIL(Tokeniser_getSize(tokeniser, patch.m_subdivisions_y)); + } - // ignore contents/flags/value - int tmp; - RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) ); + // ignore contents/flags/value + int tmp; + RETURN_FALSE_IF_FAIL(Tokeniser_getInteger(tokeniser, tmp)); + RETURN_FALSE_IF_FAIL(Tokeniser_getInteger(tokeniser, tmp)); + RETURN_FALSE_IF_FAIL(Tokeniser_getInteger(tokeniser, tmp)); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); - return true; + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); + return true; } -inline bool Patch_importMatrix( Patch& patch, Tokeniser& tokeniser ){ - // parse matrix - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); - { - for ( std::size_t c = 0; c < patch.getWidth(); c++ ) - { - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); - for ( std::size_t r = 0; r < patch.getHeight(); r++ ) - { - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); - - RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_vertex[0] ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_vertex[1] ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_vertex[2] ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_texcoord[0] ) ); - RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, patch.ctrlAt( r,c ).m_texcoord[1] ) ); - - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); - } - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); - } - } - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); - return true; -} - -inline bool Patch_importFooter( Patch& patch, Tokeniser& tokeniser ){ - patch.controlPointsChanged(); +inline bool Patch_importMatrix(Patch &patch, Tokeniser &tokeniser) +{ + // parse matrix + tokeniser.nextLine(); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); + { + for (std::size_t c = 0; c < patch.getWidth(); c++) { + tokeniser.nextLine(); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); + for (std::size_t r = 0; r < patch.getHeight(); r++) { + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); + + RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, patch.ctrlAt(r, c).m_vertex[0])); + RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, patch.ctrlAt(r, c).m_vertex[1])); + RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, patch.ctrlAt(r, c).m_vertex[2])); + RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, patch.ctrlAt(r, c).m_texcoord[0])); + RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, patch.ctrlAt(r, c).m_texcoord[1])); + + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); + } + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); + } + } + tokeniser.nextLine(); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); + return true; +} + +inline bool Patch_importFooter(Patch &patch, Tokeniser &tokeniser) +{ + patch.controlPointsChanged(); - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) ); + tokeniser.nextLine(); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "}")); - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) ); - return true; + tokeniser.nextLine(); + RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "}")); + return true; } -class PatchTokenImporter : public MapImporter -{ -Patch& m_patch; +class PatchTokenImporter : public MapImporter { + Patch &m_patch; public: -PatchTokenImporter( Patch& patch ) : m_patch( patch ){ -} -bool importTokens( Tokeniser& tokeniser ){ - RETURN_FALSE_IF_FAIL( Patch_importHeader( m_patch, tokeniser ) ); - RETURN_FALSE_IF_FAIL( Patch_importShader( m_patch, tokeniser ) ); - RETURN_FALSE_IF_FAIL( Patch_importParams( m_patch, tokeniser ) ); - RETURN_FALSE_IF_FAIL( Patch_importMatrix( m_patch, tokeniser ) ); - RETURN_FALSE_IF_FAIL( Patch_importFooter( m_patch, tokeniser ) ); - - return true; -} + PatchTokenImporter(Patch &patch) : m_patch(patch) + { + } + + bool importTokens(Tokeniser &tokeniser) + { + RETURN_FALSE_IF_FAIL(Patch_importHeader(m_patch, tokeniser)); + RETURN_FALSE_IF_FAIL(Patch_importShader(m_patch, tokeniser)); + RETURN_FALSE_IF_FAIL(Patch_importParams(m_patch, tokeniser)); + RETURN_FALSE_IF_FAIL(Patch_importMatrix(m_patch, tokeniser)); + RETURN_FALSE_IF_FAIL(Patch_importFooter(m_patch, tokeniser)); + + return true; + } }; -class PatchDoom3TokenImporter : public MapImporter -{ -Patch& m_patch; +class PatchDoom3TokenImporter : public MapImporter { + Patch &m_patch; public: -PatchDoom3TokenImporter( Patch& patch ) : m_patch( patch ){ -} -bool importTokens( Tokeniser& tokeniser ){ - RETURN_FALSE_IF_FAIL( Patch_importHeader( m_patch, tokeniser ) ); - RETURN_FALSE_IF_FAIL( PatchDoom3_importShader( m_patch, tokeniser ) ); - RETURN_FALSE_IF_FAIL( Patch_importParams( m_patch, tokeniser ) ); - RETURN_FALSE_IF_FAIL( Patch_importMatrix( m_patch, tokeniser ) ); - RETURN_FALSE_IF_FAIL( Patch_importFooter( m_patch, tokeniser ) ); - - return true; -} + PatchDoom3TokenImporter(Patch &patch) : m_patch(patch) + { + } + + bool importTokens(Tokeniser &tokeniser) + { + RETURN_FALSE_IF_FAIL(Patch_importHeader(m_patch, tokeniser)); + RETURN_FALSE_IF_FAIL(PatchDoom3_importShader(m_patch, tokeniser)); + RETURN_FALSE_IF_FAIL(Patch_importParams(m_patch, tokeniser)); + RETURN_FALSE_IF_FAIL(Patch_importMatrix(m_patch, tokeniser)); + RETURN_FALSE_IF_FAIL(Patch_importFooter(m_patch, tokeniser)); + + return true; + } }; -inline void Patch_exportHeader( const Patch& patch, TokenWriter& writer ){ - writer.writeToken( "{" ); - writer.nextLine(); - writer.writeToken( patch.m_patchDef3 ? "patchDef3" : "patchDef2" ); - writer.nextLine(); - writer.writeToken( "{" ); - writer.nextLine(); -} - -inline void Patch_exportShader( const Patch& patch, TokenWriter& writer ){ - // write shader name - if ( *( shader_get_textureName( patch.GetShader() ) ) == '\0' ) { - writer.writeToken( "NULL" ); - } - else - { - writer.writeToken( shader_get_textureName( patch.GetShader() ) ); - } - writer.nextLine(); -} - -inline void PatchDoom3_exportShader( const Patch& patch, TokenWriter& writer ){ - // write shader name - if ( *( shader_get_textureName( patch.GetShader() ) ) == '\0' ) { - writer.writeString( "_emptyname" ); - } - else - { - writer.writeString( patch.GetShader() ); - } - writer.nextLine(); -} - -inline void Patch_exportParams( const Patch& patch, TokenWriter& writer ){ - // write matrix dimensions - writer.writeToken( "(" ); - writer.writeUnsigned( patch.getWidth() ); - writer.writeUnsigned( patch.getHeight() ); - if ( patch.m_patchDef3 ) { - writer.writeUnsigned( patch.m_subdivisions_x ); - writer.writeUnsigned( patch.m_subdivisions_y ); - } - writer.writeInteger( 0 ); - writer.writeInteger( 0 ); - writer.writeInteger( 0 ); - writer.writeToken( ")" ); - writer.nextLine(); +inline void Patch_exportHeader(const Patch &patch, TokenWriter &writer) +{ + writer.writeToken("{"); + writer.nextLine(); + writer.writeToken(patch.m_patchDef3 ? "patchDef3" : "patchDef2"); + writer.nextLine(); + writer.writeToken("{"); + writer.nextLine(); } -inline void Patch_exportMatrix( const Patch& patch, TokenWriter& writer ){ - // write matrix - writer.writeToken( "(" ); - writer.nextLine(); - for ( std::size_t c = 0; c < patch.getWidth(); c++ ) - { - writer.writeToken( "(" ); - for ( std::size_t r = 0; r < patch.getHeight(); r++ ) - { - writer.writeToken( "(" ); - - writer.writeFloat( patch.ctrlAt( r,c ).m_vertex[0] ); - writer.writeFloat( patch.ctrlAt( r,c ).m_vertex[1] ); - writer.writeFloat( patch.ctrlAt( r,c ).m_vertex[2] ); - writer.writeFloat( patch.ctrlAt( r,c ).m_texcoord[0] ); - writer.writeFloat( patch.ctrlAt( r,c ).m_texcoord[1] ); - - writer.writeToken( ")" ); - } - writer.writeToken( ")" ); - writer.nextLine(); - } - writer.writeToken( ")" ); - writer.nextLine(); +inline void Patch_exportShader(const Patch &patch, TokenWriter &writer) +{ + // write shader name + if (*(shader_get_textureName(patch.GetShader())) == '\0') { + writer.writeToken("NULL"); + } else { + writer.writeToken(shader_get_textureName(patch.GetShader())); + } + writer.nextLine(); } -inline void Patch_exportFooter( const Patch& patch, TokenWriter& writer ){ - writer.writeToken( "}" ); - writer.nextLine(); - writer.writeToken( "}" ); - writer.nextLine(); +inline void PatchDoom3_exportShader(const Patch &patch, TokenWriter &writer) +{ + // write shader name + if (*(shader_get_textureName(patch.GetShader())) == '\0') { + writer.writeString("_emptyname"); + } else { + writer.writeString(patch.GetShader()); + } + writer.nextLine(); } -class PatchTokenExporter : public MapExporter +inline void Patch_exportParams(const Patch &patch, TokenWriter &writer) { -const Patch& m_patch; -public: -PatchTokenExporter( Patch& patch ) : m_patch( patch ){ -} -void exportTokens( TokenWriter& writer ) const { - Patch_exportHeader( m_patch, writer ); - Patch_exportShader( m_patch, writer ); - Patch_exportParams( m_patch, writer ); - Patch_exportMatrix( m_patch, writer ); - Patch_exportFooter( m_patch, writer ); + // write matrix dimensions + writer.writeToken("("); + writer.writeUnsigned(patch.getWidth()); + writer.writeUnsigned(patch.getHeight()); + if (patch.m_patchDef3) { + writer.writeUnsigned(patch.m_subdivisions_x); + writer.writeUnsigned(patch.m_subdivisions_y); + } + writer.writeInteger(0); + writer.writeInteger(0); + writer.writeInteger(0); + writer.writeToken(")"); + writer.nextLine(); +} + +inline void Patch_exportMatrix(const Patch &patch, TokenWriter &writer) +{ + // write matrix + writer.writeToken("("); + writer.nextLine(); + for (std::size_t c = 0; c < patch.getWidth(); c++) { + writer.writeToken("("); + for (std::size_t r = 0; r < patch.getHeight(); r++) { + writer.writeToken("("); + + writer.writeFloat(patch.ctrlAt(r, c).m_vertex[0]); + writer.writeFloat(patch.ctrlAt(r, c).m_vertex[1]); + writer.writeFloat(patch.ctrlAt(r, c).m_vertex[2]); + writer.writeFloat(patch.ctrlAt(r, c).m_texcoord[0]); + writer.writeFloat(patch.ctrlAt(r, c).m_texcoord[1]); + + writer.writeToken(")"); + } + writer.writeToken(")"); + writer.nextLine(); + } + writer.writeToken(")"); + writer.nextLine(); +} + +inline void Patch_exportFooter(const Patch &patch, TokenWriter &writer) +{ + writer.writeToken("}"); + writer.nextLine(); + writer.writeToken("}"); + writer.nextLine(); } -}; -class PatchDoom3TokenExporter : public MapExporter -{ -const Patch& m_patch; +class PatchTokenExporter : public MapExporter { + const Patch &m_patch; public: -PatchDoom3TokenExporter( Patch& patch ) : m_patch( patch ){ -} -void exportTokens( TokenWriter& writer ) const { - Patch_exportHeader( m_patch, writer ); - PatchDoom3_exportShader( m_patch, writer ); - Patch_exportParams( m_patch, writer ); - Patch_exportMatrix( m_patch, writer ); - Patch_exportFooter( m_patch, writer ); -} + PatchTokenExporter(Patch &patch) : m_patch(patch) + { + } + + void exportTokens(TokenWriter &writer) const + { + Patch_exportHeader(m_patch, writer); + Patch_exportShader(m_patch, writer); + Patch_exportParams(m_patch, writer); + Patch_exportMatrix(m_patch, writer); + Patch_exportFooter(m_patch, writer); + } }; -class PatchControlInstance -{ +class PatchDoom3TokenExporter : public MapExporter { + const Patch &m_patch; public: -PatchControl* m_ctrl; -ObservedSelectable m_selectable; - -PatchControlInstance( PatchControl* ctrl, const SelectionChangeCallback& observer ) - : m_ctrl( ctrl ), m_selectable( observer ){ -} - -void testSelect( Selector& selector, SelectionTest& test ){ - SelectionIntersection best; - test.TestPoint( m_ctrl->m_vertex, best ); - if ( best.valid() ) { - Selector_add( selector, m_selectable, best ); - } -} -void snapto( float snap ){ - vector3_snap( m_ctrl->m_vertex, snap ); -} + PatchDoom3TokenExporter(Patch &patch) : m_patch(patch) + { + } + + void exportTokens(TokenWriter &writer) const + { + Patch_exportHeader(m_patch, writer); + PatchDoom3_exportShader(m_patch, writer); + Patch_exportParams(m_patch, writer); + Patch_exportMatrix(m_patch, writer); + Patch_exportFooter(m_patch, writer); + } }; - -class PatchInstance : - public Patch::Observer, - public scene::Instance, - public Selectable, - public Renderable, - public SelectionTestable, - public ComponentSelectionTestable, - public ComponentEditable, - public ComponentSnappable, - public PlaneSelectable, - public LightCullable -{ -class TypeCasts -{ -InstanceTypeCastTable m_casts; +class PatchControlInstance { public: -TypeCasts(){ - InstanceStaticCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceStaticCast::install( m_casts ); - InstanceIdentityCast::install( m_casts ); - InstanceContainedCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} + PatchControl *m_ctrl; + ObservedSelectable m_selectable; + + PatchControlInstance(PatchControl *ctrl, const SelectionChangeCallback &observer) + : m_ctrl(ctrl), m_selectable(observer) + { + } + + void testSelect(Selector &selector, SelectionTest &test) + { + SelectionIntersection best; + test.TestPoint(m_ctrl->m_vertex, best); + if (best.valid()) { + Selector_add(selector, m_selectable, best); + } + } + + void snapto(float snap) + { + vector3_snap(m_ctrl->m_vertex, snap); + } }; -Patch& m_patch; -typedef std::vector PatchControlInstances; -PatchControlInstances m_ctrl_instances; - -ObservedSelectable m_selectable; - -DragPlanes m_dragPlanes; - -mutable RenderablePointVector m_render_selected; -mutable AABB m_aabb_component; - -static Shader* m_state_selpoint; - -const LightList* m_lightList; - -TransformModifier m_transform; +class PatchInstance : + public Patch::Observer, + public scene::Instance, + public Selectable, + public Renderable, + public SelectionTestable, + public ComponentSelectionTestable, + public ComponentEditable, + public ComponentSnappable, + public PlaneSelectable, + public LightCullable { + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + InstanceStaticCast::install(m_casts); + InstanceContainedCast::install(m_casts); + InstanceContainedCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceStaticCast::install(m_casts); + InstanceIdentityCast::install(m_casts); + InstanceContainedCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + + Patch &m_patch; + typedef std::vector PatchControlInstances; + PatchControlInstances m_ctrl_instances; + + ObservedSelectable m_selectable; + + DragPlanes m_dragPlanes; + + mutable RenderablePointVector m_render_selected; + mutable AABB m_aabb_component; + + static Shader *m_state_selpoint; + + const LightList *m_lightList; + + TransformModifier m_transform; public: -typedef LazyStatic StaticTypeCasts; - -void lightsChanged(){ - m_lightList->lightsChanged(); -} -typedef MemberCaller LightsChangedCaller; - -STRING_CONSTANT( Name, "PatchInstance" ); - -PatchInstance( const scene::Path& path, scene::Instance* parent, Patch& patch ) : - Instance( path, parent, this, StaticTypeCasts::instance().get() ), - m_patch( patch ), - m_selectable( SelectedChangedCaller( *this ) ), - m_dragPlanes( SelectedChangedComponentCaller( *this ) ), - m_render_selected( GL_POINTS ), - m_transform( Patch::TransformChangedCaller( m_patch ), ApplyTransformCaller( *this ) ){ - m_patch.instanceAttach( Instance::path() ); - m_patch.attach( this ); - - m_lightList = &GlobalShaderCache().attach( *this ); - m_patch.m_lightsChanged = LightsChangedCaller( *this ); - - Instance::setTransformChangedCallback( LightsChangedCaller( *this ) ); -} -~PatchInstance(){ - Instance::setTransformChangedCallback( Callback() ); - - m_patch.m_lightsChanged = Callback(); - GlobalShaderCache().detach( *this ); - - m_patch.detach( this ); - m_patch.instanceDetach( Instance::path() ); -} - -void selectedChanged( const Selectable& selectable ){ - GlobalSelectionSystem().getObserver ( SelectionSystem::ePrimitive )( selectable ); - GlobalSelectionSystem().onSelectedChanged( *this, selectable ); - - Instance::selectedChanged(); -} -typedef MemberCaller SelectedChangedCaller; - -void selectedChangedComponent( const Selectable& selectable ){ - GlobalSelectionSystem().getObserver ( SelectionSystem::eComponent )( selectable ); - GlobalSelectionSystem().onComponentSelection( *this, selectable ); -} -typedef MemberCaller SelectedChangedComponentCaller; - -Patch& getPatch(){ - return m_patch; -} -Bounded& get( NullType){ - return m_patch; -} -Cullable& get( NullType){ - return m_patch; -} -Transformable& get( NullType){ - return m_transform; -} - -static void constructStatic(){ - m_state_selpoint = GlobalShaderCache().capture( "$SELPOINT" ); -} - -static void destroyStatic(){ - GlobalShaderCache().release( "$SELPOINT" ); -} - - -void allocate( std::size_t size ){ - m_ctrl_instances.clear(); - m_ctrl_instances.reserve( size ); - for ( Patch::iterator i = m_patch.begin(); i != m_patch.end(); ++i ) - { - m_ctrl_instances.push_back( PatchControlInstance( &( *i ), SelectedChangedComponentCaller( *this ) ) ); - } -} - -void setSelected( bool select ){ - m_selectable.setSelected( select ); -} -bool isSelected() const { - return m_selectable.isSelected(); -} - - -void update_selected() const { - m_render_selected.clear(); - Patch::iterator ctrl = m_patch.getControlPointsTransformed().begin(); - for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl ) - { - if ( ( *i ).m_selectable.isSelected() ) { - const Colour4b colour_selected( 0, 0, 255, 255 ); - m_render_selected.push_back( PointVertex( reinterpret_cast( ( *ctrl ).m_vertex ), colour_selected ) ); - } - } -} + typedef LazyStatic StaticTypeCasts; + + void lightsChanged() + { + m_lightList->lightsChanged(); + } + + typedef MemberCaller LightsChangedCaller; + + STRING_CONSTANT(Name, "PatchInstance"); + + PatchInstance(const scene::Path &path, scene::Instance *parent, Patch &patch) : + Instance(path, parent, this, StaticTypeCasts::instance().get()), + m_patch(patch), + m_selectable(SelectedChangedCaller(*this)), + m_dragPlanes(SelectedChangedComponentCaller(*this)), + m_render_selected(GL_POINTS), + m_transform(Patch::TransformChangedCaller(m_patch), ApplyTransformCaller(*this)) + { + m_patch.instanceAttach(Instance::path()); + m_patch.attach(this); + + m_lightList = &GlobalShaderCache().attach(*this); + m_patch.m_lightsChanged = LightsChangedCaller(*this); + + Instance::setTransformChangedCallback(LightsChangedCaller(*this)); + } + + ~PatchInstance() + { + Instance::setTransformChangedCallback(Callback()); + + m_patch.m_lightsChanged = Callback(); + GlobalShaderCache().detach(*this); + + m_patch.detach(this); + m_patch.instanceDetach(Instance::path()); + } + + void selectedChanged(const Selectable &selectable) + { + GlobalSelectionSystem().getObserver(SelectionSystem::ePrimitive)(selectable); + GlobalSelectionSystem().onSelectedChanged(*this, selectable); + + Instance::selectedChanged(); + } + + typedef MemberCaller SelectedChangedCaller; + + void selectedChangedComponent(const Selectable &selectable) + { + GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable); + GlobalSelectionSystem().onComponentSelection(*this, selectable); + } + + typedef MemberCaller SelectedChangedComponentCaller; + + Patch &getPatch() + { + return m_patch; + } + + Bounded &get(NullType) + { + return m_patch; + } + + Cullable &get(NullType) + { + return m_patch; + } + + Transformable &get(NullType) + { + return m_transform; + } + + static void constructStatic() + { + m_state_selpoint = GlobalShaderCache().capture("$SELPOINT"); + } + + static void destroyStatic() + { + GlobalShaderCache().release("$SELPOINT"); + } + + + void allocate(std::size_t size) + { + m_ctrl_instances.clear(); + m_ctrl_instances.reserve(size); + for (Patch::iterator i = m_patch.begin(); i != m_patch.end(); ++i) { + m_ctrl_instances.push_back(PatchControlInstance(&(*i), SelectedChangedComponentCaller(*this))); + } + } + + void setSelected(bool select) + { + m_selectable.setSelected(select); + } + + bool isSelected() const + { + return m_selectable.isSelected(); + } + + + void update_selected() const + { + m_render_selected.clear(); + Patch::iterator ctrl = m_patch.getControlPointsTransformed().begin(); + for (PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); + i != m_ctrl_instances.end(); ++i, ++ctrl) { + if ((*i).m_selectable.isSelected()) { + const Colour4b colour_selected(0, 0, 255, 255); + m_render_selected.push_back( + PointVertex(reinterpret_cast((*ctrl).m_vertex ), colour_selected)); + } + } + } #if 0 -void render( Renderer& renderer, const VolumeTest& volume ) const { + void render( Renderer& renderer, const VolumeTest& volume ) const { if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent && m_selectable.isSelected() ) { renderer.Highlight( Renderer::eFace, false ); @@ -1454,408 +1592,475 @@ void render( Renderer& renderer, const VolumeTest& volume ) const { } #endif -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - m_patch.evaluateTransform(); - renderer.setLights( *m_lightList ); - m_patch.render_solid( renderer, volume, localToWorld() ); - - renderComponentsSelected( renderer, volume ); -} - -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - m_patch.evaluateTransform(); - m_patch.render_wireframe( renderer, volume, localToWorld() ); - - renderComponentsSelected( renderer, volume ); -} - -void renderComponentsSelected( Renderer& renderer, const VolumeTest& volume ) const { - m_patch.evaluateTransform(); - update_selected(); - if ( !m_render_selected.empty() ) { - renderer.Highlight( Renderer::ePrimitive, false ); - renderer.SetState( m_state_selpoint, Renderer::eWireframeOnly ); - renderer.SetState( m_state_selpoint, Renderer::eFullMaterials ); - renderer.addRenderable( m_render_selected, localToWorld() ); - } -} -void renderComponents( Renderer& renderer, const VolumeTest& volume ) const { - m_patch.evaluateTransform(); - if ( GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex ) { - m_patch.render_component( renderer, volume, localToWorld() ); - } -} - -void testSelect( Selector& selector, SelectionTest& test ){ - test.BeginMesh( localToWorld(), true ); - m_patch.testSelect( selector, test ); -} - -void selectCtrl( bool select ){ - for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) - { - ( *i ).m_selectable.setSelected( select ); - } -} -bool isSelectedComponents() const { - for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) - { - if ( ( *i ).m_selectable.isSelected() ) { - return true; - } - } - return false; -} -void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ){ - if ( mode == SelectionSystem::eVertex ) { - selectCtrl( select ); - } - else if ( mode == SelectionSystem::eFace ) { - m_dragPlanes.setSelected( select ); - } -} -const AABB& getSelectedComponentsBounds() const { - m_aabb_component = AABB(); - - for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) - { - if ( ( *i ).m_selectable.isSelected() ) { - aabb_extend_by_point_safe( m_aabb_component, ( *i ).m_ctrl->m_vertex ); - } - } - - return m_aabb_component; -} - -void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ){ - test.BeginMesh( localToWorld() ); - - switch ( mode ) - { - case SelectionSystem::eVertex: - { - for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) - { - ( *i ).testSelect( selector, test ); - } - } - break; - default: - break; - } -} - -bool selectedVertices(){ - for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) - { - if ( ( *i ).m_selectable.isSelected() ) { - return true; - } - } - return false; -} - -void transformComponents( const Matrix4& matrix ){ - if ( selectedVertices() ) { - PatchControlIter ctrl = m_patch.getControlPointsTransformed().begin(); - for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl ) - { - if ( ( *i ).m_selectable.isSelected() ) { - matrix4_transform_point( matrix, ( *ctrl ).m_vertex ); - } - } - m_patch.UpdateCachedData(); - } - - if ( m_dragPlanes.isSelected() ) { // this should only be true when the transform is a pure translation. - m_patch.transform( m_dragPlanes.evaluateTransform( vector4_to_vector3( matrix.t() ) ) ); - } -} - - -void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){ - test.BeginMesh( localToWorld() ); - - m_dragPlanes.selectPlanes( m_patch.localAABB(), selector, test, selectedPlaneCallback ); -} -void selectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ){ - m_dragPlanes.selectReversedPlanes( m_patch.localAABB(), selector, selectedPlanes ); -} - - -void snapComponents( float snap ){ - if ( selectedVertices() ) { - m_patch.undoSave(); - for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) - { - if ( ( *i ).m_selectable.isSelected() ) { - ( *i ).snapto( snap ); - } - } - m_patch.controlPointsChanged(); - } -} - -void evaluateTransform(){ - Matrix4 matrix( m_transform.calculateTransform() ); - - if ( m_transform.getType() == TRANSFORM_PRIMITIVE ) { - m_patch.transform( matrix ); - } - else - { - transformComponents( matrix ); - } -} -void applyTransform(){ - m_patch.revertTransform(); - evaluateTransform(); - m_patch.freezeTransform(); -} -typedef MemberCaller ApplyTransformCaller; - - -bool testLight( const RendererLight& light ) const { - return light.testAABB( worldAABB() ); -} + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + m_patch.evaluateTransform(); + renderer.setLights(*m_lightList); + m_patch.render_solid(renderer, volume, localToWorld()); + + renderComponentsSelected(renderer, volume); + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + m_patch.evaluateTransform(); + m_patch.render_wireframe(renderer, volume, localToWorld()); + + renderComponentsSelected(renderer, volume); + } + + void renderComponentsSelected(Renderer &renderer, const VolumeTest &volume) const + { + m_patch.evaluateTransform(); + update_selected(); + if (!m_render_selected.empty()) { + renderer.Highlight(Renderer::ePrimitive, false); + renderer.SetState(m_state_selpoint, Renderer::eWireframeOnly); + renderer.SetState(m_state_selpoint, Renderer::eFullMaterials); + renderer.addRenderable(m_render_selected, localToWorld()); + } + } + + void renderComponents(Renderer &renderer, const VolumeTest &volume) const + { + m_patch.evaluateTransform(); + if (GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex) { + m_patch.render_component(renderer, volume, localToWorld()); + } + } + + void testSelect(Selector &selector, SelectionTest &test) + { + test.BeginMesh(localToWorld(), true); + m_patch.testSelect(selector, test); + } + + void selectCtrl(bool select) + { + for (PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) { + (*i).m_selectable.setSelected(select); + } + } + + bool isSelectedComponents() const + { + for (PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) { + if ((*i).m_selectable.isSelected()) { + return true; + } + } + return false; + } + + void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) + { + if (mode == SelectionSystem::eVertex) { + selectCtrl(select); + } else if (mode == SelectionSystem::eFace) { + m_dragPlanes.setSelected(select); + } + } + + const AABB &getSelectedComponentsBounds() const + { + m_aabb_component = AABB(); + + for (PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) { + if ((*i).m_selectable.isSelected()) { + aabb_extend_by_point_safe(m_aabb_component, (*i).m_ctrl->m_vertex); + } + } + + return m_aabb_component; + } + + void testSelectComponents(Selector &selector, SelectionTest &test, SelectionSystem::EComponentMode mode) + { + test.BeginMesh(localToWorld()); + + switch (mode) { + case SelectionSystem::eVertex: { + for (PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) { + (*i).testSelect(selector, test); + } + } + break; + default: + break; + } + } + + bool selectedVertices() + { + for (PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) { + if ((*i).m_selectable.isSelected()) { + return true; + } + } + return false; + } + + void transformComponents(const Matrix4 &matrix) + { + if (selectedVertices()) { + PatchControlIter ctrl = m_patch.getControlPointsTransformed().begin(); + for (PatchControlInstances::iterator i = m_ctrl_instances.begin(); + i != m_ctrl_instances.end(); ++i, ++ctrl) { + if ((*i).m_selectable.isSelected()) { + matrix4_transform_point(matrix, (*ctrl).m_vertex); + } + } + m_patch.UpdateCachedData(); + } + + if (m_dragPlanes.isSelected()) { // this should only be true when the transform is a pure translation. + m_patch.transform(m_dragPlanes.evaluateTransform(vector4_to_vector3(matrix.t()))); + } + } + + + void selectPlanes(Selector &selector, SelectionTest &test, const PlaneCallback &selectedPlaneCallback) + { + test.BeginMesh(localToWorld()); + + m_dragPlanes.selectPlanes(m_patch.localAABB(), selector, test, selectedPlaneCallback); + } + + void selectReversedPlanes(Selector &selector, const SelectedPlanes &selectedPlanes) + { + m_dragPlanes.selectReversedPlanes(m_patch.localAABB(), selector, selectedPlanes); + } + + + void snapComponents(float snap) + { + if (selectedVertices()) { + m_patch.undoSave(); + for (PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) { + if ((*i).m_selectable.isSelected()) { + (*i).snapto(snap); + } + } + m_patch.controlPointsChanged(); + } + } + + void evaluateTransform() + { + Matrix4 matrix(m_transform.calculateTransform()); + + if (m_transform.getType() == TRANSFORM_PRIMITIVE) { + m_patch.transform(matrix); + } else { + transformComponents(matrix); + } + } + + void applyTransform() + { + m_patch.revertTransform(); + evaluateTransform(); + m_patch.freezeTransform(); + } + + typedef MemberCaller ApplyTransformCaller; + + + bool testLight(const RendererLight &light) const + { + return light.testAABB(worldAABB()); + } }; template class PatchNode : - public scene::Node::Symbiot, - public scene::Instantiable, - public scene::Cloneable -{ -typedef PatchNode Self; + public scene::Node::Symbiot, + public scene::Instantiable, + public scene::Cloneable { + typedef PatchNode Self; + + class TypeCasts { + InstanceTypeCastTable m_casts; + public: + TypeCasts() + { + NodeStaticCast::install(m_casts); + NodeStaticCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + NodeContainedCast::install(m_casts); + } + + InstanceTypeCastTable &get() + { + return m_casts; + } + }; + + + scene::Node m_node; + InstanceSet m_instances; + Patch m_patch; + TokenImporter m_importMap; + TokenExporter m_exportMap; -class TypeCasts -{ -InstanceTypeCastTable m_casts; public: -TypeCasts(){ - NodeStaticCast::install( m_casts ); - NodeStaticCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); - NodeContainedCast::install( m_casts ); -} -InstanceTypeCastTable& get(){ - return m_casts; -} -}; - -scene::Node m_node; -InstanceSet m_instances; -Patch m_patch; -TokenImporter m_importMap; -TokenExporter m_exportMap; - -public: - -typedef LazyStatic StaticTypeCasts; - -Snappable& get( NullType){ - return m_patch; -} -TransformNode& get( NullType){ - return m_patch; -} -Patch& get( NullType){ - return m_patch; -} -XMLImporter& get( NullType){ - return m_patch; -} -XMLExporter& get( NullType){ - return m_patch; -} -MapImporter& get( NullType){ - return m_importMap; -} -MapExporter& get( NullType){ - return m_exportMap; -} -Nameable& get( NullType){ - return m_patch; -} - -PatchNode( bool patchDef3 = false ) : - m_node( this, this, StaticTypeCasts::instance().get() ), - m_patch( m_node, InstanceSetEvaluateTransform::Caller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ) ), - m_importMap( m_patch ), - m_exportMap( m_patch ){ - m_patch.m_patchDef3 = patchDef3; -} -PatchNode( const PatchNode& other ) : - scene::Node::Symbiot( other ), - scene::Instantiable( other ), - scene::Cloneable( other ), - m_node( this, this, StaticTypeCasts::instance().get() ), - m_patch( other.m_patch, m_node, InstanceSetEvaluateTransform::Caller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ) ), - m_importMap( m_patch ), - m_exportMap( m_patch ){ -} -void release(){ - delete this; -} -scene::Node& node(){ - return m_node; -} -Patch& get(){ - return m_patch; -} -const Patch& get() const { - return m_patch; -} - -scene::Node& clone() const { - return ( new PatchNode( *this ) )->node(); -} - -scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ - return new PatchInstance( path, parent, m_patch ); -} -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 ); -} + typedef LazyStatic StaticTypeCasts; + + Snappable &get(NullType) + { + return m_patch; + } + + TransformNode &get(NullType) + { + return m_patch; + } + + Patch &get(NullType) + { + return m_patch; + } + + XMLImporter &get(NullType) + { + return m_patch; + } + + XMLExporter &get(NullType) + { + return m_patch; + } + + MapImporter &get(NullType) + { + return m_importMap; + } + + MapExporter &get(NullType) + { + return m_exportMap; + } + + Nameable &get(NullType) + { + return m_patch; + } + + PatchNode(bool patchDef3 = false) : + m_node(this, this, StaticTypeCasts::instance().get()), + m_patch(m_node, InstanceSetEvaluateTransform::Caller(m_instances), + InstanceSet::BoundsChangedCaller(m_instances)), + m_importMap(m_patch), + m_exportMap(m_patch) + { + m_patch.m_patchDef3 = patchDef3; + } + + PatchNode(const PatchNode &other) : + scene::Node::Symbiot(other), + scene::Instantiable(other), + scene::Cloneable(other), + m_node(this, this, StaticTypeCasts::instance().get()), + m_patch(other.m_patch, m_node, InstanceSetEvaluateTransform::Caller(m_instances), + InstanceSet::BoundsChangedCaller(m_instances)), + m_importMap(m_patch), + m_exportMap(m_patch) + { + } + + void release() + { + delete this; + } + + scene::Node &node() + { + return m_node; + } + + Patch &get() + { + return m_patch; + } + + const Patch &get() const + { + return m_patch; + } + + scene::Node &clone() const + { + return (new PatchNode(*this))->node(); + } + + scene::Instance *create(const scene::Path &path, scene::Instance *parent) + { + return new PatchInstance(path, parent, m_patch); + } + + 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); + } }; - typedef PatchNode PatchNodeQuake3; typedef PatchNode PatchNodeDoom3; -inline Patch* Node_getPatch( scene::Node& node ){ - return NodeTypeCast::cast( node ); +inline Patch *Node_getPatch(scene::Node &node) +{ + return NodeTypeCast::cast(node); } -inline PatchInstance* Instance_getPatch( scene::Instance& instance ){ - return InstanceTypeCast::cast( instance ); +inline PatchInstance *Instance_getPatch(scene::Instance &instance) +{ + return InstanceTypeCast::cast(instance); } template -class PatchSelectedVisitor : public SelectionSystem::Visitor -{ -const Functor& m_functor; +class PatchSelectedVisitor : public SelectionSystem::Visitor { + const Functor &m_functor; public: -PatchSelectedVisitor( const Functor& functor ) : m_functor( functor ){ -} -void visit( scene::Instance& instance ) const { - PatchInstance* patch = Instance_getPatch( instance ); - if ( patch != 0 ) { - m_functor( *patch ); - } -} + PatchSelectedVisitor(const Functor &functor) : m_functor(functor) + { + } + + void visit(scene::Instance &instance) const + { + PatchInstance *patch = Instance_getPatch(instance); + if (patch != 0) { + m_functor(*patch); + } + } }; template -inline void Scene_forEachSelectedPatch( const Functor& functor ){ - GlobalSelectionSystem().foreachSelected( PatchSelectedVisitor( functor ) ); +inline void Scene_forEachSelectedPatch(const Functor &functor) +{ + GlobalSelectionSystem().foreachSelected(PatchSelectedVisitor(functor)); } template -class PatchVisibleSelectedVisitor : public SelectionSystem::Visitor -{ -const Functor& m_functor; +class PatchVisibleSelectedVisitor : public SelectionSystem::Visitor { + const Functor &m_functor; public: -PatchVisibleSelectedVisitor( const Functor& functor ) : m_functor( functor ){ -} -void visit( scene::Instance& instance ) const { - PatchInstance* patch = Instance_getPatch( instance ); - if ( patch != 0 - && instance.path().top().get().visible() ) { - m_functor( *patch ); - } -} + PatchVisibleSelectedVisitor(const Functor &functor) : m_functor(functor) + { + } + + void visit(scene::Instance &instance) const + { + PatchInstance *patch = Instance_getPatch(instance); + if (patch != 0 + && instance.path().top().get().visible()) { + m_functor(*patch); + } + } }; template -inline void Scene_forEachVisibleSelectedPatchInstance( const Functor& functor ){ - GlobalSelectionSystem().foreachSelected( PatchVisibleSelectedVisitor( functor ) ); +inline void Scene_forEachVisibleSelectedPatchInstance(const Functor &functor) +{ + GlobalSelectionSystem().foreachSelected(PatchVisibleSelectedVisitor(functor)); } template -class PatchForEachWalker : public scene::Graph::Walker -{ -const Functor& m_functor; +class PatchForEachWalker : public scene::Graph::Walker { + const Functor &m_functor; public: -PatchForEachWalker( const Functor& functor ) : m_functor( functor ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - Patch* patch = Node_getPatch( path.top() ); - if ( patch != 0 ) { - m_functor( *patch ); - } - } - return true; -} + PatchForEachWalker(const Functor &functor) : m_functor(functor) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + Patch *patch = Node_getPatch(path.top()); + if (patch != 0) { + m_functor(*patch); + } + } + return true; + } }; template -inline void Scene_forEachVisiblePatch( const Functor& functor ){ - GlobalSceneGraph().traverse( PatchForEachWalker( functor ) ); +inline void Scene_forEachVisiblePatch(const Functor &functor) +{ + GlobalSceneGraph().traverse(PatchForEachWalker(functor)); } template -class PatchForEachSelectedWalker : public scene::Graph::Walker -{ -const Functor& m_functor; +class PatchForEachSelectedWalker : public scene::Graph::Walker { + const Functor &m_functor; public: -PatchForEachSelectedWalker( const Functor& functor ) : m_functor( functor ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - Patch* patch = Node_getPatch( path.top() ); - if ( patch != 0 - && Instance_getSelectable( instance )->isSelected() ) { - m_functor( *patch ); - } - } - return true; -} + PatchForEachSelectedWalker(const Functor &functor) : m_functor(functor) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + Patch *patch = Node_getPatch(path.top()); + if (patch != 0 + && Instance_getSelectable(instance)->isSelected()) { + m_functor(*patch); + } + } + return true; + } }; template -inline void Scene_forEachVisibleSelectedPatch( const Functor& functor ){ - GlobalSceneGraph().traverse( PatchForEachSelectedWalker( functor ) ); +inline void Scene_forEachVisibleSelectedPatch(const Functor &functor) +{ + GlobalSceneGraph().traverse(PatchForEachSelectedWalker(functor)); } template -class PatchForEachInstanceWalker : public scene::Graph::Walker -{ -const Functor& m_functor; +class PatchForEachInstanceWalker : public scene::Graph::Walker { + const Functor &m_functor; public: -PatchForEachInstanceWalker( const Functor& functor ) : m_functor( functor ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - PatchInstance* patch = Instance_getPatch( instance ); - if ( patch != 0 ) { - m_functor( *patch ); - } - } - return true; -} + PatchForEachInstanceWalker(const Functor &functor) : m_functor(functor) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + PatchInstance *patch = Instance_getPatch(instance); + if (patch != 0) { + m_functor(*patch); + } + } + return true; + } }; template -inline void Scene_forEachVisiblePatchInstance( const Functor& functor ){ - GlobalSceneGraph().traverse( PatchForEachInstanceWalker( functor ) ); +inline void Scene_forEachVisiblePatchInstance(const Functor &functor) +{ + GlobalSceneGraph().traverse(PatchForEachInstanceWalker(functor)); } #endif diff --git a/radiant/patchdialog.cpp b/radiant/patchdialog.cpp index 6a29298d..ba534918 100644 --- a/radiant/patchdialog.cpp +++ b/radiant/patchdialog.cpp @@ -50,251 +50,280 @@ #include // the increment we are using for the patch inspector (this is saved in the prefs) -struct pi_globals_t -{ - float shift[2]; - float scale[2]; - float rotate; - - pi_globals_t(){ - shift[0] = 8.0f; - shift[1] = 8.0f; - scale[0] = 0.5f; - scale[1] = 0.5f; - rotate = 45.0f; - } +struct pi_globals_t { + float shift[2]; + float scale[2]; + float rotate; + + pi_globals_t() + { + shift[0] = 8.0f; + shift[1] = 8.0f; + scale[0] = 0.5f; + scale[1] = 0.5f; + rotate = 45.0f; + } }; pi_globals_t g_pi_globals; -class PatchFixedSubdivisions -{ +class PatchFixedSubdivisions { public: -PatchFixedSubdivisions() : m_enabled( false ), m_x( 0 ), m_y( 0 ){ -} -PatchFixedSubdivisions( bool enabled, std::size_t x, std::size_t y ) : m_enabled( enabled ), m_x( x ), m_y( y ){ -} -bool m_enabled; -std::size_t m_x; -std::size_t m_y; + PatchFixedSubdivisions() : m_enabled(false), m_x(0), m_y(0) + { + } + + PatchFixedSubdivisions(bool enabled, std::size_t x, std::size_t y) : m_enabled(enabled), m_x(x), m_y(y) + { + } + + bool m_enabled; + std::size_t m_x; + std::size_t m_y; }; -void Patch_getFixedSubdivisions( const Patch& patch, PatchFixedSubdivisions& subdivisions ){ - subdivisions.m_enabled = patch.m_patchDef3; - subdivisions.m_x = patch.m_subdivisions_x; - subdivisions.m_y = patch.m_subdivisions_y; +void Patch_getFixedSubdivisions(const Patch &patch, PatchFixedSubdivisions &subdivisions) +{ + subdivisions.m_enabled = patch.m_patchDef3; + subdivisions.m_x = patch.m_subdivisions_x; + subdivisions.m_y = patch.m_subdivisions_y; } const std::size_t MAX_PATCH_SUBDIVISIONS = 32; -void Patch_setFixedSubdivisions( Patch& patch, const PatchFixedSubdivisions& subdivisions ){ - patch.undoSave(); - - patch.m_patchDef3 = subdivisions.m_enabled; - patch.m_subdivisions_x = subdivisions.m_x; - patch.m_subdivisions_y = subdivisions.m_y; - - if ( patch.m_subdivisions_x == 0 ) { - patch.m_subdivisions_x = 4; - } - else if ( patch.m_subdivisions_x > MAX_PATCH_SUBDIVISIONS ) { - patch.m_subdivisions_x = MAX_PATCH_SUBDIVISIONS; - } - if ( patch.m_subdivisions_y == 0 ) { - patch.m_subdivisions_y = 4; - } - else if ( patch.m_subdivisions_y > MAX_PATCH_SUBDIVISIONS ) { - patch.m_subdivisions_y = MAX_PATCH_SUBDIVISIONS; - } - - SceneChangeNotify(); - Patch_textureChanged(); - patch.controlPointsChanged(); +void Patch_setFixedSubdivisions(Patch &patch, const PatchFixedSubdivisions &subdivisions) +{ + patch.undoSave(); + + patch.m_patchDef3 = subdivisions.m_enabled; + patch.m_subdivisions_x = subdivisions.m_x; + patch.m_subdivisions_y = subdivisions.m_y; + + if (patch.m_subdivisions_x == 0) { + patch.m_subdivisions_x = 4; + } else if (patch.m_subdivisions_x > MAX_PATCH_SUBDIVISIONS) { + patch.m_subdivisions_x = MAX_PATCH_SUBDIVISIONS; + } + if (patch.m_subdivisions_y == 0) { + patch.m_subdivisions_y = 4; + } else if (patch.m_subdivisions_y > MAX_PATCH_SUBDIVISIONS) { + patch.m_subdivisions_y = MAX_PATCH_SUBDIVISIONS; + } + + SceneChangeNotify(); + Patch_textureChanged(); + patch.controlPointsChanged(); } -class PatchGetFixedSubdivisions -{ -PatchFixedSubdivisions& m_subdivisions; +class PatchGetFixedSubdivisions { + PatchFixedSubdivisions &m_subdivisions; public: -PatchGetFixedSubdivisions( PatchFixedSubdivisions& subdivisions ) : m_subdivisions( subdivisions ){ -} -void operator()( Patch& patch ){ - Patch_getFixedSubdivisions( patch, m_subdivisions ); - SceneChangeNotify(); -} + PatchGetFixedSubdivisions(PatchFixedSubdivisions &subdivisions) : m_subdivisions(subdivisions) + { + } + + void operator()(Patch &patch) + { + Patch_getFixedSubdivisions(patch, m_subdivisions); + SceneChangeNotify(); + } }; -void Scene_PatchGetFixedSubdivisions( PatchFixedSubdivisions& subdivisions ){ +void Scene_PatchGetFixedSubdivisions(PatchFixedSubdivisions &subdivisions) +{ #if 1 - if ( GlobalSelectionSystem().countSelected() != 0 ) { - Patch* patch = Node_getPatch( GlobalSelectionSystem().ultimateSelected().path().top() ); - if ( patch != 0 ) { - Patch_getFixedSubdivisions( *patch, subdivisions ); - } - } + if (GlobalSelectionSystem().countSelected() != 0) { + Patch *patch = Node_getPatch(GlobalSelectionSystem().ultimateSelected().path().top()); + if (patch != 0) { + Patch_getFixedSubdivisions(*patch, subdivisions); + } + } #else - Scene_forEachVisibleSelectedPatch( PatchGetFixedSubdivisions( subdivisions ) ); + Scene_forEachVisibleSelectedPatch( PatchGetFixedSubdivisions( subdivisions ) ); #endif } -void Scene_PatchSetFixedSubdivisions( const PatchFixedSubdivisions& subdivisions ){ - UndoableCommand command( "patchSetFixedSubdivisions" ); - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - Patch_setFixedSubdivisions(patch, subdivisions); - }); +void Scene_PatchSetFixedSubdivisions(const PatchFixedSubdivisions &subdivisions) +{ + UndoableCommand command("patchSetFixedSubdivisions"); + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + Patch_setFixedSubdivisions(patch, subdivisions); + }); } -class Subdivisions -{ +class Subdivisions { public: -ui::CheckButton m_enabled; -ui::Entry m_horizontal; -ui::Entry m_vertical; -Subdivisions() : m_enabled( ui::null ), m_horizontal( ui::null ), m_vertical( ui::null ){ -} -void update(){ - PatchFixedSubdivisions subdivisions; - Scene_PatchGetFixedSubdivisions( subdivisions ); - - toggle_button_set_active_no_signal( m_enabled, subdivisions.m_enabled ); - - if ( subdivisions.m_enabled ) { - entry_set_int( m_horizontal, static_cast( subdivisions.m_x ) ); - entry_set_int( m_vertical, static_cast( subdivisions.m_y ) ); - gtk_widget_set_sensitive( m_horizontal , TRUE ); - gtk_widget_set_sensitive( m_vertical , TRUE ); - } - else - { - m_horizontal.text(""); - m_vertical.text(""); - gtk_widget_set_sensitive( m_horizontal , FALSE ); - gtk_widget_set_sensitive( m_vertical , FALSE ); - } -} -void cancel(){ - update(); -} -typedef MemberCaller CancelCaller; -void apply(){ - Scene_PatchSetFixedSubdivisions( - PatchFixedSubdivisions( - gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( m_enabled ) ) != FALSE, - static_cast( entry_get_int( m_horizontal ) ), - static_cast( entry_get_int( m_vertical ) ) - ) - ); -} -typedef MemberCaller ApplyCaller; -static void applyGtk( ui::ToggleButton toggle, Subdivisions* self ){ - self->apply(); -} + ui::CheckButton m_enabled; + ui::Entry m_horizontal; + ui::Entry m_vertical; + + Subdivisions() : m_enabled(ui::null), m_horizontal(ui::null), m_vertical(ui::null) + { + } + + void update() + { + PatchFixedSubdivisions subdivisions; + Scene_PatchGetFixedSubdivisions(subdivisions); + + toggle_button_set_active_no_signal(m_enabled, subdivisions.m_enabled); + + if (subdivisions.m_enabled) { + entry_set_int(m_horizontal, static_cast( subdivisions.m_x )); + entry_set_int(m_vertical, static_cast( subdivisions.m_y )); + gtk_widget_set_sensitive(m_horizontal, TRUE); + gtk_widget_set_sensitive(m_vertical, TRUE); + } else { + m_horizontal.text(""); + m_vertical.text(""); + gtk_widget_set_sensitive(m_horizontal, FALSE); + gtk_widget_set_sensitive(m_vertical, FALSE); + } + } + + void cancel() + { + update(); + } + + typedef MemberCaller CancelCaller; + + void apply() + { + Scene_PatchSetFixedSubdivisions( + PatchFixedSubdivisions( + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(m_enabled)) != FALSE, + static_cast( entry_get_int(m_horizontal)), + static_cast( entry_get_int(m_vertical)) + ) + ); + } + + typedef MemberCaller ApplyCaller; + + static void applyGtk(ui::ToggleButton toggle, Subdivisions *self) + { + self->apply(); + } }; -class PatchInspector : public Dialog -{ -ui::Window BuildDialog(); -Subdivisions m_subdivisions; -NonModalEntry m_horizontalSubdivisionsEntry; -NonModalEntry m_verticalSubdivisionsEntry; +class PatchInspector : public Dialog { + ui::Window BuildDialog(); + + Subdivisions m_subdivisions; + NonModalEntry m_horizontalSubdivisionsEntry; + NonModalEntry m_verticalSubdivisionsEntry; public: -IdleDraw m_idleDraw; -WindowPositionTracker m_position_tracker; + IdleDraw m_idleDraw; + WindowPositionTracker m_position_tracker; -Patch *m_Patch; + Patch *m_Patch; -CopiedString m_strName; -float m_fS; -float m_fT; -float m_fX; -float m_fY; -float m_fZ; + CopiedString m_strName; + float m_fS; + float m_fT; + float m_fX; + float m_fY; + float m_fZ; /* float m_fHScale; float m_fHShift; float m_fRotate; float m_fVScale; float m_fVShift; */ -int m_nCol; -int m_nRow; -ui::ComboBoxText m_pRowCombo{ui::null}; -ui::ComboBoxText m_pColCombo{ui::null}; -std::size_t m_countRows; -std::size_t m_countCols; + int m_nCol; + int m_nRow; + ui::ComboBoxText m_pRowCombo{ui::null}; + ui::ComboBoxText m_pColCombo{ui::null}; + std::size_t m_countRows; + std::size_t m_countCols; // turn on/off processing of the "changed" "value_changed" messages // (need to turn off when we are feeding data in) // NOTE: much more simple than blocking signals -bool m_bListenChanged; - -PatchInspector() : - m_horizontalSubdivisionsEntry( Subdivisions::ApplyCaller( m_subdivisions ), Subdivisions::CancelCaller( m_subdivisions ) ), - m_verticalSubdivisionsEntry( Subdivisions::ApplyCaller( m_subdivisions ), Subdivisions::CancelCaller( m_subdivisions ) ), - m_idleDraw( MemberCaller( *this ) ){ - m_fS = 0.0f; - m_fT = 0.0f; - m_fX = 0.0f; - m_fY = 0.0f; - m_fZ = 0.0f; - m_nCol = 0; - m_nRow = 0; - m_countRows = 0; - m_countCols = 0; - m_Patch = 0; - m_bListenChanged = true; - - m_position_tracker.setPosition( c_default_window_pos ); -} - -bool visible(){ - return GetWidget().visible(); -} + bool m_bListenChanged; + + PatchInspector() : + m_horizontalSubdivisionsEntry(Subdivisions::ApplyCaller(m_subdivisions), + Subdivisions::CancelCaller(m_subdivisions)), + m_verticalSubdivisionsEntry(Subdivisions::ApplyCaller(m_subdivisions), + Subdivisions::CancelCaller(m_subdivisions)), + m_idleDraw(MemberCaller(*this)) + { + m_fS = 0.0f; + m_fT = 0.0f; + m_fX = 0.0f; + m_fY = 0.0f; + m_fZ = 0.0f; + m_nCol = 0; + m_nRow = 0; + m_countRows = 0; + m_countCols = 0; + m_Patch = 0; + m_bListenChanged = true; + + m_position_tracker.setPosition(c_default_window_pos); + } + + bool visible() + { + return GetWidget().visible(); + } // void UpdateInfo(); // void SetPatchInfo(); -void GetPatchInfo(); -void UpdateSpinners( bool bUp, int nID ); + void GetPatchInfo(); + + void UpdateSpinners(bool bUp, int nID); + // read the current patch on map and initialize m_fX m_fY accordingly -void UpdateRowColInfo(); + void UpdateRowColInfo(); + // sync the dialog our internal data structures // depending on the flag it will read or write // we use m_nCol m_nRow m_fX m_fY m_fZ m_fS m_fT m_strName // (NOTE: this doesn't actually commit stuff to the map or read from it) -void importData(); -void exportData(); + void importData(); + + void exportData(); }; PatchInspector g_PatchInspector; -void PatchInspector_constructWindow( ui::Window main_window ){ - g_PatchInspector.m_parent = main_window; - g_PatchInspector.Create(); +void PatchInspector_constructWindow(ui::Window main_window) +{ + g_PatchInspector.m_parent = main_window; + g_PatchInspector.Create(); } -void PatchInspector_destroyWindow(){ - g_PatchInspector.Destroy(); + +void PatchInspector_destroyWindow() +{ + g_PatchInspector.Destroy(); } -void PatchInspector_queueDraw(){ - if ( g_PatchInspector.visible() ) { - g_PatchInspector.m_idleDraw.queueDraw(); - } +void PatchInspector_queueDraw() +{ + if (g_PatchInspector.visible()) { + g_PatchInspector.m_idleDraw.queueDraw(); + } } -void DoPatchInspector(){ - g_PatchInspector.GetPatchInfo(); - if ( !g_PatchInspector.visible() ) { - g_PatchInspector.ShowDlg(); - } +void DoPatchInspector() +{ + g_PatchInspector.GetPatchInfo(); + if (!g_PatchInspector.visible()) { + g_PatchInspector.ShowDlg(); + } } -void PatchInspector_toggleShown(){ - if ( g_PatchInspector.visible() ) { - g_PatchInspector.m_Patch = 0; - g_PatchInspector.HideDlg(); - } - else{ - DoPatchInspector(); - } +void PatchInspector_toggleShown() +{ + if (g_PatchInspector.visible()) { + g_PatchInspector.m_Patch = 0; + g_PatchInspector.HideDlg(); + } else { + DoPatchInspector(); + } } @@ -302,750 +331,769 @@ void PatchInspector_toggleShown(){ // static functions // memorize the current state (that is don't try to undo our do before changing something else) -static void OnApply( ui::Widget widget, gpointer data ){ - g_PatchInspector.exportData(); - if ( g_PatchInspector.m_Patch != 0 ) { - UndoableCommand command( "patchSetTexture" ); - g_PatchInspector.m_Patch->undoSave(); - - if ( !texdef_name_valid( g_PatchInspector.m_strName.c_str() ) ) { - globalErrorStream() << "invalid texture name '" << g_PatchInspector.m_strName.c_str() << "'\n"; - g_PatchInspector.m_strName = texdef_name_default(); - } - g_PatchInspector.m_Patch->SetShader( g_PatchInspector.m_strName.c_str() ); - - std::size_t r = g_PatchInspector.m_nRow; - std::size_t c = g_PatchInspector.m_nCol; - if ( r < g_PatchInspector.m_Patch->getHeight() - && c < g_PatchInspector.m_Patch->getWidth() ) { - PatchControl& p = g_PatchInspector.m_Patch->ctrlAt( r,c ); - p.m_vertex[0] = g_PatchInspector.m_fX; - p.m_vertex[1] = g_PatchInspector.m_fY; - p.m_vertex[2] = g_PatchInspector.m_fZ; - p.m_texcoord[0] = g_PatchInspector.m_fS; - p.m_texcoord[1] = g_PatchInspector.m_fT; - g_PatchInspector.m_Patch->controlPointsChanged(); - } - } +static void OnApply(ui::Widget widget, gpointer data) +{ + g_PatchInspector.exportData(); + if (g_PatchInspector.m_Patch != 0) { + UndoableCommand command("patchSetTexture"); + g_PatchInspector.m_Patch->undoSave(); + + if (!texdef_name_valid(g_PatchInspector.m_strName.c_str())) { + globalErrorStream() << "invalid texture name '" << g_PatchInspector.m_strName.c_str() << "'\n"; + g_PatchInspector.m_strName = texdef_name_default(); + } + g_PatchInspector.m_Patch->SetShader(g_PatchInspector.m_strName.c_str()); + + std::size_t r = g_PatchInspector.m_nRow; + std::size_t c = g_PatchInspector.m_nCol; + if (r < g_PatchInspector.m_Patch->getHeight() + && c < g_PatchInspector.m_Patch->getWidth()) { + PatchControl &p = g_PatchInspector.m_Patch->ctrlAt(r, c); + p.m_vertex[0] = g_PatchInspector.m_fX; + p.m_vertex[1] = g_PatchInspector.m_fY; + p.m_vertex[2] = g_PatchInspector.m_fZ; + p.m_texcoord[0] = g_PatchInspector.m_fS; + p.m_texcoord[1] = g_PatchInspector.m_fT; + g_PatchInspector.m_Patch->controlPointsChanged(); + } + } } -static void OnSelchangeComboColRow( ui::Widget widget, gpointer data ){ - if ( !g_PatchInspector.m_bListenChanged ) { - return; - } - // retrieve the current m_nRow and m_nCol, other params are not relevant - g_PatchInspector.exportData(); - // read the changed values ourselves - g_PatchInspector.UpdateRowColInfo(); - // now reflect our changes - g_PatchInspector.importData(); +static void OnSelchangeComboColRow(ui::Widget widget, gpointer data) +{ + if (!g_PatchInspector.m_bListenChanged) { + return; + } + // retrieve the current m_nRow and m_nCol, other params are not relevant + g_PatchInspector.exportData(); + // read the changed values ourselves + g_PatchInspector.UpdateRowColInfo(); + // now reflect our changes + g_PatchInspector.importData(); } -void Scene_PatchTileTexture_Selected( scene::Graph& graph, float s, float t ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.SetTextureRepeat(s, t); - }); - SceneChangeNotify(); +void Scene_PatchTileTexture_Selected(scene::Graph &graph, float s, float t) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.SetTextureRepeat(s, t); + }); + SceneChangeNotify(); } -static void OnBtnPatchdetails( ui::Widget widget, gpointer data ){ - Patch_CapTexture(); +static void OnBtnPatchdetails(ui::Widget widget, gpointer data) +{ + Patch_CapTexture(); } -static void OnBtnPatchfit( ui::Widget widget, gpointer data ){ - Patch_FitTexture(); +static void OnBtnPatchfit(ui::Widget widget, gpointer data) +{ + Patch_FitTexture(); } -static void OnBtnPatchnatural( ui::Widget widget, gpointer data ){ - Patch_NaturalTexture(); +static void OnBtnPatchnatural(ui::Widget widget, gpointer data) +{ + Patch_NaturalTexture(); } -static void OnBtnPatchreset( ui::Widget widget, gpointer data ){ - Patch_ResetTexture(); +static void OnBtnPatchreset(ui::Widget widget, gpointer data) +{ + Patch_ResetTexture(); } -static void OnBtnPatchFlipX( ui::Widget widget, gpointer data ){ - Patch_FlipTextureX(); +static void OnBtnPatchFlipX(ui::Widget widget, gpointer data) +{ + Patch_FlipTextureX(); } -static void OnBtnPatchFlipY( ui::Widget widget, gpointer data ){ - Patch_FlipTextureY(); +static void OnBtnPatchFlipY(ui::Widget widget, gpointer data) +{ + Patch_FlipTextureY(); } -void Scene_PatchRotateTexture_Selected( scene::Graph& graph, float angle ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.RotateTexture(angle); - }); +void Scene_PatchRotateTexture_Selected(scene::Graph &graph, float angle) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.RotateTexture(angle); + }); } -float Patch_convertScale( float scale ){ - if ( scale > 0 ) { - return scale; - } - if ( scale < 0 ) { - return -1 / scale; - } - return 1; +float Patch_convertScale(float scale) +{ + if (scale > 0) { + return scale; + } + if (scale < 0) { + return -1 / scale; + } + return 1; } -void Scene_PatchScaleTexture_Selected( scene::Graph& graph, float s, float t ){ - s = Patch_convertScale(s); - t = Patch_convertScale(t); - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.ScaleTexture(s, t); - }); +void Scene_PatchScaleTexture_Selected(scene::Graph &graph, float s, float t) +{ + s = Patch_convertScale(s); + t = Patch_convertScale(t); + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.ScaleTexture(s, t); + }); } -void Scene_PatchTranslateTexture_Selected( scene::Graph& graph, float s, float t ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.TranslateTexture(s, t); - }); +void Scene_PatchTranslateTexture_Selected(scene::Graph &graph, float s, float t) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.TranslateTexture(s, t); + }); } -static void OnBtnPatchAutoCap( ui::Widget widget, gpointer data ){ - Patch_AutoCapTexture(); +static void OnBtnPatchAutoCap(ui::Widget widget, gpointer data) +{ + Patch_AutoCapTexture(); } -static void OnSpinChanged(ui::Adjustment adj, gpointer data ){ - texdef_t td; - - td.rotate = 0; - td.scale[0] = td.scale[1] = 0; - td.shift[0] = td.shift[1] = 0; - - if ( gtk_adjustment_get_value(adj) == 0 ) { - return; - } - - if ( adj == g_object_get_data( G_OBJECT( g_PatchInspector.GetWidget() ), "hshift_adj" ) ) { - g_pi_globals.shift[0] = static_cast( atof( gtk_entry_get_text( GTK_ENTRY( data ) ) ) ); - - if ( gtk_adjustment_get_value(adj) > 0 ) { - td.shift[0] = g_pi_globals.shift[0]; - } - else{ - td.shift[0] = -g_pi_globals.shift[0]; - } - } - else if ( adj == g_object_get_data( G_OBJECT( g_PatchInspector.GetWidget() ), "vshift_adj" ) ) { - g_pi_globals.shift[1] = static_cast( atof( gtk_entry_get_text( GTK_ENTRY( data ) ) ) ); - - if ( gtk_adjustment_get_value(adj) > 0 ) { - td.shift[1] = g_pi_globals.shift[1]; - } - else{ - td.shift[1] = -g_pi_globals.shift[1]; - } - } - else if ( adj == g_object_get_data( G_OBJECT( g_PatchInspector.GetWidget() ), "hscale_adj" ) ) { - g_pi_globals.scale[0] = static_cast( atof( gtk_entry_get_text( GTK_ENTRY( data ) ) ) ); - if ( g_pi_globals.scale[0] == 0.0f ) { - return; - } - if ( gtk_adjustment_get_value(adj) > 0 ) { - td.scale[0] = g_pi_globals.scale[0]; - } - else{ - td.scale[0] = -g_pi_globals.scale[0]; - } - } - else if ( adj == g_object_get_data( G_OBJECT( g_PatchInspector.GetWidget() ), "vscale_adj" ) ) { - g_pi_globals.scale[1] = static_cast( atof( gtk_entry_get_text( GTK_ENTRY( data ) ) ) ); - if ( g_pi_globals.scale[1] == 0.0f ) { - return; - } - if ( gtk_adjustment_get_value(adj) > 0 ) { - td.scale[1] = g_pi_globals.scale[1]; - } - else{ - td.scale[1] = -g_pi_globals.scale[1]; - } - } - else if ( adj == g_object_get_data( G_OBJECT( g_PatchInspector.GetWidget() ), "rotate_adj" ) ) { - g_pi_globals.rotate = static_cast( atof( gtk_entry_get_text( GTK_ENTRY( data ) ) ) ); - - if ( gtk_adjustment_get_value(adj) > 0 ) { - td.rotate = g_pi_globals.rotate; - } - else{ - td.rotate = -g_pi_globals.rotate; - } - } - - gtk_adjustment_set_value(adj, 0); - - // will scale shift rotate the patch accordingly - - - if ( td.shift[0] || td.shift[1] ) { - UndoableCommand command( "patchTranslateTexture" ); - Scene_PatchTranslateTexture_Selected( GlobalSceneGraph(), td.shift[0], td.shift[1] ); - } - else if ( td.scale[0] || td.scale[1] ) { - UndoableCommand command( "patchScaleTexture" ); - Scene_PatchScaleTexture_Selected( GlobalSceneGraph(), td.scale[0], td.scale[1] ); - } - else if ( td.rotate ) { - UndoableCommand command( "patchRotateTexture" ); - Scene_PatchRotateTexture_Selected( GlobalSceneGraph(), td.rotate ); - } - - // update the point-by-point view - OnSelchangeComboColRow( ui::root, 0 ); +static void OnSpinChanged(ui::Adjustment adj, gpointer data) +{ + texdef_t td; + + td.rotate = 0; + td.scale[0] = td.scale[1] = 0; + td.shift[0] = td.shift[1] = 0; + + if (gtk_adjustment_get_value(adj) == 0) { + return; + } + + if (adj == g_object_get_data(G_OBJECT(g_PatchInspector.GetWidget()), "hshift_adj")) { + g_pi_globals.shift[0] = static_cast( atof(gtk_entry_get_text(GTK_ENTRY(data)))); + + if (gtk_adjustment_get_value(adj) > 0) { + td.shift[0] = g_pi_globals.shift[0]; + } else { + td.shift[0] = -g_pi_globals.shift[0]; + } + } else if (adj == g_object_get_data(G_OBJECT(g_PatchInspector.GetWidget()), "vshift_adj")) { + g_pi_globals.shift[1] = static_cast( atof(gtk_entry_get_text(GTK_ENTRY(data)))); + + if (gtk_adjustment_get_value(adj) > 0) { + td.shift[1] = g_pi_globals.shift[1]; + } else { + td.shift[1] = -g_pi_globals.shift[1]; + } + } else if (adj == g_object_get_data(G_OBJECT(g_PatchInspector.GetWidget()), "hscale_adj")) { + g_pi_globals.scale[0] = static_cast( atof(gtk_entry_get_text(GTK_ENTRY(data)))); + if (g_pi_globals.scale[0] == 0.0f) { + return; + } + if (gtk_adjustment_get_value(adj) > 0) { + td.scale[0] = g_pi_globals.scale[0]; + } else { + td.scale[0] = -g_pi_globals.scale[0]; + } + } else if (adj == g_object_get_data(G_OBJECT(g_PatchInspector.GetWidget()), "vscale_adj")) { + g_pi_globals.scale[1] = static_cast( atof(gtk_entry_get_text(GTK_ENTRY(data)))); + if (g_pi_globals.scale[1] == 0.0f) { + return; + } + if (gtk_adjustment_get_value(adj) > 0) { + td.scale[1] = g_pi_globals.scale[1]; + } else { + td.scale[1] = -g_pi_globals.scale[1]; + } + } else if (adj == g_object_get_data(G_OBJECT(g_PatchInspector.GetWidget()), "rotate_adj")) { + g_pi_globals.rotate = static_cast( atof(gtk_entry_get_text(GTK_ENTRY(data)))); + + if (gtk_adjustment_get_value(adj) > 0) { + td.rotate = g_pi_globals.rotate; + } else { + td.rotate = -g_pi_globals.rotate; + } + } + + gtk_adjustment_set_value(adj, 0); + + // will scale shift rotate the patch accordingly + + + if (td.shift[0] || td.shift[1]) { + UndoableCommand command("patchTranslateTexture"); + Scene_PatchTranslateTexture_Selected(GlobalSceneGraph(), td.shift[0], td.shift[1]); + } else if (td.scale[0] || td.scale[1]) { + UndoableCommand command("patchScaleTexture"); + Scene_PatchScaleTexture_Selected(GlobalSceneGraph(), td.scale[0], td.scale[1]); + } else if (td.rotate) { + UndoableCommand command("patchRotateTexture"); + Scene_PatchRotateTexture_Selected(GlobalSceneGraph(), td.rotate); + } + + // update the point-by-point view + OnSelchangeComboColRow(ui::root, 0); } -static gint OnDialogKey( ui::Widget widget, GdkEventKey* event, gpointer data ){ - if ( event->keyval == GDK_KEY_Return ) { - OnApply( ui::root, 0 ); - return TRUE; - } - else if ( event->keyval == GDK_KEY_Escape ) { - g_PatchInspector.GetPatchInfo(); - return TRUE; - } - return FALSE; +static gint OnDialogKey(ui::Widget widget, GdkEventKey *event, gpointer data) +{ + if (event->keyval == GDK_KEY_Return) { + OnApply(ui::root, 0); + return TRUE; + } else if (event->keyval == GDK_KEY_Escape) { + g_PatchInspector.GetPatchInfo(); + return TRUE; + } + return FALSE; } // ============================================================================= // PatchInspector class -ui::Window PatchInspector::BuildDialog(){ - ui::Window window = ui::Window(create_floating_window( "Patch Properties", m_parent )); - - m_position_tracker.connect( window ); - - global_accel_connect_window( window ); - - window_connect_focus_in_clear_focus_widget( window ); - - - { - auto vbox = ui::VBox( FALSE, 5 ); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - vbox.show(); - window.add(vbox); - { - auto hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox.pack_start( hbox, TRUE, TRUE, 0 ); - { - auto vbox2 = ui::VBox( FALSE, 0 ); - gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 0 ); - vbox2.show(); - hbox.pack_start( vbox2, TRUE, TRUE, 0 ); - { - auto frame = ui::Frame( "Details" ); - frame.show(); - vbox2.pack_start( frame, TRUE, TRUE, 0 ); - { - auto vbox3 = ui::VBox( FALSE, 5 ); - gtk_container_set_border_width( GTK_CONTAINER( vbox3 ), 5 ); - vbox3.show(); - frame.add(vbox3); - { - auto table = ui::Table( 2, 2, FALSE ); - table.show(); - vbox3.pack_start( table, TRUE, TRUE, 0 ); - gtk_table_set_row_spacings( table, 5 ); - gtk_table_set_col_spacings( table, 5 ); - { - auto label = ui::Label( "Row:" ); - label.show(); - table.attach(label, {0, 1, 0, 1}, {(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0)}, {0, 0}); - } - { - auto label = ui::Label( "Column:" ); - label.show(); - table.attach(label, {1, 2, 0, 1}, {(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0)}, {0, 0}); - } - { - auto combo = ui::ComboBoxText(ui::New); - combo.connect( "changed", G_CALLBACK( OnSelchangeComboColRow ), this ); - AddDialogData( combo, m_nRow ); - - combo.show(); - table.attach(combo, {0, 1, 1, 2}, {(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0)}, {0, 0}); - combo.dimensions(60, -1); - m_pRowCombo = combo; - } - - { - auto combo = ui::ComboBoxText(ui::New); - combo.connect( "changed", G_CALLBACK( OnSelchangeComboColRow ), this ); - AddDialogData( combo, m_nCol ); - - combo.show(); - table.attach(combo, {1, 2, 1, 2}, {(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0)}, {0, 0}); - combo.dimensions(60, -1); - m_pColCombo = combo; - } - } - auto table = ui::Table( 5, 2, FALSE ); - table.show(); - vbox3.pack_start( table, TRUE, TRUE, 0 ); - gtk_table_set_row_spacings( table, 5 ); - gtk_table_set_col_spacings( table, 5 ); - { - auto label = ui::Label( "X:" ); - label.show(); +ui::Window PatchInspector::BuildDialog() +{ + ui::Window window = ui::Window(create_floating_window("Patch Properties", m_parent)); + + m_position_tracker.connect(window); + + global_accel_connect_window(window); + + window_connect_focus_in_clear_focus_widget(window); + + + { + auto vbox = ui::VBox(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + vbox.show(); + window.add(vbox); + { + auto hbox = ui::HBox(FALSE, 5); + hbox.show(); + vbox.pack_start(hbox, TRUE, TRUE, 0); + { + auto vbox2 = ui::VBox(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(vbox2), 0); + vbox2.show(); + hbox.pack_start(vbox2, TRUE, TRUE, 0); + { + auto frame = ui::Frame("Details"); + frame.show(); + vbox2.pack_start(frame, TRUE, TRUE, 0); + { + auto vbox3 = ui::VBox(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(vbox3), 5); + vbox3.show(); + frame.add(vbox3); + { + auto table = ui::Table(2, 2, FALSE); + table.show(); + vbox3.pack_start(table, TRUE, TRUE, 0); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + { + auto label = ui::Label("Row:"); + label.show(); + table.attach(label, {0, 1, 0, 1}, + {(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0)}, + {0, 0}); + } + { + auto label = ui::Label("Column:"); + label.show(); + table.attach(label, {1, 2, 0, 1}, + {(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0)}, + {0, 0}); + } + { + auto combo = ui::ComboBoxText(ui::New); + combo.connect("changed", G_CALLBACK(OnSelchangeComboColRow), this); + AddDialogData(combo, m_nRow); + + combo.show(); + table.attach(combo, {0, 1, 1, 2}, + {(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0)}, + {0, 0}); + combo.dimensions(60, -1); + m_pRowCombo = combo; + } + + { + auto combo = ui::ComboBoxText(ui::New); + combo.connect("changed", G_CALLBACK(OnSelchangeComboColRow), this); + AddDialogData(combo, m_nCol); + + combo.show(); + table.attach(combo, {1, 2, 1, 2}, + {(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0)}, + {0, 0}); + combo.dimensions(60, -1); + m_pColCombo = combo; + } + } + auto table = ui::Table(5, 2, FALSE); + table.show(); + vbox3.pack_start(table, TRUE, TRUE, 0); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + { + auto label = ui::Label("X:"); + label.show(); table.attach(label, {0, 1, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - } - { - auto label = ui::Label( "Y:" ); - label.show(); + } + { + auto label = ui::Label("Y:"); + label.show(); table.attach(label, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - } - { - auto label = ui::Label( "Z:" ); - label.show(); + } + { + auto label = ui::Label("Z:"); + label.show(); table.attach(label, {0, 1, 2, 3}, {GTK_EXPAND | GTK_FILL, 0}); - } - { - auto label = ui::Label( "S:" ); - label.show(); + } + { + auto label = ui::Label("S:"); + label.show(); table.attach(label, {0, 1, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); - } - { - auto label = ui::Label( "T:" ); - label.show(); + } + { + auto label = ui::Label("T:"); + label.show(); table.attach(label, {0, 1, 4, 5}, {GTK_EXPAND | GTK_FILL, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - AddDialogData( entry, m_fX ); + AddDialogData(entry, m_fX); - entry.connect( "key_press_event", G_CALLBACK( OnDialogKey ), 0 ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + entry.connect("key_press_event", G_CALLBACK(OnDialogKey), 0); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - AddDialogData( entry, m_fY ); + AddDialogData(entry, m_fY); - entry.connect( "key_press_event", G_CALLBACK( OnDialogKey ), 0 ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + entry.connect("key_press_event", G_CALLBACK(OnDialogKey), 0); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 2, 3}, {GTK_EXPAND | GTK_FILL, 0}); - AddDialogData( entry, m_fZ ); + AddDialogData(entry, m_fZ); - entry.connect( "key_press_event", G_CALLBACK( OnDialogKey ), 0 ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + entry.connect("key_press_event", G_CALLBACK(OnDialogKey), 0); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); - AddDialogData( entry, m_fS ); + AddDialogData(entry, m_fS); - entry.connect( "key_press_event", G_CALLBACK( OnDialogKey ), 0 ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + entry.connect("key_press_event", G_CALLBACK(OnDialogKey), 0); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 4, 5}, {GTK_EXPAND | GTK_FILL, 0}); - AddDialogData( entry, m_fT ); - - entry.connect( "key_press_event", G_CALLBACK( OnDialogKey ), 0 ); - } - } - } - if ( g_pGameDescription->mGameType == "doom3" ) { - auto frame = ui::Frame( "Tesselation" ); - frame.show(); - vbox2.pack_start( frame, TRUE, TRUE, 0 ); - { - auto vbox3 = ui::VBox( FALSE, 5 ); - gtk_container_set_border_width( GTK_CONTAINER( vbox3 ), 5 ); - vbox3.show(); - frame.add(vbox3); - { - auto table = ui::Table( 3, 2, FALSE ); - table.show(); - vbox3.pack_start( table, TRUE, TRUE, 0 ); - gtk_table_set_row_spacings( table, 5 ); - gtk_table_set_col_spacings( table, 5 ); - { - auto label = ui::Label( "Fixed" ); - label.show(); + AddDialogData(entry, m_fT); + + entry.connect("key_press_event", G_CALLBACK(OnDialogKey), 0); + } + } + } + if (g_pGameDescription->mGameType == "doom3") { + auto frame = ui::Frame("Tesselation"); + frame.show(); + vbox2.pack_start(frame, TRUE, TRUE, 0); + { + auto vbox3 = ui::VBox(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(vbox3), 5); + vbox3.show(); + frame.add(vbox3); + { + auto table = ui::Table(3, 2, FALSE); + table.show(); + vbox3.pack_start(table, TRUE, TRUE, 0); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + { + auto label = ui::Label("Fixed"); + label.show(); table.attach(label, {0, 1, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - } - { - auto check = ui::CheckButton::from( gtk_check_button_new() ); - check.show(); + } + { + auto check = ui::CheckButton::from(gtk_check_button_new()); + check.show(); table.attach(check, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - m_subdivisions.m_enabled = check; - guint handler_id = check.connect( "toggled", G_CALLBACK( &Subdivisions::applyGtk ), &m_subdivisions ); - g_object_set_data( G_OBJECT( check ), "handler", gint_to_pointer( handler_id ) ); - } - { - auto label = ui::Label( "Horizontal" ); - label.show(); + m_subdivisions.m_enabled = check; + guint handler_id = check.connect("toggled", G_CALLBACK(&Subdivisions::applyGtk), + &m_subdivisions); + g_object_set_data(G_OBJECT(check), "handler", gint_to_pointer(handler_id)); + } + { + auto label = ui::Label("Horizontal"); + label.show(); table.attach(label, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - m_subdivisions.m_horizontal = entry; - m_horizontalSubdivisionsEntry.connect( entry ); - } - { - auto label = ui::Label( "Vertical" ); - label.show(); + m_subdivisions.m_horizontal = entry; + m_horizontalSubdivisionsEntry.connect(entry); + } + { + auto label = ui::Label("Vertical"); + label.show(); table.attach(label, {0, 1, 2, 3}, {GTK_EXPAND | GTK_FILL, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 2, 3}, {GTK_EXPAND | GTK_FILL, 0}); - m_subdivisions.m_vertical = entry; - m_verticalSubdivisionsEntry.connect( entry ); - } - } - } - } - } - { - auto frame = ui::Frame( "Texturing" ); - frame.show(); - hbox.pack_start( frame, TRUE, TRUE, 0 ); - { - auto vbox2 = ui::VBox( FALSE, 5 ); - vbox2.show(); - frame.add(vbox2); - gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 5 ); - { - auto label = ui::Label( "Name:" ); - label.show(); - vbox2.pack_start( label, TRUE, TRUE, 0 ); - gtk_label_set_justify( label, GTK_JUSTIFY_LEFT ); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto entry = ui::Entry(ui::New); - // gtk_editable_set_editable (GTK_ENTRY (entry), false); - entry.show(); - vbox2.pack_start( entry, TRUE, TRUE, 0 ); - AddDialogData( entry, m_strName ); - - entry.connect( "key_press_event", G_CALLBACK( OnDialogKey ), 0 ); - } - { - auto table = ui::Table( 5, 4, FALSE ); - table.show(); - vbox2.pack_start( table, TRUE, TRUE, 0 ); - gtk_table_set_row_spacings( table, 5 ); - gtk_table_set_col_spacings( table, 5 ); - { - auto label = ui::Label( "Horizontal Shift Step" ); - label.show(); + m_subdivisions.m_vertical = entry; + m_verticalSubdivisionsEntry.connect(entry); + } + } + } + } + } + { + auto frame = ui::Frame("Texturing"); + frame.show(); + hbox.pack_start(frame, TRUE, TRUE, 0); + { + auto vbox2 = ui::VBox(FALSE, 5); + vbox2.show(); + frame.add(vbox2); + gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); + { + auto label = ui::Label("Name:"); + label.show(); + vbox2.pack_start(label, TRUE, TRUE, 0); + gtk_label_set_justify(label, GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto entry = ui::Entry(ui::New); + // gtk_editable_set_editable (GTK_ENTRY (entry), false); + entry.show(); + vbox2.pack_start(entry, TRUE, TRUE, 0); + AddDialogData(entry, m_strName); + + entry.connect("key_press_event", G_CALLBACK(OnDialogKey), 0); + } + { + auto table = ui::Table(5, 4, FALSE); + table.show(); + vbox2.pack_start(table, TRUE, TRUE, 0); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + { + auto label = ui::Label("Horizontal Shift Step"); + label.show(); table.attach(label, {2, 4, 0, 1}, {GTK_FILL | GTK_EXPAND, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto label = ui::Label( "Vertical Shift Step" ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto label = ui::Label("Vertical Shift Step"); + label.show(); table.attach(label, {2, 4, 1, 2}, {GTK_FILL | GTK_EXPAND, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto label = ui::Label( "Horizontal Stretch Step" ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto label = ui::Label("Horizontal Stretch Step"); + label.show(); table.attach(label, {2, 3, 2, 3}, {GTK_FILL | GTK_EXPAND, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto button = ui::Button( "Flip" ); - button.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto button = ui::Button("Flip"); + button.show(); table.attach(button, {3, 4, 2, 3}, {GTK_FILL, 0}); - button.connect( "clicked", G_CALLBACK( OnBtnPatchFlipX ), 0 ); - button.dimensions(60, -1); - } - { - auto label = ui::Label( "Vertical Stretch Step" ); - label.show(); + button.connect("clicked", G_CALLBACK(OnBtnPatchFlipX), 0); + button.dimensions(60, -1); + } + { + auto label = ui::Label("Vertical Stretch Step"); + label.show(); table.attach(label, {2, 3, 3, 4}, {GTK_FILL | GTK_EXPAND, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto button = ui::Button( "Flip" ); - button.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto button = ui::Button("Flip"); + button.show(); table.attach(button, {3, 4, 3, 4}, {GTK_FILL, 0}); - button.connect( "clicked", G_CALLBACK( OnBtnPatchFlipY ), 0 ); - button.dimensions(60, -1); - } - { - auto label = ui::Label( "Rotate Step" ); - label.show(); + button.connect("clicked", G_CALLBACK(OnBtnPatchFlipY), 0); + button.dimensions(60, -1); + } + { + auto label = ui::Label("Rotate Step"); + label.show(); table.attach(label, {2, 4, 4, 5}, {GTK_FILL | GTK_EXPAND, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {0, 1, 0, 1}, {GTK_FILL, 0}); - entry.dimensions(50, -1); - g_object_set_data( G_OBJECT( window ), "hshift_entry", (void *) entry ); - // we fill in this data, if no patch is selected the widgets are unmodified when the inspector is raised - // so we need to have at least one initialisation somewhere - entry_set_float( entry, g_pi_globals.shift[0] ); - - auto adj = ui::Adjustment( 0, -8192, 8192, 1, 1, 0 ); - adj.connect( "value_changed", G_CALLBACK( OnSpinChanged ), (gpointer) entry ); - g_object_set_data( G_OBJECT( window ), "hshift_adj", (gpointer) adj ); - - auto spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); + entry.dimensions(50, -1); + g_object_set_data(G_OBJECT(window), "hshift_entry", (void *) entry); + // we fill in this data, if no patch is selected the widgets are unmodified when the inspector is raised + // so we need to have at least one initialisation somewhere + entry_set_float(entry, g_pi_globals.shift[0]); + + auto adj = ui::Adjustment(0, -8192, 8192, 1, 1, 0); + adj.connect("value_changed", G_CALLBACK(OnSpinChanged), (gpointer) entry); + g_object_set_data(G_OBJECT(window), "hshift_adj", (gpointer) adj); + + auto spin = ui::SpinButton(adj, 1, 0); + spin.show(); table.attach(spin, {1, 2, 0, 1}, {0, 0}); - spin.dimensions(10, -1); - gtk_widget_set_can_focus( spin, false ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + spin.dimensions(10, -1); + gtk_widget_set_can_focus(spin, false); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {0, 1, 1, 2}, {GTK_FILL, 0}); - entry.dimensions(50, -1); - entry_set_float( entry, g_pi_globals.shift[1] ); + entry.dimensions(50, -1); + entry_set_float(entry, g_pi_globals.shift[1]); - auto adj = ui::Adjustment( 0, -8192, 8192, 1, 1, 0 ); - adj.connect( "value_changed", G_CALLBACK( OnSpinChanged ), entry ); - g_object_set_data( G_OBJECT( window ), "vshift_adj", (gpointer) adj ); + auto adj = ui::Adjustment(0, -8192, 8192, 1, 1, 0); + adj.connect("value_changed", G_CALLBACK(OnSpinChanged), entry); + g_object_set_data(G_OBJECT(window), "vshift_adj", (gpointer) adj); - auto spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); + auto spin = ui::SpinButton(adj, 1, 0); + spin.show(); table.attach(spin, {1, 2, 1, 2}, {0, 0}); - spin.dimensions(10, -1); - gtk_widget_set_can_focus( spin, false ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + spin.dimensions(10, -1); + gtk_widget_set_can_focus(spin, false); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {0, 1, 2, 3}, {GTK_FILL, 0}); - entry.dimensions(50, -1); - entry_set_float( entry, g_pi_globals.scale[0] ); + entry.dimensions(50, -1); + entry_set_float(entry, g_pi_globals.scale[0]); - auto adj = ui::Adjustment( 0, -1000, 1000, 1, 1, 0 ); - adj.connect( "value_changed", G_CALLBACK( OnSpinChanged ), entry ); - g_object_set_data( G_OBJECT( window ), "hscale_adj", (gpointer) adj ); + auto adj = ui::Adjustment(0, -1000, 1000, 1, 1, 0); + adj.connect("value_changed", G_CALLBACK(OnSpinChanged), entry); + g_object_set_data(G_OBJECT(window), "hscale_adj", (gpointer) adj); - auto spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); + auto spin = ui::SpinButton(adj, 1, 0); + spin.show(); table.attach(spin, {1, 2, 2, 3}, {0, 0}); - spin.dimensions(10, -1); - gtk_widget_set_can_focus( spin, false ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + spin.dimensions(10, -1); + gtk_widget_set_can_focus(spin, false); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {0, 1, 3, 4}, {GTK_FILL, 0}); - entry.dimensions(50, -1); - entry_set_float( entry, g_pi_globals.scale[1] ); + entry.dimensions(50, -1); + entry_set_float(entry, g_pi_globals.scale[1]); - auto adj = ui::Adjustment( 0, -1000, 1000, 1, 1, 0 ); - adj.connect( "value_changed", G_CALLBACK( OnSpinChanged ), entry ); - g_object_set_data( G_OBJECT( window ), "vscale_adj", (gpointer) adj ); + auto adj = ui::Adjustment(0, -1000, 1000, 1, 1, 0); + adj.connect("value_changed", G_CALLBACK(OnSpinChanged), entry); + g_object_set_data(G_OBJECT(window), "vscale_adj", (gpointer) adj); - auto spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); + auto spin = ui::SpinButton(adj, 1, 0); + spin.show(); table.attach(spin, {1, 2, 3, 4}, {0, 0}); - spin.dimensions(10, -1); - gtk_widget_set_can_focus( spin, false ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + spin.dimensions(10, -1); + gtk_widget_set_can_focus(spin, false); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {0, 1, 4, 5}, {GTK_FILL, 0}); - entry.dimensions(50, -1); - entry_set_float( entry, g_pi_globals.rotate ); + entry.dimensions(50, -1); + entry_set_float(entry, g_pi_globals.rotate); - auto adj = ui::Adjustment( 0, -1000, 1000, 1, 1, 0 ); // NOTE: Arnout - this really should be 360 but can't change it anymore as it could break existing maps - adj.connect( "value_changed", G_CALLBACK( OnSpinChanged ), entry ); - g_object_set_data( G_OBJECT( window ), "rotate_adj", (gpointer) adj ); + auto adj = ui::Adjustment(0, -1000, 1000, 1, 1, + 0); // NOTE: Arnout - this really should be 360 but can't change it anymore as it could break existing maps + adj.connect("value_changed", G_CALLBACK(OnSpinChanged), entry); + g_object_set_data(G_OBJECT(window), "rotate_adj", (gpointer) adj); - auto spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); + auto spin = ui::SpinButton(adj, 1, 0); + spin.show(); table.attach(spin, {1, 2, 4, 5}, {0, 0}); - spin.dimensions(10, -1); - gtk_widget_set_can_focus( spin, false ); - } - } - auto hbox2 = ui::HBox( TRUE, 5 ); - hbox2.show(); - vbox2.pack_start( hbox2, TRUE, FALSE, 0 ); - { - auto button = ui::Button( "Auto Cap" ); - button.show(); - hbox2.pack_end(button, TRUE, FALSE, 0); - button.connect( "clicked", G_CALLBACK( OnBtnPatchAutoCap ), 0 ); - button.dimensions(60, -1); - } - { - auto button = ui::Button( "CAP" ); - button.show(); - hbox2.pack_end(button, TRUE, FALSE, 0); - button.connect( "clicked", G_CALLBACK( OnBtnPatchdetails ), 0 ); - button.dimensions(60, -1); - } - { - auto button = ui::Button( "Set..." ); - button.show(); - hbox2.pack_end(button, TRUE, FALSE, 0); - button.connect( "clicked", G_CALLBACK( OnBtnPatchreset ), 0 ); - button.dimensions(60, -1); - } - { - auto button = ui::Button( "Natural" ); - button.show(); - hbox2.pack_end(button, TRUE, FALSE, 0); - button.connect( "clicked", G_CALLBACK( OnBtnPatchnatural ), 0 ); - button.dimensions(60, -1); - } - { - auto button = ui::Button( "Fit" ); - button.show(); - hbox2.pack_end(button, TRUE, FALSE, 0); - button.connect( "clicked", G_CALLBACK( OnBtnPatchfit ), 0 ); - button.dimensions(60, -1); - } - } - } - } - } - - return window; + spin.dimensions(10, -1); + gtk_widget_set_can_focus(spin, false); + } + } + auto hbox2 = ui::HBox(TRUE, 5); + hbox2.show(); + vbox2.pack_start(hbox2, TRUE, FALSE, 0); + { + auto button = ui::Button("Auto Cap"); + button.show(); + hbox2.pack_end(button, TRUE, FALSE, 0); + button.connect("clicked", G_CALLBACK(OnBtnPatchAutoCap), 0); + button.dimensions(60, -1); + } + { + auto button = ui::Button("CAP"); + button.show(); + hbox2.pack_end(button, TRUE, FALSE, 0); + button.connect("clicked", G_CALLBACK(OnBtnPatchdetails), 0); + button.dimensions(60, -1); + } + { + auto button = ui::Button("Set..."); + button.show(); + hbox2.pack_end(button, TRUE, FALSE, 0); + button.connect("clicked", G_CALLBACK(OnBtnPatchreset), 0); + button.dimensions(60, -1); + } + { + auto button = ui::Button("Natural"); + button.show(); + hbox2.pack_end(button, TRUE, FALSE, 0); + button.connect("clicked", G_CALLBACK(OnBtnPatchnatural), 0); + button.dimensions(60, -1); + } + { + auto button = ui::Button("Fit"); + button.show(); + hbox2.pack_end(button, TRUE, FALSE, 0); + button.connect("clicked", G_CALLBACK(OnBtnPatchfit), 0); + button.dimensions(60, -1); + } + } + } + } + } + + return window; } // sync the dialog our internal data structures -void PatchInspector::exportData(){ - m_bListenChanged = false; - Dialog::exportData(); - m_bListenChanged = true; +void PatchInspector::exportData() +{ + m_bListenChanged = false; + Dialog::exportData(); + m_bListenChanged = true; } -void PatchInspector::importData(){ - m_bListenChanged = false; - Dialog::importData(); - m_bListenChanged = true; + +void PatchInspector::importData() +{ + m_bListenChanged = false; + Dialog::importData(); + m_bListenChanged = true; } // read the map and feed in the stuff to the dialog box -void PatchInspector::GetPatchInfo(){ - if ( g_pGameDescription->mGameType == "doom3" ) { - m_subdivisions.update(); - } - - if ( GlobalSelectionSystem().countSelected() == 0 ) { - m_Patch = 0; - } - else - { - m_Patch = Node_getPatch( GlobalSelectionSystem().ultimateSelected().path().top() ); - } - - if ( m_Patch != 0 ) { - m_strName = m_Patch->GetShader(); - - // fill in the numbers for Row / Col selection - m_bListenChanged = false; - - { - gtk_combo_box_set_active( m_pRowCombo, 0 ); - - for ( std::size_t i = 0; i < m_countRows; ++i ) - { - gtk_combo_box_text_remove( m_pRowCombo, gint( m_countRows - i - 1 ) ); - } - - m_countRows = m_Patch->getHeight(); - for ( std::size_t i = 0; i < m_countRows; ++i ) - { - char buffer[16]; - sprintf( buffer, "%u", Unsigned( i ) ); - gtk_combo_box_text_append_text( m_pRowCombo, buffer ); - } - - gtk_combo_box_set_active( m_pRowCombo, 0 ); - } - - { - gtk_combo_box_set_active( m_pColCombo, 0 ); - - for ( std::size_t i = 0; i < m_countCols; ++i ) - { - gtk_combo_box_text_remove( m_pColCombo, gint( m_countCols - i - 1 ) ); - } - - m_countCols = m_Patch->getWidth(); - for ( std::size_t i = 0; i < m_countCols; ++i ) - { - char buffer[16]; - sprintf( buffer, "%u", Unsigned( i ) ); - gtk_combo_box_text_append_text( m_pColCombo, buffer ); - } - - gtk_combo_box_set_active( m_pColCombo, 0 ); - } - - m_bListenChanged = true; - - } - else - { - //globalOutputStream() << "WARNING: no patch\n"; - } - // fill in our internal structs - m_nRow = 0; m_nCol = 0; - UpdateRowColInfo(); - // now update the dialog box - importData(); +void PatchInspector::GetPatchInfo() +{ + if (g_pGameDescription->mGameType == "doom3") { + m_subdivisions.update(); + } + + if (GlobalSelectionSystem().countSelected() == 0) { + m_Patch = 0; + } else { + m_Patch = Node_getPatch(GlobalSelectionSystem().ultimateSelected().path().top()); + } + + if (m_Patch != 0) { + m_strName = m_Patch->GetShader(); + + // fill in the numbers for Row / Col selection + m_bListenChanged = false; + + { + gtk_combo_box_set_active(m_pRowCombo, 0); + + for (std::size_t i = 0; i < m_countRows; ++i) { + gtk_combo_box_text_remove(m_pRowCombo, gint(m_countRows - i - 1)); + } + + m_countRows = m_Patch->getHeight(); + for (std::size_t i = 0; i < m_countRows; ++i) { + char buffer[16]; + sprintf(buffer, "%u", Unsigned(i)); + gtk_combo_box_text_append_text(m_pRowCombo, buffer); + } + + gtk_combo_box_set_active(m_pRowCombo, 0); + } + + { + gtk_combo_box_set_active(m_pColCombo, 0); + + for (std::size_t i = 0; i < m_countCols; ++i) { + gtk_combo_box_text_remove(m_pColCombo, gint(m_countCols - i - 1)); + } + + m_countCols = m_Patch->getWidth(); + for (std::size_t i = 0; i < m_countCols; ++i) { + char buffer[16]; + sprintf(buffer, "%u", Unsigned(i)); + gtk_combo_box_text_append_text(m_pColCombo, buffer); + } + + gtk_combo_box_set_active(m_pColCombo, 0); + } + + m_bListenChanged = true; + + } else { + //globalOutputStream() << "WARNING: no patch\n"; + } + // fill in our internal structs + m_nRow = 0; + m_nCol = 0; + UpdateRowColInfo(); + // now update the dialog box + importData(); } // read the current patch on map and initialize m_fX m_fY accordingly // NOTE: don't call UpdateData in there, it's not meant for -void PatchInspector::UpdateRowColInfo(){ - m_fX = m_fY = m_fZ = m_fS = m_fT = 0.0; - - if ( m_Patch != 0 ) { - // we rely on whatever active row/column has been set before we get called - std::size_t r = m_nRow; - std::size_t c = m_nCol; - if ( r < m_Patch->getHeight() - && c < m_Patch->getWidth() ) { - const PatchControl& p = m_Patch->ctrlAt( r,c ); - m_fX = p.m_vertex[0]; - m_fY = p.m_vertex[1]; - m_fZ = p.m_vertex[2]; - m_fS = p.m_texcoord[0]; - m_fT = p.m_texcoord[1]; - } - } +void PatchInspector::UpdateRowColInfo() +{ + m_fX = m_fY = m_fZ = m_fS = m_fT = 0.0; + + if (m_Patch != 0) { + // we rely on whatever active row/column has been set before we get called + std::size_t r = m_nRow; + std::size_t c = m_nCol; + if (r < m_Patch->getHeight() + && c < m_Patch->getWidth()) { + const PatchControl &p = m_Patch->ctrlAt(r, c); + m_fX = p.m_vertex[0]; + m_fY = p.m_vertex[1]; + m_fZ = p.m_vertex[2]; + m_fS = p.m_texcoord[0]; + m_fT = p.m_texcoord[1]; + } + } } -void PatchInspector_SelectionChanged( const Selectable& selectable ){ - PatchInspector_queueDraw(); +void PatchInspector_SelectionChanged(const Selectable &selectable) +{ + PatchInspector_queueDraw(); } #include "preferencesystem.h" -void PatchInspector_Construct(){ - GlobalCommands_insert( "PatchInspector", makeCallbackF(PatchInspector_toggleShown), Accelerator( 'S', (GdkModifierType)GDK_SHIFT_MASK ) ); - - GlobalPreferenceSystem().registerPreference( "PatchWnd", make_property( g_PatchInspector.m_position_tracker ) ); - GlobalPreferenceSystem().registerPreference( "SI_PatchTexdef_Scale1", make_property_string( g_pi_globals.scale[0] ) ); - GlobalPreferenceSystem().registerPreference( "SI_PatchTexdef_Scale2", make_property_string( g_pi_globals.scale[1] ) ); - GlobalPreferenceSystem().registerPreference( "SI_PatchTexdef_Shift1", make_property_string( g_pi_globals.shift[0] ) ); - GlobalPreferenceSystem().registerPreference( "SI_PatchTexdef_Shift2", make_property_string( g_pi_globals.shift[1] ) ); - GlobalPreferenceSystem().registerPreference( "SI_PatchTexdef_Rotate", make_property_string( g_pi_globals.rotate ) ); - - typedef FreeCaller PatchInspectorSelectionChangedCaller; - GlobalSelectionSystem().addSelectionChangeCallback( PatchInspectorSelectionChangedCaller() ); - typedef FreeCaller PatchInspectorQueueDrawCaller; - Patch_addTextureChangedCallback( PatchInspectorQueueDrawCaller() ); +void PatchInspector_Construct() +{ + GlobalCommands_insert("PatchInspector", makeCallbackF(PatchInspector_toggleShown), + Accelerator('S', (GdkModifierType) GDK_SHIFT_MASK)); + + GlobalPreferenceSystem().registerPreference("PatchWnd", make_property( + g_PatchInspector.m_position_tracker)); + GlobalPreferenceSystem().registerPreference("SI_PatchTexdef_Scale1", make_property_string(g_pi_globals.scale[0])); + GlobalPreferenceSystem().registerPreference("SI_PatchTexdef_Scale2", make_property_string(g_pi_globals.scale[1])); + GlobalPreferenceSystem().registerPreference("SI_PatchTexdef_Shift1", make_property_string(g_pi_globals.shift[0])); + GlobalPreferenceSystem().registerPreference("SI_PatchTexdef_Shift2", make_property_string(g_pi_globals.shift[1])); + GlobalPreferenceSystem().registerPreference("SI_PatchTexdef_Rotate", make_property_string(g_pi_globals.rotate)); + + typedef FreeCaller PatchInspectorSelectionChangedCaller; + GlobalSelectionSystem().addSelectionChangeCallback(PatchInspectorSelectionChangedCaller()); + typedef FreeCaller PatchInspectorQueueDrawCaller; + Patch_addTextureChangedCallback(PatchInspectorQueueDrawCaller()); } -void PatchInspector_Destroy(){ + +void PatchInspector_Destroy() +{ } diff --git a/radiant/patchdialog.h b/radiant/patchdialog.h index ca1f6c9e..692ccfe8 100644 --- a/radiant/patchdialog.h +++ b/radiant/patchdialog.h @@ -25,19 +25,22 @@ #define INCLUDED_PATCHDIALOG_H void PatchInspector_Construct(); + void PatchInspector_Destroy(); -void PatchInspector_constructWindow( ui::Window main_window ); +void PatchInspector_constructWindow(ui::Window main_window); + void PatchInspector_destroyWindow(); -namespace scene -{ -class Graph; +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 ); +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 diff --git a/radiant/patchmanip.cpp b/radiant/patchmanip.cpp index bd9d378b..4e30f212 100644 --- a/radiant/patchmanip.cpp +++ b/radiant/patchmanip.cpp @@ -47,957 +47,1066 @@ #include "patch.h" #include "grid.h" -PatchCreator* g_patchCreator = 0; - -void Scene_PatchConstructPrefab( scene::Graph& graph, const AABB aabb, const char* shader, EPatchPrefab eType, int axis, std::size_t width = 3, std::size_t height = 3 ){ - Select_Delete(); - GlobalSelectionSystem().setSelectedAll( false ); - - NodeSmartReference node( g_patchCreator->createPatch() ); - Node_getTraversable( Map_FindOrInsertWorldspawn( g_map ) )->insert( node ); - - Patch* patch = Node_getPatch( node ); - patch->SetShader( shader ); - - patch->ConstructPrefab( aabb, eType, axis, width, height ); - patch->controlPointsChanged(); - - { - scene::Path patchpath( makeReference( GlobalSceneGraph().root() ) ); - patchpath.push( makeReference( *Map_GetWorldspawn( g_map ) ) ); - patchpath.push( makeReference( node.get() ) ); - Instance_getSelectable( *graph.find( patchpath ) )->setSelected( true ); - } -} - -void PatchAutoCapTexture( Patch& patch ) { - - AABB box = patch.localAABB(); - float x = box.extents.x(); - float y = box.extents.y(); - float z = box.extents.z(); - - int cap_direction = -1; - if ( x < y && x < z ) - cap_direction = 0; - else if ( y < x && y < z ) - cap_direction = 1; - else if ( z < x && z < x ) - cap_direction = 2; - - if ( cap_direction >= 0 ) - patch.ProjectTexture(cap_direction); - else - patch.NaturalTexture(); -} - -void Patch_AutoCapTexture(){ - UndoableCommand command( "patchAutoCapTexture" ); - Scene_forEachVisibleSelectedPatch( &PatchAutoCapTexture ); - SceneChangeNotify(); -} - -void Patch_makeCaps( Patch& patch, scene::Instance& instance, EPatchCap type, const char* shader ){ - if ( ( type == eCapEndCap || type == eCapIEndCap ) - && patch.getWidth() != 5 ) { - globalErrorStream() << "cannot create end-cap - patch width != 5\n"; - return; - } - if ( ( type == eCapBevel || type == eCapIBevel ) - && patch.getWidth() != 3 && patch.getWidth() != 5 ) { - globalErrorStream() << "cannot create bevel-cap - patch width != 3\n"; - return; - } - if ( type == eCapCylinder - && patch.getWidth() != 9 ) { - globalErrorStream() << "cannot create cylinder-cap - patch width != 9\n"; - return; - } - - { - NodeSmartReference cap( g_patchCreator->createPatch() ); - Node_getTraversable( instance.path().parent() )->insert( cap ); - - Patch* cap_patch = Node_getPatch( cap ); - patch.MakeCap( cap_patch, type, ROW, true ); - cap_patch->SetShader( shader ); - PatchAutoCapTexture(*cap_patch); - - scene::Path path( instance.path() ); - path.pop(); - path.push( makeReference( cap.get() ) ); - selectPath( path, true ); - } - - { - NodeSmartReference cap( g_patchCreator->createPatch() ); - Node_getTraversable( instance.path().parent() )->insert( cap ); - - Patch* cap_patch = Node_getPatch( cap ); - patch.MakeCap( cap_patch, type, ROW, false ); - cap_patch->SetShader( shader ); - PatchAutoCapTexture(*cap_patch); - - scene::Path path( instance.path() ); - path.pop(); - path.push( makeReference( cap.get() ) ); - selectPath( path, true ); - } -} - -typedef std::vector InstanceVector; +PatchCreator *g_patchCreator = 0; -enum ECapDialog { - PATCHCAP_BEVEL = 0, - PATCHCAP_ENDCAP, - PATCHCAP_INVERTED_BEVEL, - PATCHCAP_INVERTED_ENDCAP, - PATCHCAP_CYLINDER -}; +void Scene_PatchConstructPrefab(scene::Graph &graph, const AABB aabb, const char *shader, EPatchPrefab eType, int axis, + std::size_t width = 3, std::size_t height = 3) +{ + Select_Delete(); + GlobalSelectionSystem().setSelectedAll(false); + + NodeSmartReference node(g_patchCreator->createPatch()); + Node_getTraversable(Map_FindOrInsertWorldspawn(g_map))->insert(node); + + Patch *patch = Node_getPatch(node); + patch->SetShader(shader); + + patch->ConstructPrefab(aabb, eType, axis, width, height); + patch->controlPointsChanged(); -EMessageBoxReturn DoCapDlg( ECapDialog *type ); + { + scene::Path patchpath(makeReference(GlobalSceneGraph().root())); + patchpath.push(makeReference(*Map_GetWorldspawn(g_map))); + patchpath.push(makeReference(node.get())); + Instance_getSelectable(*graph.find(patchpath))->setSelected(true); + } +} + +void PatchAutoCapTexture(Patch &patch) +{ -void Scene_PatchDoCap_Selected( scene::Graph& graph, const char* shader ){ - ECapDialog nType; + AABB box = patch.localAABB(); + float x = box.extents.x(); + float y = box.extents.y(); + float z = box.extents.z(); - if ( DoCapDlg( &nType ) == eIDOK ) { - EPatchCap eType; - switch ( nType ) - { - case PATCHCAP_INVERTED_BEVEL: - eType = eCapIBevel; - break; - case PATCHCAP_BEVEL: - eType = eCapBevel; - break; - case PATCHCAP_INVERTED_ENDCAP: - eType = eCapIEndCap; - break; - case PATCHCAP_ENDCAP: - eType = eCapEndCap; - break; - case PATCHCAP_CYLINDER: - eType = eCapCylinder; - break; - default: - ERROR_MESSAGE( "invalid patch cap type" ); - return; - } + int cap_direction = -1; + if (x < y && x < z) { + cap_direction = 0; + } else if (y < x && y < z) { + cap_direction = 1; + } else if (z < x && z < x) { + cap_direction = 2; + } - InstanceVector instances; - Scene_forEachVisibleSelectedPatchInstance([&](PatchInstance &patch) { - instances.push_back(&patch); - }); - for ( InstanceVector::const_iterator i = instances.begin(); i != instances.end(); ++i ) - { - Patch_makeCaps( *Node_getPatch( ( *i )->path().top() ), *( *i ), eType, shader ); - } - } + if (cap_direction >= 0) { + patch.ProjectTexture(cap_direction); + } else { + patch.NaturalTexture(); + } +} + +void Patch_AutoCapTexture() +{ + UndoableCommand command("patchAutoCapTexture"); + Scene_forEachVisibleSelectedPatch(&PatchAutoCapTexture); + SceneChangeNotify(); } -Patch* Scene_GetUltimateSelectedVisiblePatch(){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - scene::Node& node = GlobalSelectionSystem().ultimateSelected().path().top(); - if ( node.visible() ) { - return Node_getPatch( node ); - } - } - return 0; +void Patch_makeCaps(Patch &patch, scene::Instance &instance, EPatchCap type, const char *shader) +{ + if ((type == eCapEndCap || type == eCapIEndCap) + && patch.getWidth() != 5) { + globalErrorStream() << "cannot create end-cap - patch width != 5\n"; + return; + } + if ((type == eCapBevel || type == eCapIBevel) + && patch.getWidth() != 3 && patch.getWidth() != 5) { + globalErrorStream() << "cannot create bevel-cap - patch width != 3\n"; + return; + } + if (type == eCapCylinder + && patch.getWidth() != 9) { + globalErrorStream() << "cannot create cylinder-cap - patch width != 9\n"; + return; + } + + { + NodeSmartReference cap(g_patchCreator->createPatch()); + Node_getTraversable(instance.path().parent())->insert(cap); + + Patch *cap_patch = Node_getPatch(cap); + patch.MakeCap(cap_patch, type, ROW, true); + cap_patch->SetShader(shader); + PatchAutoCapTexture(*cap_patch); + + scene::Path path(instance.path()); + path.pop(); + path.push(makeReference(cap.get())); + selectPath(path, true); + } + + { + NodeSmartReference cap(g_patchCreator->createPatch()); + Node_getTraversable(instance.path().parent())->insert(cap); + + Patch *cap_patch = Node_getPatch(cap); + patch.MakeCap(cap_patch, type, ROW, false); + cap_patch->SetShader(shader); + PatchAutoCapTexture(*cap_patch); + + scene::Path path(instance.path()); + path.pop(); + path.push(makeReference(cap.get())); + selectPath(path, true); + } +} + +typedef std::vector InstanceVector; + +enum ECapDialog { + PATCHCAP_BEVEL = 0, + PATCHCAP_ENDCAP, + PATCHCAP_INVERTED_BEVEL, + PATCHCAP_INVERTED_ENDCAP, + PATCHCAP_CYLINDER +}; + +EMessageBoxReturn DoCapDlg(ECapDialog *type); + +void Scene_PatchDoCap_Selected(scene::Graph &graph, const char *shader) +{ + ECapDialog nType; + + if (DoCapDlg(&nType) == eIDOK) { + EPatchCap eType; + switch (nType) { + case PATCHCAP_INVERTED_BEVEL: + eType = eCapIBevel; + break; + case PATCHCAP_BEVEL: + eType = eCapBevel; + break; + case PATCHCAP_INVERTED_ENDCAP: + eType = eCapIEndCap; + break; + case PATCHCAP_ENDCAP: + eType = eCapEndCap; + break; + case PATCHCAP_CYLINDER: + eType = eCapCylinder; + break; + default: + ERROR_MESSAGE("invalid patch cap type"); + return; + } + + InstanceVector instances; + Scene_forEachVisibleSelectedPatchInstance([&](PatchInstance &patch) { + instances.push_back(&patch); + }); + for (InstanceVector::const_iterator i = instances.begin(); i != instances.end(); ++i) { + Patch_makeCaps(*Node_getPatch((*i)->path().top()), *(*i), eType, shader); + } + } +} + +Patch *Scene_GetUltimateSelectedVisiblePatch() +{ + if (GlobalSelectionSystem().countSelected() != 0) { + scene::Node &node = GlobalSelectionSystem().ultimateSelected().path().top(); + if (node.visible()) { + return Node_getPatch(node); + } + } + return 0; } -void Scene_PatchCapTexture_Selected( scene::Graph& graph ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.ProjectTexture(Patch::m_CycleCapIndex); - }); - Patch::m_CycleCapIndex = ( Patch::m_CycleCapIndex == 0 ) ? 1 : ( Patch::m_CycleCapIndex == 1 ) ? 2 : 0; - SceneChangeNotify(); +void Scene_PatchCapTexture_Selected(scene::Graph &graph) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.ProjectTexture(Patch::m_CycleCapIndex); + }); + Patch::m_CycleCapIndex = (Patch::m_CycleCapIndex == 0) ? 1 : (Patch::m_CycleCapIndex == 1) ? 2 : 0; + SceneChangeNotify(); } -void Scene_PatchFlipTexture_Selected( scene::Graph& graph, int axis ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.FlipTexture(axis); - }); +void Scene_PatchFlipTexture_Selected(scene::Graph &graph, int axis) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.FlipTexture(axis); + }); } -void Scene_PatchNaturalTexture_Selected( scene::Graph& graph ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.NaturalTexture(); - }); - SceneChangeNotify(); +void Scene_PatchNaturalTexture_Selected(scene::Graph &graph) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.NaturalTexture(); + }); + SceneChangeNotify(); } -void Scene_PatchInsertRemove_Selected( scene::Graph& graph, bool bInsert, bool bColumn, bool bFirst ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.InsertRemove(bInsert, bColumn, bFirst); - }); +void Scene_PatchInsertRemove_Selected(scene::Graph &graph, bool bInsert, bool bColumn, bool bFirst) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.InsertRemove(bInsert, bColumn, bFirst); + }); } -void Scene_PatchInvert_Selected( scene::Graph& graph ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.InvertMatrix(); - }); +void Scene_PatchInvert_Selected(scene::Graph &graph) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.InvertMatrix(); + }); } -void Scene_PatchRedisperse_Selected( scene::Graph& graph, EMatrixMajor major ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.Redisperse(major); - }); +void Scene_PatchRedisperse_Selected(scene::Graph &graph, EMatrixMajor major) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.Redisperse(major); + }); } -void Scene_PatchSmooth_Selected( scene::Graph& graph, EMatrixMajor major ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.Smooth(major); - }); +void Scene_PatchSmooth_Selected(scene::Graph &graph, EMatrixMajor major) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.Smooth(major); + }); } -void Scene_PatchTranspose_Selected( scene::Graph& graph ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.TransposeMatrix(); - }); +void Scene_PatchTranspose_Selected(scene::Graph &graph) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.TransposeMatrix(); + }); } -void Scene_PatchSetShader_Selected( scene::Graph& graph, const char* name ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - patch.SetShader(name); - }); - SceneChangeNotify(); +void Scene_PatchSetShader_Selected(scene::Graph &graph, const char *name) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + patch.SetShader(name); + }); + SceneChangeNotify(); } -void Scene_PatchGetShader_Selected( scene::Graph& graph, CopiedString& name ){ - Patch* patch = Scene_GetUltimateSelectedVisiblePatch(); - if ( patch != 0 ) { - name = patch->GetShader(); - } +void Scene_PatchGetShader_Selected(scene::Graph &graph, CopiedString &name) +{ + Patch *patch = Scene_GetUltimateSelectedVisiblePatch(); + if (patch != 0) { + name = patch->GetShader(); + } } -void Scene_PatchSelectByShader( scene::Graph& graph, const char* name ){ - Scene_forEachVisiblePatchInstance([&](PatchInstance &patch) { - if (shader_equal(patch.getPatch().GetShader(), name)) { - patch.setSelected(true); - } - }); +void Scene_PatchSelectByShader(scene::Graph &graph, const char *name) +{ + Scene_forEachVisiblePatchInstance([&](PatchInstance &patch) { + if (shader_equal(patch.getPatch().GetShader(), name)) { + patch.setSelected(true); + } + }); } -void Scene_PatchFindReplaceShader( scene::Graph& graph, const char* find, const char* replace ){ - Scene_forEachVisiblePatch([&](Patch &patch) { - if (shader_equal(patch.GetShader(), find)) { - patch.SetShader(replace); - } - }); +void Scene_PatchFindReplaceShader(scene::Graph &graph, const char *find, const char *replace) +{ + Scene_forEachVisiblePatch([&](Patch &patch) { + if (shader_equal(patch.GetShader(), find)) { + patch.SetShader(replace); + } + }); } -void Scene_PatchFindReplaceShader_Selected( scene::Graph& graph, const char* find, const char* replace ){ - Scene_forEachVisibleSelectedPatch([&](Patch &patch) { - if (shader_equal(patch.GetShader(), find)) { - patch.SetShader(replace); - } - }); +void Scene_PatchFindReplaceShader_Selected(scene::Graph &graph, const char *find, const char *replace) +{ + Scene_forEachVisibleSelectedPatch([&](Patch &patch) { + if (shader_equal(patch.GetShader(), find)) { + patch.SetShader(replace); + } + }); } -AABB PatchCreator_getBounds(){ - AABB aabb( aabb_for_minmax( Select_getWorkZone().d_work_min, Select_getWorkZone().d_work_max ) ); +AABB PatchCreator_getBounds() +{ + AABB aabb(aabb_for_minmax(Select_getWorkZone().d_work_min, Select_getWorkZone().d_work_max)); - float gridSize = GetGridSize(); + float gridSize = GetGridSize(); - if ( aabb.extents[0] == 0 ) { - aabb.extents[0] = gridSize; - } - if ( aabb.extents[1] == 0 ) { - aabb.extents[1] = gridSize; - } - if ( aabb.extents[2] == 0 ) { - aabb.extents[2] = gridSize; - } + if (aabb.extents[0] == 0) { + aabb.extents[0] = gridSize; + } + if (aabb.extents[1] == 0) { + aabb.extents[1] = gridSize; + } + if (aabb.extents[2] == 0) { + aabb.extents[2] = gridSize; + } - if ( aabb_valid( aabb ) ) { - return aabb; - } - return AABB( Vector3( 0, 0, 0 ), Vector3( 64, 64, 64 ) ); + if (aabb_valid(aabb)) { + return aabb; + } + return AABB(Vector3(0, 0, 0), Vector3(64, 64, 64)); } -void DoNewPatchDlg( EPatchPrefab prefab, int minrows, int mincols, int defrows, int defcols, int maxrows, int maxcols ); +void DoNewPatchDlg(EPatchPrefab prefab, int minrows, int mincols, int defrows, int defcols, int maxrows, int maxcols); -void Patch_XactCylinder(){ - UndoableCommand undo( "patchCreateXactCylinder" ); +void Patch_XactCylinder() +{ + UndoableCommand undo("patchCreateXactCylinder"); - DoNewPatchDlg( eXactCylinder, 3, 7, 3, 13, 0, 0 ); + DoNewPatchDlg(eXactCylinder, 3, 7, 3, 13, 0, 0); } -void Patch_XactSphere(){ - UndoableCommand undo( "patchCreateXactSphere" ); +void Patch_XactSphere() +{ + UndoableCommand undo("patchCreateXactSphere"); - DoNewPatchDlg( eXactSphere, 5, 7, 7, 13, 0, 0 ); + DoNewPatchDlg(eXactSphere, 5, 7, 7, 13, 0, 0); } -void Patch_XactCone(){ - UndoableCommand undo( "patchCreateXactCone" ); +void Patch_XactCone() +{ + UndoableCommand undo("patchCreateXactCone"); - DoNewPatchDlg( eXactCone, 3, 7, 3, 13, 0, 0 ); + DoNewPatchDlg(eXactCone, 3, 7, 3, 13, 0, 0); } -void Patch_Cylinder(){ - UndoableCommand undo( "patchCreateCylinder" ); +void Patch_Cylinder() +{ + UndoableCommand undo("patchCreateCylinder"); - Scene_PatchConstructPrefab( GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), eCylinder, GlobalXYWnd_getCurrentViewType() ); + Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eCylinder, + GlobalXYWnd_getCurrentViewType()); } -void Patch_DenseCylinder(){ - UndoableCommand undo( "patchCreateDenseCylinder" ); +void Patch_DenseCylinder() +{ + UndoableCommand undo("patchCreateDenseCylinder"); - Scene_PatchConstructPrefab( GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), eDenseCylinder, GlobalXYWnd_getCurrentViewType() ); + Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eDenseCylinder, + GlobalXYWnd_getCurrentViewType()); } -void Patch_VeryDenseCylinder(){ - UndoableCommand undo( "patchCreateVeryDenseCylinder" ); +void Patch_VeryDenseCylinder() +{ + UndoableCommand undo("patchCreateVeryDenseCylinder"); - Scene_PatchConstructPrefab( GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), eVeryDenseCylinder, GlobalXYWnd_getCurrentViewType() ); + Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eVeryDenseCylinder, + GlobalXYWnd_getCurrentViewType()); } -void Patch_SquareCylinder(){ - UndoableCommand undo( "patchCreateSquareCylinder" ); +void Patch_SquareCylinder() +{ + UndoableCommand undo("patchCreateSquareCylinder"); - Scene_PatchConstructPrefab( GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), eSqCylinder, GlobalXYWnd_getCurrentViewType() ); + Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eSqCylinder, + GlobalXYWnd_getCurrentViewType()); } -void Patch_Endcap(){ - UndoableCommand undo( "patchCreateCaps" ); +void Patch_Endcap() +{ + UndoableCommand undo("patchCreateCaps"); - Scene_PatchConstructPrefab( GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), eEndCap, GlobalXYWnd_getCurrentViewType() ); + Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eEndCap, + GlobalXYWnd_getCurrentViewType()); } -void Patch_Bevel(){ - UndoableCommand undo( "patchCreateBevel" ); +void Patch_Bevel() +{ + UndoableCommand undo("patchCreateBevel"); - Scene_PatchConstructPrefab( GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), eBevel, GlobalXYWnd_getCurrentViewType() ); + Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eBevel, + GlobalXYWnd_getCurrentViewType()); } -void Patch_Sphere(){ - UndoableCommand undo( "patchCreateSphere" ); +void Patch_Sphere() +{ + UndoableCommand undo("patchCreateSphere"); - Scene_PatchConstructPrefab( GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), eSphere, GlobalXYWnd_getCurrentViewType() ); + Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eSphere, + GlobalXYWnd_getCurrentViewType()); } -void Patch_SquareBevel(){ +void Patch_SquareBevel() +{ } -void Patch_SquareEndcap(){ +void Patch_SquareEndcap() +{ } -void Patch_Cone(){ - UndoableCommand undo( "patchCreateCone" ); +void Patch_Cone() +{ + UndoableCommand undo("patchCreateCone"); - Scene_PatchConstructPrefab( GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), eCone, GlobalXYWnd_getCurrentViewType() ); + Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eCone, + GlobalXYWnd_getCurrentViewType()); } -void Patch_Plane(){ - UndoableCommand undo( "patchCreatePlane" ); +void Patch_Plane() +{ + UndoableCommand undo("patchCreatePlane"); - DoNewPatchDlg( ePlane, 3, 3, 3, 3, 0, 0 ); + DoNewPatchDlg(ePlane, 3, 3, 3, 3, 0, 0); } -void Patch_InsertInsertColumn(){ - UndoableCommand undo( "patchInsertColumns" ); +void Patch_InsertInsertColumn() +{ + UndoableCommand undo("patchInsertColumns"); - Scene_PatchInsertRemove_Selected( GlobalSceneGraph(), true, true, false ); + Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), true, true, false); } -void Patch_InsertAddColumn(){ - UndoableCommand undo( "patchAddColumns" ); +void Patch_InsertAddColumn() +{ + UndoableCommand undo("patchAddColumns"); - Scene_PatchInsertRemove_Selected( GlobalSceneGraph(), true, true, true ); + Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), true, true, true); } -void Patch_InsertInsertRow(){ - UndoableCommand undo( "patchInsertRows" ); +void Patch_InsertInsertRow() +{ + UndoableCommand undo("patchInsertRows"); - Scene_PatchInsertRemove_Selected( GlobalSceneGraph(), true, false, false ); + Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), true, false, false); } -void Patch_InsertAddRow(){ - UndoableCommand undo( "patchAddRows" ); +void Patch_InsertAddRow() +{ + UndoableCommand undo("patchAddRows"); - Scene_PatchInsertRemove_Selected( GlobalSceneGraph(), true, false, true ); + Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), true, false, true); } -void Patch_DeleteFirstColumn(){ - UndoableCommand undo( "patchDeleteFirstColumns" ); +void Patch_DeleteFirstColumn() +{ + UndoableCommand undo("patchDeleteFirstColumns"); - Scene_PatchInsertRemove_Selected( GlobalSceneGraph(), false, true, true ); + Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), false, true, true); } -void Patch_DeleteLastColumn(){ - UndoableCommand undo( "patchDeleteLastColumns" ); +void Patch_DeleteLastColumn() +{ + UndoableCommand undo("patchDeleteLastColumns"); - Scene_PatchInsertRemove_Selected( GlobalSceneGraph(), false, true, false ); + Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), false, true, false); } -void Patch_DeleteFirstRow(){ - UndoableCommand undo( "patchDeleteFirstRows" ); +void Patch_DeleteFirstRow() +{ + UndoableCommand undo("patchDeleteFirstRows"); - Scene_PatchInsertRemove_Selected( GlobalSceneGraph(), false, false, true ); + Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), false, false, true); } -void Patch_DeleteLastRow(){ - UndoableCommand undo( "patchDeleteLastRows" ); +void Patch_DeleteLastRow() +{ + UndoableCommand undo("patchDeleteLastRows"); - Scene_PatchInsertRemove_Selected( GlobalSceneGraph(), false, false, false ); + Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), false, false, false); } -void Patch_Invert(){ - UndoableCommand undo( "patchInvert" ); +void Patch_Invert() +{ + UndoableCommand undo("patchInvert"); - Scene_PatchInvert_Selected( GlobalSceneGraph() ); + Scene_PatchInvert_Selected(GlobalSceneGraph()); } -void Patch_RedisperseRows(){ - UndoableCommand undo( "patchRedisperseRows" ); +void Patch_RedisperseRows() +{ + UndoableCommand undo("patchRedisperseRows"); - Scene_PatchRedisperse_Selected( GlobalSceneGraph(), ROW ); + Scene_PatchRedisperse_Selected(GlobalSceneGraph(), ROW); } -void Patch_RedisperseCols(){ - UndoableCommand undo( "patchRedisperseColumns" ); +void Patch_RedisperseCols() +{ + UndoableCommand undo("patchRedisperseColumns"); - Scene_PatchRedisperse_Selected( GlobalSceneGraph(), COL ); + Scene_PatchRedisperse_Selected(GlobalSceneGraph(), COL); } -void Patch_SmoothRows(){ - UndoableCommand undo( "patchSmoothRows" ); +void Patch_SmoothRows() +{ + UndoableCommand undo("patchSmoothRows"); - Scene_PatchSmooth_Selected( GlobalSceneGraph(), ROW ); + Scene_PatchSmooth_Selected(GlobalSceneGraph(), ROW); } -void Patch_SmoothCols(){ - UndoableCommand undo( "patchSmoothColumns" ); +void Patch_SmoothCols() +{ + UndoableCommand undo("patchSmoothColumns"); - Scene_PatchSmooth_Selected( GlobalSceneGraph(), COL ); + Scene_PatchSmooth_Selected(GlobalSceneGraph(), COL); } -void Patch_Transpose(){ - UndoableCommand undo( "patchTranspose" ); +void Patch_Transpose() +{ + UndoableCommand undo("patchTranspose"); - Scene_PatchTranspose_Selected( GlobalSceneGraph() ); + Scene_PatchTranspose_Selected(GlobalSceneGraph()); } -void Patch_Cap(){ - // FIXME: add support for patch cap creation - // Patch_CapCurrent(); - UndoableCommand undo( "patchCreateCaps" ); +void Patch_Cap() +{ + // FIXME: add support for patch cap creation + // Patch_CapCurrent(); + UndoableCommand undo("patchCreateCaps"); - Scene_PatchDoCap_Selected( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); + Scene_PatchDoCap_Selected(GlobalSceneGraph(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); } -void Patch_CycleProjection(){ - UndoableCommand undo( "patchCycleUVProjectionAxis" ); +void Patch_CycleProjection() +{ + UndoableCommand undo("patchCycleUVProjectionAxis"); - Scene_PatchCapTexture_Selected( GlobalSceneGraph() ); + Scene_PatchCapTexture_Selected(GlobalSceneGraph()); } ///\todo Unfinished. -void Patch_OverlayOn(){ +void Patch_OverlayOn() +{ } ///\todo Unfinished. -void Patch_OverlayOff(){ +void Patch_OverlayOff() +{ } -void Patch_FlipTextureX(){ - UndoableCommand undo( "patchFlipTextureU" ); +void Patch_FlipTextureX() +{ + UndoableCommand undo("patchFlipTextureU"); - Scene_PatchFlipTexture_Selected( GlobalSceneGraph(), 0 ); + Scene_PatchFlipTexture_Selected(GlobalSceneGraph(), 0); } -void Patch_FlipTextureY(){ - UndoableCommand undo( "patchFlipTextureV" ); +void Patch_FlipTextureY() +{ + UndoableCommand undo("patchFlipTextureV"); - Scene_PatchFlipTexture_Selected( GlobalSceneGraph(), 1 ); + Scene_PatchFlipTexture_Selected(GlobalSceneGraph(), 1); } -void Patch_NaturalTexture(){ - UndoableCommand undo( "patchNaturalTexture" ); +void Patch_NaturalTexture() +{ + UndoableCommand undo("patchNaturalTexture"); - Scene_PatchNaturalTexture_Selected( GlobalSceneGraph() ); + Scene_PatchNaturalTexture_Selected(GlobalSceneGraph()); } -void Patch_CapTexture(){ - UndoableCommand command( "patchCapTexture" ); +void Patch_CapTexture() +{ + UndoableCommand command("patchCapTexture"); - Scene_PatchCapTexture_Selected( GlobalSceneGraph() ); + Scene_PatchCapTexture_Selected(GlobalSceneGraph()); } -void Patch_ResetTexture(){ - float fx, fy; - if ( DoTextureLayout( &fx, &fy ) == eIDOK ) { - UndoableCommand command( "patchTileTexture" ); - Scene_PatchTileTexture_Selected( GlobalSceneGraph(), fx, fy ); - } +void Patch_ResetTexture() +{ + float fx, fy; + if (DoTextureLayout(&fx, &fy) == eIDOK) { + UndoableCommand command("patchTileTexture"); + Scene_PatchTileTexture_Selected(GlobalSceneGraph(), fx, fy); + } } -void Patch_FitTexture(){ - UndoableCommand command( "patchFitTexture" ); +void Patch_FitTexture() +{ + UndoableCommand command("patchFitTexture"); - Scene_PatchTileTexture_Selected( GlobalSceneGraph(), 1, 1 ); + Scene_PatchTileTexture_Selected(GlobalSceneGraph(), 1, 1); } #include "ifilter.h" -class filter_patch_all : public PatchFilter -{ +class filter_patch_all : public PatchFilter { public: -bool filter( const Patch& patch ) const { - return true; -} + bool filter(const Patch &patch) const + { + return true; + } }; -class filter_patch_shader : public PatchFilter -{ -const char* m_shader; +class filter_patch_shader : public PatchFilter { + const char *m_shader; public: -filter_patch_shader( const char* shader ) : m_shader( shader ){ -} -bool filter( const Patch& patch ) const { - return shader_equal( patch.GetShader(), m_shader ); -} + filter_patch_shader(const char *shader) : m_shader(shader) + { + } + + bool filter(const Patch &patch) const + { + return shader_equal(patch.GetShader(), m_shader); + } }; -class filter_patch_flags : public PatchFilter -{ -int m_flags; +class filter_patch_flags : public PatchFilter { + int m_flags; public: -filter_patch_flags( int flags ) : m_flags( flags ){ -} -bool filter( const Patch& patch ) const { - return ( patch.getShaderFlags() & m_flags ) != 0; -} + filter_patch_flags(int flags) : m_flags(flags) + { + } + + bool filter(const Patch &patch) const + { + return (patch.getShaderFlags() & m_flags) != 0; + } }; filter_patch_all g_filter_patch_all; -filter_patch_shader g_filter_patch_clip( "textures/common/clip" ); -filter_patch_shader g_filter_patch_weapclip( "textures/common/weapclip" ); -filter_patch_flags g_filter_patch_translucent( QER_TRANS ); +filter_patch_shader g_filter_patch_clip("textures/common/clip"); +filter_patch_shader g_filter_patch_weapclip("textures/common/weapclip"); +filter_patch_flags g_filter_patch_translucent(QER_TRANS); -void PatchFilters_construct(){ - add_patch_filter( g_filter_patch_all, EXCLUDE_CURVES ); - add_patch_filter( g_filter_patch_clip, EXCLUDE_CLIP ); - add_patch_filter( g_filter_patch_weapclip, EXCLUDE_CLIP ); - add_patch_filter( g_filter_patch_translucent, EXCLUDE_TRANSLUCENT ); +void PatchFilters_construct() +{ + add_patch_filter(g_filter_patch_all, EXCLUDE_CURVES); + add_patch_filter(g_filter_patch_clip, EXCLUDE_CLIP); + add_patch_filter(g_filter_patch_weapclip, EXCLUDE_CLIP); + add_patch_filter(g_filter_patch_translucent, EXCLUDE_TRANSLUCENT); } #include "preferences.h" -void Patch_constructPreferences( PreferencesPage& page ){ - page.appendEntry( "Patch Subdivide Threshold", g_PatchSubdivideThreshold ); +void Patch_constructPreferences(PreferencesPage &page) +{ + page.appendEntry("Patch Subdivide Threshold", g_PatchSubdivideThreshold); } -void Patch_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Patches", "Patch Display Preferences" ) ); - Patch_constructPreferences( page ); + +void Patch_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Patches", "Patch Display Preferences")); + Patch_constructPreferences(page); } -void Patch_registerPreferencesPage(){ - PreferencesDialog_addDisplayPage( makeCallbackF(Patch_constructPage) ); + +void Patch_registerPreferencesPage() +{ + PreferencesDialog_addDisplayPage(makeCallbackF(Patch_constructPage)); } #include "preferencesystem.h" -void PatchPreferences_construct(){ - GlobalPreferenceSystem().registerPreference( "Subdivisions", make_property_string( g_PatchSubdivideThreshold ) ); +void PatchPreferences_construct() +{ + GlobalPreferenceSystem().registerPreference("Subdivisions", make_property_string(g_PatchSubdivideThreshold)); } #include "generic/callback.h" -void Patch_registerCommands(){ - GlobalCommands_insert( "InvertCurveTextureX", makeCallbackF(Patch_FlipTextureX), Accelerator( 'I', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "InvertCurveTextureY", makeCallbackF(Patch_FlipTextureY), Accelerator( 'I', (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "NaturalizePatch", makeCallbackF(Patch_NaturalTexture), Accelerator( 'N', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "PatchCylinder", makeCallbackF(Patch_Cylinder) ); - GlobalCommands_insert( "PatchDenseCylinder", makeCallbackF(Patch_DenseCylinder) ); - GlobalCommands_insert( "PatchVeryDenseCylinder", makeCallbackF(Patch_VeryDenseCylinder) ); - GlobalCommands_insert( "PatchSquareCylinder", makeCallbackF(Patch_SquareCylinder) ); - GlobalCommands_insert( "PatchXactCylinder", makeCallbackF(Patch_XactCylinder) ); - GlobalCommands_insert( "PatchXactSphere", makeCallbackF(Patch_XactSphere) ); - GlobalCommands_insert( "PatchXactCone", makeCallbackF(Patch_XactCone) ); - GlobalCommands_insert( "PatchEndCap", makeCallbackF(Patch_Endcap) ); - GlobalCommands_insert( "PatchBevel", makeCallbackF(Patch_Bevel) ); - GlobalCommands_insert( "PatchSquareBevel", makeCallbackF(Patch_SquareBevel) ); - GlobalCommands_insert( "PatchSquareEndcap", makeCallbackF(Patch_SquareEndcap) ); - GlobalCommands_insert( "PatchCone", makeCallbackF(Patch_Cone) ); - GlobalCommands_insert( "PatchSphere", makeCallbackF(Patch_Sphere) ); - GlobalCommands_insert( "SimplePatchMesh", makeCallbackF(Patch_Plane), Accelerator( 'P', (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "PatchInsertInsertColumn", makeCallbackF(Patch_InsertInsertColumn), Accelerator( GDK_KEY_KP_Add, (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "PatchInsertAddColumn", makeCallbackF(Patch_InsertAddColumn) ); - GlobalCommands_insert( "PatchInsertInsertRow", makeCallbackF(Patch_InsertInsertRow), Accelerator( GDK_KEY_KP_Add, (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "PatchInsertAddRow", makeCallbackF(Patch_InsertAddRow) ); - GlobalCommands_insert( "PatchDeleteFirstColumn", makeCallbackF(Patch_DeleteFirstColumn) ); - GlobalCommands_insert( "PatchDeleteLastColumn", makeCallbackF(Patch_DeleteLastColumn), Accelerator( GDK_KEY_KP_Subtract, (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "PatchDeleteFirstRow", makeCallbackF(Patch_DeleteFirstRow), Accelerator( GDK_KEY_KP_Subtract, (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "PatchDeleteLastRow", makeCallbackF(Patch_DeleteLastRow) ); - GlobalCommands_insert( "InvertCurve", makeCallbackF(Patch_Invert), Accelerator( 'I', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "RedisperseRows", makeCallbackF(Patch_RedisperseRows), Accelerator( 'E', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "RedisperseCols", makeCallbackF(Patch_RedisperseCols), Accelerator( 'E', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "SmoothRows", makeCallbackF(Patch_SmoothRows), Accelerator( 'W', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "SmoothCols", makeCallbackF(Patch_SmoothCols), Accelerator( 'W', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "MatrixTranspose", makeCallbackF(Patch_Transpose), Accelerator( 'M', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "CapCurrentCurve", makeCallbackF(Patch_Cap), Accelerator( 'C', (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "CycleCapTexturePatch", makeCallbackF(Patch_CycleProjection), Accelerator( 'N', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "MakeOverlayPatch", makeCallbackF(Patch_OverlayOn), Accelerator( 'Y' ) ); - GlobalCommands_insert( "ClearPatchOverlays", makeCallbackF(Patch_OverlayOff), Accelerator( 'L', (GdkModifierType)GDK_CONTROL_MASK ) ); -} - -void Patch_constructToolbar( ui::Toolbar toolbar ){ - toolbar_append_button( toolbar, "Put caps on the current patch (SHIFT + C)", "cap_curve.png", "CapCurrentCurve" ); -} - -void Patch_constructMenu( ui::Menu menu ){ - create_menu_item_with_mnemonic( menu, "Cylinder", "PatchCylinder" ); - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "More Cylinders" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Dense Cylinder", "PatchDenseCylinder" ); - create_menu_item_with_mnemonic( menu_in_menu, "Very Dense Cylinder", "PatchVeryDenseCylinder" ); - create_menu_item_with_mnemonic( menu_in_menu, "Square Cylinder", "PatchSquareCylinder" ); - create_menu_item_with_mnemonic( menu_in_menu, "Exact Cylinder...", "PatchXactCylinder" ); - } - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "End cap", "PatchEndCap" ); - create_menu_item_with_mnemonic( menu, "Bevel", "PatchBevel" ); - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "More End caps, Bevels" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Square Endcap", "PatchSquareBevel" ); - create_menu_item_with_mnemonic( menu_in_menu, "Square Bevel", "PatchSquareEndcap" ); - } - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Cone", "PatchCone" ); - create_menu_item_with_mnemonic( menu, "Exact Cone...", "PatchXactCone" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Sphere", "PatchSphere" ); - create_menu_item_with_mnemonic( menu, "Exact Sphere...", "PatchXactSphere" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Simple Patch Mesh...", "SimplePatchMesh" ); - menu_separator( menu ); - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Insert" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Insert (2) Columns", "PatchInsertInsertColumn" ); - create_menu_item_with_mnemonic( menu_in_menu, "Add (2) Columns", "PatchInsertAddColumn" ); - menu_separator( menu_in_menu ); - create_menu_item_with_mnemonic( menu_in_menu, "Insert (2) Rows", "PatchInsertInsertRow" ); - create_menu_item_with_mnemonic( menu_in_menu, "Add (2) Rows", "PatchInsertAddRow" ); - } - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Delete" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "First (2) Columns", "PatchDeleteFirstColumn" ); - create_menu_item_with_mnemonic( menu_in_menu, "Last (2) Columns", "PatchDeleteLastColumn" ); - menu_separator( menu_in_menu ); - create_menu_item_with_mnemonic( menu_in_menu, "First (2) Rows", "PatchDeleteFirstRow" ); - create_menu_item_with_mnemonic( menu_in_menu, "Last (2) Rows", "PatchDeleteLastRow" ); - } - menu_separator( menu ); - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Matrix" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Invert", "InvertCurve" ); - auto menu_3 = create_sub_menu_with_mnemonic( menu_in_menu, "Re-disperse" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_3 ); - } - create_menu_item_with_mnemonic( menu_3, "Rows", "RedisperseRows" ); - create_menu_item_with_mnemonic( menu_3, "Columns", "RedisperseCols" ); - auto menu_4 = create_sub_menu_with_mnemonic( menu_in_menu, "Smooth" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_4 ); - } - create_menu_item_with_mnemonic( menu_4, "Rows", "SmoothRows" ); - create_menu_item_with_mnemonic( menu_4, "Columns", "SmoothCols" ); - create_menu_item_with_mnemonic( menu_in_menu, "Transpose", "MatrixTranspose" ); - } - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Cap Selection", "CapCurrentCurve" ); - create_menu_item_with_mnemonic( menu, "Cycle Cap Texture", "CycleCapTexturePatch" ); - menu_separator( menu ); - { - auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Overlay" ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu_in_menu ); - } - create_menu_item_with_mnemonic( menu_in_menu, "Set", "MakeOverlayPatch" ); - create_menu_item_with_mnemonic( menu_in_menu, "Clear", "ClearPatchOverlays" ); - } +void Patch_registerCommands() +{ + GlobalCommands_insert("InvertCurveTextureX", makeCallbackF(Patch_FlipTextureX), + Accelerator('I', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("InvertCurveTextureY", makeCallbackF(Patch_FlipTextureY), + Accelerator('I', (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("NaturalizePatch", makeCallbackF(Patch_NaturalTexture), + Accelerator('N', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("PatchCylinder", makeCallbackF(Patch_Cylinder)); + GlobalCommands_insert("PatchDenseCylinder", makeCallbackF(Patch_DenseCylinder)); + GlobalCommands_insert("PatchVeryDenseCylinder", makeCallbackF(Patch_VeryDenseCylinder)); + GlobalCommands_insert("PatchSquareCylinder", makeCallbackF(Patch_SquareCylinder)); + GlobalCommands_insert("PatchXactCylinder", makeCallbackF(Patch_XactCylinder)); + GlobalCommands_insert("PatchXactSphere", makeCallbackF(Patch_XactSphere)); + GlobalCommands_insert("PatchXactCone", makeCallbackF(Patch_XactCone)); + GlobalCommands_insert("PatchEndCap", makeCallbackF(Patch_Endcap)); + GlobalCommands_insert("PatchBevel", makeCallbackF(Patch_Bevel)); + GlobalCommands_insert("PatchSquareBevel", makeCallbackF(Patch_SquareBevel)); + GlobalCommands_insert("PatchSquareEndcap", makeCallbackF(Patch_SquareEndcap)); + GlobalCommands_insert("PatchCone", makeCallbackF(Patch_Cone)); + GlobalCommands_insert("PatchSphere", makeCallbackF(Patch_Sphere)); + GlobalCommands_insert("SimplePatchMesh", makeCallbackF(Patch_Plane), + Accelerator('P', (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("PatchInsertInsertColumn", makeCallbackF(Patch_InsertInsertColumn), + Accelerator(GDK_KEY_KP_Add, (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("PatchInsertAddColumn", makeCallbackF(Patch_InsertAddColumn)); + GlobalCommands_insert("PatchInsertInsertRow", makeCallbackF(Patch_InsertInsertRow), + Accelerator(GDK_KEY_KP_Add, (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("PatchInsertAddRow", makeCallbackF(Patch_InsertAddRow)); + GlobalCommands_insert("PatchDeleteFirstColumn", makeCallbackF(Patch_DeleteFirstColumn)); + GlobalCommands_insert("PatchDeleteLastColumn", makeCallbackF(Patch_DeleteLastColumn), + Accelerator(GDK_KEY_KP_Subtract, (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("PatchDeleteFirstRow", makeCallbackF(Patch_DeleteFirstRow), + Accelerator(GDK_KEY_KP_Subtract, (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("PatchDeleteLastRow", makeCallbackF(Patch_DeleteLastRow)); + GlobalCommands_insert("InvertCurve", makeCallbackF(Patch_Invert), + Accelerator('I', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("RedisperseRows", makeCallbackF(Patch_RedisperseRows), + Accelerator('E', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("RedisperseCols", makeCallbackF(Patch_RedisperseCols), + Accelerator('E', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("SmoothRows", makeCallbackF(Patch_SmoothRows), + Accelerator('W', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("SmoothCols", makeCallbackF(Patch_SmoothCols), + Accelerator('W', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("MatrixTranspose", makeCallbackF(Patch_Transpose), + Accelerator('M', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("CapCurrentCurve", makeCallbackF(Patch_Cap), + Accelerator('C', (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("CycleCapTexturePatch", makeCallbackF(Patch_CycleProjection), + Accelerator('N', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("MakeOverlayPatch", makeCallbackF(Patch_OverlayOn), Accelerator('Y')); + GlobalCommands_insert("ClearPatchOverlays", makeCallbackF(Patch_OverlayOff), + Accelerator('L', (GdkModifierType) GDK_CONTROL_MASK)); +} + +void Patch_constructToolbar(ui::Toolbar toolbar) +{ + toolbar_append_button(toolbar, "Put caps on the current patch (SHIFT + C)", "cap_curve.png", "CapCurrentCurve"); +} + +void Patch_constructMenu(ui::Menu menu) +{ + create_menu_item_with_mnemonic(menu, "Cylinder", "PatchCylinder"); + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "More Cylinders"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Dense Cylinder", "PatchDenseCylinder"); + create_menu_item_with_mnemonic(menu_in_menu, "Very Dense Cylinder", "PatchVeryDenseCylinder"); + create_menu_item_with_mnemonic(menu_in_menu, "Square Cylinder", "PatchSquareCylinder"); + create_menu_item_with_mnemonic(menu_in_menu, "Exact Cylinder...", "PatchXactCylinder"); + } + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "End cap", "PatchEndCap"); + create_menu_item_with_mnemonic(menu, "Bevel", "PatchBevel"); + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "More End caps, Bevels"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Square Endcap", "PatchSquareBevel"); + create_menu_item_with_mnemonic(menu_in_menu, "Square Bevel", "PatchSquareEndcap"); + } + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Cone", "PatchCone"); + create_menu_item_with_mnemonic(menu, "Exact Cone...", "PatchXactCone"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Sphere", "PatchSphere"); + create_menu_item_with_mnemonic(menu, "Exact Sphere...", "PatchXactSphere"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Simple Patch Mesh...", "SimplePatchMesh"); + menu_separator(menu); + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Insert"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Insert (2) Columns", "PatchInsertInsertColumn"); + create_menu_item_with_mnemonic(menu_in_menu, "Add (2) Columns", "PatchInsertAddColumn"); + menu_separator(menu_in_menu); + create_menu_item_with_mnemonic(menu_in_menu, "Insert (2) Rows", "PatchInsertInsertRow"); + create_menu_item_with_mnemonic(menu_in_menu, "Add (2) Rows", "PatchInsertAddRow"); + } + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Delete"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "First (2) Columns", "PatchDeleteFirstColumn"); + create_menu_item_with_mnemonic(menu_in_menu, "Last (2) Columns", "PatchDeleteLastColumn"); + menu_separator(menu_in_menu); + create_menu_item_with_mnemonic(menu_in_menu, "First (2) Rows", "PatchDeleteFirstRow"); + create_menu_item_with_mnemonic(menu_in_menu, "Last (2) Rows", "PatchDeleteLastRow"); + } + menu_separator(menu); + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Matrix"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Invert", "InvertCurve"); + auto menu_3 = create_sub_menu_with_mnemonic(menu_in_menu, "Re-disperse"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_3); + } + create_menu_item_with_mnemonic(menu_3, "Rows", "RedisperseRows"); + create_menu_item_with_mnemonic(menu_3, "Columns", "RedisperseCols"); + auto menu_4 = create_sub_menu_with_mnemonic(menu_in_menu, "Smooth"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_4); + } + create_menu_item_with_mnemonic(menu_4, "Rows", "SmoothRows"); + create_menu_item_with_mnemonic(menu_4, "Columns", "SmoothCols"); + create_menu_item_with_mnemonic(menu_in_menu, "Transpose", "MatrixTranspose"); + } + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Cap Selection", "CapCurrentCurve"); + create_menu_item_with_mnemonic(menu, "Cycle Cap Texture", "CycleCapTexturePatch"); + menu_separator(menu); + { + auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Overlay"); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu_in_menu); + } + create_menu_item_with_mnemonic(menu_in_menu, "Set", "MakeOverlayPatch"); + create_menu_item_with_mnemonic(menu_in_menu, "Clear", "ClearPatchOverlays"); + } } #include "gtkutil/dialog.h" #include "gtkutil/widget.h" -void DoNewPatchDlg( EPatchPrefab prefab, int minrows, int mincols, int defrows, int defcols, int maxrows, int maxcols ){ - ModalDialog dialog; - - ui::Window window = MainFrame_getWindow().create_dialog_window("Patch density", G_CALLBACK(dialog_delete_callback ), &dialog ); - - auto accel = ui::AccelGroup(ui::New); - window.add_accel_group( accel ); - auto width = ui::ComboBoxText(ui::New); - auto height = ui::ComboBoxText(ui::New); - { - auto hbox = create_dialog_hbox( 4, 4 ); - window.add(hbox); - { - auto table = create_dialog_table( 2, 2, 4, 4 ); - hbox.pack_start( table, TRUE, TRUE, 0 ); - { - auto label = ui::Label( "Width:" ); - label.show(); +void DoNewPatchDlg(EPatchPrefab prefab, int minrows, int mincols, int defrows, int defcols, int maxrows, int maxcols) +{ + ModalDialog dialog; + + ui::Window window = MainFrame_getWindow().create_dialog_window("Patch density", G_CALLBACK(dialog_delete_callback), + &dialog); + + auto accel = ui::AccelGroup(ui::New); + window.add_accel_group(accel); + auto width = ui::ComboBoxText(ui::New); + auto height = ui::ComboBoxText(ui::New); + { + auto hbox = create_dialog_hbox(4, 4); + window.add(hbox); + { + auto table = create_dialog_table(2, 2, 4, 4); + hbox.pack_start(table, TRUE, TRUE, 0); + { + auto label = ui::Label("Width:"); + label.show(); table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - { - auto label = ui::Label( "Height:" ); - label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + { + auto label = ui::Label("Height:"); + label.show(); table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); - } - - { - auto combo = width; -#define D_ITEM( x ) if ( x >= mincols && ( !maxcols || x <= maxcols ) ) gtk_combo_box_text_append_text( combo, #x ) - D_ITEM( 3 ); - D_ITEM( 5 ); - D_ITEM( 7 ); - D_ITEM( 9 ); - D_ITEM( 11 ); - D_ITEM( 13 ); - D_ITEM( 15 ); - D_ITEM( 17 ); - D_ITEM( 19 ); - D_ITEM( 21 ); - D_ITEM( 23 ); - D_ITEM( 25 ); - D_ITEM( 27 ); - D_ITEM( 29 ); - D_ITEM( 31 ); // MAX_PATCH_SIZE is 32, so we should be able to do 31... + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + + { + auto combo = width; +#define D_ITEM(x) if ( x >= mincols && ( !maxcols || x <= maxcols ) ) gtk_combo_box_text_append_text( combo, #x ) + D_ITEM(3); + D_ITEM(5); + D_ITEM(7); + D_ITEM(9); + D_ITEM(11); + D_ITEM(13); + D_ITEM(15); + D_ITEM(17); + D_ITEM(19); + D_ITEM(21); + D_ITEM(23); + D_ITEM(25); + D_ITEM(27); + D_ITEM(29); + D_ITEM(31); // MAX_PATCH_SIZE is 32, so we should be able to do 31... #undef D_ITEM - combo.show(); + combo.show(); table.attach(combo, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - } - { - auto combo = height; -#define D_ITEM( x ) if ( x >= minrows && ( !maxrows || x <= maxrows ) ) gtk_combo_box_text_append_text( combo, #x ) - D_ITEM( 3 ); - D_ITEM( 5 ); - D_ITEM( 7 ); - D_ITEM( 9 ); - D_ITEM( 11 ); - D_ITEM( 13 ); - D_ITEM( 15 ); - D_ITEM( 17 ); - D_ITEM( 19 ); - D_ITEM( 21 ); - D_ITEM( 23 ); - D_ITEM( 25 ); - D_ITEM( 27 ); - D_ITEM( 29 ); - D_ITEM( 31 ); // MAX_PATCH_SIZE is 32, so we should be able to do 31... + } + { + auto combo = height; +#define D_ITEM(x) if ( x >= minrows && ( !maxrows || x <= maxrows ) ) gtk_combo_box_text_append_text( combo, #x ) + D_ITEM(3); + D_ITEM(5); + D_ITEM(7); + D_ITEM(9); + D_ITEM(11); + D_ITEM(13); + D_ITEM(15); + D_ITEM(17); + D_ITEM(19); + D_ITEM(21); + D_ITEM(23); + D_ITEM(25); + D_ITEM(27); + D_ITEM(29); + D_ITEM(31); // MAX_PATCH_SIZE is 32, so we should be able to do 31... #undef D_ITEM - combo.show(); + combo.show(); table.attach(combo, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - } - } - - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, TRUE, TRUE, 0 ); - { - auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_grab_focus( button ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - { - auto button = create_dialog_button( "Cancel", G_CALLBACK( dialog_button_cancel ), &dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - } - } - - // Initialize dialog - gtk_combo_box_set_active( width, ( defcols - mincols ) / 2 ); - gtk_combo_box_set_active( height, ( defrows - minrows ) / 2 ); - - if ( modal_dialog_show( window, dialog ) == eIDOK ) { - int w = gtk_combo_box_get_active( width ) * 2 + mincols; - int h = gtk_combo_box_get_active( height ) * 2 + minrows; - - Scene_PatchConstructPrefab( GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), prefab, GlobalXYWnd_getCurrentViewType(), w, h ); - } - - window.destroy(); -} - - - - -EMessageBoxReturn DoCapDlg( ECapDialog* type ){ - ModalDialog dialog; - ModalDialogButton ok_button( dialog, eIDOK ); - ModalDialogButton cancel_button( dialog, eIDCANCEL ); - ui::Widget bevel{ui::null}; - ui::Widget ibevel{ui::null}; - ui::Widget endcap{ui::null}; - ui::Widget iendcap{ui::null}; - ui::Widget cylinder{ui::null}; - - ui::Window window = MainFrame_getWindow().create_modal_dialog_window( "Cap", dialog ); - - auto accel_group = ui::AccelGroup(ui::New); - window.add_accel_group( accel_group ); - - { - auto hbox = create_dialog_hbox( 4, 4 ); - window.add(hbox); - - { - // Gef: Added a vbox to contain the toggle buttons - auto radio_vbox = create_dialog_vbox( 4 ); - hbox.add(radio_vbox); - - { - auto table = ui::Table( 5, 2, FALSE ); - table.show(); - radio_vbox.pack_start( table, TRUE, TRUE, 0 ); - gtk_table_set_row_spacings( table, 5 ); - gtk_table_set_col_spacings( table, 5 ); - - { - auto image = new_local_image( "cap_bevel.png" ); - image.show(); + } + } + + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, TRUE, TRUE, 0); + { + auto button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_grab_focus(button); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + { + auto button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + } + } + + // Initialize dialog + gtk_combo_box_set_active(width, (defcols - mincols) / 2); + gtk_combo_box_set_active(height, (defrows - minrows) / 2); + + if (modal_dialog_show(window, dialog) == eIDOK) { + int w = gtk_combo_box_get_active(width) * 2 + mincols; + int h = gtk_combo_box_get_active(height) * 2 + minrows; + + Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), prefab, + GlobalXYWnd_getCurrentViewType(), w, h); + } + + window.destroy(); +} + + +EMessageBoxReturn DoCapDlg(ECapDialog *type) +{ + ModalDialog dialog; + ModalDialogButton ok_button(dialog, eIDOK); + ModalDialogButton cancel_button(dialog, eIDCANCEL); + ui::Widget bevel{ui::null}; + ui::Widget ibevel{ui::null}; + ui::Widget endcap{ui::null}; + ui::Widget iendcap{ui::null}; + ui::Widget cylinder{ui::null}; + + ui::Window window = MainFrame_getWindow().create_modal_dialog_window("Cap", dialog); + + auto accel_group = ui::AccelGroup(ui::New); + window.add_accel_group(accel_group); + + { + auto hbox = create_dialog_hbox(4, 4); + window.add(hbox); + + { + // Gef: Added a vbox to contain the toggle buttons + auto radio_vbox = create_dialog_vbox(4); + hbox.add(radio_vbox); + + { + auto table = ui::Table(5, 2, FALSE); + table.show(); + radio_vbox.pack_start(table, TRUE, TRUE, 0); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + + { + auto image = new_local_image("cap_bevel.png"); + image.show(); table.attach(image, {0, 1, 0, 1}, {GTK_FILL, 0}); - } - { - auto image = new_local_image( "cap_endcap.png" ); - image.show(); + } + { + auto image = new_local_image("cap_endcap.png"); + image.show(); table.attach(image, {0, 1, 1, 2}, {GTK_FILL, 0}); - } - { - auto image = new_local_image( "cap_ibevel.png" ); - image.show(); + } + { + auto image = new_local_image("cap_ibevel.png"); + image.show(); table.attach(image, {0, 1, 2, 3}, {GTK_FILL, 0}); - } - { - auto image = new_local_image( "cap_iendcap.png" ); - image.show(); + } + { + auto image = new_local_image("cap_iendcap.png"); + image.show(); table.attach(image, {0, 1, 3, 4}, {GTK_FILL, 0}); - } - { - auto image = new_local_image( "cap_cylinder.png" ); - image.show(); + } + { + auto image = new_local_image("cap_cylinder.png"); + image.show(); table.attach(image, {0, 1, 4, 5}, {GTK_FILL, 0}); - } + } - GSList* group = 0; - { - ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label( group, "Bevel" )); - button.show(); + GSList *group = 0; + { + ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label(group, "Bevel")); + button.show(); table.attach(button, {1, 2, 0, 1}, {GTK_FILL | GTK_EXPAND, 0}); - group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( button ) ); + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)); - bevel = button; - } - { - ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label( group, "Endcap" )); - button.show(); + bevel = button; + } + { + ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label(group, "Endcap")); + button.show(); table.attach(button, {1, 2, 1, 2}, {GTK_FILL | GTK_EXPAND, 0}); - group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( button ) ); + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)); - endcap = button; - } - { - ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label( group, "Inverted Bevel" )); - button.show(); + endcap = button; + } + { + ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label(group, "Inverted Bevel")); + button.show(); table.attach(button, {1, 2, 2, 3}, {GTK_FILL | GTK_EXPAND, 0}); - group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( button ) ); + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)); - ibevel = button; - } - { - ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label( group, "Inverted Endcap" )); - button.show(); + ibevel = button; + } + { + ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label(group, "Inverted Endcap")); + button.show(); table.attach(button, {1, 2, 3, 4}, {GTK_FILL | GTK_EXPAND, 0}); - group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( button ) ); + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)); - iendcap = button; - } - { - ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label( group, "Cylinder" )); - button.show(); + iendcap = button; + } + { + ui::Widget button = ui::Widget::from(gtk_radio_button_new_with_label(group, "Cylinder")); + button.show(); table.attach(button, {1, 2, 4, 5}, {GTK_FILL | GTK_EXPAND, 0}); - group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( button ) ); - - cylinder = button; - } - } - } - - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, FALSE, FALSE, 0 ); - { - auto button = create_modal_dialog_button( "OK", ok_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel_group, GDK_KEY_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE ); - } - { - auto button = create_modal_dialog_button( "Cancel", cancel_button ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel_group, GDK_KEY_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE ); - } - } - } - - // Initialize dialog - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( bevel ), TRUE ); - - EMessageBoxReturn ret = modal_dialog_show( window, dialog ); - if ( ret == eIDOK ) { - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( bevel ) ) ) { - *type = PATCHCAP_BEVEL; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( endcap ) ) ) { - *type = PATCHCAP_ENDCAP; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ibevel ) ) ) { - *type = PATCHCAP_INVERTED_BEVEL; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( iendcap ) ) ) { - *type = PATCHCAP_INVERTED_ENDCAP; - } - else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( cylinder ) ) ) { - *type = PATCHCAP_CYLINDER; - } - } - - window.destroy(); - - return ret; + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)); + + cylinder = button; + } + } + } + + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, FALSE, FALSE, 0); + { + auto button = create_modal_dialog_button("OK", ok_button); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_add_accelerator(button, "clicked", accel_group, GDK_KEY_Return, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + } + { + auto button = create_modal_dialog_button("Cancel", cancel_button); + vbox.pack_start(button, FALSE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel_group, GDK_KEY_Escape, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + } + } + } + + // Initialize dialog + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bevel), TRUE); + + EMessageBoxReturn ret = modal_dialog_show(window, dialog); + if (ret == eIDOK) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(bevel))) { + *type = PATCHCAP_BEVEL; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(endcap))) { + *type = PATCHCAP_ENDCAP; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ibevel))) { + *type = PATCHCAP_INVERTED_BEVEL; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(iendcap))) { + *type = PATCHCAP_INVERTED_ENDCAP; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cylinder))) { + *type = PATCHCAP_CYLINDER; + } + } + + window.destroy(); + + return ret; } diff --git a/radiant/patchmanip.h b/radiant/patchmanip.h index 512a3f95..6ac361b9 100644 --- a/radiant/patchmanip.h +++ b/radiant/patchmanip.h @@ -26,23 +26,30 @@ #include "string/stringfwd.h" void Patch_registerCommands(); -void Patch_constructToolbar( ui::Toolbar toolbar ); -void Patch_constructMenu( ui::Menu menu ); -namespace scene -{ -class Graph; +void Patch_constructToolbar(ui::Toolbar toolbar); + +void Patch_constructMenu(ui::Menu 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_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_PatchCapTexture_Selected( scene::Graph& graph ); -void Scene_PatchNaturalTexture_Selected( scene::Graph& graph ); -void Scene_PatchTileTexture_Selected( scene::Graph& graph, float s, float t ); +void Scene_PatchTileTexture_Selected(scene::Graph &graph, float s, float t); void PatchFilters_construct(); @@ -51,14 +58,21 @@ void PatchPreferences_construct(); void Patch_registerPreferencesPage(); void Patch_NaturalTexture(); + void Patch_CapTexture(); + void Patch_ResetTexture(); + void Patch_FitTexture(); + void Patch_FlipTextureX(); + void Patch_FlipTextureY(); + void Patch_AutoCapTexture(); class PatchCreator; -extern PatchCreator* g_patchCreator; + +extern PatchCreator *g_patchCreator; #endif diff --git a/radiant/patchmodule.cpp b/radiant/patchmodule.cpp index 7f273591..c257dc65 100644 --- a/radiant/patchmodule.cpp +++ b/radiant/patchmodule.cpp @@ -27,196 +27,221 @@ #include "patch.h" #include "patchmanip.h" -namespace -{ -std::size_t g_patchModuleCount = 0; +namespace { + std::size_t g_patchModuleCount = 0; } -void Patch_Construct( EPatchType type ){ - if ( ++g_patchModuleCount != 1 ) { - return; - } +void Patch_Construct(EPatchType type) +{ + if (++g_patchModuleCount != 1) { + return; + } - PatchFilters_construct(); + PatchFilters_construct(); - PatchPreferences_construct(); + PatchPreferences_construct(); - Patch_registerPreferencesPage(); + Patch_registerPreferencesPage(); - Patch::constructStatic( type ); - PatchInstance::constructStatic(); + Patch::constructStatic(type); + PatchInstance::constructStatic(); - if ( type == ePatchTypeDoom3 ) { - MAX_PATCH_WIDTH = MAX_PATCH_HEIGHT = 99; - } - else - { - MAX_PATCH_WIDTH = MAX_PATCH_HEIGHT = 31; // matching q3map2 - } + if (type == ePatchTypeDoom3) { + MAX_PATCH_WIDTH = MAX_PATCH_HEIGHT = 99; + } else { + MAX_PATCH_WIDTH = MAX_PATCH_HEIGHT = 31; // matching q3map2 + } } -void Patch_Destroy(){ - if ( --g_patchModuleCount != 0 ) { - return; - } +void Patch_Destroy() +{ + if (--g_patchModuleCount != 0) { + return; + } - Patch::destroyStatic(); - PatchInstance::destroyStatic(); + Patch::destroyStatic(); + PatchInstance::destroyStatic(); } -class CommonPatchCreator : public PatchCreator -{ +class CommonPatchCreator : public PatchCreator { public: -void Patch_undoSave( scene::Node& patch ) const { - Node_getPatch( patch )->undoSave(); -} -void Patch_resize( scene::Node& patch, std::size_t width, std::size_t height ) const { - Node_getPatch( patch )->setDims( width, height ); -} -PatchControlMatrix Patch_getControlPoints( scene::Node& node ) const { - Patch& patch = *Node_getPatch( node ); - return PatchControlMatrix( patch.getHeight(), patch.getWidth(), patch.getControlPoints().data() ); -} -void Patch_controlPointsChanged( scene::Node& patch ) const { - return Node_getPatch( patch )->controlPointsChanged(); -} -const char* Patch_getShader( scene::Node& patch ) const { - return Node_getPatch( patch )->GetShader(); -} -void Patch_setShader( scene::Node& patch, const char* shader ) const { - Node_getPatch( patch )->SetShader( shader ); -} + void Patch_undoSave(scene::Node &patch) const + { + Node_getPatch(patch)->undoSave(); + } + + void Patch_resize(scene::Node &patch, std::size_t width, std::size_t height) const + { + Node_getPatch(patch)->setDims(width, height); + } + + PatchControlMatrix Patch_getControlPoints(scene::Node &node) const + { + Patch &patch = *Node_getPatch(node); + return PatchControlMatrix(patch.getHeight(), patch.getWidth(), patch.getControlPoints().data()); + } + + void Patch_controlPointsChanged(scene::Node &patch) const + { + return Node_getPatch(patch)->controlPointsChanged(); + } + + const char *Patch_getShader(scene::Node &patch) const + { + return Node_getPatch(patch)->GetShader(); + } + + void Patch_setShader(scene::Node &patch, const char *shader) const + { + Node_getPatch(patch)->SetShader(shader); + } }; -class Quake3PatchCreator : public CommonPatchCreator -{ +class Quake3PatchCreator : public CommonPatchCreator { public: -scene::Node& createPatch(){ - return ( new PatchNodeQuake3() )->node(); -} + scene::Node &createPatch() + { + return (new PatchNodeQuake3())->node(); + } }; Quake3PatchCreator g_Quake3PatchCreator; -PatchCreator& GetQuake3PatchCreator(){ - return g_Quake3PatchCreator; +PatchCreator &GetQuake3PatchCreator() +{ + return g_Quake3PatchCreator; } -class Doom3PatchCreator : public CommonPatchCreator -{ +class Doom3PatchCreator : public CommonPatchCreator { public: -scene::Node& createPatch(){ - return ( new PatchNodeDoom3( true ) )->node(); -} + scene::Node &createPatch() + { + return (new PatchNodeDoom3(true))->node(); + } }; Doom3PatchCreator g_Doom3PatchCreator; -PatchCreator& GetDoom3PatchCreator(){ - return g_Doom3PatchCreator; +PatchCreator &GetDoom3PatchCreator() +{ + return g_Doom3PatchCreator; } -class Doom3PatchDef2Creator : public CommonPatchCreator -{ +class Doom3PatchDef2Creator : public CommonPatchCreator { public: -scene::Node& createPatch(){ - return ( new PatchNodeDoom3() )->node(); -} + scene::Node &createPatch() + { + return (new PatchNodeDoom3())->node(); + } }; Doom3PatchDef2Creator g_Doom3PatchDef2Creator; -PatchCreator& GetDoom3PatchDef2Creator(){ - return 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 -{ + public GlobalRadiantModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalSelectionModuleRef, + public GlobalOpenGLModuleRef, + public GlobalUndoModuleRef, + public GlobalFilterModuleRef { }; -class PatchQuake3API : public TypeSystemRef -{ -PatchCreator* m_patchquake3; +class PatchQuake3API : public TypeSystemRef { + PatchCreator *m_patchquake3; public: -typedef PatchCreator Type; -STRING_CONSTANT( Name, "quake3" ); + typedef PatchCreator Type; -PatchQuake3API(){ - Patch_Construct( ePatchTypeQuake3 ); + STRING_CONSTANT(Name, "quake3"); - m_patchquake3 = &GetQuake3PatchCreator(); - g_patchCreator = m_patchquake3; -} -~PatchQuake3API(){ - Patch_Destroy(); -} -PatchCreator* getTable(){ - return m_patchquake3; -} + PatchQuake3API() + { + Patch_Construct(ePatchTypeQuake3); + + m_patchquake3 = &GetQuake3PatchCreator(); + g_patchCreator = m_patchquake3; + } + + ~PatchQuake3API() + { + Patch_Destroy(); + } + + PatchCreator *getTable() + { + return m_patchquake3; + } }; typedef SingletonModule PatchQuake3Module; typedef Static StaticPatchQuake3Module; -StaticRegisterModule staticRegisterPatchQuake3( StaticPatchQuake3Module::instance() ); +StaticRegisterModule staticRegisterPatchQuake3(StaticPatchQuake3Module::instance()); - -class PatchDoom3API : public TypeSystemRef -{ -PatchCreator* m_patchdoom3; +class PatchDoom3API : public TypeSystemRef { + PatchCreator *m_patchdoom3; public: -typedef PatchCreator Type; -STRING_CONSTANT( Name, "doom3" ); + typedef PatchCreator Type; -PatchDoom3API(){ - Patch_Construct( ePatchTypeDoom3 ); + STRING_CONSTANT(Name, "doom3"); - m_patchdoom3 = &GetDoom3PatchCreator(); -} -~PatchDoom3API(){ - Patch_Destroy(); -} -PatchCreator* getTable(){ - return m_patchdoom3; -} + PatchDoom3API() + { + Patch_Construct(ePatchTypeDoom3); + + m_patchdoom3 = &GetDoom3PatchCreator(); + } + + ~PatchDoom3API() + { + Patch_Destroy(); + } + + PatchCreator *getTable() + { + return m_patchdoom3; + } }; typedef SingletonModule PatchDoom3Module; typedef Static StaticPatchDoom3Module; -StaticRegisterModule staticRegisterPatchDoom3( StaticPatchDoom3Module::instance() ); +StaticRegisterModule staticRegisterPatchDoom3(StaticPatchDoom3Module::instance()); -class PatchDef2Doom3API : public TypeSystemRef -{ -PatchCreator* m_patchdef2doom3; +class PatchDef2Doom3API : public TypeSystemRef { + PatchCreator *m_patchdef2doom3; public: -typedef PatchCreator Type; -STRING_CONSTANT( Name, "def2doom3" ); + typedef PatchCreator Type; -PatchDef2Doom3API(){ - Patch_Construct( ePatchTypeDoom3 ); + STRING_CONSTANT(Name, "def2doom3"); - m_patchdef2doom3 = &GetDoom3PatchDef2Creator(); - g_patchCreator = m_patchdef2doom3; -} -~PatchDef2Doom3API(){ - Patch_Destroy(); -} -PatchCreator* getTable(){ - return m_patchdef2doom3; -} + PatchDef2Doom3API() + { + Patch_Construct(ePatchTypeDoom3); + + m_patchdef2doom3 = &GetDoom3PatchDef2Creator(); + g_patchCreator = m_patchdef2doom3; + } + + ~PatchDef2Doom3API() + { + Patch_Destroy(); + } + + PatchCreator *getTable() + { + return m_patchdef2doom3; + } }; typedef SingletonModule PatchDef2Doom3Module; typedef Static StaticPatchDef2Doom3Module; -StaticRegisterModule staticRegisterPatchDef2Doom3( StaticPatchDef2Doom3Module::instance() ); +StaticRegisterModule staticRegisterPatchDef2Doom3(StaticPatchDef2Doom3Module::instance()); diff --git a/radiant/plugin.cpp b/radiant/plugin.cpp index 9d55cf3b..fc77af1f 100644 --- a/radiant/plugin.cpp +++ b/radiant/plugin.cpp @@ -83,246 +83,274 @@ #include "generic/callback.h" -const char* GameDescription_getKeyValue( const char* key ){ - return g_pGameDescription->getKeyValue( key ); +const char *GameDescription_getKeyValue(const char *key) +{ + return g_pGameDescription->getKeyValue(key); } -const char* GameDescription_getRequiredKeyValue( const char* key ){ - return g_pGameDescription->getRequiredKeyValue( key ); +const char *GameDescription_getRequiredKeyValue(const char *key) +{ + return g_pGameDescription->getRequiredKeyValue(key); } -const char* getMapName(){ - return Map_Name( g_map ); +const char *getMapName() +{ + return Map_Name(g_map); } -scene::Node& getMapWorldEntity(){ - return Map_FindOrInsertWorldspawn( g_map ); +scene::Node &getMapWorldEntity() +{ + return Map_FindOrInsertWorldspawn(g_map); } -VIEWTYPE XYWindow_getViewType(){ - return g_pParentWnd->GetXYWnd()->GetViewType(); +VIEWTYPE XYWindow_getViewType() +{ + return g_pParentWnd->GetXYWnd()->GetViewType(); } -Vector3 XYWindow_windowToWorld( const WindowVector& position ){ - Vector3 result( 0, 0, 0 ); - g_pParentWnd->GetXYWnd()->XY_ToPoint( static_cast( position.x() ), static_cast( position.y() ), result ); - return result; +Vector3 XYWindow_windowToWorld(const WindowVector &position) +{ + Vector3 result(0, 0, 0); + g_pParentWnd->GetXYWnd()->XY_ToPoint(static_cast( position.x()), static_cast( position.y()), result); + return result; } -const char* TextureBrowser_getSelectedShader(){ - return TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ); +const char *TextureBrowser_getSelectedShader() +{ + return TextureBrowser_GetSelectedShader(GlobalTextureBrowser()); } -const char* getGameFile(){ - return g_GamesDialog.m_sGameFile.c_str(); +const char *getGameFile() +{ + return g_GamesDialog.m_sGameFile.c_str(); } -class RadiantCoreAPI -{ -_QERFuncTable_1 m_radiantcore; +class RadiantCoreAPI { + _QERFuncTable_1 m_radiantcore; public: -typedef _QERFuncTable_1 Type; -STRING_CONSTANT( Name, "*" ); - -RadiantCoreAPI(){ - m_radiantcore.getEnginePath = &EnginePath_get; - m_radiantcore.getLocalRcPath = &LocalRcPath_get; - m_radiantcore.getAppPath = &AppPath_get; - m_radiantcore.getGameToolsPath = &GameToolsPath_get; - m_radiantcore.getSettingsPath = &SettingsPath_get; - m_radiantcore.getMapsPath = &getMapsPath; - - m_radiantcore.getGameFile = &getGameFile; - m_radiantcore.getGameName = &gamename_get; - m_radiantcore.getGameMode = &gamemode_get; - - m_radiantcore.getMapName = &getMapName; - m_radiantcore.getMapWorldEntity = getMapWorldEntity; - m_radiantcore.getGridSize = GetGridSize; - - m_radiantcore.getGameDescriptionKeyValue = &GameDescription_getKeyValue; - m_radiantcore.getRequiredGameDescriptionKeyValue = &GameDescription_getRequiredKeyValue; - - m_radiantcore.XYWindowDestroyed_connect = XYWindowDestroyed_connect; - m_radiantcore.XYWindowDestroyed_disconnect = XYWindowDestroyed_disconnect; - m_radiantcore.XYWindowMouseDown_connect = XYWindowMouseDown_connect; - m_radiantcore.XYWindowMouseDown_disconnect = XYWindowMouseDown_disconnect; - m_radiantcore.XYWindow_getViewType = XYWindow_getViewType; - m_radiantcore.XYWindow_windowToWorld = XYWindow_windowToWorld; - m_radiantcore.TextureBrowser_getSelectedShader = TextureBrowser_getSelectedShader; - - 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 _QERFuncTable_1 Type; + + STRING_CONSTANT(Name, "*"); + + RadiantCoreAPI() + { + m_radiantcore.getEnginePath = &EnginePath_get; + m_radiantcore.getLocalRcPath = &LocalRcPath_get; + m_radiantcore.getAppPath = &AppPath_get; + m_radiantcore.getGameToolsPath = &GameToolsPath_get; + m_radiantcore.getSettingsPath = &SettingsPath_get; + m_radiantcore.getMapsPath = &getMapsPath; + + m_radiantcore.getGameFile = &getGameFile; + m_radiantcore.getGameName = &gamename_get; + m_radiantcore.getGameMode = &gamemode_get; + + m_radiantcore.getMapName = &getMapName; + m_radiantcore.getMapWorldEntity = getMapWorldEntity; + m_radiantcore.getGridSize = GetGridSize; + + m_radiantcore.getGameDescriptionKeyValue = &GameDescription_getKeyValue; + m_radiantcore.getRequiredGameDescriptionKeyValue = &GameDescription_getRequiredKeyValue; + + m_radiantcore.XYWindowDestroyed_connect = XYWindowDestroyed_connect; + m_radiantcore.XYWindowDestroyed_disconnect = XYWindowDestroyed_disconnect; + m_radiantcore.XYWindowMouseDown_connect = XYWindowMouseDown_connect; + m_radiantcore.XYWindowMouseDown_disconnect = XYWindowMouseDown_disconnect; + m_radiantcore.XYWindow_getViewType = XYWindow_getViewType; + m_radiantcore.XYWindow_windowToWorld = XYWindow_windowToWorld; + m_radiantcore.TextureBrowser_getSelectedShader = TextureBrowser_getSelectedShader; + + 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 RadiantCoreModule; typedef Static StaticRadiantCoreModule; -StaticRegisterModule staticRegisterRadiantCore( StaticRadiantCoreModule::instance() ); +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 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(); -} + 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 -{ +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(); -} + 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; +namespace { + bool g_RadiantInitialised = false; + RadiantDependencies *g_RadiantDependencies; + Radiant *g_Radiant; } +bool Radiant_Construct(ModuleServer &server) +{ + GlobalModuleServer::instance().set(server); + StaticModuleRegistryList().instance().registerModules(); -bool Radiant_Construct( ModuleServer& server ){ - GlobalModuleServer::instance().set( server ); - StaticModuleRegistryList().instance().registerModules(); - - g_RadiantDependencies = new RadiantDependencies(); + g_RadiantDependencies = new RadiantDependencies(); - g_RadiantInitialised = !server.getError(); + g_RadiantInitialised = !server.getError(); - if ( g_RadiantInitialised ) { - g_Radiant = new Radiant; - } + if (g_RadiantInitialised) { + g_Radiant = new Radiant; + } - return g_RadiantInitialised; + return g_RadiantInitialised; } -void Radiant_Destroy(){ - if ( g_RadiantInitialised ) { - delete g_Radiant; - } - delete g_RadiantDependencies; +void Radiant_Destroy() +{ + if (g_RadiantInitialised) { + delete g_Radiant; + } + + delete g_RadiantDependencies; } -ImageModules& Radiant_getImageModules(){ - return g_RadiantDependencies->getImageModules(); +ImageModules &Radiant_getImageModules() +{ + return g_RadiantDependencies->getImageModules(); } -MapModules& Radiant_getMapModules(){ - return g_RadiantDependencies->getMapModules(); + +MapModules &Radiant_getMapModules() +{ + return g_RadiantDependencies->getMapModules(); } -ToolbarModules& Radiant_getToolbarModules(){ - return g_RadiantDependencies->getToolbarModules(); + +ToolbarModules &Radiant_getToolbarModules() +{ + return g_RadiantDependencies->getToolbarModules(); } -PluginModules& Radiant_getPluginModules(){ - return g_RadiantDependencies->getPluginModules(); + +PluginModules &Radiant_getPluginModules() +{ + return g_RadiantDependencies->getPluginModules(); } diff --git a/radiant/plugin.h b/radiant/plugin.h index 75ab5c4c..4b0992a3 100644 --- a/radiant/plugin.h +++ b/radiant/plugin.h @@ -23,7 +23,9 @@ #define INCLUDED_PLUGIN_H class ModuleServer; -bool Radiant_Construct( ModuleServer& server ); + +bool Radiant_Construct(ModuleServer &server); + void Radiant_Destroy(); @@ -32,16 +34,24 @@ class Modules; struct _QERPlugImageTable; typedef Modules<_QERPlugImageTable> ImageModules; -ImageModules& Radiant_getImageModules(); + +ImageModules &Radiant_getImageModules(); + class MapFormat; + typedef Modules MapModules; -MapModules& Radiant_getMapModules(); + +MapModules &Radiant_getMapModules(); + struct _QERPlugToolbarTable; typedef Modules<_QERPlugToolbarTable> ToolbarModules; -ToolbarModules& Radiant_getToolbarModules(); + +ToolbarModules &Radiant_getToolbarModules(); + struct _QERPluginTable; typedef Modules<_QERPluginTable> PluginModules; -PluginModules& Radiant_getPluginModules(); + +PluginModules &Radiant_getPluginModules(); #endif diff --git a/radiant/pluginapi.cpp b/radiant/pluginapi.cpp index c006913d..e951b412 100644 --- a/radiant/pluginapi.cpp +++ b/radiant/pluginapi.cpp @@ -35,46 +35,52 @@ // camera API -void QERApp_GetCamera( Vector3& origin, Vector3& angles ){ - CamWnd& camwnd = *g_pParentWnd->GetCamWnd(); - origin = Camera_getOrigin( camwnd ); - angles = Camera_getAngles( camwnd ); +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_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 ){ +void QERApp_GetCamWindowExtents(int *x, int *y, int *width, int *height) +{ #if 0 - CamWnd* camwnd = g_pParentWnd->GetCamWnd(); + CamWnd* camwnd = g_pParentWnd->GetCamWnd(); - gtk_window_get_position( camwnd->m_window, x, y ); + gtk_window_get_position( camwnd->m_window, x, y ); - *width = camwnd->Camera()->width; - *height = camwnd->Camera()->height; + *width = camwnd->Camera()->width; + *height = camwnd->Camera()->height; #endif } #include "icamera.h" -class CameraAPI -{ -_QERCameraTable m_camera; +class CameraAPI { + _QERCameraTable m_camera; public: -typedef _QERCameraTable Type; -STRING_CONSTANT( Name, "*" ); + typedef _QERCameraTable Type; -CameraAPI(){ - m_camera.m_pfnGetCamera = &QERApp_GetCamera; - m_camera.m_pfnSetCamera = &QERApp_SetCamera; - m_camera.m_pfnGetCamWindowExtents = &QERApp_GetCamWindowExtents; -} -_QERCameraTable* getTable(){ - return &m_camera; -} + 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" @@ -82,4 +88,4 @@ _QERCameraTable* getTable(){ typedef SingletonModule CameraModule; typedef Static StaticCameraModule; -StaticRegisterModule staticRegisterCamera( StaticCameraModule::instance() ); +StaticRegisterModule staticRegisterCamera(StaticCameraModule::instance()); diff --git a/radiant/pluginapi.h b/radiant/pluginapi.h index 332e07d0..f145c09a 100644 --- a/radiant/pluginapi.h +++ b/radiant/pluginapi.h @@ -22,12 +22,16 @@ #if !defined( INCLUDED_PLUGINAPI_H ) #define INCLUDED_PLUGINAPI_H -template class BasicVector3; +template +class BasicVector3; + typedef BasicVector3 Vector3; // camera API -void QERApp_GetCamera( Vector3& origin, Vector3& angles ); -void QERApp_SetCamera( const Vector3& origin, const Vector3& angles ); -void QERApp_GetCamWindowExtents( int *x, int *y, int *width, int *height ); +void QERApp_GetCamera(Vector3 &origin, Vector3 &angles); + +void QERApp_SetCamera(const Vector3 &origin, const Vector3 &angles); + +void QERApp_GetCamWindowExtents(int *x, int *y, int *width, int *height); #endif diff --git a/radiant/pluginmanager.cpp b/radiant/pluginmanager.cpp index 91e9f9ae..33d7a2f1 100644 --- a/radiant/pluginmanager.cpp +++ b/radiant/pluginmanager.cpp @@ -41,170 +41,186 @@ #include /* plugin manager --------------------------------------- */ -class CPluginSlot : public IPlugIn -{ -CopiedString m_menu_name; -const _QERPluginTable *mpTable; -std::list m_CommandStrings; -std::list m_CommandTitleStrings; -std::list m_CommandIDs; +class CPluginSlot : public IPlugIn { + CopiedString m_menu_name; + const _QERPluginTable *mpTable; + std::list m_CommandStrings; + std::list m_CommandTitleStrings; + std::list m_CommandIDs; public: /*! build directly from a SYN_PROVIDE interface */ -CPluginSlot( ui::Widget main_window, const char* name, const _QERPluginTable& table ); + CPluginSlot(ui::Widget main_window, const char *name, const _QERPluginTable &table); + /*! dispatching a command by name to the plugin */ -void Dispatch( const char *p ); + void Dispatch(const char *p); // IPlugIn ------------------------------------------------------------ -const char* getMenuName(); -std::size_t getCommandCount(); -const char* getCommand( std::size_t n ); -const char* getCommandTitle( std::size_t n ); -void addMenuID( std::size_t n ); -bool ownsCommandID( std::size_t n ); + const char *getMenuName(); -}; + std::size_t getCommandCount(); -CPluginSlot::CPluginSlot( ui::Widget main_window, const char* name, const _QERPluginTable& table ){ - mpTable = &table; - m_menu_name = name; + const char *getCommand(std::size_t n); - const char* commands = mpTable->m_pfnQERPlug_GetCommandList(); - const char* titles = mpTable->m_pfnQERPlug_GetCommandTitleList(); + const char *getCommandTitle(std::size_t n); - StringTokeniser commandTokeniser( commands, ",;" ); - StringTokeniser titleTokeniser( titles, ",;" ); + void addMenuID(std::size_t n); - const char* cmdToken = commandTokeniser.getToken(); - const char *titleToken = titleTokeniser.getToken(); - while ( !string_empty( cmdToken ) ) - { - if ( string_empty( titleToken ) ) { - m_CommandStrings.push_back( cmdToken ); - m_CommandTitleStrings.push_back( cmdToken ); - cmdToken = commandTokeniser.getToken(); - titleToken = ""; - } - else - { - m_CommandStrings.push_back( cmdToken ); - m_CommandTitleStrings.push_back( titleToken ); - cmdToken = commandTokeniser.getToken(); - titleToken = titleTokeniser.getToken(); - } - } - mpTable->m_pfnQERPlug_Init( 0, (void*)main_window ); -} + bool ownsCommandID(std::size_t n); -const char* CPluginSlot::getMenuName(){ - return m_menu_name.c_str(); +}; + +CPluginSlot::CPluginSlot(ui::Widget main_window, const char *name, const _QERPluginTable &table) +{ + mpTable = &table; + m_menu_name = name; + + const char *commands = mpTable->m_pfnQERPlug_GetCommandList(); + const char *titles = mpTable->m_pfnQERPlug_GetCommandTitleList(); + + StringTokeniser commandTokeniser(commands, ",;"); + StringTokeniser titleTokeniser(titles, ",;"); + + const char *cmdToken = commandTokeniser.getToken(); + const char *titleToken = titleTokeniser.getToken(); + while (!string_empty(cmdToken)) { + if (string_empty(titleToken)) { + m_CommandStrings.push_back(cmdToken); + m_CommandTitleStrings.push_back(cmdToken); + cmdToken = commandTokeniser.getToken(); + titleToken = ""; + } else { + m_CommandStrings.push_back(cmdToken); + m_CommandTitleStrings.push_back(titleToken); + cmdToken = commandTokeniser.getToken(); + titleToken = titleTokeniser.getToken(); + } + } + mpTable->m_pfnQERPlug_Init(0, (void *) main_window); +} + +const char *CPluginSlot::getMenuName() +{ + return m_menu_name.c_str(); } -std::size_t CPluginSlot::getCommandCount(){ - return m_CommandStrings.size(); +std::size_t CPluginSlot::getCommandCount() +{ + return m_CommandStrings.size(); } -const char* CPluginSlot::getCommand( std::size_t n ){ - std::list::iterator i = m_CommandStrings.begin(); - while ( n-- != 0 ) - ++i; - return ( *i ).c_str(); +const char *CPluginSlot::getCommand(std::size_t n) +{ + std::list::iterator i = m_CommandStrings.begin(); + while (n-- != 0) { + ++i; + } + return (*i).c_str(); } -const char* CPluginSlot::getCommandTitle( std::size_t n ){ - std::list::iterator i = m_CommandTitleStrings.begin(); - while ( n-- != 0 ) - ++i; - return ( *i ).c_str(); +const char *CPluginSlot::getCommandTitle(std::size_t n) +{ + std::list::iterator i = m_CommandTitleStrings.begin(); + while (n-- != 0) { + ++i; + } + return (*i).c_str(); } -void CPluginSlot::addMenuID( std::size_t n ){ - m_CommandIDs.push_back( n ); +void CPluginSlot::addMenuID(std::size_t n) +{ + m_CommandIDs.push_back(n); } -bool CPluginSlot::ownsCommandID( std::size_t n ){ - for ( std::list::iterator i = m_CommandIDs.begin(); i != m_CommandIDs.end(); ++i ) - { - if ( *i == n ) { - return true; - } - } - return false; +bool CPluginSlot::ownsCommandID(std::size_t n) +{ + for (std::list::iterator i = m_CommandIDs.begin(); i != m_CommandIDs.end(); ++i) { + if (*i == n) { + return true; + } + } + return false; } -void CPluginSlot::Dispatch( const char *p ){ - Vector3 vMin, vMax; - Select_GetBounds( vMin, vMax ); - mpTable->m_pfnQERPlug_Dispatch( p, reinterpret_cast( &vMin ), reinterpret_cast( &vMax ), true ); //QE_SingleBrush(true)); +void CPluginSlot::Dispatch(const char *p) +{ + Vector3 vMin, vMax; + Select_GetBounds(vMin, vMax); + mpTable->m_pfnQERPlug_Dispatch(p, reinterpret_cast( &vMin ), reinterpret_cast( &vMax ), + true); //QE_SingleBrush(true)); } -class CPluginSlots -{ -std::list mSlots; +class CPluginSlots { + std::list mSlots; public: -virtual ~CPluginSlots(); + virtual ~CPluginSlots(); -void AddPluginSlot( ui::Widget main_window, const char* name, const _QERPluginTable& table ){ - mSlots.push_back( new CPluginSlot( main_window, name, table ) ); -} + void AddPluginSlot(ui::Widget main_window, const char *name, const _QERPluginTable &table) + { + mSlots.push_back(new CPluginSlot(main_window, name, table)); + } -void PopulateMenu( PluginsVisitor& menu ); -bool Dispatch( std::size_t n, const char* p ); + void PopulateMenu(PluginsVisitor &menu); + + bool Dispatch(std::size_t n, const char *p); }; -CPluginSlots::~CPluginSlots(){ - std::list::iterator iSlot; - for ( iSlot = mSlots.begin(); iSlot != mSlots.end(); ++iSlot ) - { - delete *iSlot; - *iSlot = 0; - } +CPluginSlots::~CPluginSlots() +{ + std::list::iterator iSlot; + for (iSlot = mSlots.begin(); iSlot != mSlots.end(); ++iSlot) { + delete *iSlot; + *iSlot = 0; + } } -void CPluginSlots::PopulateMenu( PluginsVisitor& menu ){ - std::list::iterator iPlug; - for ( iPlug = mSlots.begin(); iPlug != mSlots.end(); ++iPlug ) - { - menu.visit( *( *iPlug ) ); - } +void CPluginSlots::PopulateMenu(PluginsVisitor &menu) +{ + std::list::iterator iPlug; + for (iPlug = mSlots.begin(); iPlug != mSlots.end(); ++iPlug) { + menu.visit(*(*iPlug)); + } } -bool CPluginSlots::Dispatch( std::size_t n, const char* p ){ - std::list::iterator iPlug; - for ( iPlug = mSlots.begin(); iPlug != mSlots.end(); ++iPlug ) - { - CPluginSlot *pPlug = *iPlug; - if ( pPlug->ownsCommandID( n ) ) { - pPlug->Dispatch( p ); - return true; - } - } - return false; +bool CPluginSlots::Dispatch(std::size_t n, const char *p) +{ + std::list::iterator iPlug; + for (iPlug = mSlots.begin(); iPlug != mSlots.end(); ++iPlug) { + CPluginSlot *pPlug = *iPlug; + if (pPlug->ownsCommandID(n)) { + pPlug->Dispatch(p); + return true; + } + } + return false; } CPluginSlots g_plugin_slots; -void FillPluginSlots( CPluginSlots& slots, ui::Widget main_window ){ - class AddPluginVisitor : public PluginModules::Visitor - { - CPluginSlots& m_slots; - ui::Widget m_main_window; -public: - AddPluginVisitor( CPluginSlots& slots, ui::Widget main_window ) - : m_slots( slots ), m_main_window( main_window ){ - } - void visit( const char* name, const _QERPluginTable& table ) const { - m_slots.AddPluginSlot( m_main_window, name, table ); - } - } visitor( slots, main_window ); +void FillPluginSlots(CPluginSlots &slots, ui::Widget main_window) +{ + class AddPluginVisitor : public PluginModules::Visitor { + CPluginSlots &m_slots; + ui::Widget m_main_window; + public: + AddPluginVisitor(CPluginSlots &slots, ui::Widget main_window) + : m_slots(slots), m_main_window(main_window) + { + } + + void visit(const char *name, const _QERPluginTable &table) const + { + m_slots.AddPluginSlot(m_main_window, name, table); + } + } visitor(slots, main_window); - Radiant_getPluginModules().foreachModule( visitor ); + Radiant_getPluginModules().foreachModule(visitor); } @@ -212,21 +228,26 @@ public: CPlugInManager g_PlugInMgr; -CPlugInManager& GetPlugInMgr(){ - return g_PlugInMgr; +CPlugInManager &GetPlugInMgr() +{ + return g_PlugInMgr; } -void CPlugInManager::Dispatch( std::size_t n, const char * p ){ - g_plugin_slots.Dispatch( n, p ); +void CPlugInManager::Dispatch(std::size_t n, const char *p) +{ + g_plugin_slots.Dispatch(n, p); } -void CPlugInManager::Init( ui::Widget main_window ){ - FillPluginSlots( g_plugin_slots, main_window ); +void CPlugInManager::Init(ui::Widget main_window) +{ + FillPluginSlots(g_plugin_slots, main_window); } -void CPlugInManager::constructMenu( PluginsVisitor& menu ){ - g_plugin_slots.PopulateMenu( menu ); +void CPlugInManager::constructMenu(PluginsVisitor &menu) +{ + g_plugin_slots.PopulateMenu(menu); } -void CPlugInManager::Shutdown(){ +void CPlugInManager::Shutdown() +{ } diff --git a/radiant/pluginmanager.h b/radiant/pluginmanager.h index 6603f6e1..61334ea0 100644 --- a/radiant/pluginmanager.h +++ b/radiant/pluginmanager.h @@ -31,35 +31,43 @@ pure virtual interface for a plugin temporary solution for migration from old plugin tech to synapse plugins */ -class IPlugIn -{ +class IPlugIn { public: -IPlugIn() { } -virtual ~IPlugIn() { } - -virtual const char* getMenuName() = 0; -virtual std::size_t getCommandCount() = 0; -virtual const char* getCommand( std::size_t ) = 0; -virtual const char* getCommandTitle( std::size_t ) = 0; -virtual void addMenuID( std::size_t ) = 0; -virtual bool ownsCommandID( std::size_t n ) = 0; + IPlugIn() + {} + + virtual ~IPlugIn() + {} + + virtual const char *getMenuName() = 0; + + virtual std::size_t getCommandCount() = 0; + + virtual const char *getCommand(std::size_t) = 0; + + virtual const char *getCommandTitle(std::size_t) = 0; + + virtual void addMenuID(std::size_t) = 0; + + virtual bool ownsCommandID(std::size_t n) = 0; }; -class PluginsVisitor -{ +class PluginsVisitor { public: -virtual void visit( IPlugIn& plugin ) = 0; + virtual void visit(IPlugIn &plugin) = 0; }; -class CPlugInManager -{ +class CPlugInManager { public: -void Dispatch( std::size_t n, const char *p ); -void Init( ui::Widget main_window ); -void constructMenu( PluginsVisitor& menu ); -void Shutdown(); + void Dispatch(std::size_t n, const char *p); + + void Init(ui::Widget main_window); + + void constructMenu(PluginsVisitor &menu); + + void Shutdown(); }; -CPlugInManager& GetPlugInMgr(); +CPlugInManager &GetPlugInMgr(); #endif diff --git a/radiant/pluginmenu.cpp b/radiant/pluginmenu.cpp index 8155d0a9..e13a8219 100644 --- a/radiant/pluginmenu.cpp +++ b/radiant/pluginmenu.cpp @@ -35,144 +35,147 @@ int m_nNextPlugInID = 0; -void plugin_activated( ui::Widget widget, gpointer data ){ - const char* str = (const char*)g_object_get_data( G_OBJECT( widget ),"command" ); - GetPlugInMgr().Dispatch( gpointer_to_int( data ), str ); +void plugin_activated(ui::Widget widget, gpointer data) +{ + const char *str = (const char *) g_object_get_data(G_OBJECT(widget), "command"); + GetPlugInMgr().Dispatch(gpointer_to_int(data), str); } #include -void PlugInMenu_Add( ui::Menu plugin_menu, IPlugIn* pPlugIn ){ - ui::Widget item{ui::null}, parent{ui::null}; - ui::Menu menu{ui::null}, subMenu{ui::null}; - const char *menuText, *menuCommand; - std::stack menuStack; - - parent = ui::MenuItem( pPlugIn->getMenuName() ); - parent.show(); - plugin_menu.add(parent); - - std::size_t nCount = pPlugIn->getCommandCount(); - if ( nCount > 0 ) { - menu = ui::Menu(ui::New); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } - while ( nCount > 0 ) - { - menuText = pPlugIn->getCommandTitle( --nCount ); - menuCommand = pPlugIn->getCommand( nCount ); - - if ( menuText != 0 && strlen( menuText ) > 0 ) { - if ( !strcmp( menuText, "-" ) ) { - item = ui::Widget::from(gtk_menu_item_new()); - gtk_widget_set_sensitive( item, FALSE ); - } - else if ( !strcmp( menuText, ">" ) ) { - menuText = pPlugIn->getCommandTitle( --nCount ); - menuCommand = pPlugIn->getCommand( nCount ); - if ( !strcmp( menuText, "-" ) || !strcmp( menuText, ">" ) || !strcmp( menuText, "<" ) ) { - globalErrorStream() << pPlugIn->getMenuName() << " Invalid title (" << menuText << ") for submenu.\n"; - continue; - } - - item = ui::MenuItem( menuText ); - item.show(); - menu.add(item); - - subMenu = ui::Menu(ui::New); - gtk_menu_item_set_submenu( GTK_MENU_ITEM( item ), subMenu ); - menuStack.push( menu ); - menu = subMenu; - continue; - } - else if ( !strcmp( menuText, "<" ) ) { - if ( !menuStack.empty() ) { - menu = menuStack.top(); - menuStack.pop(); - } - else - { - globalErrorStream() << pPlugIn->getMenuName() << ": Attempt to end non-existent submenu ignored.\n"; - } - continue; - } - else - { - item = ui::MenuItem( menuText ); - g_object_set_data( G_OBJECT( item ),"command", const_cast( static_cast( menuCommand ) ) ); - item.connect( "activate", G_CALLBACK( plugin_activated ), gint_to_pointer( m_nNextPlugInID ) ); - } - item.show(); - menu.add(item); - pPlugIn->addMenuID( m_nNextPlugInID++ ); - } - } - if ( !menuStack.empty() ) { - std::size_t size = menuStack.size(); - if ( size != 0 ) { - globalErrorStream() << pPlugIn->getMenuName() << " mismatched > <. " << Unsigned( size ) << " submenu(s) not closed.\n"; - } - for ( std::size_t i = 0; i < ( size - 1 ); i++ ) - { - menuStack.pop(); - } - menu = menuStack.top(); - menuStack.pop(); - } - gtk_menu_item_set_submenu( GTK_MENU_ITEM( parent ), menu ); - } +void PlugInMenu_Add(ui::Menu plugin_menu, IPlugIn *pPlugIn) +{ + ui::Widget item{ui::null}, parent{ui::null}; + ui::Menu menu{ui::null}, subMenu{ui::null}; + const char *menuText, *menuCommand; + std::stack menuStack; + + parent = ui::MenuItem(pPlugIn->getMenuName()); + parent.show(); + plugin_menu.add(parent); + + std::size_t nCount = pPlugIn->getCommandCount(); + if (nCount > 0) { + menu = ui::Menu(ui::New); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } + while (nCount > 0) { + menuText = pPlugIn->getCommandTitle(--nCount); + menuCommand = pPlugIn->getCommand(nCount); + + if (menuText != 0 && strlen(menuText) > 0) { + if (!strcmp(menuText, "-")) { + item = ui::Widget::from(gtk_menu_item_new()); + gtk_widget_set_sensitive(item, FALSE); + } else if (!strcmp(menuText, ">")) { + menuText = pPlugIn->getCommandTitle(--nCount); + menuCommand = pPlugIn->getCommand(nCount); + if (!strcmp(menuText, "-") || !strcmp(menuText, ">") || !strcmp(menuText, "<")) { + globalErrorStream() << pPlugIn->getMenuName() << " Invalid title (" << menuText + << ") for submenu.\n"; + continue; + } + + item = ui::MenuItem(menuText); + item.show(); + menu.add(item); + + subMenu = ui::Menu(ui::New); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), subMenu); + menuStack.push(menu); + menu = subMenu; + continue; + } else if (!strcmp(menuText, "<")) { + if (!menuStack.empty()) { + menu = menuStack.top(); + menuStack.pop(); + } else { + globalErrorStream() << pPlugIn->getMenuName() + << ": Attempt to end non-existent submenu ignored.\n"; + } + continue; + } else { + item = ui::MenuItem(menuText); + g_object_set_data(G_OBJECT(item), "command", + const_cast( static_cast( menuCommand ))); + item.connect("activate", G_CALLBACK(plugin_activated), gint_to_pointer(m_nNextPlugInID)); + } + item.show(); + menu.add(item); + pPlugIn->addMenuID(m_nNextPlugInID++); + } + } + if (!menuStack.empty()) { + std::size_t size = menuStack.size(); + if (size != 0) { + globalErrorStream() << pPlugIn->getMenuName() << " mismatched > <. " << Unsigned(size) + << " submenu(s) not closed.\n"; + } + for (std::size_t i = 0; i < (size - 1); i++) { + menuStack.pop(); + } + menu = menuStack.top(); + menuStack.pop(); + } + gtk_menu_item_set_submenu(GTK_MENU_ITEM(parent), menu); + } } ui::Menu g_plugins_menu{ui::null}; ui::MenuItem g_plugins_menu_separator{ui::null}; -void PluginsMenu_populate(){ - class PluginsMenuConstructor : public PluginsVisitor - { - ui::Menu m_menu; -public: - PluginsMenuConstructor( ui::Menu menu ) : m_menu( menu ){ - } - void visit( IPlugIn& plugin ){ - PlugInMenu_Add( m_menu, &plugin ); - } - }; - - PluginsMenuConstructor constructor( g_plugins_menu ); - GetPlugInMgr().constructMenu( constructor ); +void PluginsMenu_populate() +{ + class PluginsMenuConstructor : public PluginsVisitor { + ui::Menu m_menu; + public: + PluginsMenuConstructor(ui::Menu menu) : m_menu(menu) + { + } + + void visit(IPlugIn &plugin) + { + PlugInMenu_Add(m_menu, &plugin); + } + }; + + PluginsMenuConstructor constructor(g_plugins_menu); + GetPlugInMgr().constructMenu(constructor); } -void PluginsMenu_clear(){ - m_nNextPlugInID = 0; +void PluginsMenu_clear() +{ + m_nNextPlugInID = 0; - GList* lst = g_list_find( gtk_container_get_children( GTK_CONTAINER( g_plugins_menu ) ), g_plugins_menu_separator._handle ); - while ( lst->next ) - { - g_plugins_menu.remove(ui::Widget::from(lst->next->data)); - lst = g_list_find( gtk_container_get_children( GTK_CONTAINER( g_plugins_menu ) ), g_plugins_menu_separator._handle ); - } + GList *lst = g_list_find(gtk_container_get_children(GTK_CONTAINER(g_plugins_menu)), + g_plugins_menu_separator._handle); + while (lst->next) { + g_plugins_menu.remove(ui::Widget::from(lst->next->data)); + lst = g_list_find(gtk_container_get_children(GTK_CONTAINER(g_plugins_menu)), g_plugins_menu_separator._handle); + } } -ui::MenuItem create_plugins_menu(){ - // Plugins menu - auto plugins_menu_item = new_sub_menu_item_with_mnemonic( "_Plugins" ); - auto menu = ui::Menu::from( gtk_menu_item_get_submenu( plugins_menu_item ) ); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } +ui::MenuItem create_plugins_menu() +{ + // Plugins menu + auto plugins_menu_item = new_sub_menu_item_with_mnemonic("_Plugins"); + auto menu = ui::Menu::from(gtk_menu_item_get_submenu(plugins_menu_item)); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - g_plugins_menu = menu; + g_plugins_menu = menu; - //TODO: some modules/plugins do not yet support refresh + //TODO: some modules/plugins do not yet support refresh #if 0 - create_menu_item_with_mnemonic( menu, "Refresh", makeCallbackF(Restart) ); + create_menu_item_with_mnemonic( menu, "Refresh", makeCallbackF(Restart) ); - // NOTE: the seperator is used when doing a refresh of the list, everything past the seperator is removed - g_plugins_menu_separator = menu_separator( menu ); + // NOTE: the seperator is used when doing a refresh of the list, everything past the seperator is removed + g_plugins_menu_separator = menu_separator( menu ); #endif - PluginsMenu_populate(); + PluginsMenu_populate(); - return plugins_menu_item; + return plugins_menu_item; } diff --git a/radiant/pluginmenu.h b/radiant/pluginmenu.h index b1685a61..1d2f8b65 100644 --- a/radiant/pluginmenu.h +++ b/radiant/pluginmenu.h @@ -27,6 +27,7 @@ ui::MenuItem create_plugins_menu(); void PluginsMenu_populate(); + void PluginsMenu_clear(); #endif diff --git a/radiant/plugintoolbar.cpp b/radiant/plugintoolbar.cpp index aea1b321..43122527 100644 --- a/radiant/plugintoolbar.cpp +++ b/radiant/plugintoolbar.cpp @@ -33,101 +33,113 @@ #include "mainframe.h" #include "plugin.h" -ui::Image new_plugin_image( const char* filename ){ - { - StringOutputStream fullpath( 256 ); - fullpath << GameToolsPath_get() << g_pluginsDir << "bitmaps/" << filename; - if ( auto image = image_new_from_file_with_mask(fullpath.c_str()) ) return image; - } - - { - StringOutputStream fullpath( 256 ); - fullpath << AppPath_get() << g_pluginsDir << "bitmaps/" << filename; - if ( auto image = image_new_from_file_with_mask(fullpath.c_str()) ) return image; - } - - { - StringOutputStream fullpath( 256 ); - fullpath << AppPath_get() << g_modulesDir << "bitmaps/" << filename; - if ( auto image = image_new_from_file_with_mask(fullpath.c_str()) ) return image; - } - - return image_new_missing(); +ui::Image new_plugin_image(const char *filename) +{ + { + StringOutputStream fullpath(256); + fullpath << GameToolsPath_get() << g_pluginsDir << "bitmaps/" << filename; + if (auto image = image_new_from_file_with_mask(fullpath.c_str())) { return image; } + } + + { + StringOutputStream fullpath(256); + fullpath << AppPath_get() << g_pluginsDir << "bitmaps/" << filename; + if (auto image = image_new_from_file_with_mask(fullpath.c_str())) { return image; } + } + + { + StringOutputStream fullpath(256); + fullpath << AppPath_get() << g_modulesDir << "bitmaps/" << filename; + if (auto image = image_new_from_file_with_mask(fullpath.c_str())) { return image; } + } + + return image_new_missing(); } -void toolbar_insert( ui::Toolbar toolbar, const char* icon, const char* text, const char* tooltip, IToolbarButton::EType type, GCallback handler, gpointer data ){ - if (type == IToolbarButton::eSpace) { - auto it = ui::ToolItem::from(gtk_separator_tool_item_new()); - it.show(); - toolbar.add(it); - return; - } - if (type == IToolbarButton::eButton) { - auto button = ui::ToolButton::from(gtk_tool_button_new(new_plugin_image(icon), text)); - gtk_widget_set_tooltip_text(button, tooltip); - gtk_widget_show_all(button); - button.connect("clicked", G_CALLBACK(handler), data); - toolbar.add(button); - return; - } - if (type == IToolbarButton::eToggleButton) { - auto button = ui::ToolButton::from(gtk_toggle_tool_button_new()); - gtk_tool_button_set_icon_widget(button, new_plugin_image(icon)); - gtk_tool_button_set_label(button, text); - gtk_widget_set_tooltip_text(button, tooltip); - gtk_widget_show_all(button); - button.connect("toggled", G_CALLBACK(handler), data); - toolbar.add(button); - return; - } - ERROR_MESSAGE( "invalid toolbar button type" ); +void +toolbar_insert(ui::Toolbar toolbar, const char *icon, const char *text, const char *tooltip, IToolbarButton::EType type, + GCallback handler, gpointer data) +{ + if (type == IToolbarButton::eSpace) { + auto it = ui::ToolItem::from(gtk_separator_tool_item_new()); + it.show(); + toolbar.add(it); + return; + } + if (type == IToolbarButton::eButton) { + auto button = ui::ToolButton::from(gtk_tool_button_new(new_plugin_image(icon), text)); + gtk_widget_set_tooltip_text(button, tooltip); + gtk_widget_show_all(button); + button.connect("clicked", G_CALLBACK(handler), data); + toolbar.add(button); + return; + } + if (type == IToolbarButton::eToggleButton) { + auto button = ui::ToolButton::from(gtk_toggle_tool_button_new()); + gtk_tool_button_set_icon_widget(button, new_plugin_image(icon)); + gtk_tool_button_set_label(button, text); + gtk_widget_set_tooltip_text(button, tooltip); + gtk_widget_show_all(button); + button.connect("toggled", G_CALLBACK(handler), data); + toolbar.add(button); + return; + } + ERROR_MESSAGE("invalid toolbar button type"); } -void ActivateToolbarButton( ui::ToolButton widget, gpointer data ){ - (const_cast( reinterpret_cast( data )))->activate(); +void ActivateToolbarButton(ui::ToolButton widget, gpointer data) +{ + (const_cast( reinterpret_cast( data )))->activate(); } -void PlugInToolbar_AddButton( ui::Toolbar toolbar, const IToolbarButton* button ){ - toolbar_insert( toolbar, button->getImage(), button->getText(), button->getTooltip(), button->getType(), G_CALLBACK( ActivateToolbarButton ), reinterpret_cast( const_cast( button ) ) ); +void PlugInToolbar_AddButton(ui::Toolbar toolbar, const IToolbarButton *button) +{ + toolbar_insert(toolbar, button->getImage(), button->getText(), button->getTooltip(), button->getType(), + G_CALLBACK(ActivateToolbarButton), + reinterpret_cast( const_cast( button ))); } ui::Toolbar g_plugin_toolbar{ui::null}; -void PluginToolbar_populate(){ - class AddToolbarItemVisitor : public ToolbarModules::Visitor - { - ui::Toolbar m_toolbar; -public: - AddToolbarItemVisitor( ui::Toolbar toolbar ) - : m_toolbar( toolbar ){ - } - void visit( const char* name, const _QERPlugToolbarTable& table ) const { - const std::size_t count = table.m_pfnToolbarButtonCount(); - for ( std::size_t i = 0; i < count; ++i ) - { - PlugInToolbar_AddButton( m_toolbar, table.m_pfnGetToolbarButton( i ) ); - } - } - - } visitor( g_plugin_toolbar ); - - Radiant_getToolbarModules().foreachModule( visitor ); +void PluginToolbar_populate() +{ + class AddToolbarItemVisitor : public ToolbarModules::Visitor { + ui::Toolbar m_toolbar; + public: + AddToolbarItemVisitor(ui::Toolbar toolbar) + : m_toolbar(toolbar) + { + } + + void visit(const char *name, const _QERPlugToolbarTable &table) const + { + const std::size_t count = table.m_pfnToolbarButtonCount(); + for (std::size_t i = 0; i < count; ++i) { + PlugInToolbar_AddButton(m_toolbar, table.m_pfnGetToolbarButton(i)); + } + } + + } visitor(g_plugin_toolbar); + + Radiant_getToolbarModules().foreachModule(visitor); } -void PluginToolbar_clear(){ - container_remove_all( g_plugin_toolbar ); +void PluginToolbar_clear() +{ + container_remove_all(g_plugin_toolbar); } -ui::Toolbar create_plugin_toolbar(){ +ui::Toolbar create_plugin_toolbar() +{ - auto toolbar = ui::Toolbar::from( gtk_toolbar_new() ); - gtk_orientable_set_orientation( GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL ); - gtk_toolbar_set_style( toolbar, GTK_TOOLBAR_ICONS ); - toolbar.show(); + auto toolbar = ui::Toolbar::from(gtk_toolbar_new()); + gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL); + gtk_toolbar_set_style(toolbar, GTK_TOOLBAR_ICONS); + toolbar.show(); - g_plugin_toolbar = toolbar; + g_plugin_toolbar = toolbar; - PluginToolbar_populate(); + PluginToolbar_populate(); - return toolbar; + return toolbar; } diff --git a/radiant/plugintoolbar.h b/radiant/plugintoolbar.h index ca35b1bc..9445cdf6 100644 --- a/radiant/plugintoolbar.h +++ b/radiant/plugintoolbar.h @@ -25,9 +25,11 @@ #define INCLUDED_PLUGINTOOLBAR_H ui::Toolbar create_plugin_toolbar(); + void PluginToolbar_populate(); + void PluginToolbar_clear(); -ui::Image new_plugin_image( const char* filename ); // filename is relative to plugin bitmaps path +ui::Image new_plugin_image(const char *filename); // filename is relative to plugin bitmaps path #endif diff --git a/radiant/points.cpp b/radiant/points.cpp index c4a56492..6e29109c 100644 --- a/radiant/points.cpp +++ b/radiant/points.cpp @@ -50,330 +50,365 @@ class CPointfile; -void Pointfile_Parse( CPointfile& pointfile ); +void Pointfile_Parse(CPointfile &pointfile); -class CPointfile : public ISAXHandler, public Renderable, public OpenGLRenderable -{ -enum -{ - MAX_POINTFILE = 8192, -}; -Vector3 s_pointvecs[MAX_POINTFILE]; -std::size_t s_num_points; -int m_displaylist; -static Shader* m_renderstate; -StringOutputStream m_characters; -public: -CPointfile(){ -} -~CPointfile(){ -} -void Init(); -void PushPoint( const Vector3& v ); -void GenerateDisplayList(); -// SAX interface -void Release(){ - // blank because not heap-allocated -} -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 ); -const char* getName(); -typedef const Vector3* const_iterator; - -const_iterator begin() const { - return &s_pointvecs[0]; -} -const_iterator end() const { - return &s_pointvecs[s_num_points]; -} +class CPointfile : public ISAXHandler, public Renderable, public OpenGLRenderable { + enum { + MAX_POINTFILE = 8192, + }; + Vector3 s_pointvecs[MAX_POINTFILE]; + std::size_t s_num_points; + int m_displaylist; + static Shader *m_renderstate; + StringOutputStream m_characters; +public: + CPointfile() + { + } -bool shown() const { - return m_displaylist != 0; -} -void show( bool show ){ - if ( show && !shown() ) { - Pointfile_Parse( *this ); - GenerateDisplayList(); - SceneChangeNotify(); - } - else if ( !show && shown() ) { - glDeleteLists( m_displaylist, 1 ); - m_displaylist = 0; - SceneChangeNotify(); - } -} + ~CPointfile() + { + } -void render( RenderStateFlags state ) const { - glCallList( m_displaylist ); -} + void Init(); -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - if ( shown() ) { - renderer.SetState( m_renderstate, Renderer::eWireframeOnly ); - renderer.SetState( m_renderstate, Renderer::eFullMaterials ); - renderer.addRenderable( *this, g_matrix4_identity ); - } -} -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - renderSolid( renderer, volume ); -} + void PushPoint(const Vector3 &v); -static void constructStatic(){ - m_renderstate = GlobalShaderCache().capture( "$POINTFILE" ); -} + void GenerateDisplayList(); -static void destroyStatic(){ - GlobalShaderCache().release( "$POINTFILE" ); -} +// SAX interface + void Release() + { + // blank because not heap-allocated + } + + 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); + + const char *getName(); + + typedef const Vector3 *const_iterator; + + const_iterator begin() const + { + return &s_pointvecs[0]; + } + + const_iterator end() const + { + return &s_pointvecs[s_num_points]; + } + + bool shown() const + { + return m_displaylist != 0; + } + + void show(bool show) + { + if (show && !shown()) { + Pointfile_Parse(*this); + GenerateDisplayList(); + SceneChangeNotify(); + } else if (!show && shown()) { + glDeleteLists(m_displaylist, 1); + m_displaylist = 0; + SceneChangeNotify(); + } + } + + void render(RenderStateFlags state) const + { + glCallList(m_displaylist); + } + + void renderSolid(Renderer &renderer, const VolumeTest &volume) const + { + if (shown()) { + renderer.SetState(m_renderstate, Renderer::eWireframeOnly); + renderer.SetState(m_renderstate, Renderer::eFullMaterials); + renderer.addRenderable(*this, g_matrix4_identity); + } + } + + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + renderSolid(renderer, volume); + } + + static void constructStatic() + { + m_renderstate = GlobalShaderCache().capture("$POINTFILE"); + } + + static void destroyStatic() + { + GlobalShaderCache().release("$POINTFILE"); + } }; -Shader* CPointfile::m_renderstate = 0; +Shader *CPointfile::m_renderstate = 0; -namespace -{ -CPointfile s_pointfile; +namespace { + CPointfile s_pointfile; } -ISAXHandler& g_pointfile = s_pointfile; +ISAXHandler &g_pointfile = s_pointfile; static CPointfile::const_iterator s_check_point; -void CPointfile::Init(){ - s_num_points = 0; - m_displaylist = 0; +void CPointfile::Init() +{ + s_num_points = 0; + m_displaylist = 0; } -void CPointfile::PushPoint( const Vector3& v ){ - if ( s_num_points < MAX_POINTFILE ) { - s_pointvecs[s_num_points] = v; - ++s_num_points; - } +void CPointfile::PushPoint(const Vector3 &v) +{ + if (s_num_points < MAX_POINTFILE) { + s_pointvecs[s_num_points] = v; + ++s_num_points; + } } // create the display list at the end -void CPointfile::GenerateDisplayList(){ - m_displaylist = glGenLists( 1 ); +void CPointfile::GenerateDisplayList() +{ + m_displaylist = glGenLists(1); - glNewList( m_displaylist, GL_COMPILE ); + glNewList(m_displaylist, GL_COMPILE); - glBegin( GL_LINE_STRIP ); - for ( std::size_t i = 0; i < s_num_points; i++ ) - glVertex3fv( vector3_to_array( s_pointvecs[i] ) ); - glEnd(); - glLineWidth( 1 ); + glBegin(GL_LINE_STRIP); + for (std::size_t i = 0; i < s_num_points; i++) + glVertex3fv(vector3_to_array(s_pointvecs[i])); + glEnd(); + glLineWidth(1); - glEndList(); + glEndList(); } // old (but still relevant) pointfile code ------------------------------------- -void Pointfile_Delete( void ){ - const char* mapname = Map_Name( g_map ); - StringOutputStream name( 256 ); - name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".lin"; - file_remove( name.c_str() ); +void Pointfile_Delete(void) +{ + const char *mapname = Map_Name(g_map); + StringOutputStream name(256); + name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".lin"; + file_remove(name.c_str()); } // advance camera to next point -void Pointfile_Next( void ){ - if ( !s_pointfile.shown() ) { - return; - } - - if ( s_check_point + 2 == s_pointfile.end() ) { - globalOutputStream() << "End of pointfile\n"; - return; - } - - CPointfile::const_iterator i = ++s_check_point; - - - CamWnd& camwnd = *g_pParentWnd->GetCamWnd(); - Camera_setOrigin( camwnd, *i ); - g_pParentWnd->GetXYWnd()->SetOrigin( *i ); - { - Vector3 dir( vector3_normalised( vector3_subtracted( *( ++i ), Camera_getOrigin( camwnd ) ) ) ); - Vector3 angles( Camera_getAngles( camwnd ) ); - angles[CAMERA_YAW] = static_cast( radians_to_degrees( atan2( dir[1], dir[0] ) ) ); - angles[CAMERA_PITCH] = static_cast( radians_to_degrees( asin( dir[2] ) ) ); - Camera_setAngles( camwnd, angles ); - } +void Pointfile_Next(void) +{ + if (!s_pointfile.shown()) { + return; + } + + if (s_check_point + 2 == s_pointfile.end()) { + globalOutputStream() << "End of pointfile\n"; + return; + } + + CPointfile::const_iterator i = ++s_check_point; + + + CamWnd &camwnd = *g_pParentWnd->GetCamWnd(); + Camera_setOrigin(camwnd, *i); + g_pParentWnd->GetXYWnd()->SetOrigin(*i); + { + Vector3 dir(vector3_normalised(vector3_subtracted(*(++i), Camera_getOrigin(camwnd)))); + Vector3 angles(Camera_getAngles(camwnd)); + angles[CAMERA_YAW] = static_cast( radians_to_degrees(atan2(dir[1], dir[0]))); + angles[CAMERA_PITCH] = static_cast( radians_to_degrees(asin(dir[2]))); + Camera_setAngles(camwnd, angles); + } } // advance camera to previous point -void Pointfile_Prev( void ){ - if ( !s_pointfile.shown() ) { - return; - } - - if ( s_check_point == s_pointfile.begin() ) { - globalOutputStream() << "Start of pointfile\n"; - return; - } - - CPointfile::const_iterator i = --s_check_point; - - CamWnd& camwnd = *g_pParentWnd->GetCamWnd(); - Camera_setOrigin( camwnd, *i ); - g_pParentWnd->GetXYWnd()->SetOrigin( *i ); - { - Vector3 dir( vector3_normalised( vector3_subtracted( *( ++i ), Camera_getOrigin( camwnd ) ) ) ); - Vector3 angles( Camera_getAngles( camwnd ) ); - angles[CAMERA_YAW] = static_cast( radians_to_degrees( atan2( dir[1], dir[0] ) ) ); - angles[CAMERA_PITCH] = static_cast( radians_to_degrees( asin( dir[2] ) ) ); - Camera_setAngles( camwnd, angles ); - } +void Pointfile_Prev(void) +{ + if (!s_pointfile.shown()) { + return; + } + + if (s_check_point == s_pointfile.begin()) { + globalOutputStream() << "Start of pointfile\n"; + return; + } + + CPointfile::const_iterator i = --s_check_point; + + CamWnd &camwnd = *g_pParentWnd->GetCamWnd(); + Camera_setOrigin(camwnd, *i); + g_pParentWnd->GetXYWnd()->SetOrigin(*i); + { + Vector3 dir(vector3_normalised(vector3_subtracted(*(++i), Camera_getOrigin(camwnd)))); + Vector3 angles(Camera_getAngles(camwnd)); + angles[CAMERA_YAW] = static_cast( radians_to_degrees(atan2(dir[1], dir[0]))); + angles[CAMERA_PITCH] = static_cast( radians_to_degrees(asin(dir[2]))); + Camera_setAngles(camwnd, angles); + } } -int LoadFile( const char *filename, void **bufferptr ){ - FILE *f; - long len; +int LoadFile(const char *filename, void **bufferptr) +{ + FILE *f; + long len; - f = fopen( filename, "rb" ); - if ( f == 0 ) { - return -1; - } + f = fopen(filename, "rb"); + if (f == 0) { + return -1; + } - fseek( f, 0, SEEK_END ); - len = ftell( f ); - rewind( f ); + fseek(f, 0, SEEK_END); + len = ftell(f); + rewind(f); - *bufferptr = malloc( len + 1 ); - if ( *bufferptr == 0 ) { - return -1; - } + *bufferptr = malloc(len + 1); + if (*bufferptr == 0) { + return -1; + } - fread( *bufferptr, 1, len, f ); - fclose( f ); + fread(*bufferptr, 1, len, f); + fclose(f); - // we need to end the buffer with a 0 - ( (char*) ( *bufferptr ) )[len] = 0; + // we need to end the buffer with a 0 + ((char *) (*bufferptr))[len] = 0; - return len; + return len; } -void Pointfile_Parse( CPointfile& pointfile ){ - int size; - char *data; - char *text; - int line = 1; - - const char* mapname = Map_Name( g_map ); - StringOutputStream name( 256 ); - name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".lin"; - - size = LoadFile( name.c_str(), (void**)&data ); - if ( size == -1 ) { - globalErrorStream() << "Pointfile " << name.c_str() << " not found\n"; - return; - } - - // store a pointer - text = data; - - globalOutputStream() << "Reading pointfile " << name.c_str() << "\n"; - - pointfile.Init(); - - while ( *data ) - { - Vector3 v; - if ( sscanf( data,"%f %f %f", &v[0], &v[1], &v[2] ) != 3 ) { - globalOutputStream() << "Corrupt point file, line " << line << "\n"; - break; - } - - while ( *data && *data != '\n' ) - { - if ( *( data - 1 ) == ' ' && *( data ) == '-' && *( data + 1 ) == ' ' ) { - break; - } - data++; - } - // deal with zhlt style point files. - if ( *data == '-' ) { - if ( sscanf( data,"- %f %f %f", &v[0], &v[1], &v[2] ) != 3 ) { - globalOutputStream() << "Corrupt point file, line " << line << "\n"; - break; - } - - while ( *data && *data != '\n' ) - data++; - - } - while ( *data == '\n' ) - { - data++; // skip the \n - line++; - } - pointfile.PushPoint( v ); - } - - g_free( text ); +void Pointfile_Parse(CPointfile &pointfile) +{ + int size; + char *data; + char *text; + int line = 1; + + const char *mapname = Map_Name(g_map); + StringOutputStream name(256); + name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".lin"; + + size = LoadFile(name.c_str(), (void **) &data); + if (size == -1) { + globalErrorStream() << "Pointfile " << name.c_str() << " not found\n"; + return; + } + + // store a pointer + text = data; + + globalOutputStream() << "Reading pointfile " << name.c_str() << "\n"; + + pointfile.Init(); + + while (*data) { + Vector3 v; + if (sscanf(data, "%f %f %f", &v[0], &v[1], &v[2]) != 3) { + globalOutputStream() << "Corrupt point file, line " << line << "\n"; + break; + } + + while (*data && *data != '\n') { + if (*(data - 1) == ' ' && *(data) == '-' && *(data + 1) == ' ') { + break; + } + data++; + } + // deal with zhlt style point files. + if (*data == '-') { + if (sscanf(data, "- %f %f %f", &v[0], &v[1], &v[2]) != 3) { + globalOutputStream() << "Corrupt point file, line " << line << "\n"; + break; + } + + while (*data && *data != '\n') { + data++; + } + + } + while (*data == '\n') { + data++; // skip the \n + line++; + } + pointfile.PushPoint(v); + } + + g_free(text); } -void Pointfile_Clear(){ - s_pointfile.show( false ); +void Pointfile_Clear() +{ + s_pointfile.show(false); } -void Pointfile_Toggle(){ - s_pointfile.show( !s_pointfile.shown() ); +void Pointfile_Toggle() +{ + s_pointfile.show(!s_pointfile.shown()); - s_check_point = s_pointfile.begin(); + s_check_point = s_pointfile.begin(); } -void Pointfile_Construct(){ - CPointfile::constructStatic(); +void Pointfile_Construct() +{ + CPointfile::constructStatic(); - GlobalShaderCache().attachRenderable( s_pointfile ); + GlobalShaderCache().attachRenderable(s_pointfile); - GlobalCommands_insert( "TogglePointfile", makeCallbackF(Pointfile_Toggle) ); - GlobalCommands_insert( "NextLeakSpot", makeCallbackF(Pointfile_Next), Accelerator( 'K', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalCommands_insert( "PrevLeakSpot", makeCallbackF(Pointfile_Prev), Accelerator( 'L', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); + GlobalCommands_insert("TogglePointfile", makeCallbackF(Pointfile_Toggle)); + GlobalCommands_insert("NextLeakSpot", makeCallbackF(Pointfile_Next), + Accelerator('K', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalCommands_insert("PrevLeakSpot", makeCallbackF(Pointfile_Prev), + Accelerator('L', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); } -void Pointfile_Destroy(){ - GlobalShaderCache().detachRenderable( s_pointfile ); +void Pointfile_Destroy() +{ + GlobalShaderCache().detachRenderable(s_pointfile); - CPointfile::destroyStatic(); + CPointfile::destroyStatic(); } - // CPointfile implementation for SAX-specific stuff ------------------------------- -void CPointfile::saxStartElement( message_info_t *ctx, const xmlChar *name, const xmlChar **attrs ){ - if ( string_equal( reinterpret_cast( name ), "polyline" ) ) { - Init(); - // there's a prefs setting to avoid stopping on leak - if ( !g_WatchBSP_LeakStop ) { - ctx->stop_depth = 0; - } - } +void CPointfile::saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs) +{ + if (string_equal(reinterpret_cast( name ), "polyline")) { + Init(); + // there's a prefs setting to avoid stopping on leak + if (!g_WatchBSP_LeakStop) { + ctx->stop_depth = 0; + } + } } -void CPointfile::saxEndElement( message_info_t *ctx, const xmlChar *name ){ - if ( string_equal( reinterpret_cast( name ), "polyline" ) ) { - // we are done - GenerateDisplayList(); - SceneChangeNotify(); - s_check_point = begin(); - } - else if ( string_equal( reinterpret_cast( name ), "point" ) ) { - Vector3 v; - sscanf( m_characters.c_str(), "%f %f %f\n", &v[0], &v[1], &v[2] ); - PushPoint( v ); - m_characters.clear(); - } +void CPointfile::saxEndElement(message_info_t *ctx, const xmlChar *name) +{ + if (string_equal(reinterpret_cast( name ), "polyline")) { + // we are done + GenerateDisplayList(); + SceneChangeNotify(); + s_check_point = begin(); + } else if (string_equal(reinterpret_cast( name ), "point")) { + Vector3 v; + sscanf(m_characters.c_str(), "%f %f %f\n", &v[0], &v[1], &v[2]); + PushPoint(v); + m_characters.clear(); + } } // only "point" is expected to have characters around here -void CPointfile::saxCharacters( message_info_t *ctx, const xmlChar *ch, int len ){ - m_characters.write( reinterpret_cast( ch ), len ); +void CPointfile::saxCharacters(message_info_t *ctx, const xmlChar *ch, int len) +{ + m_characters.write(reinterpret_cast( ch ), len); } -const char* CPointfile::getName(){ - return "Map leaked"; +const char *CPointfile::getName() +{ + return "Map leaked"; } diff --git a/radiant/points.h b/radiant/points.h index bd970e6e..449af54f 100644 --- a/radiant/points.h +++ b/radiant/points.h @@ -29,12 +29,15 @@ #define INCLUDED_POINTS_H void Pointfile_Clear(); -void Pointfile_Delete( void ); + +void Pointfile_Delete(void); void Pointfile_Construct(); + void Pointfile_Destroy(); class ISAXHandler; -extern ISAXHandler& g_pointfile; + +extern ISAXHandler &g_pointfile; #endif diff --git a/radiant/preferencedictionary.h b/radiant/preferencedictionary.h index 382271ee..7f826e84 100644 --- a/radiant/preferencedictionary.h +++ b/radiant/preferencedictionary.h @@ -29,235 +29,252 @@ #include "versionlib.h" #include -class PreferenceDictionary : public PreferenceSystem -{ -class PreferenceEntry -{ -Property m_cb; -public: -PreferenceEntry( const Property& cb ) - : m_cb( cb ){ -} -void importString( const char* string ){ - m_cb.set( string ); -} -void exportString( const Callback & importer ){ - m_cb.get( importer ); -} -}; - -typedef std::map PreferenceEntries; -PreferenceEntries m_preferences; - -typedef std::map PreferenceCache; -PreferenceCache m_cache; +class PreferenceDictionary : public PreferenceSystem { + class PreferenceEntry { + Property m_cb; + public: + PreferenceEntry(const Property &cb) + : m_cb(cb) + { + } + + void importString(const char *string) + { + m_cb.set(string); + } + + void exportString(const Callback &importer) + { + m_cb.get(importer); + } + }; + + typedef std::map PreferenceEntries; + PreferenceEntries m_preferences; + + typedef std::map PreferenceCache; + PreferenceCache m_cache; public: -typedef PreferenceEntries::iterator iterator; - -iterator begin(){ - return m_preferences.begin(); -} -iterator end(){ - return m_preferences.end(); -} -iterator find( const char* name ){ - return m_preferences.find( name ); -} - -void registerPreference( const char* name, const Property& cb ){ - m_preferences.insert( PreferenceEntries::value_type( name, PreferenceEntry( cb ) ) ); - PreferenceCache::iterator i = m_cache.find( name ); - if ( i != m_cache.end() ) { - cb.set( i->second.c_str() ); - m_cache.erase( i ); - } -} - -void importPref( const char* name, const char* value ){ - PreferenceEntries::iterator i = m_preferences.find( name ); - if ( i != m_preferences.end() ) { - ( *i ).second.importString( value ); - } - else - { - m_cache.erase( name ); - m_cache.insert( PreferenceCache::value_type( name, value ) ); - } -} -}; - -inline void XMLPreference_importString( XMLImporter& importer, const char* value ){ - importer.write( value, string_length( value ) ); -} -typedef ReferenceCaller XMLPreferenceImportStringCaller; - -class XMLPreferenceDictionaryExporter : public XMLExporter -{ -class XMLQPrefElement : public XMLElement -{ -const char* m_version; -public: -XMLQPrefElement( const char* version ) : m_version( version ){ -} -const char* name() const { - return "qpref"; -} -const char* attribute( const char* name ) const { - if ( string_equal( name, "version" ) ) { - return m_version; - } - return ""; -} -void forEachAttribute( XMLAttrVisitor& visitor ) const { - visitor.visit( "version", m_version ); -} + typedef PreferenceEntries::iterator iterator; + + iterator begin() + { + return m_preferences.begin(); + } + + iterator end() + { + return m_preferences.end(); + } + + iterator find(const char *name) + { + return m_preferences.find(name); + } + + void registerPreference(const char *name, const Property &cb) + { + m_preferences.insert(PreferenceEntries::value_type(name, PreferenceEntry(cb))); + PreferenceCache::iterator i = m_cache.find(name); + if (i != m_cache.end()) { + cb.set(i->second.c_str()); + m_cache.erase(i); + } + } + + void importPref(const char *name, const char *value) + { + PreferenceEntries::iterator i = m_preferences.find(name); + if (i != m_preferences.end()) { + (*i).second.importString(value); + } else { + m_cache.erase(name); + m_cache.insert(PreferenceCache::value_type(name, value)); + } + } }; -class XMLPreferenceElement : public XMLElement +inline void XMLPreference_importString(XMLImporter &importer, const char *value) { -const char* m_name; -public: -XMLPreferenceElement( const char* name ) - : m_name( name ){ + importer.write(value, string_length(value)); } -const char* name() const { - return "epair"; -} -const char* attribute( const char* name ) const { - if ( string_equal( name, "name" ) ) { - return m_name; - } - return ""; -} -void forEachAttribute( XMLAttrVisitor& visitor ) const { - visitor.visit( "name", m_name ); -} -}; -typedef PreferenceDictionary PreferenceEntries; -PreferenceEntries& m_preferences; -const char* m_version; +typedef ReferenceCaller XMLPreferenceImportStringCaller; + +class XMLPreferenceDictionaryExporter : public XMLExporter { + class XMLQPrefElement : public XMLElement { + const char *m_version; + public: + XMLQPrefElement(const char *version) : m_version(version) + { + } + + const char *name() const + { + return "qpref"; + } + + const char *attribute(const char *name) const + { + if (string_equal(name, "version")) { + return m_version; + } + return ""; + } + + void forEachAttribute(XMLAttrVisitor &visitor) const + { + visitor.visit("version", m_version); + } + }; + + class XMLPreferenceElement : public XMLElement { + const char *m_name; + public: + XMLPreferenceElement(const char *name) + : m_name(name) + { + } + + const char *name() const + { + return "epair"; + } + + const char *attribute(const char *name) const + { + if (string_equal(name, "name")) { + return m_name; + } + return ""; + } + + void forEachAttribute(XMLAttrVisitor &visitor) const + { + visitor.visit("name", m_name); + } + }; + + typedef PreferenceDictionary PreferenceEntries; + PreferenceEntries &m_preferences; + const char *m_version; public: -XMLPreferenceDictionaryExporter( PreferenceDictionary& preferences, const char* version ) - : m_preferences( preferences ), m_version( version ){ -} + XMLPreferenceDictionaryExporter(PreferenceDictionary &preferences, const char *version) + : m_preferences(preferences), m_version(version) + { + } -void exportXML( XMLImporter& importer ){ - importer.write( "\n", 1 ); + void exportXML(XMLImporter &importer) + { + importer.write("\n", 1); - XMLQPrefElement qpref_element( m_version ); - importer.pushElement( qpref_element ); - importer.write( "\n", 1 ); + XMLQPrefElement qpref_element(m_version); + importer.pushElement(qpref_element); + importer.write("\n", 1); - for ( PreferenceEntries::iterator i = m_preferences.begin(); i != m_preferences.end(); ++i ) - { - XMLPreferenceElement epair_element( ( *i ).first.c_str() ); + for (PreferenceEntries::iterator i = m_preferences.begin(); i != m_preferences.end(); ++i) { + XMLPreferenceElement epair_element((*i).first.c_str()); - importer.pushElement( epair_element ); + importer.pushElement(epair_element); - ( *i ).second.exportString( XMLPreferenceImportStringCaller( importer ) ); + (*i).second.exportString(XMLPreferenceImportStringCaller(importer)); - importer.popElement( epair_element.name() ); - importer.write( "\n", 1 ); - } + importer.popElement(epair_element.name()); + importer.write("\n", 1); + } - importer.popElement( qpref_element.name() ); - importer.write( "\n", 1 ); -} + importer.popElement(qpref_element.name()); + importer.write("\n", 1); + } }; -class XMLPreferenceDictionaryImporter : public XMLImporter -{ -struct xml_state_t -{ - enum ETag - { - tag_qpref, - tag_qpref_ignore, - tag_epair, - tag_epair_ignore - }; - - xml_state_t( ETag tag ) - : m_tag( tag ){ - } - - ETag m_tag; - CopiedString m_name; - StringOutputStream m_ostream; -}; - -typedef std::vector xml_stack_t; -xml_stack_t m_xml_stack; - -typedef PreferenceDictionary PreferenceEntries; -PreferenceEntries& m_preferences; -Version m_version; +class XMLPreferenceDictionaryImporter : public XMLImporter { + struct xml_state_t { + enum ETag { + tag_qpref, + tag_qpref_ignore, + tag_epair, + tag_epair_ignore + }; + + xml_state_t(ETag tag) + : m_tag(tag) + { + } + + ETag m_tag; + CopiedString m_name; + StringOutputStream m_ostream; + }; + + typedef std::vector xml_stack_t; + xml_stack_t m_xml_stack; + + typedef PreferenceDictionary PreferenceEntries; + PreferenceEntries &m_preferences; + Version m_version; public: -XMLPreferenceDictionaryImporter( PreferenceDictionary& preferences, const char* version ) - : m_preferences( preferences ), m_version( version_parse( version ) ){ -} - -void pushElement( const XMLElement& element ){ - if ( m_xml_stack.empty() ) { - if ( string_equal( element.name(), "qpref" ) ) { - Version dataVersion( version_parse( element.attribute( "version" ) ) ); - if ( !version_compatible( m_version, dataVersion ) ) { - globalOutputStream() << "qpref import: data version " << dataVersion << " is not compatible with code version " << m_version << "\n"; - m_xml_stack.push_back( xml_state_t::tag_qpref_ignore ); - } - else - { - globalOutputStream() << "qpref import: data version " << dataVersion << " is compatible with code version " << m_version << "\n"; - m_xml_stack.push_back( xml_state_t::tag_qpref ); - } - } - else - { - // not valid - } - } - else - { - switch ( m_xml_stack.back().m_tag ) - { - case xml_state_t::tag_qpref: - if ( string_equal( element.name(), "epair" ) ) { - m_xml_stack.push_back( xml_state_t::tag_epair ); - m_xml_stack.back().m_name = element.attribute( "name" ); - } - else - { - // not valid - } - break; - case xml_state_t::tag_qpref_ignore: - if ( string_equal( element.name(), "epair" ) ) { - m_xml_stack.push_back( xml_state_t::tag_epair_ignore ); - } - else - { - // not valid - } - break; - case xml_state_t::tag_epair: - case xml_state_t::tag_epair_ignore: - // not valid - break; - } - } - -} -void popElement( const char* name ){ - if ( m_xml_stack.back().m_tag == xml_state_t::tag_epair ) { - m_preferences.importPref( m_xml_stack.back().m_name.c_str(), m_xml_stack.back().m_ostream.c_str() ); - } - m_xml_stack.pop_back(); -} -std::size_t write( const char* buffer, std::size_t length ){ - return m_xml_stack.back().m_ostream.write( buffer, length ); -} + XMLPreferenceDictionaryImporter(PreferenceDictionary &preferences, const char *version) + : m_preferences(preferences), m_version(version_parse(version)) + { + } + + void pushElement(const XMLElement &element) + { + if (m_xml_stack.empty()) { + if (string_equal(element.name(), "qpref")) { + Version dataVersion(version_parse(element.attribute("version"))); + if (!version_compatible(m_version, dataVersion)) { + globalOutputStream() << "qpref import: data version " << dataVersion + << " is not compatible with code version " << m_version << "\n"; + m_xml_stack.push_back(xml_state_t::tag_qpref_ignore); + } else { + globalOutputStream() << "qpref import: data version " << dataVersion + << " is compatible with code version " << m_version << "\n"; + m_xml_stack.push_back(xml_state_t::tag_qpref); + } + } else { + // not valid + } + } else { + switch (m_xml_stack.back().m_tag) { + case xml_state_t::tag_qpref: + if (string_equal(element.name(), "epair")) { + m_xml_stack.push_back(xml_state_t::tag_epair); + m_xml_stack.back().m_name = element.attribute("name"); + } else { + // not valid + } + break; + case xml_state_t::tag_qpref_ignore: + if (string_equal(element.name(), "epair")) { + m_xml_stack.push_back(xml_state_t::tag_epair_ignore); + } else { + // not valid + } + break; + case xml_state_t::tag_epair: + case xml_state_t::tag_epair_ignore: + // not valid + break; + } + } + + } + + void popElement(const char *name) + { + if (m_xml_stack.back().m_tag == xml_state_t::tag_epair) { + m_preferences.importPref(m_xml_stack.back().m_name.c_str(), m_xml_stack.back().m_ostream.c_str()); + } + m_xml_stack.pop_back(); + } + + std::size_t write(const char *buffer, std::size_t length) + { + return m_xml_stack.back().m_ostream.write(buffer, length); + } }; #endif diff --git a/radiant/preferences.cpp b/radiant/preferences.cpp index 091a88f3..fbd98151 100644 --- a/radiant/preferences.cpp +++ b/radiant/preferences.cpp @@ -52,36 +52,42 @@ #include "gtkdlgs.h" - -void Global_constructPreferences( PreferencesPage& page ){ - page.appendCheckBox( "Console", "Enable Logging", g_Console_enableLogging ); +void Global_constructPreferences(PreferencesPage &page) +{ + page.appendCheckBox("Console", "Enable Logging", g_Console_enableLogging); } -void Interface_constructPreferences( PreferencesPage& page ){ +void Interface_constructPreferences(PreferencesPage &page) +{ #if GDEF_OS_WINDOWS - page.appendCheckBox( "", "Default Text Editor", g_TextEditor_useWin32Editor ); + page.appendCheckBox( "", "Default Text Editor", g_TextEditor_useWin32Editor ); #else - { - ui::CheckButton use_custom = page.appendCheckBox( "Text Editor", "Custom", g_TextEditor_useCustomEditor ); - ui::Widget custom_editor = page.appendPathEntry( "Text Editor Command", g_TextEditor_editorCommand, true ); - Widget_connectToggleDependency( custom_editor, use_custom ); - } + { + ui::CheckButton use_custom = page.appendCheckBox("Text Editor", "Custom", g_TextEditor_useCustomEditor); + ui::Widget custom_editor = page.appendPathEntry("Text Editor Command", g_TextEditor_editorCommand, true); + Widget_connectToggleDependency(custom_editor, use_custom); + } #endif } -void Mouse_constructPreferences( PreferencesPage& page ){ - { - const char* buttons[] = { "2 button", "3 button", }; - page.appendRadio( "Mouse Type", g_glwindow_globals.m_nMouseType, STRING_ARRAY_RANGE( buttons ) ); - } - page.appendCheckBox( "Right Button", "Activates Context Menu", g_xywindow_globals.m_bRightClick ); +void Mouse_constructPreferences(PreferencesPage &page) +{ + { + const char *buttons[] = {"2 button", "3 button",}; + page.appendRadio("Mouse Type", g_glwindow_globals.m_nMouseType, STRING_ARRAY_RANGE(buttons)); + } + page.appendCheckBox("Right Button", "Activates Context Menu", g_xywindow_globals.m_bRightClick); } -void Mouse_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Mouse", "Mouse Preferences" ) ); - Mouse_constructPreferences( page ); + +void Mouse_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Mouse", "Mouse Preferences")); + Mouse_constructPreferences(page); } -void Mouse_registerPreferencesPage(){ - PreferencesDialog_addInterfacePage( makeCallbackF(Mouse_constructPage) ); + +void Mouse_registerPreferencesPage() +{ + PreferencesDialog_addInterfacePage(makeCallbackF(Mouse_constructPage)); } @@ -94,61 +100,62 @@ void Mouse_registerPreferencesPage(){ #include #include -inline const char* xmlAttr_getName( xmlAttrPtr attr ){ - return reinterpret_cast( attr->name ); -} - -inline const char* xmlAttr_getValue( xmlAttrPtr attr ){ - return reinterpret_cast( attr->children->content ); +inline const char *xmlAttr_getName(xmlAttrPtr attr) +{ + return reinterpret_cast( attr->name ); } -CGameDescription::CGameDescription( xmlDocPtr pDoc, const CopiedString& gameFile ){ - // read the user-friendly game name - xmlNodePtr pNode = pDoc->children; - - while ( strcmp( (const char*)pNode->name, "game" ) && pNode != 0 ) - { - pNode = pNode->next; - } - if ( !pNode ) { - Error( "Didn't find 'game' node in the game description file '%s'\n", pDoc->URL ); - } - - for ( xmlAttrPtr attr = pNode->properties; attr != 0; attr = attr->next ) - { - m_gameDescription.insert( GameDescription::value_type( xmlAttr_getName( attr ), xmlAttr_getValue( attr ) ) ); - } - - { - StringOutputStream path( 256 ); - path << AppPath_get() << gameFile.c_str() << "/"; - mGameToolsPath = path.c_str(); - } - - ASSERT_MESSAGE( file_exists( mGameToolsPath.c_str() ), "game directory not found: " << makeQuoted( mGameToolsPath.c_str() ) ); - - mGameFile = gameFile; - - { - GameDescription::iterator i = m_gameDescription.find( "type" ); - if ( i == m_gameDescription.end() ) { - globalErrorStream() << "Warning, 'type' attribute not found in '" << reinterpret_cast( pDoc->URL ) << "'\n"; - // default - mGameType = "q3"; - } - else - { - mGameType = ( *i ).second.c_str(); - } - } +inline const char *xmlAttr_getValue(xmlAttrPtr attr) +{ + return reinterpret_cast( attr->children->content ); } -void CGameDescription::Dump(){ - globalOutputStream() << "game description file: " << makeQuoted( mGameFile.c_str() ) << "\n"; - for ( GameDescription::iterator i = m_gameDescription.begin(); i != m_gameDescription.end(); ++i ) - { - globalOutputStream() << ( *i ).first.c_str() << " = " << makeQuoted( ( *i ).second.c_str() ) << "\n"; - } +CGameDescription::CGameDescription(xmlDocPtr pDoc, const CopiedString &gameFile) +{ + // read the user-friendly game name + xmlNodePtr pNode = pDoc->children; + + while (strcmp((const char *) pNode->name, "game") && pNode != 0) { + pNode = pNode->next; + } + if (!pNode) { + Error("Didn't find 'game' node in the game description file '%s'\n", pDoc->URL); + } + + for (xmlAttrPtr attr = pNode->properties; attr != 0; attr = attr->next) { + m_gameDescription.insert(GameDescription::value_type(xmlAttr_getName(attr), xmlAttr_getValue(attr))); + } + + { + StringOutputStream path(256); + path << AppPath_get() << gameFile.c_str() << "/"; + mGameToolsPath = path.c_str(); + } + + ASSERT_MESSAGE(file_exists(mGameToolsPath.c_str()), + "game directory not found: " << makeQuoted(mGameToolsPath.c_str())); + + mGameFile = gameFile; + + { + GameDescription::iterator i = m_gameDescription.find("type"); + if (i == m_gameDescription.end()) { + globalErrorStream() << "Warning, 'type' attribute not found in '" + << reinterpret_cast( pDoc->URL ) << "'\n"; + // default + mGameType = "q3"; + } else { + mGameType = (*i).second.c_str(); + } + } +} + +void CGameDescription::Dump() +{ + globalOutputStream() << "game description file: " << makeQuoted(mGameFile.c_str()) << "\n"; + for (GameDescription::iterator i = m_gameDescription.begin(); i != m_gameDescription.end(); ++i) { + globalOutputStream() << (*i).first.c_str() << " = " << makeQuoted((*i).second.c_str()) << "\n"; + } } CGameDescription *g_pGameDescription; ///< shortcut to g_GamesDialog.m_pCurrentDescription @@ -164,306 +171,319 @@ CGameDescription *g_pGameDescription; ///< shortcut to g_GamesDialog.m_pCurrentD #include "preferencedictionary.h" #include "stringio.h" -const char* const PREFERENCES_VERSION = "1.0"; - -bool Preferences_Load( PreferenceDictionary& preferences, const char* filename, const char *cmdline_prefix ){ - bool ret = false; - TextFileInputStream file( filename ); - if ( !file.failed() ) { - XMLStreamParser parser( file ); - XMLPreferenceDictionaryImporter importer( preferences, PREFERENCES_VERSION ); - parser.exportXML( importer ); - ret = true; - } - - int l = strlen( cmdline_prefix ); - for ( int i = 1; i < g_argc - 1; ++i ) - { - if ( g_argv[i][0] == '-' ) { - if ( !strncmp( g_argv[i] + 1, cmdline_prefix, l ) ) { - if ( g_argv[i][l + 1] == '-' ) { - preferences.importPref( g_argv[i] + l + 2, g_argv[i + 1] ); - } - } - ++i; - } - } - - return ret; -} - -bool Preferences_Save( PreferenceDictionary& preferences, const char* filename ){ - TextFileOutputStream file( filename ); - if ( !file.failed() ) { - XMLStreamWriter writer( file ); - XMLPreferenceDictionaryExporter exporter( preferences, PREFERENCES_VERSION ); - exporter.exportXML( writer ); - return true; - } - return false; -} - -bool Preferences_Save_Safe( PreferenceDictionary& preferences, const char* filename ){ - Array tmpName( filename, filename + strlen( filename ) + 1 + 3 ); - *( tmpName.end() - 4 ) = 'T'; - *( tmpName.end() - 3 ) = 'M'; - *( tmpName.end() - 2 ) = 'P'; - *( tmpName.end() - 1 ) = '\0'; - - return Preferences_Save( preferences, tmpName.data() ) - && ( !file_exists( filename ) || file_remove( filename ) ) - && file_move( tmpName.data(), filename ); +const char *const PREFERENCES_VERSION = "1.0"; + +bool Preferences_Load(PreferenceDictionary &preferences, const char *filename, const char *cmdline_prefix) +{ + bool ret = false; + TextFileInputStream file(filename); + if (!file.failed()) { + XMLStreamParser parser(file); + XMLPreferenceDictionaryImporter importer(preferences, PREFERENCES_VERSION); + parser.exportXML(importer); + ret = true; + } + + int l = strlen(cmdline_prefix); + for (int i = 1; i < g_argc - 1; ++i) { + if (g_argv[i][0] == '-') { + if (!strncmp(g_argv[i] + 1, cmdline_prefix, l)) { + if (g_argv[i][l + 1] == '-') { + preferences.importPref(g_argv[i] + l + 2, g_argv[i + 1]); + } + } + ++i; + } + } + + return ret; +} + +bool Preferences_Save(PreferenceDictionary &preferences, const char *filename) +{ + TextFileOutputStream file(filename); + if (!file.failed()) { + XMLStreamWriter writer(file); + XMLPreferenceDictionaryExporter exporter(preferences, PREFERENCES_VERSION); + exporter.exportXML(writer); + return true; + } + return false; +} + +bool Preferences_Save_Safe(PreferenceDictionary &preferences, const char *filename) +{ + Array tmpName(filename, filename + strlen(filename) + 1 + 3); + *(tmpName.end() - 4) = 'T'; + *(tmpName.end() - 3) = 'M'; + *(tmpName.end() - 2) = 'P'; + *(tmpName.end() - 1) = '\0'; + + return Preferences_Save(preferences, tmpName.data()) + && (!file_exists(filename) || file_remove(filename)) + && file_move(tmpName.data(), filename); } struct LogConsole { - static void Export(const Callback &returnz) { - returnz(g_Console_enableLogging); - } - - static void Import(bool value) { - g_Console_enableLogging = value; - Sys_LogFile(g_Console_enableLogging); - } + static void Export(const Callback &returnz) + { + returnz(g_Console_enableLogging); + } + + static void Import(bool value) + { + g_Console_enableLogging = value; + Sys_LogFile(g_Console_enableLogging); + } }; -void RegisterGlobalPreferences( PreferenceSystem& preferences ){ - preferences.registerPreference( "gamefile", make_property_string( g_GamesDialog.m_sGameFile ) ); - preferences.registerPreference( "gamePrompt", make_property_string( g_GamesDialog.m_bGamePrompt ) ); - preferences.registerPreference( "log console", make_property_string() ); +void RegisterGlobalPreferences(PreferenceSystem &preferences) +{ + preferences.registerPreference("gamefile", make_property_string(g_GamesDialog.m_sGameFile)); + preferences.registerPreference("gamePrompt", make_property_string(g_GamesDialog.m_bGamePrompt)); + preferences.registerPreference("log console", make_property_string()); } PreferenceDictionary g_global_preferences; -void GlobalPreferences_Init(){ - RegisterGlobalPreferences( g_global_preferences ); +void GlobalPreferences_Init() +{ + RegisterGlobalPreferences(g_global_preferences); } -void CGameDialog::LoadPrefs(){ - // load global .pref file - StringOutputStream strGlobalPref( 256 ); - strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; +void CGameDialog::LoadPrefs() +{ + // load global .pref file + StringOutputStream strGlobalPref(256); + strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; - globalOutputStream() << "loading global preferences from " << makeQuoted( strGlobalPref.c_str() ) << "\n"; + globalOutputStream() << "loading global preferences from " << makeQuoted(strGlobalPref.c_str()) << "\n"; - if ( !Preferences_Load( g_global_preferences, strGlobalPref.c_str(), "global" ) ) { - globalOutputStream() << "failed to load global preferences from " << strGlobalPref.c_str() << "\n"; - } + if (!Preferences_Load(g_global_preferences, strGlobalPref.c_str(), "global")) { + globalOutputStream() << "failed to load global preferences from " << strGlobalPref.c_str() << "\n"; + } } -void CGameDialog::SavePrefs(){ - StringOutputStream strGlobalPref( 256 ); - strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; +void CGameDialog::SavePrefs() +{ + StringOutputStream strGlobalPref(256); + strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; - globalOutputStream() << "saving global preferences to " << strGlobalPref.c_str() << "\n"; + globalOutputStream() << "saving global preferences to " << strGlobalPref.c_str() << "\n"; - if ( !Preferences_Save_Safe( g_global_preferences, strGlobalPref.c_str() ) ) { - globalOutputStream() << "failed to save global preferences to " << strGlobalPref.c_str() << "\n"; - } + if (!Preferences_Save_Safe(g_global_preferences, strGlobalPref.c_str())) { + globalOutputStream() << "failed to save global preferences to " << strGlobalPref.c_str() << "\n"; + } } -void CGameDialog::DoGameDialog(){ - // show the UI - DoModal(); +void CGameDialog::DoGameDialog() +{ + // show the UI + DoModal(); - // we save the prefs file - SavePrefs(); + // we save the prefs file + SavePrefs(); } -void CGameDialog::GameFileImport( int value ){ - m_nComboSelect = value; - // use value to set m_sGameFile - std::list::iterator iGame = mGames.begin(); - int i; - for ( i = 0; i < value; i++ ) - { - ++iGame; - } - m_sGameFile = ( *iGame )->mGameFile; +void CGameDialog::GameFileImport(int value) +{ + m_nComboSelect = value; + // use value to set m_sGameFile + std::list::iterator iGame = mGames.begin(); + int i; + for (i = 0; i < value; i++) { + ++iGame; + } + m_sGameFile = (*iGame)->mGameFile; } -void CGameDialog::GameFileExport( const Callback & importCallback ) const { - // use m_sGameFile to set value - std::list::const_iterator iGame; - int i = 0; - for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame ) - { - if ( ( *iGame )->mGameFile == m_sGameFile ) { - m_nComboSelect = i; - break; - } - i++; - } - importCallback( m_nComboSelect ); +void CGameDialog::GameFileExport(const Callback &importCallback) const +{ + // use m_sGameFile to set value + std::list::const_iterator iGame; + int i = 0; + for (iGame = mGames.begin(); iGame != mGames.end(); ++iGame) { + if ((*iGame)->mGameFile == m_sGameFile) { + m_nComboSelect = i; + break; + } + i++; + } + importCallback(m_nComboSelect); } struct CGameDialog_GameFile { - static void Export(const CGameDialog &self, const Callback &returnz) { - self.GameFileExport(returnz); - } - - static void Import(CGameDialog &self, int value) { - self.GameFileImport(value); - } + static void Export(const CGameDialog &self, const Callback &returnz) + { + self.GameFileExport(returnz); + } + + static void Import(CGameDialog &self, int value) + { + self.GameFileImport(value); + } }; -void CGameDialog::CreateGlobalFrame( PreferencesPage& page ){ - std::vector games; - games.reserve( mGames.size() ); - for ( std::list::iterator i = mGames.begin(); i != mGames.end(); ++i ) - { - games.push_back( ( *i )->getRequiredKeyValue( "name" ) ); - } - page.appendCombo( - "Select the game", - StringArrayRange( &( *games.begin() ), &( *games.end() ) ), - make_property(*this) - ); - page.appendCheckBox( "Startup", "Show Global Preferences", m_bGamePrompt ); -} - -ui::Window CGameDialog::BuildDialog(){ - auto frame = create_dialog_frame( "Game settings", ui::Shadow::ETCHED_IN ); - - auto vbox2 = create_dialog_vbox( 0, 4 ); - frame.add(vbox2); - - { - PreferencesPage preferencesPage( *this, vbox2 ); - Global_constructPreferences( preferencesPage ); - CreateGlobalFrame( preferencesPage ); - } - - return create_simple_modal_dialog_window( "Global Preferences", m_modal, frame ); -} - -void CGameDialog::ScanForGames(){ - StringOutputStream strGamesPath( 256 ); - strGamesPath << AppPath_get() << "games/"; - const char *path = strGamesPath.c_str(); - - globalOutputStream() << "Scanning for game description files: " << path << '\n'; - - /*! - \todo FIXME LINUX: - do we put game description files below AppPath, or in ~/.radiant - i.e. read only or read/write? - my guess .. readonly cause it's an install - we will probably want to add ~/.radiant//games/ scanning on top of that for developers - (if that's really needed) - */ - - Directory_forEach(path, [&](const char *name) { - if (!extension_equal(path_get_extension(name), "game")) { - return; - } - StringOutputStream strPath(256); - strPath << path << name; - globalOutputStream() << strPath.c_str() << '\n'; - - xmlDocPtr pDoc = xmlParseFile(strPath.c_str()); - if (pDoc) { - mGames.push_front(new CGameDescription(pDoc, name)); - xmlFreeDoc(pDoc); - } else { - globalErrorStream() << "XML parser failed on '" << strPath.c_str() << "'\n"; - } - }); -} - -CGameDescription* CGameDialog::GameDescriptionForComboItem(){ - std::list::iterator iGame; - int i = 0; - for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame,i++ ) - { - if ( i == m_nComboSelect ) { - return ( *iGame ); - } - } - return 0; // not found -} - -void CGameDialog::InitGlobalPrefPath(){ - g_Preferences.m_global_rc_path = g_string_new( SettingsPath_get() ); -} - -void CGameDialog::Reset(){ - if ( !g_Preferences.m_global_rc_path ) { - InitGlobalPrefPath(); - } - StringOutputStream strGlobalPref( 256 ); - strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; - file_remove( strGlobalPref.c_str() ); -} - -void CGameDialog::Init(){ - InitGlobalPrefPath(); - LoadPrefs(); - ScanForGames(); - if ( mGames.empty() ) { - Error( "Didn't find any valid game file descriptions, aborting\n" ); - } - else - { - std::list::iterator iGame, iPrevGame; - for ( iGame = mGames.begin(), iPrevGame = mGames.end(); iGame != mGames.end(); iPrevGame = iGame, ++iGame ) - { - if ( iPrevGame != mGames.end() ) { - if ( strcmp( ( *iGame )->getRequiredKeyValue( "name" ), ( *iPrevGame )->getRequiredKeyValue( "name" ) ) < 0 ) { - CGameDescription *h = *iGame; - *iGame = *iPrevGame; - *iPrevGame = h; - } - } - } - } - - CGameDescription* currentGameDescription = 0; - - if ( !m_bGamePrompt ) { - // search by .game name - std::list::iterator iGame; - for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame ) - { - if ( ( *iGame )->mGameFile == m_sGameFile ) { - currentGameDescription = ( *iGame ); - break; - } - } - } - if ( m_bGamePrompt || !currentGameDescription ) { - Create(); - DoGameDialog(); - // use m_nComboSelect to identify the game to run as and set the globals - currentGameDescription = GameDescriptionForComboItem(); - ASSERT_NOTNULL( currentGameDescription ); - } - g_pGameDescription = currentGameDescription; - - g_pGameDescription->Dump(); -} - -CGameDialog::~CGameDialog(){ - // free all the game descriptions - std::list::iterator iGame; - for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame ) - { - delete ( *iGame ); - *iGame = 0; - } - if ( GetWidget() ) { - Destroy(); - } -} - -inline const char* GameDescription_getIdentifier( const CGameDescription& gameDescription ){ - const char* identifier = gameDescription.getKeyValue( "index" ); - if ( string_empty( identifier ) ) { - identifier = "1"; - } - return identifier; +void CGameDialog::CreateGlobalFrame(PreferencesPage &page) +{ + std::vector games; + games.reserve(mGames.size()); + for (std::list::iterator i = mGames.begin(); i != mGames.end(); ++i) { + games.push_back((*i)->getRequiredKeyValue("name")); + } + page.appendCombo( + "Select the game", + StringArrayRange(&(*games.begin()), &(*games.end())), + make_property(*this) + ); + page.appendCheckBox("Startup", "Show Global Preferences", m_bGamePrompt); +} + +ui::Window CGameDialog::BuildDialog() +{ + auto frame = create_dialog_frame("Game settings", ui::Shadow::ETCHED_IN); + + auto vbox2 = create_dialog_vbox(0, 4); + frame.add(vbox2); + + { + PreferencesPage preferencesPage(*this, vbox2); + Global_constructPreferences(preferencesPage); + CreateGlobalFrame(preferencesPage); + } + + return create_simple_modal_dialog_window("Global Preferences", m_modal, frame); +} + +void CGameDialog::ScanForGames() +{ + StringOutputStream strGamesPath(256); + strGamesPath << AppPath_get() << "games/"; + const char *path = strGamesPath.c_str(); + + globalOutputStream() << "Scanning for game description files: " << path << '\n'; + + /*! + \todo FIXME LINUX: + do we put game description files below AppPath, or in ~/.radiant + i.e. read only or read/write? + my guess .. readonly cause it's an install + we will probably want to add ~/.radiant//games/ scanning on top of that for developers + (if that's really needed) + */ + + Directory_forEach(path, [&](const char *name) { + if (!extension_equal(path_get_extension(name), "game")) { + return; + } + StringOutputStream strPath(256); + strPath << path << name; + globalOutputStream() << strPath.c_str() << '\n'; + + xmlDocPtr pDoc = xmlParseFile(strPath.c_str()); + if (pDoc) { + mGames.push_front(new CGameDescription(pDoc, name)); + xmlFreeDoc(pDoc); + } else { + globalErrorStream() << "XML parser failed on '" << strPath.c_str() << "'\n"; + } + }); +} + +CGameDescription *CGameDialog::GameDescriptionForComboItem() +{ + std::list::iterator iGame; + int i = 0; + for (iGame = mGames.begin(); iGame != mGames.end(); ++iGame, i++) { + if (i == m_nComboSelect) { + return (*iGame); + } + } + return 0; // not found +} + +void CGameDialog::InitGlobalPrefPath() +{ + g_Preferences.m_global_rc_path = g_string_new(SettingsPath_get()); +} + +void CGameDialog::Reset() +{ + if (!g_Preferences.m_global_rc_path) { + InitGlobalPrefPath(); + } + StringOutputStream strGlobalPref(256); + strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; + file_remove(strGlobalPref.c_str()); +} + +void CGameDialog::Init() +{ + InitGlobalPrefPath(); + LoadPrefs(); + ScanForGames(); + if (mGames.empty()) { + Error("Didn't find any valid game file descriptions, aborting\n"); + } else { + std::list::iterator iGame, iPrevGame; + for (iGame = mGames.begin(), iPrevGame = mGames.end(); iGame != mGames.end(); iPrevGame = iGame, ++iGame) { + if (iPrevGame != mGames.end()) { + if (strcmp((*iGame)->getRequiredKeyValue("name"), (*iPrevGame)->getRequiredKeyValue("name")) < 0) { + CGameDescription *h = *iGame; + *iGame = *iPrevGame; + *iPrevGame = h; + } + } + } + } + + CGameDescription *currentGameDescription = 0; + + if (!m_bGamePrompt) { + // search by .game name + std::list::iterator iGame; + for (iGame = mGames.begin(); iGame != mGames.end(); ++iGame) { + if ((*iGame)->mGameFile == m_sGameFile) { + currentGameDescription = (*iGame); + break; + } + } + } + if (m_bGamePrompt || !currentGameDescription) { + Create(); + DoGameDialog(); + // use m_nComboSelect to identify the game to run as and set the globals + currentGameDescription = GameDescriptionForComboItem(); + ASSERT_NOTNULL(currentGameDescription); + } + g_pGameDescription = currentGameDescription; + + g_pGameDescription->Dump(); +} + +CGameDialog::~CGameDialog() +{ + // free all the game descriptions + std::list::iterator iGame; + for (iGame = mGames.begin(); iGame != mGames.end(); ++iGame) { + delete (*iGame); + *iGame = 0; + } + if (GetWidget()) { + Destroy(); + } +} + +inline const char *GameDescription_getIdentifier(const CGameDescription &gameDescription) +{ + const char *identifier = gameDescription.getKeyValue("index"); + if (string_empty(identifier)) { + identifier = "1"; + } + return identifier; } @@ -473,18 +493,19 @@ CGameDialog g_GamesDialog; // ============================================================================= // Widget callbacks for PrefsDlg -static void OnButtonClean( ui::Widget widget, gpointer data ){ - // make sure this is what the user wants - if ( ui::alert( g_Preferences.GetWidget(), "This will close Radiant and clean the corresponding registry entries.\n" - "Next time you start Radiant it will be good as new. Do you wish to continue?", - "Reset Registry", ui::alert_type::YESNO, ui::alert_icon::Asterisk ) == ui::alert_response::YES ) { - PrefsDlg *dlg = (PrefsDlg*)data; - dlg->EndModal( eIDCANCEL ); +static void OnButtonClean(ui::Widget widget, gpointer data) +{ + // make sure this is what the user wants + if (ui::alert(g_Preferences.GetWidget(), "This will close Radiant and clean the corresponding registry entries.\n" + "Next time you start Radiant it will be good as new. Do you wish to continue?", + "Reset Registry", ui::alert_type::YESNO, ui::alert_icon::Asterisk) == ui::alert_response::YES) { + PrefsDlg *dlg = (PrefsDlg *) data; + dlg->EndModal(eIDCANCEL); - g_preferences_globals.disable_ini = true; - Preferences_Reset(); - gtk_main_quit(); - } + g_preferences_globals.disable_ini = true; + Preferences_Reset(); + gtk_main_quit(); + } } // ============================================================================= @@ -505,319 +526,353 @@ static void OnButtonClean( ui::Widget widget, gpointer data ){ const char *PREFS_LOCAL_FILENAME = "local.pref"; -void PrefsDlg::Init(){ - // m_global_rc_path has been set above - // m_rc_path is for game specific preferences - // takes the form: global-pref-path/gamename/prefs-file +void PrefsDlg::Init() +{ + // m_global_rc_path has been set above + // m_rc_path is for game specific preferences + // takes the form: global-pref-path/gamename/prefs-file - // this is common to win32 and Linux init now - m_rc_path = g_string_new( m_global_rc_path->str ); + // this is common to win32 and Linux init now + m_rc_path = g_string_new(m_global_rc_path->str); - // game sub-dir - g_string_append( m_rc_path, g_pGameDescription->mGameFile.c_str() ); - g_string_append( m_rc_path, "/" ); - Q_mkdir( m_rc_path->str ); + // game sub-dir + g_string_append(m_rc_path, g_pGameDescription->mGameFile.c_str()); + g_string_append(m_rc_path, "/"); + Q_mkdir(m_rc_path->str); - // then the ini file - m_inipath = g_string_new( m_rc_path->str ); - g_string_append( m_inipath, PREFS_LOCAL_FILENAME ); + // then the ini file + m_inipath = g_string_new(m_rc_path->str); + g_string_append(m_inipath, PREFS_LOCAL_FILENAME); } -void notebook_set_page( ui::Widget notebook, ui::Widget page ){ - int pagenum = gtk_notebook_page_num( GTK_NOTEBOOK( notebook ), page ); - if ( gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) != pagenum ) { - gtk_notebook_set_current_page( GTK_NOTEBOOK( notebook ), pagenum ); - } +void notebook_set_page(ui::Widget notebook, ui::Widget page) +{ + int pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), page); + if (gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)) != pagenum) { + gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), pagenum); + } } -void PrefsDlg::showPrefPage( ui::Widget prefpage ){ - notebook_set_page( m_notebook, prefpage ); - return; +void PrefsDlg::showPrefPage(ui::Widget prefpage) +{ + notebook_set_page(m_notebook, prefpage); + return; } -static void treeSelection( ui::TreeSelection selection, gpointer data ){ - PrefsDlg *dlg = (PrefsDlg*)data; +static void treeSelection(ui::TreeSelection selection, gpointer data) +{ + PrefsDlg *dlg = (PrefsDlg *) data; - GtkTreeModel* model; - GtkTreeIter selected; - if ( gtk_tree_selection_get_selected( selection, &model, &selected ) ) { - ui::Widget prefpage{ui::null}; - gtk_tree_model_get( model, &selected, 1, (gpointer*)&prefpage, -1 ); - dlg->showPrefPage( prefpage ); - } + GtkTreeModel *model; + GtkTreeIter selected; + if (gtk_tree_selection_get_selected(selection, &model, &selected)) { + ui::Widget prefpage{ui::null}; + gtk_tree_model_get(model, &selected, 1, (gpointer *) &prefpage, -1); + dlg->showPrefPage(prefpage); + } } typedef std::list PreferenceGroupCallbacks; -inline void PreferenceGroupCallbacks_constructGroup( const PreferenceGroupCallbacks& callbacks, PreferenceGroup& group ){ - for ( PreferenceGroupCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i ) - { - ( *i )( group ); - } +inline void PreferenceGroupCallbacks_constructGroup(const PreferenceGroupCallbacks &callbacks, PreferenceGroup &group) +{ + for (PreferenceGroupCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) { + (*i)(group); + } } -inline void PreferenceGroupCallbacks_pushBack( PreferenceGroupCallbacks& callbacks, const PreferenceGroupCallback& callback ){ - callbacks.push_back( callback ); +inline void +PreferenceGroupCallbacks_pushBack(PreferenceGroupCallbacks &callbacks, const PreferenceGroupCallback &callback) +{ + callbacks.push_back(callback); } typedef std::list PreferencesPageCallbacks; -inline void PreferencesPageCallbacks_constructPage( const PreferencesPageCallbacks& callbacks, PreferencesPage& page ){ - for ( PreferencesPageCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i ) - { - ( *i )( page ); - } +inline void PreferencesPageCallbacks_constructPage(const PreferencesPageCallbacks &callbacks, PreferencesPage &page) +{ + for (PreferencesPageCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) { + (*i)(page); + } } -inline void PreferencesPageCallbacks_pushBack( PreferencesPageCallbacks& callbacks, const PreferencesPageCallback& callback ){ - callbacks.push_back( callback ); +inline void +PreferencesPageCallbacks_pushBack(PreferencesPageCallbacks &callbacks, const PreferencesPageCallback &callback) +{ + callbacks.push_back(callback); } PreferencesPageCallbacks g_interfacePreferences; -void PreferencesDialog_addInterfacePreferences( const PreferencesPageCallback& callback ){ - PreferencesPageCallbacks_pushBack( g_interfacePreferences, callback ); + +void PreferencesDialog_addInterfacePreferences(const PreferencesPageCallback &callback) +{ + PreferencesPageCallbacks_pushBack(g_interfacePreferences, callback); } + PreferenceGroupCallbacks g_interfaceCallbacks; -void PreferencesDialog_addInterfacePage( const PreferenceGroupCallback& callback ){ - PreferenceGroupCallbacks_pushBack( g_interfaceCallbacks, callback ); + +void PreferencesDialog_addInterfacePage(const PreferenceGroupCallback &callback) +{ + PreferenceGroupCallbacks_pushBack(g_interfaceCallbacks, callback); } PreferencesPageCallbacks g_displayPreferences; -void PreferencesDialog_addDisplayPreferences( const PreferencesPageCallback& callback ){ - PreferencesPageCallbacks_pushBack( g_displayPreferences, callback ); + +void PreferencesDialog_addDisplayPreferences(const PreferencesPageCallback &callback) +{ + PreferencesPageCallbacks_pushBack(g_displayPreferences, callback); } + PreferenceGroupCallbacks g_displayCallbacks; -void PreferencesDialog_addDisplayPage( const PreferenceGroupCallback& callback ){ - PreferenceGroupCallbacks_pushBack( g_displayCallbacks, callback ); + +void PreferencesDialog_addDisplayPage(const PreferenceGroupCallback &callback) +{ + PreferenceGroupCallbacks_pushBack(g_displayCallbacks, callback); } PreferencesPageCallbacks g_settingsPreferences; -void PreferencesDialog_addSettingsPreferences( const PreferencesPageCallback& callback ){ - PreferencesPageCallbacks_pushBack( g_settingsPreferences, callback ); + +void PreferencesDialog_addSettingsPreferences(const PreferencesPageCallback &callback) +{ + PreferencesPageCallbacks_pushBack(g_settingsPreferences, callback); } + PreferenceGroupCallbacks g_settingsCallbacks; -void PreferencesDialog_addSettingsPage( const PreferenceGroupCallback& callback ){ - PreferenceGroupCallbacks_pushBack( g_settingsCallbacks, callback ); + +void PreferencesDialog_addSettingsPage(const PreferenceGroupCallback &callback) +{ + PreferenceGroupCallbacks_pushBack(g_settingsCallbacks, callback); } -void Widget_updateDependency( ui::Widget self, ui::Widget toggleButton ){ - gtk_widget_set_sensitive( self, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( toggleButton ) ) && gtk_widget_is_sensitive( toggleButton ) ); +void Widget_updateDependency(ui::Widget self, ui::Widget toggleButton) +{ + gtk_widget_set_sensitive(self, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggleButton)) && + gtk_widget_is_sensitive(toggleButton)); } -void ToggleButton_toggled_Widget_updateDependency( ui::Widget toggleButton, ui::Widget self ){ - Widget_updateDependency( self, toggleButton ); +void ToggleButton_toggled_Widget_updateDependency(ui::Widget toggleButton, ui::Widget self) +{ + Widget_updateDependency(self, toggleButton); } -void ToggleButton_state_changed_Widget_updateDependency( ui::Widget toggleButton, GtkStateType state, ui::Widget self ){ - if ( state == GTK_STATE_INSENSITIVE ) { - Widget_updateDependency( self, toggleButton ); - } +void ToggleButton_state_changed_Widget_updateDependency(ui::Widget toggleButton, GtkStateType state, ui::Widget self) +{ + if (state == GTK_STATE_INSENSITIVE) { + Widget_updateDependency(self, toggleButton); + } } -void Widget_connectToggleDependency( ui::Widget self, ui::Widget toggleButton ){ - toggleButton.connect( "state_changed", G_CALLBACK( ToggleButton_state_changed_Widget_updateDependency ), self ); - toggleButton.connect( "toggled", G_CALLBACK( ToggleButton_toggled_Widget_updateDependency ), self ); - Widget_updateDependency( self, toggleButton ); +void Widget_connectToggleDependency(ui::Widget self, ui::Widget toggleButton) +{ + toggleButton.connect("state_changed", G_CALLBACK(ToggleButton_state_changed_Widget_updateDependency), self); + toggleButton.connect("toggled", G_CALLBACK(ToggleButton_toggled_Widget_updateDependency), self); + Widget_updateDependency(self, toggleButton); } -inline ui::VBox getVBox( ui::Bin page ){ - return ui::VBox::from(gtk_bin_get_child(page)); +inline ui::VBox getVBox(ui::Bin page) +{ + return ui::VBox::from(gtk_bin_get_child(page)); } -GtkTreeIter PreferenceTree_appendPage( ui::TreeStore store, GtkTreeIter* parent, const char* name, ui::Widget page ){ - GtkTreeIter group; - gtk_tree_store_append( store, &group, parent ); - gtk_tree_store_set( store, &group, 0, name, 1, page, -1 ); - return group; +GtkTreeIter PreferenceTree_appendPage(ui::TreeStore store, GtkTreeIter *parent, const char *name, ui::Widget page) +{ + GtkTreeIter group; + gtk_tree_store_append(store, &group, parent); + gtk_tree_store_set(store, &group, 0, name, 1, page, -1); + return group; } -ui::Bin PreferencePages_addPage( ui::Widget notebook, const char* name ){ - ui::Widget preflabel = ui::Label( name ); - preflabel.show(); +ui::Bin PreferencePages_addPage(ui::Widget notebook, const char *name) +{ + ui::Widget preflabel = ui::Label(name); + preflabel.show(); - auto pageframe = ui::Frame( name ); - gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 4 ); - pageframe.show(); + auto pageframe = ui::Frame(name); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 4); + pageframe.show(); - ui::Widget vbox = ui::VBox( FALSE, 4 ); - vbox.show(); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 4 ); - pageframe.add(vbox); + ui::Widget vbox = ui::VBox(FALSE, 4); + vbox.show(); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 4); + pageframe.add(vbox); - // Add the page to the notebook - gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - return pageframe; + return pageframe; } -class PreferenceTreeGroup : public PreferenceGroup -{ -Dialog& m_dialog; -ui::Widget m_notebook; -ui::TreeStore m_store; -GtkTreeIter m_group; +class PreferenceTreeGroup : public PreferenceGroup { + Dialog &m_dialog; + ui::Widget m_notebook; + ui::TreeStore m_store; + GtkTreeIter m_group; public: -PreferenceTreeGroup( Dialog& dialog, ui::Widget notebook, ui::TreeStore store, GtkTreeIter group ) : - m_dialog( dialog ), - m_notebook( notebook ), - m_store( store ), - m_group( group ){ -} -PreferencesPage createPage( const char* treeName, const char* frameName ){ - auto page = PreferencePages_addPage( m_notebook, frameName ); - PreferenceTree_appendPage( m_store, &m_group, treeName, page ); - return PreferencesPage( m_dialog, getVBox( page ) ); -} + PreferenceTreeGroup(Dialog &dialog, ui::Widget notebook, ui::TreeStore store, GtkTreeIter group) : + m_dialog(dialog), + m_notebook(notebook), + m_store(store), + m_group(group) + { + } + + PreferencesPage createPage(const char *treeName, const char *frameName) + { + auto page = PreferencePages_addPage(m_notebook, frameName); + PreferenceTree_appendPage(m_store, &m_group, treeName, page); + return PreferencesPage(m_dialog, getVBox(page)); + } }; -ui::Window PrefsDlg::BuildDialog(){ - PreferencesDialog_addInterfacePreferences( makeCallbackF(Interface_constructPreferences) ); - Mouse_registerPreferencesPage(); - - ui::Window dialog = ui::Window(create_floating_window( "NetRadiant Preferences", m_parent )); - - { - auto mainvbox = ui::VBox( FALSE, 5 ); - dialog.add(mainvbox); - gtk_container_set_border_width( GTK_CONTAINER( mainvbox ), 5 ); - mainvbox.show(); - - { - auto hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - mainvbox.pack_end(hbox, FALSE, TRUE, 0); - - { - auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &m_modal ); - hbox.pack_end(button, FALSE, FALSE, 0); - } - { - auto button = create_dialog_button( "Cancel", G_CALLBACK( dialog_button_cancel ), &m_modal ); - hbox.pack_end(button, FALSE, FALSE, 0); - } - { - auto button = create_dialog_button( "Clean", G_CALLBACK( OnButtonClean ), this ); - hbox.pack_end(button, FALSE, FALSE, 0); - } - } - - { - auto hbox = ui::HBox( FALSE, 5 ); - mainvbox.pack_start( hbox, TRUE, TRUE, 0 ); - hbox.show(); - - { - auto sc_win = ui::ScrolledWindow(ui::New); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sc_win ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC ); - hbox.pack_start( sc_win, FALSE, FALSE, 0 ); - sc_win.show(); - gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( sc_win ), GTK_SHADOW_IN ); - - // prefs pages notebook - m_notebook = ui::Widget::from(gtk_notebook_new()); - // hide the notebook tabs since its not supposed to look like a notebook - gtk_notebook_set_show_tabs( GTK_NOTEBOOK( m_notebook ), FALSE ); - hbox.pack_start( m_notebook, TRUE, TRUE, 0 ); - m_notebook.show(); - - - { - auto store = ui::TreeStore::from(gtk_tree_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER )); - - auto view = ui::TreeView(ui::TreeModel::from(store._handle)); - gtk_tree_view_set_headers_visible(view, FALSE ); - - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn( "Preferences", renderer, {{"text", 0}} ); - gtk_tree_view_append_column(view, column ); - } - - { - auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); - selection.connect( "changed", G_CALLBACK( treeSelection ), this ); - } - - view.show(); - - sc_win.add(view); - - { - /********************************************************************/ - /* Add preference tree options */ - /********************************************************************/ - // Front page... - //GtkWidget* front = - PreferencePages_addPage( m_notebook, "Front Page" ); - - { - auto global = PreferencePages_addPage( m_notebook, "Global Preferences" ); - { - PreferencesPage preferencesPage( *this, getVBox( global ) ); - Global_constructPreferences( preferencesPage ); - } - auto group = PreferenceTree_appendPage( store, 0, "Global", global ); - { - auto game = PreferencePages_addPage( m_notebook, "Game" ); - PreferencesPage preferencesPage( *this, getVBox( game ) ); - g_GamesDialog.CreateGlobalFrame( preferencesPage ); - - PreferenceTree_appendPage( store, &group, "Game", game ); - } - } - - { - auto interfacePage = PreferencePages_addPage( m_notebook, "Interface Preferences" ); - { - PreferencesPage preferencesPage( *this, getVBox( interfacePage ) ); - PreferencesPageCallbacks_constructPage( g_interfacePreferences, preferencesPage ); - } - - auto group = PreferenceTree_appendPage( store, 0, "Interface", interfacePage ); - PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group ); - - PreferenceGroupCallbacks_constructGroup( g_interfaceCallbacks, preferenceGroup ); - } - - { - auto display = PreferencePages_addPage( m_notebook, "Display Preferences" ); - { - PreferencesPage preferencesPage( *this, getVBox( display ) ); - PreferencesPageCallbacks_constructPage( g_displayPreferences, preferencesPage ); - } - auto group = PreferenceTree_appendPage( store, 0, "Display", display ); - PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group ); - - PreferenceGroupCallbacks_constructGroup( g_displayCallbacks, preferenceGroup ); - } - - { - auto settings = PreferencePages_addPage( m_notebook, "General Settings" ); - { - PreferencesPage preferencesPage( *this, getVBox( settings ) ); - PreferencesPageCallbacks_constructPage( g_settingsPreferences, preferencesPage ); - } - - auto group = PreferenceTree_appendPage( store, 0, "Settings", settings ); - PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group ); - - PreferenceGroupCallbacks_constructGroup( g_settingsCallbacks, preferenceGroup ); - } - } - - gtk_tree_view_expand_all(view ); - - g_object_unref( G_OBJECT( store ) ); - } - } - } - } - - gtk_notebook_set_current_page( GTK_NOTEBOOK( m_notebook ), 0 ); - - return dialog; +ui::Window PrefsDlg::BuildDialog() +{ + PreferencesDialog_addInterfacePreferences(makeCallbackF(Interface_constructPreferences)); + Mouse_registerPreferencesPage(); + + ui::Window dialog = ui::Window(create_floating_window("NetRadiant Preferences", m_parent)); + + { + auto mainvbox = ui::VBox(FALSE, 5); + dialog.add(mainvbox); + gtk_container_set_border_width(GTK_CONTAINER(mainvbox), 5); + mainvbox.show(); + + { + auto hbox = ui::HBox(FALSE, 5); + hbox.show(); + mainvbox.pack_end(hbox, FALSE, TRUE, 0); + + { + auto button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &m_modal); + hbox.pack_end(button, FALSE, FALSE, 0); + } + { + auto button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &m_modal); + hbox.pack_end(button, FALSE, FALSE, 0); + } + { + auto button = create_dialog_button("Clean", G_CALLBACK(OnButtonClean), this); + hbox.pack_end(button, FALSE, FALSE, 0); + } + } + + { + auto hbox = ui::HBox(FALSE, 5); + mainvbox.pack_start(hbox, TRUE, TRUE, 0); + hbox.show(); + + { + auto sc_win = ui::ScrolledWindow(ui::New); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sc_win), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + hbox.pack_start(sc_win, FALSE, FALSE, 0); + sc_win.show(); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sc_win), GTK_SHADOW_IN); + + // prefs pages notebook + m_notebook = ui::Widget::from(gtk_notebook_new()); + // hide the notebook tabs since its not supposed to look like a notebook + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(m_notebook), FALSE); + hbox.pack_start(m_notebook, TRUE, TRUE, 0); + m_notebook.show(); + + + { + auto store = ui::TreeStore::from(gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER)); + + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_headers_visible(view, FALSE); + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("Preferences", renderer, {{"text", 0}}); + gtk_tree_view_append_column(view, column); + } + + { + auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); + selection.connect("changed", G_CALLBACK(treeSelection), this); + } + + view.show(); + + sc_win.add(view); + + { + /********************************************************************/ + /* Add preference tree options */ + /********************************************************************/ + // Front page... + //GtkWidget* front = + PreferencePages_addPage(m_notebook, "Front Page"); + + { + auto global = PreferencePages_addPage(m_notebook, "Global Preferences"); + { + PreferencesPage preferencesPage(*this, getVBox(global)); + Global_constructPreferences(preferencesPage); + } + auto group = PreferenceTree_appendPage(store, 0, "Global", global); + { + auto game = PreferencePages_addPage(m_notebook, "Game"); + PreferencesPage preferencesPage(*this, getVBox(game)); + g_GamesDialog.CreateGlobalFrame(preferencesPage); + + PreferenceTree_appendPage(store, &group, "Game", game); + } + } + + { + auto interfacePage = PreferencePages_addPage(m_notebook, "Interface Preferences"); + { + PreferencesPage preferencesPage(*this, getVBox(interfacePage)); + PreferencesPageCallbacks_constructPage(g_interfacePreferences, preferencesPage); + } + + auto group = PreferenceTree_appendPage(store, 0, "Interface", interfacePage); + PreferenceTreeGroup preferenceGroup(*this, m_notebook, store, group); + + PreferenceGroupCallbacks_constructGroup(g_interfaceCallbacks, preferenceGroup); + } + + { + auto display = PreferencePages_addPage(m_notebook, "Display Preferences"); + { + PreferencesPage preferencesPage(*this, getVBox(display)); + PreferencesPageCallbacks_constructPage(g_displayPreferences, preferencesPage); + } + auto group = PreferenceTree_appendPage(store, 0, "Display", display); + PreferenceTreeGroup preferenceGroup(*this, m_notebook, store, group); + + PreferenceGroupCallbacks_constructGroup(g_displayCallbacks, preferenceGroup); + } + + { + auto settings = PreferencePages_addPage(m_notebook, "General Settings"); + { + PreferencesPage preferencesPage(*this, getVBox(settings)); + PreferencesPageCallbacks_constructPage(g_settingsPreferences, preferencesPage); + } + + auto group = PreferenceTree_appendPage(store, 0, "Settings", settings); + PreferenceTreeGroup preferenceGroup(*this, m_notebook, store, group); + + PreferenceGroupCallbacks_constructGroup(g_settingsCallbacks, preferenceGroup); + } + } + + gtk_tree_view_expand_all(view); + + g_object_unref(G_OBJECT(store)); + } + } + } + } + + gtk_notebook_set_current_page(GTK_NOTEBOOK(m_notebook), 0); + + return dialog; } preferences_globals_t g_preferences_globals; @@ -825,34 +880,41 @@ preferences_globals_t g_preferences_globals; PrefsDlg g_Preferences; // global prefs instance -void PreferencesDialog_constructWindow( ui::Window main_window ){ - g_Preferences.m_parent = main_window; - g_Preferences.Create(); +void PreferencesDialog_constructWindow(ui::Window main_window) +{ + g_Preferences.m_parent = main_window; + g_Preferences.Create(); } -void PreferencesDialog_destroyWindow(){ - g_Preferences.Destroy(); + +void PreferencesDialog_destroyWindow() +{ + g_Preferences.Destroy(); } PreferenceDictionary g_preferences; -PreferenceSystem& GetPreferenceSystem(){ - return g_preferences; +PreferenceSystem &GetPreferenceSystem() +{ + return g_preferences; } -class PreferenceSystemAPI -{ -PreferenceSystem* m_preferencesystem; +class PreferenceSystemAPI { + PreferenceSystem *m_preferencesystem; public: -typedef PreferenceSystem Type; -STRING_CONSTANT( Name, "*" ); + typedef PreferenceSystem Type; -PreferenceSystemAPI(){ - m_preferencesystem = &GetPreferenceSystem(); -} -PreferenceSystem* getTable(){ - return m_preferencesystem; -} + STRING_CONSTANT(Name, "*"); + + PreferenceSystemAPI() + { + m_preferencesystem = &GetPreferenceSystem(); + } + + PreferenceSystem *getTable() + { + return m_preferencesystem; + } }; #include "modulesystem/singletonmodule.h" @@ -860,97 +922,109 @@ PreferenceSystem* getTable(){ typedef SingletonModule PreferenceSystemModule; typedef Static StaticPreferenceSystemModule; -StaticRegisterModule staticRegisterPreferenceSystem( StaticPreferenceSystemModule::instance() ); +StaticRegisterModule staticRegisterPreferenceSystem(StaticPreferenceSystemModule::instance()); -void Preferences_Load(){ - g_GamesDialog.LoadPrefs(); +void Preferences_Load() +{ + g_GamesDialog.LoadPrefs(); - globalOutputStream() << "loading local preferences from " << g_Preferences.m_inipath->str << "\n"; + globalOutputStream() << "loading local preferences from " << g_Preferences.m_inipath->str << "\n"; - if ( !Preferences_Load( g_preferences, g_Preferences.m_inipath->str, g_GamesDialog.m_sGameFile.c_str() ) ) { - globalOutputStream() << "failed to load local preferences from " << g_Preferences.m_inipath->str << "\n"; - } + if (!Preferences_Load(g_preferences, g_Preferences.m_inipath->str, g_GamesDialog.m_sGameFile.c_str())) { + globalOutputStream() << "failed to load local preferences from " << g_Preferences.m_inipath->str << "\n"; + } } -void Preferences_Save(){ - if ( g_preferences_globals.disable_ini ) { - return; - } +void Preferences_Save() +{ + if (g_preferences_globals.disable_ini) { + return; + } - g_GamesDialog.SavePrefs(); + g_GamesDialog.SavePrefs(); - globalOutputStream() << "saving local preferences to " << g_Preferences.m_inipath->str << "\n"; + globalOutputStream() << "saving local preferences to " << g_Preferences.m_inipath->str << "\n"; - if ( !Preferences_Save_Safe( g_preferences, g_Preferences.m_inipath->str ) ) { - globalOutputStream() << "failed to save local preferences to " << g_Preferences.m_inipath->str << "\n"; - } + if (!Preferences_Save_Safe(g_preferences, g_Preferences.m_inipath->str)) { + globalOutputStream() << "failed to save local preferences to " << g_Preferences.m_inipath->str << "\n"; + } } -void Preferences_Reset(){ - file_remove( g_Preferences.m_inipath->str ); +void Preferences_Reset() +{ + file_remove(g_Preferences.m_inipath->str); } -void PrefsDlg::PostModal( EMessageBoxReturn code ){ - if ( code == eIDOK ) { - Preferences_Save(); - UpdateAllWindows(); - } +void PrefsDlg::PostModal(EMessageBoxReturn code) +{ + if (code == eIDOK) { + Preferences_Save(); + UpdateAllWindows(); + } } -std::vector g_restart_required; +std::vector g_restart_required; -void PreferencesDialog_restartRequired( const char* staticName ){ - g_restart_required.push_back( staticName ); +void PreferencesDialog_restartRequired(const char *staticName) +{ + g_restart_required.push_back(staticName); } -void PreferencesDialog_showDialog(){ - if ( ConfirmModified( "Edit Preferences" ) && g_Preferences.DoModal() == eIDOK ) { - if ( !g_restart_required.empty() ) { - StringOutputStream message( 256 ); - message << "Preference changes require a restart:\n"; - for ( std::vector::iterator i = g_restart_required.begin(); i != g_restart_required.end(); ++i ) - { - message << ( *i ) << '\n'; - } - ui::alert( MainFrame_getWindow(), message.c_str() ); - g_restart_required.clear(); - } - } +void PreferencesDialog_showDialog() +{ + if (ConfirmModified("Edit Preferences") && g_Preferences.DoModal() == eIDOK) { + if (!g_restart_required.empty()) { + StringOutputStream message(256); + message << "Preference changes require a restart:\n"; + for (std::vector::iterator i = g_restart_required.begin(); + i != g_restart_required.end(); ++i) { + message << (*i) << '\n'; + } + ui::alert(MainFrame_getWindow(), message.c_str()); + g_restart_required.clear(); + } + } } struct GameName { - static void Export(const Callback &returnz) { - returnz(gamename_get()); - } - - static void Import(const char *value) { - gamename_set(value); - } + static void Export(const Callback &returnz) + { + returnz(gamename_get()); + } + + static void Import(const char *value) + { + gamename_set(value); + } }; struct GameMode { - static void Export(const Callback &returnz) { - returnz(gamemode_get()); - } - - static void Import(const char *value) { - gamemode_set(value); - } + static void Export(const Callback &returnz) + { + returnz(gamemode_get()); + } + + static void Import(const char *value) + { + gamemode_set(value); + } }; -void RegisterPreferences( PreferenceSystem& preferences ){ +void RegisterPreferences(PreferenceSystem &preferences) +{ #if GDEF_OS_WINDOWS - preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useWin32Editor ) ); + preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useWin32Editor ) ); #else - preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useCustomEditor ) ); - preferences.registerPreference( "CustomShaderEditorCommand", make_property_string( g_TextEditor_editorCommand ) ); + preferences.registerPreference("UseCustomShaderEditor", make_property_string(g_TextEditor_useCustomEditor)); + preferences.registerPreference("CustomShaderEditorCommand", make_property_string(g_TextEditor_editorCommand)); #endif - preferences.registerPreference( "GameName", make_property() ); - preferences.registerPreference( "GameMode", make_property() ); + preferences.registerPreference("GameName", make_property()); + preferences.registerPreference("GameMode", make_property()); } -void Preferences_Init(){ - RegisterPreferences( GetPreferenceSystem() ); +void Preferences_Init() +{ + RegisterPreferences(GetPreferenceSystem()); } diff --git a/radiant/preferences.h b/radiant/preferences.h index 59dd60da..a2e1b8e2 100644 --- a/radiant/preferences.h +++ b/radiant/preferences.h @@ -35,95 +35,141 @@ #include #include "property.h" -void Widget_connectToggleDependency( ui::Widget self, ui::Widget toggleButton ); +void Widget_connectToggleDependency(ui::Widget self, ui::Widget toggleButton); -class PreferencesPage -{ -Dialog& m_dialog; -ui::VBox m_vbox; +class PreferencesPage { + Dialog &m_dialog; + ui::VBox m_vbox; public: -PreferencesPage( Dialog& dialog, ui::VBox vbox ) : m_dialog( dialog ), m_vbox( vbox ){ -} -ui::CheckButton appendCheckBox( const char* name, const char* flag, bool& data ){ - return m_dialog.addCheckBox( m_vbox, name, flag, data ); -} -ui::CheckButton appendCheckBox( const char* name, const char* flag, Property const &cb ){ - return m_dialog.addCheckBox( m_vbox, name, flag, cb ); -} -void appendCombo( const char* name, StringArrayRange values, Property const &cb ){ - m_dialog.addCombo( m_vbox, name, values, cb ); -} -void appendCombo( const char* name, int& data, StringArrayRange values ){ - m_dialog.addCombo( m_vbox, name, data, values ); -} -void appendSlider( 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 ){ - m_dialog.addSlider( m_vbox, name, data, draw_value, low, high, value, lower, upper, step_increment, page_increment ); -} -void appendRadio( const char* name, StringArrayRange names, Property const &cb ){ - m_dialog.addRadio( m_vbox, name, names, cb ); -} -void appendRadio( const char* name, int& data, StringArrayRange names ){ - m_dialog.addRadio( m_vbox, name, data, names ); -} -void appendRadioIcons( const char* name, StringArrayRange icons, Property const &cb ){ - m_dialog.addRadioIcons( m_vbox, name, icons, cb ); -} -void appendRadioIcons( const char* name, int& data, StringArrayRange icons ){ - m_dialog.addRadioIcons( m_vbox, name, data, icons ); -} -ui::Widget appendEntry( const char* name, Property const &cb ){ - return m_dialog.addIntEntry( m_vbox, name, cb ); -} -ui::Widget appendEntry( const char* name, int& data ){ - return m_dialog.addEntry( m_vbox, name, data ); -} -ui::Widget appendEntry( const char* name, Property const &cb){ - return m_dialog.addSizeEntry( m_vbox, name, cb ); -} -ui::Widget appendEntry( const char* name, std::size_t& data ){ - return m_dialog.addEntry( m_vbox, name, data ); -} -ui::Widget appendEntry( const char* name, Property const &cb ){ - return m_dialog.addFloatEntry( m_vbox, name, cb ); -} -ui::Widget appendEntry( const char* name, float& data ){ - return m_dialog.addEntry( m_vbox, name, data ); -} -ui::Widget appendPathEntry( const char* name, bool browse_directory, Property const &cb ){ - return m_dialog.addPathEntry( m_vbox, name, browse_directory, cb ); -} -ui::Widget appendPathEntry( const char* name, CopiedString& data, bool directory ){ - return m_dialog.addPathEntry( m_vbox, name, data, directory ); -} -ui::SpinButton appendSpinner( const char* name, int& data, double value, double lower, double upper ){ - return m_dialog.addSpinner( m_vbox, name, data, value, lower, upper ); -} -ui::SpinButton appendSpinner( const char* name, double value, double lower, double upper, Property const &cb ){ - return m_dialog.addSpinner( m_vbox, name, value, lower, upper, cb ); -} -ui::SpinButton appendSpinner( const char* name, double value, double lower, double upper, Property const &cb ){ - return m_dialog.addSpinner( m_vbox, name, value, lower, upper, cb ); -} + PreferencesPage(Dialog &dialog, ui::VBox vbox) : m_dialog(dialog), m_vbox(vbox) + { + } + + ui::CheckButton appendCheckBox(const char *name, const char *flag, bool &data) + { + return m_dialog.addCheckBox(m_vbox, name, flag, data); + } + + ui::CheckButton appendCheckBox(const char *name, const char *flag, Property const &cb) + { + return m_dialog.addCheckBox(m_vbox, name, flag, cb); + } + + void appendCombo(const char *name, StringArrayRange values, Property const &cb) + { + m_dialog.addCombo(m_vbox, name, values, cb); + } + + void appendCombo(const char *name, int &data, StringArrayRange values) + { + m_dialog.addCombo(m_vbox, name, data, values); + } + + void appendSlider(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) + { + m_dialog.addSlider(m_vbox, name, data, draw_value, low, high, value, lower, upper, step_increment, + page_increment); + } + + void appendRadio(const char *name, StringArrayRange names, Property const &cb) + { + m_dialog.addRadio(m_vbox, name, names, cb); + } + + void appendRadio(const char *name, int &data, StringArrayRange names) + { + m_dialog.addRadio(m_vbox, name, data, names); + } + + void appendRadioIcons(const char *name, StringArrayRange icons, Property const &cb) + { + m_dialog.addRadioIcons(m_vbox, name, icons, cb); + } + + void appendRadioIcons(const char *name, int &data, StringArrayRange icons) + { + m_dialog.addRadioIcons(m_vbox, name, data, icons); + } + + ui::Widget appendEntry(const char *name, Property const &cb) + { + return m_dialog.addIntEntry(m_vbox, name, cb); + } + + ui::Widget appendEntry(const char *name, int &data) + { + return m_dialog.addEntry(m_vbox, name, data); + } + + ui::Widget appendEntry(const char *name, Property const &cb) + { + return m_dialog.addSizeEntry(m_vbox, name, cb); + } + + ui::Widget appendEntry(const char *name, std::size_t &data) + { + return m_dialog.addEntry(m_vbox, name, data); + } + + ui::Widget appendEntry(const char *name, Property const &cb) + { + return m_dialog.addFloatEntry(m_vbox, name, cb); + } + + ui::Widget appendEntry(const char *name, float &data) + { + return m_dialog.addEntry(m_vbox, name, data); + } + + ui::Widget appendPathEntry(const char *name, bool browse_directory, Property const &cb) + { + return m_dialog.addPathEntry(m_vbox, name, browse_directory, cb); + } + + ui::Widget appendPathEntry(const char *name, CopiedString &data, bool directory) + { + return m_dialog.addPathEntry(m_vbox, name, data, directory); + } + + ui::SpinButton appendSpinner(const char *name, int &data, double value, double lower, double upper) + { + return m_dialog.addSpinner(m_vbox, name, data, value, lower, upper); + } + + ui::SpinButton appendSpinner(const char *name, double value, double lower, double upper, Property const &cb) + { + return m_dialog.addSpinner(m_vbox, name, value, lower, upper, cb); + } + + ui::SpinButton appendSpinner(const char *name, double value, double lower, double upper, Property const &cb) + { + return m_dialog.addSpinner(m_vbox, name, value, lower, upper, cb); + } }; -typedef Callback PreferencesPageCallback; +typedef Callback PreferencesPageCallback; -class PreferenceGroup -{ +class PreferenceGroup { public: -virtual PreferencesPage createPage( const char* treeName, const char* frameName ) = 0; + virtual PreferencesPage createPage(const char *treeName, const char *frameName) = 0; }; -typedef Callback PreferenceGroupCallback; +typedef Callback PreferenceGroupCallback; + +void PreferencesDialog_addInterfacePreferences(const PreferencesPageCallback &callback); + +void PreferencesDialog_addInterfacePage(const PreferenceGroupCallback &callback); -void PreferencesDialog_addInterfacePreferences( const PreferencesPageCallback& callback ); -void PreferencesDialog_addInterfacePage( const PreferenceGroupCallback& callback ); -void PreferencesDialog_addDisplayPreferences( const PreferencesPageCallback& callback ); -void PreferencesDialog_addDisplayPage( const PreferenceGroupCallback& callback ); -void PreferencesDialog_addSettingsPreferences( const PreferencesPageCallback& callback ); -void PreferencesDialog_addSettingsPage( const PreferenceGroupCallback& callback ); +void PreferencesDialog_addDisplayPreferences(const PreferencesPageCallback &callback); -void PreferencesDialog_restartRequired( const char* staticName ); +void PreferencesDialog_addDisplayPage(const PreferenceGroupCallback &callback); + +void PreferencesDialog_addSettingsPreferences(const PreferencesPageCallback &callback); + +void PreferencesDialog_addSettingsPage(const PreferenceGroupCallback &callback); + +void PreferencesDialog_restartRequired(const char *staticName); template class LatchedValue { @@ -132,31 +178,36 @@ public: Value m_latched; const char *m_description; - LatchedValue(Value value, const char *description) : m_latched(value), m_description(description) { + LatchedValue(Value value, const char *description) : m_latched(value), m_description(description) + { } - void useLatched() { + void useLatched() + { m_value = m_latched; } }; template struct PropertyImpl, T> { - static void Export(const LatchedValue &self, const Callback &returnz) { - returnz(self.m_latched); - } - - static void Import(LatchedValue &self, T value) { - self.m_latched = value; - if (value != self.m_value) { - PreferencesDialog_restartRequired(self.m_description); - } - } + static void Export(const LatchedValue &self, const Callback &returnz) + { + returnz(self.m_latched); + } + + static void Import(LatchedValue &self, T value) + { + self.m_latched = value; + if (value != self.m_value) { + PreferencesDialog_restartRequired(self.m_description); + } + } }; template -Property make_property(LatchedValue &self) { - return make_property, T>(self); +Property make_property(LatchedValue &self) +{ + return make_property, T>(self); } /*! @@ -171,36 +222,38 @@ Property make_property(LatchedValue &self) { generate a piece that just says "the game pack is there", but put the rest of the config somwhere else (i.e. not generated, copied over during setup .. for instance in the game tools directory) */ -class CGameDescription -{ -typedef std::map GameDescription; +class CGameDescription { + typedef std::map GameDescription; public: -CopiedString mGameFile; ///< the .game file that describes this game -GameDescription m_gameDescription; - -CopiedString mGameToolsPath; ///< the explicit path to the game-dependent modules -CopiedString mGameType; ///< the type of the engine - -const char* getKeyValue( const char* key ) const { - GameDescription::const_iterator i = m_gameDescription.find( key ); - if ( i != m_gameDescription.end() ) { - return ( *i ).second.c_str(); - } - return ""; -} -const char* getRequiredKeyValue( const char* key ) const { - GameDescription::const_iterator i = m_gameDescription.find( key ); - if ( i != m_gameDescription.end() ) { - return ( *i ).second.c_str(); - } - ERROR_MESSAGE( "game attribute " << makeQuoted( key ) << " not found in " << makeQuoted( mGameFile.c_str() ) ); - return ""; -} + CopiedString mGameFile; ///< the .game file that describes this game + GameDescription m_gameDescription; + + CopiedString mGameToolsPath; ///< the explicit path to the game-dependent modules + CopiedString mGameType; ///< the type of the engine + + const char *getKeyValue(const char *key) const + { + GameDescription::const_iterator i = m_gameDescription.find(key); + if (i != m_gameDescription.end()) { + return (*i).second.c_str(); + } + return ""; + } + + const char *getRequiredKeyValue(const char *key) const + { + GameDescription::const_iterator i = m_gameDescription.find(key); + if (i != m_gameDescription.end()) { + return (*i).second.c_str(); + } + ERROR_MESSAGE("game attribute " << makeQuoted(key) << " not found in " << makeQuoted(mGameFile.c_str())); + return ""; + } -CGameDescription( xmlDocPtr pDoc, const CopiedString &GameFile ); + CGameDescription(xmlDocPtr pDoc, const CopiedString &GameFile); -void Dump(); + void Dump(); }; extern CGameDescription *g_pGameDescription; @@ -214,11 +267,10 @@ class StringOutputStream; /*! standalone dialog for games selection, and more generally global settings */ -class CGameDialog : public Dialog -{ +class CGameDialog : public Dialog { protected: -mutable int m_nComboSelect; ///< intermediate int value for combo in dialog box + mutable int m_nComboSelect; ///< intermediate int value for combo in dialog box public: @@ -233,54 +285,57 @@ public: what game has been selected this is the name of the .game file */ -CopiedString m_sGameFile; + CopiedString m_sGameFile; /*! prompt which game to load on startup */ -bool m_bGamePrompt; + bool m_bGamePrompt; /*! log console to radiant.log m_bForceLogConsole is an obscure forced latching situation */ -bool m_bForceLogConsole; + bool m_bForceLogConsole; /*@}*/ /*! the list of game descriptions we scanned from the game/ dir */ -std::list mGames; + std::list mGames; -CGameDialog() : - m_sGameFile( "" ), - m_bGamePrompt( true ), - m_bForceLogConsole( false ){ -} -virtual ~CGameDialog(); + CGameDialog() : + m_sGameFile(""), + m_bGamePrompt(true), + m_bForceLogConsole(false) + { + } + + virtual ~CGameDialog(); /*! intialize the game dialog, called at CPrefsDlg::Init will scan for games, load prefs, and do game selection dialog if needed */ -void Init(); + void Init(); /*! reset the global settings by removing the file */ -void Reset(); + void Reset(); /*! run the dialog UI for the list of games */ -void DoGameDialog(); + void DoGameDialog(); /*! Dialog API this is only called when the dialog is built at startup for main engine select */ -ui::Window BuildDialog(); + ui::Window BuildDialog(); + + void GameFileImport(int value); -void GameFileImport( int value ); -void GameFileExport( const Callback & importCallback ) const; + void GameFileExport(const Callback &importCallback) const; /*! construction of the dialog frame @@ -289,7 +344,7 @@ void GameFileExport( const Callback & importCallback ) const; for prefs, we hook the frame in the main notebook build the frame on-demand (only once) */ -void CreateGlobalFrame( PreferencesPage& page ); + void CreateGlobalFrame(PreferencesPage &page); /*! global preferences subsystem @@ -299,25 +354,25 @@ void CreateGlobalFrame( PreferencesPage& page ); could have named the class differently I guess */ /*@{*/ -void LoadPrefs(); ///< load from file into variables -void SavePrefs(); ///< save pref variables to file + void LoadPrefs(); ///< load from file into variables + void SavePrefs(); ///< save pref variables to file /*@}*/ private: /*! scan for .game files, load them */ -void ScanForGames(); + void ScanForGames(); /*! inits g_Preferences.m_global_rc_path */ -void InitGlobalPrefPath(); + void InitGlobalPrefPath(); /*! uses m_nComboItem to find the right mGames */ -CGameDescription *GameDescriptionForComboItem(); + CGameDescription *GameDescriptionForComboItem(); }; /*! @@ -328,27 +383,27 @@ extern CGameDialog g_GamesDialog; class texdef_t; -class PrefsDlg : public Dialog -{ +class PrefsDlg : public Dialog { public: protected: -std::list mGames; + std::list mGames; public: -ui::Widget m_notebook{ui::null}; + ui::Widget m_notebook{ui::null}; -virtual ~PrefsDlg(){ - g_string_free( m_rc_path, true ); - g_string_free( m_inipath, true ); -} + virtual ~PrefsDlg() + { + g_string_free(m_rc_path, true); + g_string_free(m_inipath, true); + } /*! path for global settings win32: AppPath linux: ~/.radiant/[version]/ */ -GString *m_global_rc_path; + GString *m_global_rc_path; /*! path to per-game settings @@ -356,48 +411,54 @@ GString *m_global_rc_path; win32: GameToolsPath linux: ~/.radiant/[version]/[gamename]/ */ -GString *m_rc_path; + GString *m_rc_path; /*! holds per-game settings m_rc_path+"local.pref" \todo FIXME at some point this should become XML property bag code too */ -GString *m_inipath; + GString *m_inipath; // initialize the above paths -void Init(); + void Init(); /*! Utility function for swapping notebook pages for tree list selections */ -void showPrefPage( ui::Widget prefpage ); + void showPrefPage(ui::Widget prefpage); protected: /*! Dialog API */ -ui::Window BuildDialog(); -void PostModal( EMessageBoxReturn code ); + ui::Window BuildDialog(); + + void PostModal(EMessageBoxReturn code); }; extern PrefsDlg g_Preferences; -struct preferences_globals_t -{ - // disabled all INI / registry read write .. used when shutting down after registry cleanup - bool disable_ini; - preferences_globals_t() : disable_ini( false ){ - } +struct preferences_globals_t { + // disabled all INI / registry read write .. used when shutting down after registry cleanup + bool disable_ini; + + preferences_globals_t() : disable_ini(false) + { + } }; + extern preferences_globals_t g_preferences_globals; -void PreferencesDialog_constructWindow( ui::Window main_window ); +void PreferencesDialog_constructWindow(ui::Window main_window); + void PreferencesDialog_destroyWindow(); void PreferencesDialog_showDialog(); void GlobalPreferences_Init(); + void Preferences_Init(); void Preferences_Load(); + void Preferences_Save(); void Preferences_Reset(); diff --git a/radiant/qe3.cpp b/radiant/qe3.cpp index 809df39c..789cdf16 100644 --- a/radiant/qe3.cpp +++ b/radiant/qe3.cpp @@ -72,308 +72,322 @@ QEGlobals_t g_qeglobals; #endif -void QE_InitVFS(){ - // VFS initialization ----------------------- - // we will call GlobalFileSystem().initDirectory, giving the directories to look in (for files in pk3's and for standalone files) - // we need to call in order, the mod ones first, then the base ones .. they will be searched in this order - // *nix systems have a dual filesystem in ~/.q3a, which is searched first .. so we need to add that too - - const char* gamename = gamename_get(); - const char* basegame = basegame_get(); - const char* userRoot = g_qeglobals.m_userEnginePath.c_str(); - const char* globalRoot = EnginePath_get(); - - // if we have a mod dir - if ( !string_equal( gamename, basegame ) ) { - // ~/./ - if ( userRoot && !g_disableHomePath ) { - StringOutputStream userGamePath( 256 ); - userGamePath << userRoot << gamename << '/'; - GlobalFileSystem().initDirectory( userGamePath.c_str() ); - } - - // / - if ( !g_disableEnginePath ) { - StringOutputStream globalGamePath( 256 ); - globalGamePath << globalRoot << gamename << '/'; - GlobalFileSystem().initDirectory( globalGamePath.c_str() ); - } - } - - // ~/./ - if ( userRoot && !g_disableHomePath ) { - StringOutputStream userBasePath( 256 ); - userBasePath << userRoot << basegame << '/'; - GlobalFileSystem().initDirectory( userBasePath.c_str() ); - } - - // / - if ( !g_disableEnginePath ) { - StringOutputStream globalBasePath( 256 ); - globalBasePath << globalRoot << basegame << '/'; - GlobalFileSystem().initDirectory( globalBasePath.c_str() ); - } - - // extra pakpaths - for ( int i = 0; i < g_pakPathCount; i++ ) { - if (g_strcmp0( g_strPakPath[i].c_str(), "")) { - GlobalFileSystem().initDirectory( g_strPakPath[i].c_str() ); - } - } +void QE_InitVFS() +{ + // VFS initialization ----------------------- + // we will call GlobalFileSystem().initDirectory, giving the directories to look in (for files in pk3's and for standalone files) + // we need to call in order, the mod ones first, then the base ones .. they will be searched in this order + // *nix systems have a dual filesystem in ~/.q3a, which is searched first .. so we need to add that too + + const char *gamename = gamename_get(); + const char *basegame = basegame_get(); + const char *userRoot = g_qeglobals.m_userEnginePath.c_str(); + const char *globalRoot = EnginePath_get(); + + // if we have a mod dir + if (!string_equal(gamename, basegame)) { + // ~/./ + if (userRoot && !g_disableHomePath) { + StringOutputStream userGamePath(256); + userGamePath << userRoot << gamename << '/'; + GlobalFileSystem().initDirectory(userGamePath.c_str()); + } + + // / + if (!g_disableEnginePath) { + StringOutputStream globalGamePath(256); + globalGamePath << globalRoot << gamename << '/'; + GlobalFileSystem().initDirectory(globalGamePath.c_str()); + } + } + + // ~/./ + if (userRoot && !g_disableHomePath) { + StringOutputStream userBasePath(256); + userBasePath << userRoot << basegame << '/'; + GlobalFileSystem().initDirectory(userBasePath.c_str()); + } + + // / + if (!g_disableEnginePath) { + StringOutputStream globalBasePath(256); + globalBasePath << globalRoot << basegame << '/'; + GlobalFileSystem().initDirectory(globalBasePath.c_str()); + } + + // extra pakpaths + for (int i = 0; i < g_pakPathCount; i++) { + if (g_strcmp0(g_strPakPath[i].c_str(), "")) { + GlobalFileSystem().initDirectory(g_strPakPath[i].c_str()); + } + } } int g_numbrushes = 0; int g_numentities = 0; -void QE_UpdateStatusBar(){ - char buffer[128]; - sprintf( buffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities ); - g_pParentWnd->SetStatusText( g_pParentWnd->m_brushcount_status, buffer ); +void QE_UpdateStatusBar() +{ + char buffer[128]; + sprintf(buffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities); + g_pParentWnd->SetStatusText(g_pParentWnd->m_brushcount_status, buffer); } SimpleCounter g_brushCount; -void QE_brushCountChanged(){ - g_numbrushes = int(g_brushCount.get() ); - QE_UpdateStatusBar(); +void QE_brushCountChanged() +{ + g_numbrushes = int(g_brushCount.get()); + QE_UpdateStatusBar(); } SimpleCounter g_entityCount; -void QE_entityCountChanged(){ - g_numentities = int(g_entityCount.get() ); - QE_UpdateStatusBar(); -} - -bool ConfirmModified( const char* title ){ - if ( !Map_Modified( g_map ) ) { - return true; - } - - auto result = ui::alert( MainFrame_getWindow(), "The current map has changed since it was last saved.\nDo you want to save the current map before continuing?", title, ui::alert_type::YESNOCANCEL, ui::alert_icon::Question ); - if ( result == ui::alert_response::CANCEL ) { - return false; - } - if ( result == ui::alert_response::YES ) { - if ( Map_Unnamed( g_map ) ) { - return Map_SaveAs(); - } - else - { - return Map_Save(); - } - } - return true; -} - -void bsp_init(){ - build_set_variable( "RadiantPath", AppPath_get() ); - build_set_variable( "ExecutableType", RADIANT_EXECUTABLE ); - build_set_variable( "EnginePath", EnginePath_get() ); - build_set_variable( "UserEnginePath", g_qeglobals.m_userEnginePath.c_str() ); - build_set_variable( "MonitorAddress", ( g_WatchBSP_Enabled ) ? "127.0.0.1:39000" : "" ); - build_set_variable( "GameName", gamename_get() ); - - StringBuffer ExtraQ3map2Args; - // extra pakpaths - for ( int i = 0; i < g_pakPathCount; i++ ) { - if ( g_strcmp0( g_strPakPath[i].c_str(), "") ) { - ExtraQ3map2Args.push_string( " -fs_pakpath \"" ); - ExtraQ3map2Args.push_string( g_strPakPath[i].c_str() ); - ExtraQ3map2Args.push_string( "\"" ); - } - } - - // extra switches - if ( g_disableEnginePath ) { - ExtraQ3map2Args.push_string( " -fs_nobasepath " ); - } - - if ( g_disableHomePath ) { - ExtraQ3map2Args.push_string( " -fs_nohomepath " ); - } - - build_set_variable( "ExtraQ3map2Args", ExtraQ3map2Args.c_str() ); - - const char* mapname = Map_Name( g_map ); - StringOutputStream name( 256 ); - name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".bsp"; - - build_set_variable( "MapFile", mapname ); - build_set_variable( "BspFile", name.c_str() ); +void QE_entityCountChanged() +{ + g_numentities = int(g_entityCount.get()); + QE_UpdateStatusBar(); } -void bsp_shutdown(){ - build_clear_variables(); +bool ConfirmModified(const char *title) +{ + if (!Map_Modified(g_map)) { + return true; + } + + auto result = ui::alert(MainFrame_getWindow(), + "The current map has changed since it was last saved.\nDo you want to save the current map before continuing?", + title, ui::alert_type::YESNOCANCEL, ui::alert_icon::Question); + if (result == ui::alert_response::CANCEL) { + return false; + } + if (result == ui::alert_response::YES) { + if (Map_Unnamed(g_map)) { + return Map_SaveAs(); + } else { + return Map_Save(); + } + } + return true; } -class ArrayCommandListener : public CommandListener +void bsp_init() { -GPtrArray* m_array; -public: -ArrayCommandListener(){ - m_array = g_ptr_array_new(); -} -~ArrayCommandListener(){ - g_ptr_array_free( m_array, TRUE ); + build_set_variable("RadiantPath", AppPath_get()); + build_set_variable("ExecutableType", RADIANT_EXECUTABLE); + build_set_variable("EnginePath", EnginePath_get()); + build_set_variable("UserEnginePath", g_qeglobals.m_userEnginePath.c_str()); + build_set_variable("MonitorAddress", (g_WatchBSP_Enabled) ? "127.0.0.1:39000" : ""); + build_set_variable("GameName", gamename_get()); + + StringBuffer ExtraQ3map2Args; + // extra pakpaths + for (int i = 0; i < g_pakPathCount; i++) { + if (g_strcmp0(g_strPakPath[i].c_str(), "")) { + ExtraQ3map2Args.push_string(" -fs_pakpath \""); + ExtraQ3map2Args.push_string(g_strPakPath[i].c_str()); + ExtraQ3map2Args.push_string("\""); + } + } + + // extra switches + if (g_disableEnginePath) { + ExtraQ3map2Args.push_string(" -fs_nobasepath "); + } + + if (g_disableHomePath) { + ExtraQ3map2Args.push_string(" -fs_nohomepath "); + } + + build_set_variable("ExtraQ3map2Args", ExtraQ3map2Args.c_str()); + + const char *mapname = Map_Name(g_map); + StringOutputStream name(256); + name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".bsp"; + + build_set_variable("MapFile", mapname); + build_set_variable("BspFile", name.c_str()); } -void execute( const char* command ){ - g_ptr_array_add( m_array, g_strdup( command ) ); +void bsp_shutdown() +{ + build_clear_variables(); } -GPtrArray* array() const { - return m_array; -} +class ArrayCommandListener : public CommandListener { + GPtrArray *m_array; +public: + ArrayCommandListener() + { + m_array = g_ptr_array_new(); + } + + ~ArrayCommandListener() + { + g_ptr_array_free(m_array, TRUE); + } + + void execute(const char *command) + { + g_ptr_array_add(m_array, g_strdup(command)); + } + + GPtrArray *array() const + { + return m_array; + } }; -class BatchCommandListener : public CommandListener -{ -TextOutputStream& m_file; -std::size_t m_commandCount; -const char* m_outputRedirect; +class BatchCommandListener : public CommandListener { + TextOutputStream &m_file; + std::size_t m_commandCount; + const char *m_outputRedirect; public: -BatchCommandListener( TextOutputStream& file, const char* outputRedirect ) : m_file( file ), m_commandCount( 0 ), m_outputRedirect( outputRedirect ){ -} - -void execute( const char* command ){ - m_file << command; - if ( m_commandCount == 0 ) { - m_file << " > "; - } - else - { - m_file << " >> "; - } - m_file << "\"" << m_outputRedirect << "\""; - m_file << "\n"; - ++m_commandCount; -} + BatchCommandListener(TextOutputStream &file, const char *outputRedirect) : m_file(file), m_commandCount(0), + m_outputRedirect(outputRedirect) + { + } + + void execute(const char *command) + { + m_file << command; + if (m_commandCount == 0) { + m_file << " > "; + } else { + m_file << " >> "; + } + m_file << "\"" << m_outputRedirect << "\""; + m_file << "\n"; + ++m_commandCount; + } }; -bool Region_cameraValid(){ - Vector3 vOrig( vector3_snapped( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ) ) ); - - for ( int i = 0 ; i < 3 ; i++ ) - { - if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) { - return false; - } - } - return true; +bool Region_cameraValid() +{ + Vector3 vOrig(vector3_snapped(Camera_getOrigin(*g_pParentWnd->GetCamWnd()))); + + for (int i = 0; i < 3; i++) { + if (vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i]) { + return false; + } + } + return true; } -void RunBSP( const char* name ){ - // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503 - // make sure we don't attempt to region compile a map with the camera outside the region - if ( region_active && !Region_cameraValid() ) { - globalErrorStream() << "The camera must be in the region to start a region compile.\n"; - return; - } - - SaveMap(); - - if ( Map_Unnamed( g_map ) ) { - globalOutputStream() << "build cancelled\n"; - return; - } - - if ( g_SnapShots_Enabled && !Map_Unnamed( g_map ) && Map_Modified( g_map ) ) { - Map_Snapshot(); - } - - if ( region_active ) { - const char* mapname = Map_Name( g_map ); - StringOutputStream name( 256 ); - name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".reg"; - Map_SaveRegion( name.c_str() ); - } - - Pointfile_Delete(); - - bsp_init(); - - if ( g_WatchBSP_Enabled ) { - ArrayCommandListener listener; - build_run( name, listener ); - // grab the file name for engine running - const char* fullname = Map_Name( g_map ); - StringOutputStream bspname( 64 ); - bspname << StringRange( path_get_filename_start( fullname ), path_get_filename_base_end( fullname ) ); - BuildMonitor_Run( listener.array(), bspname.c_str() ); - } - else - { - char junkpath[PATH_MAX]; - strcpy( junkpath, SettingsPath_get() ); - strcat( junkpath, "junk.txt" ); - - char batpath[PATH_MAX]; +void RunBSP(const char *name) +{ + // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503 + // make sure we don't attempt to region compile a map with the camera outside the region + if (region_active && !Region_cameraValid()) { + globalErrorStream() << "The camera must be in the region to start a region compile.\n"; + return; + } + + SaveMap(); + + if (Map_Unnamed(g_map)) { + globalOutputStream() << "build cancelled\n"; + return; + } + + if (g_SnapShots_Enabled && !Map_Unnamed(g_map) && Map_Modified(g_map)) { + Map_Snapshot(); + } + + if (region_active) { + const char *mapname = Map_Name(g_map); + StringOutputStream name(256); + name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".reg"; + Map_SaveRegion(name.c_str()); + } + + Pointfile_Delete(); + + bsp_init(); + + if (g_WatchBSP_Enabled) { + ArrayCommandListener listener; + build_run(name, listener); + // grab the file name for engine running + const char *fullname = Map_Name(g_map); + StringOutputStream bspname(64); + bspname << StringRange(path_get_filename_start(fullname), path_get_filename_base_end(fullname)); + BuildMonitor_Run(listener.array(), bspname.c_str()); + } else { + char junkpath[PATH_MAX]; + strcpy(junkpath, SettingsPath_get()); + strcat(junkpath, "junk.txt"); + + char batpath[PATH_MAX]; #if GDEF_OS_POSIX - strcpy( batpath, SettingsPath_get() ); - strcat( batpath, "qe3bsp.sh" ); + strcpy(batpath, SettingsPath_get()); + strcat(batpath, "qe3bsp.sh"); #elif GDEF_OS_WINDOWS - strcpy( batpath, SettingsPath_get() ); - strcat( batpath, "qe3bsp.bat" ); + strcpy( batpath, SettingsPath_get() ); + strcat( batpath, "qe3bsp.bat" ); #else #error "unsupported platform" #endif - bool written = false; - { - TextFileOutputStream batchFile( batpath ); - if ( !batchFile.failed() ) { + bool written = false; + { + TextFileOutputStream batchFile(batpath); + if (!batchFile.failed()) { #if GDEF_OS_POSIX - batchFile << "#!/bin/sh \n\n"; + batchFile << "#!/bin/sh \n\n"; #endif - BatchCommandListener listener( batchFile, junkpath ); - build_run( name, listener ); - written = true; - } - } - if ( written ) { + BatchCommandListener listener(batchFile, junkpath); + build_run(name, listener); + written = true; + } + } + if (written) { #if GDEF_OS_POSIX - chmod( batpath, 0744 ); + chmod(batpath, 0744); #endif - globalOutputStream() << "Writing the compile script to '" << batpath << "'\n"; - globalOutputStream() << "The build output will be saved in '" << junkpath << "'\n"; - Q_Exec( batpath, NULL, NULL, true, false ); - } - } + globalOutputStream() << "Writing the compile script to '" << batpath << "'\n"; + globalOutputStream() << "The build output will be saved in '" << junkpath << "'\n"; + Q_Exec(batpath, NULL, NULL, true, false); + } + } - bsp_shutdown(); + bsp_shutdown(); } // ============================================================================= // Sys_ functions -void Sys_SetTitle( const char *text, bool modified ){ - StringOutputStream title; - title << text; +void Sys_SetTitle(const char *text, bool modified) +{ + StringOutputStream title; + title << text; - if ( modified ) { - title << " *"; - } + if (modified) { + title << " *"; + } - gtk_window_set_title(MainFrame_getWindow(), title.c_str() ); + gtk_window_set_title(MainFrame_getWindow(), title.c_str()); } bool g_bWaitCursor = false; -void Sys_BeginWait( void ){ - ScreenUpdates_Disable( "Processing...", "Please Wait" ); - GdkCursor *cursor = gdk_cursor_new( GDK_WATCH ); - gdk_window_set_cursor( gtk_widget_get_window(MainFrame_getWindow()), cursor ); - gdk_cursor_unref( cursor ); - g_bWaitCursor = true; +void Sys_BeginWait(void) +{ + ScreenUpdates_Disable("Processing...", "Please Wait"); + GdkCursor *cursor = gdk_cursor_new(GDK_WATCH); + gdk_window_set_cursor(gtk_widget_get_window(MainFrame_getWindow()), cursor); + gdk_cursor_unref(cursor); + g_bWaitCursor = true; } -void Sys_EndWait( void ){ - ScreenUpdates_Enable(); - gdk_window_set_cursor(gtk_widget_get_window(MainFrame_getWindow()), 0 ); - g_bWaitCursor = false; +void Sys_EndWait(void) +{ + ScreenUpdates_Enable(); + gdk_window_set_cursor(gtk_widget_get_window(MainFrame_getWindow()), 0); + g_bWaitCursor = false; } -void Sys_Beep( void ){ - gdk_beep(); +void Sys_Beep(void) +{ + gdk_beep(); } diff --git a/radiant/qe3.h b/radiant/qe3.h index 88ff41aa..c702a234 100644 --- a/radiant/qe3.h +++ b/radiant/qe3.h @@ -27,38 +27,39 @@ // // system functions // -void Sys_SetTitle( const char *text, bool modified ); +void Sys_SetTitle(const char *text, bool modified); -void RunBSP( const char* name ); +void RunBSP(const char *name); void QE_InitVFS(); void QE_brushCountChanged(); + void QE_entityCountChanged(); -bool ConfirmModified( const char* title ); +bool ConfirmModified(const char *title); // most of the QE globals are stored in this structure -typedef struct -{ - /*! - win32: engine full path. - unix: user home full path + engine dir. - */ - CopiedString m_userEnginePath; - /*! - cache for m_userEnginePath + mod subdirectory. - */ - CopiedString m_userGamePath; +typedef struct { + /*! + win32: engine full path. + unix: user home full path + engine dir. + */ + CopiedString m_userEnginePath; + /*! + cache for m_userEnginePath + mod subdirectory. + */ + CopiedString m_userGamePath; } QEGlobals_t; extern QEGlobals_t g_qeglobals; class SimpleCounter; + extern SimpleCounter g_brushCount; extern SimpleCounter g_entityCount; diff --git a/radiant/qgl.cpp b/radiant/qgl.cpp index d64b7a5f..2a8297c9 100644 --- a/radiant/qgl.cpp +++ b/radiant/qgl.cpp @@ -30,29 +30,29 @@ #include #if GDEF_OS_WINDOWS -#define WINGDIAPI __declspec( dllimport ) + #define WINGDIAPI __declspec( dllimport ) #define APIENTRY __stdcall #endif #if GDEF_OS_MACOS && !defined( XWINDOWS ) #include #else + #include + #endif #if GDEF_OS_WINDOWS -#undef WINGDIAPI + #undef WINGDIAPI #undef APIENTRY #endif #include "igl.h" - - #if GDEF_OS_WINDOWS -#include + #include PROC ( WINAPI * qwglGetProcAddress )( LPCSTR ); @@ -61,12 +61,14 @@ PROC ( WINAPI * qwglGetProcAddress )( LPCSTR ); #include #include -Bool ( *qglXQueryExtension )( Display *dpy, int *errorb, int *event ); -void* ( *qglXGetProcAddressARB )( const GLubyte * procName ); -typedef void* ( *glXGetProcAddressARBProc )( const GLubyte *procName ); +Bool ( *qglXQueryExtension )(Display *dpy, int *errorb, int *event); + +void *( *qglXGetProcAddressARB )(const GLubyte *procName); + +typedef void *( *glXGetProcAddressARBProc )(const GLubyte *procName); #elif GDEF_OS_MACOS -#include + #include #include #include #else @@ -74,114 +76,114 @@ typedef void* ( *glXGetProcAddressARBProc )( const GLubyte *procName ); #endif -void QGL_Shutdown( OpenGLBinding& table ){ - globalOutputStream() << "Shutting down OpenGL module..."; +void QGL_Shutdown(OpenGLBinding &table) +{ + globalOutputStream() << "Shutting down OpenGL module..."; #if GDEF_OS_WINDOWS - qwglGetProcAddress = 0; + qwglGetProcAddress = 0; #elif defined( XWINDOWS ) - qglXQueryExtension = glXQueryExtension; - qglXGetProcAddressARB = 0; + qglXQueryExtension = glXQueryExtension; + qglXGetProcAddressARB = 0; #elif GDEF_OS_MACOS -#else + #else #error "unsupported platform" #endif - globalOutputStream() << "Done.\n"; + globalOutputStream() << "Done.\n"; } -typedef struct glu_error_struct -{ - GLenum errnum; - const char *errstr; +typedef struct glu_error_struct { + GLenum errnum; + const char *errstr; } GLU_ERROR_STRUCT; GLU_ERROR_STRUCT glu_errlist[] = { - {GL_NO_ERROR, "GL_NO_ERROR - no error"}, - {GL_INVALID_ENUM, "GL_INVALID_ENUM - An unacceptable value is specified for an enumerated argument."}, - {GL_INVALID_VALUE, "GL_INVALID_VALUE - A numeric argument is out of range."}, - {GL_INVALID_OPERATION, "GL_INVALID_OPERATION - The specified operation is not allowed in the current state."}, - {GL_STACK_OVERFLOW, "GL_STACK_OVERFLOW - Function would cause a stack overflow."}, - {GL_STACK_UNDERFLOW, "GL_STACK_UNDERFLOW - Function would cause a stack underflow."}, - {GL_OUT_OF_MEMORY, "GL_OUT_OF_MEMORY - There is not enough memory left to execute the function."}, - {0, 0} + {GL_NO_ERROR, "GL_NO_ERROR - no error"}, + {GL_INVALID_ENUM, "GL_INVALID_ENUM - An unacceptable value is specified for an enumerated argument."}, + {GL_INVALID_VALUE, "GL_INVALID_VALUE - A numeric argument is out of range."}, + {GL_INVALID_OPERATION, "GL_INVALID_OPERATION - The specified operation is not allowed in the current state."}, + {GL_STACK_OVERFLOW, "GL_STACK_OVERFLOW - Function would cause a stack overflow."}, + {GL_STACK_UNDERFLOW, "GL_STACK_UNDERFLOW - Function would cause a stack underflow."}, + {GL_OUT_OF_MEMORY, "GL_OUT_OF_MEMORY - There is not enough memory left to execute the function."}, + {0, 0} }; -const GLubyte* qgluErrorString( GLenum errCode ){ - int search = 0; - for ( search = 0; glu_errlist[search].errstr; search++ ) - { - if ( errCode == glu_errlist[search].errnum ) { - return (const GLubyte *)glu_errlist[search].errstr; - } - } //end for - return (const GLubyte *)"Unknown error"; +const GLubyte *qgluErrorString(GLenum errCode) +{ + int search = 0; + for (search = 0; glu_errlist[search].errstr; search++) { + if (errCode == glu_errlist[search].errnum) { + return (const GLubyte *) glu_errlist[search].errstr; + } + } //end for + return (const GLubyte *) "Unknown error"; } -void glInvalidFunction(){ - ERROR_MESSAGE( "calling an invalid OpenGL function" ); +void glInvalidFunction() +{ + ERROR_MESSAGE("calling an invalid OpenGL function"); } #define EXTENSIONS_ENABLED 1 -bool QGL_ExtensionSupported( const char* extension ){ +bool QGL_ExtensionSupported(const char *extension) +{ #if EXTENSIONS_ENABLED - const GLubyte *extensions = 0; - const GLubyte *start; - GLubyte *where, *terminator; + const GLubyte *extensions = 0; + const GLubyte *start; + GLubyte *where, *terminator; - // Extension names should not have spaces. - where = (GLubyte *) strchr( extension, ' ' ); - if ( where || *extension == '\0' ) { - return false; - } + // Extension names should not have spaces. + where = (GLubyte *) strchr(extension, ' '); + if (where || *extension == '\0') { + return false; + } - extensions = GlobalOpenGL().m_glGetString( GL_EXTENSIONS ); + extensions = GlobalOpenGL().m_glGetString(GL_EXTENSIONS); #if !GDEF_OS_MACOS - if ( !extensions ) { - return false; - } + if (!extensions) { + return false; + } #endif - // It takes a bit of care to be fool-proof about parsing the - // OpenGL extensions string. Don't be fooled by sub-strings, etc. - for ( start = extensions; ; ) - { - where = (GLubyte *) strstr( (const char *) start, extension ); - if ( !where ) { - break; - } - - terminator = where + strlen( extension ); - if ( where == start || *( where - 1 ) == ' ' ) { - if ( *terminator == ' ' || *terminator == '\0' ) { - return true; - } - } - - start = terminator; - } + // It takes a bit of care to be fool-proof about parsing the + // OpenGL extensions string. Don't be fooled by sub-strings, etc. + for (start = extensions;;) { + where = (GLubyte *) strstr((const char *) start, extension); + if (!where) { + break; + } + + terminator = where + strlen(extension); + if (where == start || *(where - 1) == ' ') { + if (*terminator == ' ' || *terminator == '\0') { + return true; + } + } + + start = terminator; + } #endif - return false; + return false; } -typedef int ( QGL_DLLEXPORT * QGLFunctionPointer )(); +typedef int ( QGL_DLLEXPORT *QGLFunctionPointer )(); -QGLFunctionPointer QGL_getExtensionFunc( const char* symbol ){ +QGLFunctionPointer QGL_getExtensionFunc(const char *symbol) +{ #if defined( XWINDOWS ) - //ASSERT_NOTNULL(qglXGetProcAddressARB); - if ( qglXGetProcAddressARB == 0 ) { - return reinterpret_cast( glInvalidFunction ); - } - else - { - return (QGLFunctionPointer) qglXGetProcAddressARB( reinterpret_cast( symbol ) ); - } + //ASSERT_NOTNULL(qglXGetProcAddressARB); + if (qglXGetProcAddressARB == 0) { + return reinterpret_cast( glInvalidFunction ); + } else { + return (QGLFunctionPointer) qglXGetProcAddressARB(reinterpret_cast( symbol )); + } #elif GDEF_OS_MACOS - // Prepend a '_' for the Unix C symbol mangling convention + // Prepend a '_' for the Unix C symbol mangling convention char *symbolName = (char *) malloc(strlen(symbol) + 2); strcpy(symbolName + 1, symbol); symbolName[0] = '_'; @@ -199,1321 +201,1311 @@ QGLFunctionPointer QGL_getExtensionFunc( const char* symbol ){ template -bool QGL_constructExtensionFunc( Func& func, const char* symbol ){ - func = reinterpret_cast( QGL_getExtensionFunc( symbol ) ); - return func != 0; +bool QGL_constructExtensionFunc(Func &func, const char *symbol) +{ + func = reinterpret_cast( QGL_getExtensionFunc(symbol)); + return func != 0; } template -void QGL_invalidateExtensionFunc( Func& func ){ - func = reinterpret_cast( glInvalidFunction ); +void QGL_invalidateExtensionFunc(Func &func) +{ + func = reinterpret_cast( glInvalidFunction ); } -void QGL_clear( OpenGLBinding& table ){ - QGL_invalidateExtensionFunc( table.m_glAccum ); - QGL_invalidateExtensionFunc( table.m_glAlphaFunc ); - QGL_invalidateExtensionFunc( table.m_glAreTexturesResident ); - QGL_invalidateExtensionFunc( table.m_glArrayElement ); - QGL_invalidateExtensionFunc( table.m_glBegin ); - QGL_invalidateExtensionFunc( table.m_glBindTexture ); - QGL_invalidateExtensionFunc( table.m_glBitmap ); - QGL_invalidateExtensionFunc( table.m_glBlendFunc ); - QGL_invalidateExtensionFunc( table.m_glCallList ); - QGL_invalidateExtensionFunc( table.m_glCallLists ); - QGL_invalidateExtensionFunc( table.m_glClear ); - QGL_invalidateExtensionFunc( table.m_glClearAccum ); - QGL_invalidateExtensionFunc( table.m_glClearColor ); - QGL_invalidateExtensionFunc( table.m_glClearDepth ); - QGL_invalidateExtensionFunc( table.m_glClearIndex ); - QGL_invalidateExtensionFunc( table.m_glClearStencil ); - QGL_invalidateExtensionFunc( table.m_glClipPlane ); - QGL_invalidateExtensionFunc( table.m_glColor3b ); - QGL_invalidateExtensionFunc( table.m_glColor3bv ); - QGL_invalidateExtensionFunc( table.m_glColor3d ); - QGL_invalidateExtensionFunc( table.m_glColor3dv ); - QGL_invalidateExtensionFunc( table.m_glColor3f ); - QGL_invalidateExtensionFunc( table.m_glColor3fv ); - QGL_invalidateExtensionFunc( table.m_glColor3i ); - QGL_invalidateExtensionFunc( table.m_glColor3iv ); - QGL_invalidateExtensionFunc( table.m_glColor3s ); - QGL_invalidateExtensionFunc( table.m_glColor3sv ); - QGL_invalidateExtensionFunc( table.m_glColor3ub ); - QGL_invalidateExtensionFunc( table.m_glColor3ubv ); - QGL_invalidateExtensionFunc( table.m_glColor3ui ); - QGL_invalidateExtensionFunc( table.m_glColor3uiv ); - QGL_invalidateExtensionFunc( table.m_glColor3us ); - QGL_invalidateExtensionFunc( table.m_glColor3usv ); - QGL_invalidateExtensionFunc( table.m_glColor4b ); - QGL_invalidateExtensionFunc( table.m_glColor4bv ); - QGL_invalidateExtensionFunc( table.m_glColor4d ); - QGL_invalidateExtensionFunc( table.m_glColor4dv ); - QGL_invalidateExtensionFunc( table.m_glColor4f ); - QGL_invalidateExtensionFunc( table.m_glColor4fv ); - QGL_invalidateExtensionFunc( table.m_glColor4i ); - QGL_invalidateExtensionFunc( table.m_glColor4iv ); - QGL_invalidateExtensionFunc( table.m_glColor4s ); - QGL_invalidateExtensionFunc( table.m_glColor4sv ); - QGL_invalidateExtensionFunc( table.m_glColor4ub ); - QGL_invalidateExtensionFunc( table.m_glColor4ubv ); - QGL_invalidateExtensionFunc( table.m_glColor4ui ); - QGL_invalidateExtensionFunc( table.m_glColor4uiv ); - QGL_invalidateExtensionFunc( table.m_glColor4us ); - QGL_invalidateExtensionFunc( table.m_glColor4usv ); - QGL_invalidateExtensionFunc( table.m_glColorMask ); - QGL_invalidateExtensionFunc( table.m_glColorMaterial ); - QGL_invalidateExtensionFunc( table.m_glColorPointer ); - QGL_invalidateExtensionFunc( table.m_glCopyPixels ); - QGL_invalidateExtensionFunc( table.m_glCopyTexImage1D ); - QGL_invalidateExtensionFunc( table.m_glCopyTexImage2D ); - QGL_invalidateExtensionFunc( table.m_glCopyTexSubImage1D ); - QGL_invalidateExtensionFunc( table.m_glCopyTexSubImage2D ); - QGL_invalidateExtensionFunc( table.m_glCullFace ); - QGL_invalidateExtensionFunc( table.m_glDeleteLists ); - QGL_invalidateExtensionFunc( table.m_glDeleteTextures ); - QGL_invalidateExtensionFunc( table.m_glDepthFunc ); - QGL_invalidateExtensionFunc( table.m_glDepthMask ); - QGL_invalidateExtensionFunc( table.m_glDepthRange ); - QGL_invalidateExtensionFunc( table.m_glDisable ); - QGL_invalidateExtensionFunc( table.m_glDisableClientState ); - QGL_invalidateExtensionFunc( table.m_glDrawArrays ); - QGL_invalidateExtensionFunc( table.m_glDrawBuffer ); - QGL_invalidateExtensionFunc( table.m_glDrawElements ); - QGL_invalidateExtensionFunc( table.m_glDrawPixels ); - QGL_invalidateExtensionFunc( table.m_glEdgeFlag ); - QGL_invalidateExtensionFunc( table.m_glEdgeFlagPointer ); - QGL_invalidateExtensionFunc( table.m_glEdgeFlagv ); - QGL_invalidateExtensionFunc( table.m_glEnable ); - QGL_invalidateExtensionFunc( table.m_glEnableClientState ); - QGL_invalidateExtensionFunc( table.m_glEnd ); - QGL_invalidateExtensionFunc( table.m_glEndList ); - QGL_invalidateExtensionFunc( table.m_glEvalCoord1d ); - QGL_invalidateExtensionFunc( table.m_glEvalCoord1dv ); - QGL_invalidateExtensionFunc( table.m_glEvalCoord1f ); - QGL_invalidateExtensionFunc( table.m_glEvalCoord1fv ); - QGL_invalidateExtensionFunc( table.m_glEvalCoord2d ); - QGL_invalidateExtensionFunc( table.m_glEvalCoord2dv ); - QGL_invalidateExtensionFunc( table.m_glEvalCoord2f ); - QGL_invalidateExtensionFunc( table.m_glEvalCoord2fv ); - QGL_invalidateExtensionFunc( table.m_glEvalMesh1 ); - QGL_invalidateExtensionFunc( table.m_glEvalMesh2 ); - QGL_invalidateExtensionFunc( table.m_glEvalPoint1 ); - QGL_invalidateExtensionFunc( table.m_glEvalPoint2 ); - QGL_invalidateExtensionFunc( table.m_glFeedbackBuffer ); - QGL_invalidateExtensionFunc( table.m_glFinish ); - QGL_invalidateExtensionFunc( table.m_glFlush ); - QGL_invalidateExtensionFunc( table.m_glFogf ); - QGL_invalidateExtensionFunc( table.m_glFogfv ); - QGL_invalidateExtensionFunc( table.m_glFogi ); - QGL_invalidateExtensionFunc( table.m_glFogiv ); - QGL_invalidateExtensionFunc( table.m_glFrontFace ); - QGL_invalidateExtensionFunc( table.m_glFrustum ); - QGL_invalidateExtensionFunc( table.m_glGenLists ); - QGL_invalidateExtensionFunc( table.m_glGenTextures ); - QGL_invalidateExtensionFunc( table.m_glGetBooleanv ); - QGL_invalidateExtensionFunc( table.m_glGetClipPlane ); - QGL_invalidateExtensionFunc( table.m_glGetDoublev ); - QGL_invalidateExtensionFunc( table.m_glGetError ); - QGL_invalidateExtensionFunc( table.m_glGetFloatv ); - QGL_invalidateExtensionFunc( table.m_glGetIntegerv ); - QGL_invalidateExtensionFunc( table.m_glGetLightfv ); - QGL_invalidateExtensionFunc( table.m_glGetLightiv ); - QGL_invalidateExtensionFunc( table.m_glGetMapdv ); - QGL_invalidateExtensionFunc( table.m_glGetMapfv ); - QGL_invalidateExtensionFunc( table.m_glGetMapiv ); - QGL_invalidateExtensionFunc( table.m_glGetMaterialfv ); - QGL_invalidateExtensionFunc( table.m_glGetMaterialiv ); - QGL_invalidateExtensionFunc( table.m_glGetPixelMapfv ); - QGL_invalidateExtensionFunc( table.m_glGetPixelMapuiv ); - QGL_invalidateExtensionFunc( table.m_glGetPixelMapusv ); - QGL_invalidateExtensionFunc( table.m_glGetPointerv ); - QGL_invalidateExtensionFunc( table.m_glGetPolygonStipple ); - table.m_glGetString = glGetString; - QGL_invalidateExtensionFunc( table.m_glGetTexEnvfv ); - QGL_invalidateExtensionFunc( table.m_glGetTexEnviv ); - QGL_invalidateExtensionFunc( table.m_glGetTexGendv ); - QGL_invalidateExtensionFunc( table.m_glGetTexGenfv ); - QGL_invalidateExtensionFunc( table.m_glGetTexGeniv ); - QGL_invalidateExtensionFunc( table.m_glGetTexImage ); - QGL_invalidateExtensionFunc( table.m_glGetTexLevelParameterfv ); - QGL_invalidateExtensionFunc( table.m_glGetTexLevelParameteriv ); - QGL_invalidateExtensionFunc( table.m_glGetTexParameterfv ); - QGL_invalidateExtensionFunc( table.m_glGetTexParameteriv ); - QGL_invalidateExtensionFunc( table.m_glHint ); - QGL_invalidateExtensionFunc( table.m_glIndexMask ); - QGL_invalidateExtensionFunc( table.m_glIndexPointer ); - QGL_invalidateExtensionFunc( table.m_glIndexd ); - QGL_invalidateExtensionFunc( table.m_glIndexdv ); - QGL_invalidateExtensionFunc( table.m_glIndexf ); - QGL_invalidateExtensionFunc( table.m_glIndexfv ); - QGL_invalidateExtensionFunc( table.m_glIndexi ); - QGL_invalidateExtensionFunc( table.m_glIndexiv ); - QGL_invalidateExtensionFunc( table.m_glIndexs ); - QGL_invalidateExtensionFunc( table.m_glIndexsv ); - QGL_invalidateExtensionFunc( table.m_glIndexub ); - QGL_invalidateExtensionFunc( table.m_glIndexubv ); - QGL_invalidateExtensionFunc( table.m_glInitNames ); - QGL_invalidateExtensionFunc( table.m_glInterleavedArrays ); - QGL_invalidateExtensionFunc( table.m_glIsEnabled ); - QGL_invalidateExtensionFunc( table.m_glIsList ); - QGL_invalidateExtensionFunc( table.m_glIsTexture ); - QGL_invalidateExtensionFunc( table.m_glLightModelf ); - QGL_invalidateExtensionFunc( table.m_glLightModelfv ); - QGL_invalidateExtensionFunc( table.m_glLightModeli ); - QGL_invalidateExtensionFunc( table.m_glLightModeliv ); - QGL_invalidateExtensionFunc( table.m_glLightf ); - QGL_invalidateExtensionFunc( table.m_glLightfv ); - QGL_invalidateExtensionFunc( table.m_glLighti ); - QGL_invalidateExtensionFunc( table.m_glLightiv ); - QGL_invalidateExtensionFunc( table.m_glLineStipple ); - QGL_invalidateExtensionFunc( table.m_glLineWidth ); - QGL_invalidateExtensionFunc( table.m_glListBase ); - QGL_invalidateExtensionFunc( table.m_glLoadIdentity ); - QGL_invalidateExtensionFunc( table.m_glLoadMatrixd ); - QGL_invalidateExtensionFunc( table.m_glLoadMatrixf ); - QGL_invalidateExtensionFunc( table.m_glLoadName ); - QGL_invalidateExtensionFunc( table.m_glLogicOp ); - QGL_invalidateExtensionFunc( table.m_glMap1d ); - QGL_invalidateExtensionFunc( table.m_glMap1f ); - QGL_invalidateExtensionFunc( table.m_glMap2d ); - QGL_invalidateExtensionFunc( table.m_glMap2f ); - QGL_invalidateExtensionFunc( table.m_glMapGrid1d ); - QGL_invalidateExtensionFunc( table.m_glMapGrid1f ); - QGL_invalidateExtensionFunc( table.m_glMapGrid2d ); - QGL_invalidateExtensionFunc( table.m_glMapGrid2f ); - QGL_invalidateExtensionFunc( table.m_glMaterialf ); - QGL_invalidateExtensionFunc( table.m_glMaterialfv ); - QGL_invalidateExtensionFunc( table.m_glMateriali ); - QGL_invalidateExtensionFunc( table.m_glMaterialiv ); - QGL_invalidateExtensionFunc( table.m_glMatrixMode ); - QGL_invalidateExtensionFunc( table.m_glMultMatrixd ); - QGL_invalidateExtensionFunc( table.m_glMultMatrixf ); - QGL_invalidateExtensionFunc( table.m_glNewList ); - QGL_invalidateExtensionFunc( table.m_glNormal3b ); - QGL_invalidateExtensionFunc( table.m_glNormal3bv ); - QGL_invalidateExtensionFunc( table.m_glNormal3d ); - QGL_invalidateExtensionFunc( table.m_glNormal3dv ); - QGL_invalidateExtensionFunc( table.m_glNormal3f ); - QGL_invalidateExtensionFunc( table.m_glNormal3fv ); - QGL_invalidateExtensionFunc( table.m_glNormal3i ); - QGL_invalidateExtensionFunc( table.m_glNormal3iv ); - QGL_invalidateExtensionFunc( table.m_glNormal3s ); - QGL_invalidateExtensionFunc( table.m_glNormal3sv ); - QGL_invalidateExtensionFunc( table.m_glNormalPointer ); - QGL_invalidateExtensionFunc( table.m_glOrtho ); - QGL_invalidateExtensionFunc( table.m_glPassThrough ); - QGL_invalidateExtensionFunc( table.m_glPixelMapfv ); - QGL_invalidateExtensionFunc( table.m_glPixelMapuiv ); - QGL_invalidateExtensionFunc( table.m_glPixelMapusv ); - QGL_invalidateExtensionFunc( table.m_glPixelStoref ); - QGL_invalidateExtensionFunc( table.m_glPixelStorei ); - QGL_invalidateExtensionFunc( table.m_glPixelTransferf ); - QGL_invalidateExtensionFunc( table.m_glPixelTransferi ); - QGL_invalidateExtensionFunc( table.m_glPixelZoom ); - QGL_invalidateExtensionFunc( table.m_glPointSize ); - QGL_invalidateExtensionFunc( table.m_glPolygonMode ); - QGL_invalidateExtensionFunc( table.m_glPolygonOffset ); - QGL_invalidateExtensionFunc( table.m_glPolygonStipple ); - QGL_invalidateExtensionFunc( table.m_glPopAttrib ); - QGL_invalidateExtensionFunc( table.m_glPopClientAttrib ); - QGL_invalidateExtensionFunc( table.m_glPopMatrix ); - QGL_invalidateExtensionFunc( table.m_glPopName ); - QGL_invalidateExtensionFunc( table.m_glPrioritizeTextures ); - QGL_invalidateExtensionFunc( table.m_glPushAttrib ); - QGL_invalidateExtensionFunc( table.m_glPushClientAttrib ); - QGL_invalidateExtensionFunc( table.m_glPushMatrix ); - QGL_invalidateExtensionFunc( table.m_glPushName ); - QGL_invalidateExtensionFunc( table.m_glRasterPos2d ); - QGL_invalidateExtensionFunc( table.m_glRasterPos2dv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos2f ); - QGL_invalidateExtensionFunc( table.m_glRasterPos2fv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos2i ); - QGL_invalidateExtensionFunc( table.m_glRasterPos2iv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos2s ); - QGL_invalidateExtensionFunc( table.m_glRasterPos2sv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos3d ); - QGL_invalidateExtensionFunc( table.m_glRasterPos3dv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos3f ); - QGL_invalidateExtensionFunc( table.m_glRasterPos3fv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos3i ); - QGL_invalidateExtensionFunc( table.m_glRasterPos3iv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos3s ); - QGL_invalidateExtensionFunc( table.m_glRasterPos3sv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos4d ); - QGL_invalidateExtensionFunc( table.m_glRasterPos4dv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos4f ); - QGL_invalidateExtensionFunc( table.m_glRasterPos4fv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos4i ); - QGL_invalidateExtensionFunc( table.m_glRasterPos4iv ); - QGL_invalidateExtensionFunc( table.m_glRasterPos4s ); - QGL_invalidateExtensionFunc( table.m_glRasterPos4sv ); - QGL_invalidateExtensionFunc( table.m_glReadBuffer ); - QGL_invalidateExtensionFunc( table.m_glReadPixels ); - QGL_invalidateExtensionFunc( table.m_glRectd ); - QGL_invalidateExtensionFunc( table.m_glRectdv ); - QGL_invalidateExtensionFunc( table.m_glRectf ); - QGL_invalidateExtensionFunc( table.m_glRectfv ); - QGL_invalidateExtensionFunc( table.m_glRecti ); - QGL_invalidateExtensionFunc( table.m_glRectiv ); - QGL_invalidateExtensionFunc( table.m_glRects ); - QGL_invalidateExtensionFunc( table.m_glRectsv ); - QGL_invalidateExtensionFunc( table.m_glRenderMode ); - QGL_invalidateExtensionFunc( table.m_glRotated ); - QGL_invalidateExtensionFunc( table.m_glRotatef ); - QGL_invalidateExtensionFunc( table.m_glScaled ); - QGL_invalidateExtensionFunc( table.m_glScalef ); - QGL_invalidateExtensionFunc( table.m_glScissor ); - QGL_invalidateExtensionFunc( table.m_glSelectBuffer ); - QGL_invalidateExtensionFunc( table.m_glShadeModel ); - QGL_invalidateExtensionFunc( table.m_glStencilFunc ); - QGL_invalidateExtensionFunc( table.m_glStencilMask ); - QGL_invalidateExtensionFunc( table.m_glStencilOp ); - QGL_invalidateExtensionFunc( table.m_glTexCoord1d ); - QGL_invalidateExtensionFunc( table.m_glTexCoord1dv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord1f ); - QGL_invalidateExtensionFunc( table.m_glTexCoord1fv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord1i ); - QGL_invalidateExtensionFunc( table.m_glTexCoord1iv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord1s ); - QGL_invalidateExtensionFunc( table.m_glTexCoord1sv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord2d ); - QGL_invalidateExtensionFunc( table.m_glTexCoord2dv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord2f ); - QGL_invalidateExtensionFunc( table.m_glTexCoord2fv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord2i ); - QGL_invalidateExtensionFunc( table.m_glTexCoord2iv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord2s ); - QGL_invalidateExtensionFunc( table.m_glTexCoord2sv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord3d ); - QGL_invalidateExtensionFunc( table.m_glTexCoord3dv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord3f ); - QGL_invalidateExtensionFunc( table.m_glTexCoord3fv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord3i ); - QGL_invalidateExtensionFunc( table.m_glTexCoord3iv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord3s ); - QGL_invalidateExtensionFunc( table.m_glTexCoord3sv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord4d ); - QGL_invalidateExtensionFunc( table.m_glTexCoord4dv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord4f ); - QGL_invalidateExtensionFunc( table.m_glTexCoord4fv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord4i ); - QGL_invalidateExtensionFunc( table.m_glTexCoord4iv ); - QGL_invalidateExtensionFunc( table.m_glTexCoord4s ); - QGL_invalidateExtensionFunc( table.m_glTexCoord4sv ); - QGL_invalidateExtensionFunc( table.m_glTexCoordPointer ); - QGL_invalidateExtensionFunc( table.m_glTexEnvf ); - QGL_invalidateExtensionFunc( table.m_glTexEnvfv ); - QGL_invalidateExtensionFunc( table.m_glTexEnvi ); - QGL_invalidateExtensionFunc( table.m_glTexEnviv ); - QGL_invalidateExtensionFunc( table.m_glTexGend ); - QGL_invalidateExtensionFunc( table.m_glTexGendv ); - QGL_invalidateExtensionFunc( table.m_glTexGenf ); - QGL_invalidateExtensionFunc( table.m_glTexGenfv ); - QGL_invalidateExtensionFunc( table.m_glTexGeni ); - QGL_invalidateExtensionFunc( table.m_glTexGeniv ); - QGL_invalidateExtensionFunc( table.m_glTexImage1D ); - QGL_invalidateExtensionFunc( table.m_glTexImage2D ); - QGL_invalidateExtensionFunc( table.m_glTexParameterf ); - QGL_invalidateExtensionFunc( table.m_glTexParameterfv ); - QGL_invalidateExtensionFunc( table.m_glTexParameteri ); - QGL_invalidateExtensionFunc( table.m_glTexParameteriv ); - QGL_invalidateExtensionFunc( table.m_glTexSubImage1D ); - QGL_invalidateExtensionFunc( table.m_glTexSubImage2D ); - QGL_invalidateExtensionFunc( table.m_glTranslated ); - QGL_invalidateExtensionFunc( table.m_glTranslatef ); - QGL_invalidateExtensionFunc( table.m_glVertex2d ); - QGL_invalidateExtensionFunc( table.m_glVertex2dv ); - QGL_invalidateExtensionFunc( table.m_glVertex2f ); - QGL_invalidateExtensionFunc( table.m_glVertex2fv ); - QGL_invalidateExtensionFunc( table.m_glVertex2i ); - QGL_invalidateExtensionFunc( table.m_glVertex2iv ); - QGL_invalidateExtensionFunc( table.m_glVertex2s ); - QGL_invalidateExtensionFunc( table.m_glVertex2sv ); - QGL_invalidateExtensionFunc( table.m_glVertex3d ); - QGL_invalidateExtensionFunc( table.m_glVertex3dv ); - QGL_invalidateExtensionFunc( table.m_glVertex3f ); - QGL_invalidateExtensionFunc( table.m_glVertex3fv ); - QGL_invalidateExtensionFunc( table.m_glVertex3i ); - QGL_invalidateExtensionFunc( table.m_glVertex3iv ); - QGL_invalidateExtensionFunc( table.m_glVertex3s ); - QGL_invalidateExtensionFunc( table.m_glVertex3sv ); - QGL_invalidateExtensionFunc( table.m_glVertex4d ); - QGL_invalidateExtensionFunc( table.m_glVertex4dv ); - QGL_invalidateExtensionFunc( table.m_glVertex4f ); - QGL_invalidateExtensionFunc( table.m_glVertex4fv ); - QGL_invalidateExtensionFunc( table.m_glVertex4i ); - QGL_invalidateExtensionFunc( table.m_glVertex4iv ); - QGL_invalidateExtensionFunc( table.m_glVertex4s ); - QGL_invalidateExtensionFunc( table.m_glVertex4sv ); - QGL_invalidateExtensionFunc( table.m_glVertexPointer ); - QGL_invalidateExtensionFunc( table.m_glViewport ); +void QGL_clear(OpenGLBinding &table) +{ + QGL_invalidateExtensionFunc(table.m_glAccum); + QGL_invalidateExtensionFunc(table.m_glAlphaFunc); + QGL_invalidateExtensionFunc(table.m_glAreTexturesResident); + QGL_invalidateExtensionFunc(table.m_glArrayElement); + QGL_invalidateExtensionFunc(table.m_glBegin); + QGL_invalidateExtensionFunc(table.m_glBindTexture); + QGL_invalidateExtensionFunc(table.m_glBitmap); + QGL_invalidateExtensionFunc(table.m_glBlendFunc); + QGL_invalidateExtensionFunc(table.m_glCallList); + QGL_invalidateExtensionFunc(table.m_glCallLists); + QGL_invalidateExtensionFunc(table.m_glClear); + QGL_invalidateExtensionFunc(table.m_glClearAccum); + QGL_invalidateExtensionFunc(table.m_glClearColor); + QGL_invalidateExtensionFunc(table.m_glClearDepth); + QGL_invalidateExtensionFunc(table.m_glClearIndex); + QGL_invalidateExtensionFunc(table.m_glClearStencil); + QGL_invalidateExtensionFunc(table.m_glClipPlane); + QGL_invalidateExtensionFunc(table.m_glColor3b); + QGL_invalidateExtensionFunc(table.m_glColor3bv); + QGL_invalidateExtensionFunc(table.m_glColor3d); + QGL_invalidateExtensionFunc(table.m_glColor3dv); + QGL_invalidateExtensionFunc(table.m_glColor3f); + QGL_invalidateExtensionFunc(table.m_glColor3fv); + QGL_invalidateExtensionFunc(table.m_glColor3i); + QGL_invalidateExtensionFunc(table.m_glColor3iv); + QGL_invalidateExtensionFunc(table.m_glColor3s); + QGL_invalidateExtensionFunc(table.m_glColor3sv); + QGL_invalidateExtensionFunc(table.m_glColor3ub); + QGL_invalidateExtensionFunc(table.m_glColor3ubv); + QGL_invalidateExtensionFunc(table.m_glColor3ui); + QGL_invalidateExtensionFunc(table.m_glColor3uiv); + QGL_invalidateExtensionFunc(table.m_glColor3us); + QGL_invalidateExtensionFunc(table.m_glColor3usv); + QGL_invalidateExtensionFunc(table.m_glColor4b); + QGL_invalidateExtensionFunc(table.m_glColor4bv); + QGL_invalidateExtensionFunc(table.m_glColor4d); + QGL_invalidateExtensionFunc(table.m_glColor4dv); + QGL_invalidateExtensionFunc(table.m_glColor4f); + QGL_invalidateExtensionFunc(table.m_glColor4fv); + QGL_invalidateExtensionFunc(table.m_glColor4i); + QGL_invalidateExtensionFunc(table.m_glColor4iv); + QGL_invalidateExtensionFunc(table.m_glColor4s); + QGL_invalidateExtensionFunc(table.m_glColor4sv); + QGL_invalidateExtensionFunc(table.m_glColor4ub); + QGL_invalidateExtensionFunc(table.m_glColor4ubv); + QGL_invalidateExtensionFunc(table.m_glColor4ui); + QGL_invalidateExtensionFunc(table.m_glColor4uiv); + QGL_invalidateExtensionFunc(table.m_glColor4us); + QGL_invalidateExtensionFunc(table.m_glColor4usv); + QGL_invalidateExtensionFunc(table.m_glColorMask); + QGL_invalidateExtensionFunc(table.m_glColorMaterial); + QGL_invalidateExtensionFunc(table.m_glColorPointer); + QGL_invalidateExtensionFunc(table.m_glCopyPixels); + QGL_invalidateExtensionFunc(table.m_glCopyTexImage1D); + QGL_invalidateExtensionFunc(table.m_glCopyTexImage2D); + QGL_invalidateExtensionFunc(table.m_glCopyTexSubImage1D); + QGL_invalidateExtensionFunc(table.m_glCopyTexSubImage2D); + QGL_invalidateExtensionFunc(table.m_glCullFace); + QGL_invalidateExtensionFunc(table.m_glDeleteLists); + QGL_invalidateExtensionFunc(table.m_glDeleteTextures); + QGL_invalidateExtensionFunc(table.m_glDepthFunc); + QGL_invalidateExtensionFunc(table.m_glDepthMask); + QGL_invalidateExtensionFunc(table.m_glDepthRange); + QGL_invalidateExtensionFunc(table.m_glDisable); + QGL_invalidateExtensionFunc(table.m_glDisableClientState); + QGL_invalidateExtensionFunc(table.m_glDrawArrays); + QGL_invalidateExtensionFunc(table.m_glDrawBuffer); + QGL_invalidateExtensionFunc(table.m_glDrawElements); + QGL_invalidateExtensionFunc(table.m_glDrawPixels); + QGL_invalidateExtensionFunc(table.m_glEdgeFlag); + QGL_invalidateExtensionFunc(table.m_glEdgeFlagPointer); + QGL_invalidateExtensionFunc(table.m_glEdgeFlagv); + QGL_invalidateExtensionFunc(table.m_glEnable); + QGL_invalidateExtensionFunc(table.m_glEnableClientState); + QGL_invalidateExtensionFunc(table.m_glEnd); + QGL_invalidateExtensionFunc(table.m_glEndList); + QGL_invalidateExtensionFunc(table.m_glEvalCoord1d); + QGL_invalidateExtensionFunc(table.m_glEvalCoord1dv); + QGL_invalidateExtensionFunc(table.m_glEvalCoord1f); + QGL_invalidateExtensionFunc(table.m_glEvalCoord1fv); + QGL_invalidateExtensionFunc(table.m_glEvalCoord2d); + QGL_invalidateExtensionFunc(table.m_glEvalCoord2dv); + QGL_invalidateExtensionFunc(table.m_glEvalCoord2f); + QGL_invalidateExtensionFunc(table.m_glEvalCoord2fv); + QGL_invalidateExtensionFunc(table.m_glEvalMesh1); + QGL_invalidateExtensionFunc(table.m_glEvalMesh2); + QGL_invalidateExtensionFunc(table.m_glEvalPoint1); + QGL_invalidateExtensionFunc(table.m_glEvalPoint2); + QGL_invalidateExtensionFunc(table.m_glFeedbackBuffer); + QGL_invalidateExtensionFunc(table.m_glFinish); + QGL_invalidateExtensionFunc(table.m_glFlush); + QGL_invalidateExtensionFunc(table.m_glFogf); + QGL_invalidateExtensionFunc(table.m_glFogfv); + QGL_invalidateExtensionFunc(table.m_glFogi); + QGL_invalidateExtensionFunc(table.m_glFogiv); + QGL_invalidateExtensionFunc(table.m_glFrontFace); + QGL_invalidateExtensionFunc(table.m_glFrustum); + QGL_invalidateExtensionFunc(table.m_glGenLists); + QGL_invalidateExtensionFunc(table.m_glGenTextures); + QGL_invalidateExtensionFunc(table.m_glGetBooleanv); + QGL_invalidateExtensionFunc(table.m_glGetClipPlane); + QGL_invalidateExtensionFunc(table.m_glGetDoublev); + QGL_invalidateExtensionFunc(table.m_glGetError); + QGL_invalidateExtensionFunc(table.m_glGetFloatv); + QGL_invalidateExtensionFunc(table.m_glGetIntegerv); + QGL_invalidateExtensionFunc(table.m_glGetLightfv); + QGL_invalidateExtensionFunc(table.m_glGetLightiv); + QGL_invalidateExtensionFunc(table.m_glGetMapdv); + QGL_invalidateExtensionFunc(table.m_glGetMapfv); + QGL_invalidateExtensionFunc(table.m_glGetMapiv); + QGL_invalidateExtensionFunc(table.m_glGetMaterialfv); + QGL_invalidateExtensionFunc(table.m_glGetMaterialiv); + QGL_invalidateExtensionFunc(table.m_glGetPixelMapfv); + QGL_invalidateExtensionFunc(table.m_glGetPixelMapuiv); + QGL_invalidateExtensionFunc(table.m_glGetPixelMapusv); + QGL_invalidateExtensionFunc(table.m_glGetPointerv); + QGL_invalidateExtensionFunc(table.m_glGetPolygonStipple); + table.m_glGetString = glGetString; + QGL_invalidateExtensionFunc(table.m_glGetTexEnvfv); + QGL_invalidateExtensionFunc(table.m_glGetTexEnviv); + QGL_invalidateExtensionFunc(table.m_glGetTexGendv); + QGL_invalidateExtensionFunc(table.m_glGetTexGenfv); + QGL_invalidateExtensionFunc(table.m_glGetTexGeniv); + QGL_invalidateExtensionFunc(table.m_glGetTexImage); + QGL_invalidateExtensionFunc(table.m_glGetTexLevelParameterfv); + QGL_invalidateExtensionFunc(table.m_glGetTexLevelParameteriv); + QGL_invalidateExtensionFunc(table.m_glGetTexParameterfv); + QGL_invalidateExtensionFunc(table.m_glGetTexParameteriv); + QGL_invalidateExtensionFunc(table.m_glHint); + QGL_invalidateExtensionFunc(table.m_glIndexMask); + QGL_invalidateExtensionFunc(table.m_glIndexPointer); + QGL_invalidateExtensionFunc(table.m_glIndexd); + QGL_invalidateExtensionFunc(table.m_glIndexdv); + QGL_invalidateExtensionFunc(table.m_glIndexf); + QGL_invalidateExtensionFunc(table.m_glIndexfv); + QGL_invalidateExtensionFunc(table.m_glIndexi); + QGL_invalidateExtensionFunc(table.m_glIndexiv); + QGL_invalidateExtensionFunc(table.m_glIndexs); + QGL_invalidateExtensionFunc(table.m_glIndexsv); + QGL_invalidateExtensionFunc(table.m_glIndexub); + QGL_invalidateExtensionFunc(table.m_glIndexubv); + QGL_invalidateExtensionFunc(table.m_glInitNames); + QGL_invalidateExtensionFunc(table.m_glInterleavedArrays); + QGL_invalidateExtensionFunc(table.m_glIsEnabled); + QGL_invalidateExtensionFunc(table.m_glIsList); + QGL_invalidateExtensionFunc(table.m_glIsTexture); + QGL_invalidateExtensionFunc(table.m_glLightModelf); + QGL_invalidateExtensionFunc(table.m_glLightModelfv); + QGL_invalidateExtensionFunc(table.m_glLightModeli); + QGL_invalidateExtensionFunc(table.m_glLightModeliv); + QGL_invalidateExtensionFunc(table.m_glLightf); + QGL_invalidateExtensionFunc(table.m_glLightfv); + QGL_invalidateExtensionFunc(table.m_glLighti); + QGL_invalidateExtensionFunc(table.m_glLightiv); + QGL_invalidateExtensionFunc(table.m_glLineStipple); + QGL_invalidateExtensionFunc(table.m_glLineWidth); + QGL_invalidateExtensionFunc(table.m_glListBase); + QGL_invalidateExtensionFunc(table.m_glLoadIdentity); + QGL_invalidateExtensionFunc(table.m_glLoadMatrixd); + QGL_invalidateExtensionFunc(table.m_glLoadMatrixf); + QGL_invalidateExtensionFunc(table.m_glLoadName); + QGL_invalidateExtensionFunc(table.m_glLogicOp); + QGL_invalidateExtensionFunc(table.m_glMap1d); + QGL_invalidateExtensionFunc(table.m_glMap1f); + QGL_invalidateExtensionFunc(table.m_glMap2d); + QGL_invalidateExtensionFunc(table.m_glMap2f); + QGL_invalidateExtensionFunc(table.m_glMapGrid1d); + QGL_invalidateExtensionFunc(table.m_glMapGrid1f); + QGL_invalidateExtensionFunc(table.m_glMapGrid2d); + QGL_invalidateExtensionFunc(table.m_glMapGrid2f); + QGL_invalidateExtensionFunc(table.m_glMaterialf); + QGL_invalidateExtensionFunc(table.m_glMaterialfv); + QGL_invalidateExtensionFunc(table.m_glMateriali); + QGL_invalidateExtensionFunc(table.m_glMaterialiv); + QGL_invalidateExtensionFunc(table.m_glMatrixMode); + QGL_invalidateExtensionFunc(table.m_glMultMatrixd); + QGL_invalidateExtensionFunc(table.m_glMultMatrixf); + QGL_invalidateExtensionFunc(table.m_glNewList); + QGL_invalidateExtensionFunc(table.m_glNormal3b); + QGL_invalidateExtensionFunc(table.m_glNormal3bv); + QGL_invalidateExtensionFunc(table.m_glNormal3d); + QGL_invalidateExtensionFunc(table.m_glNormal3dv); + QGL_invalidateExtensionFunc(table.m_glNormal3f); + QGL_invalidateExtensionFunc(table.m_glNormal3fv); + QGL_invalidateExtensionFunc(table.m_glNormal3i); + QGL_invalidateExtensionFunc(table.m_glNormal3iv); + QGL_invalidateExtensionFunc(table.m_glNormal3s); + QGL_invalidateExtensionFunc(table.m_glNormal3sv); + QGL_invalidateExtensionFunc(table.m_glNormalPointer); + QGL_invalidateExtensionFunc(table.m_glOrtho); + QGL_invalidateExtensionFunc(table.m_glPassThrough); + QGL_invalidateExtensionFunc(table.m_glPixelMapfv); + QGL_invalidateExtensionFunc(table.m_glPixelMapuiv); + QGL_invalidateExtensionFunc(table.m_glPixelMapusv); + QGL_invalidateExtensionFunc(table.m_glPixelStoref); + QGL_invalidateExtensionFunc(table.m_glPixelStorei); + QGL_invalidateExtensionFunc(table.m_glPixelTransferf); + QGL_invalidateExtensionFunc(table.m_glPixelTransferi); + QGL_invalidateExtensionFunc(table.m_glPixelZoom); + QGL_invalidateExtensionFunc(table.m_glPointSize); + QGL_invalidateExtensionFunc(table.m_glPolygonMode); + QGL_invalidateExtensionFunc(table.m_glPolygonOffset); + QGL_invalidateExtensionFunc(table.m_glPolygonStipple); + QGL_invalidateExtensionFunc(table.m_glPopAttrib); + QGL_invalidateExtensionFunc(table.m_glPopClientAttrib); + QGL_invalidateExtensionFunc(table.m_glPopMatrix); + QGL_invalidateExtensionFunc(table.m_glPopName); + QGL_invalidateExtensionFunc(table.m_glPrioritizeTextures); + QGL_invalidateExtensionFunc(table.m_glPushAttrib); + QGL_invalidateExtensionFunc(table.m_glPushClientAttrib); + QGL_invalidateExtensionFunc(table.m_glPushMatrix); + QGL_invalidateExtensionFunc(table.m_glPushName); + QGL_invalidateExtensionFunc(table.m_glRasterPos2d); + QGL_invalidateExtensionFunc(table.m_glRasterPos2dv); + QGL_invalidateExtensionFunc(table.m_glRasterPos2f); + QGL_invalidateExtensionFunc(table.m_glRasterPos2fv); + QGL_invalidateExtensionFunc(table.m_glRasterPos2i); + QGL_invalidateExtensionFunc(table.m_glRasterPos2iv); + QGL_invalidateExtensionFunc(table.m_glRasterPos2s); + QGL_invalidateExtensionFunc(table.m_glRasterPos2sv); + QGL_invalidateExtensionFunc(table.m_glRasterPos3d); + QGL_invalidateExtensionFunc(table.m_glRasterPos3dv); + QGL_invalidateExtensionFunc(table.m_glRasterPos3f); + QGL_invalidateExtensionFunc(table.m_glRasterPos3fv); + QGL_invalidateExtensionFunc(table.m_glRasterPos3i); + QGL_invalidateExtensionFunc(table.m_glRasterPos3iv); + QGL_invalidateExtensionFunc(table.m_glRasterPos3s); + QGL_invalidateExtensionFunc(table.m_glRasterPos3sv); + QGL_invalidateExtensionFunc(table.m_glRasterPos4d); + QGL_invalidateExtensionFunc(table.m_glRasterPos4dv); + QGL_invalidateExtensionFunc(table.m_glRasterPos4f); + QGL_invalidateExtensionFunc(table.m_glRasterPos4fv); + QGL_invalidateExtensionFunc(table.m_glRasterPos4i); + QGL_invalidateExtensionFunc(table.m_glRasterPos4iv); + QGL_invalidateExtensionFunc(table.m_glRasterPos4s); + QGL_invalidateExtensionFunc(table.m_glRasterPos4sv); + QGL_invalidateExtensionFunc(table.m_glReadBuffer); + QGL_invalidateExtensionFunc(table.m_glReadPixels); + QGL_invalidateExtensionFunc(table.m_glRectd); + QGL_invalidateExtensionFunc(table.m_glRectdv); + QGL_invalidateExtensionFunc(table.m_glRectf); + QGL_invalidateExtensionFunc(table.m_glRectfv); + QGL_invalidateExtensionFunc(table.m_glRecti); + QGL_invalidateExtensionFunc(table.m_glRectiv); + QGL_invalidateExtensionFunc(table.m_glRects); + QGL_invalidateExtensionFunc(table.m_glRectsv); + QGL_invalidateExtensionFunc(table.m_glRenderMode); + QGL_invalidateExtensionFunc(table.m_glRotated); + QGL_invalidateExtensionFunc(table.m_glRotatef); + QGL_invalidateExtensionFunc(table.m_glScaled); + QGL_invalidateExtensionFunc(table.m_glScalef); + QGL_invalidateExtensionFunc(table.m_glScissor); + QGL_invalidateExtensionFunc(table.m_glSelectBuffer); + QGL_invalidateExtensionFunc(table.m_glShadeModel); + QGL_invalidateExtensionFunc(table.m_glStencilFunc); + QGL_invalidateExtensionFunc(table.m_glStencilMask); + QGL_invalidateExtensionFunc(table.m_glStencilOp); + QGL_invalidateExtensionFunc(table.m_glTexCoord1d); + QGL_invalidateExtensionFunc(table.m_glTexCoord1dv); + QGL_invalidateExtensionFunc(table.m_glTexCoord1f); + QGL_invalidateExtensionFunc(table.m_glTexCoord1fv); + QGL_invalidateExtensionFunc(table.m_glTexCoord1i); + QGL_invalidateExtensionFunc(table.m_glTexCoord1iv); + QGL_invalidateExtensionFunc(table.m_glTexCoord1s); + QGL_invalidateExtensionFunc(table.m_glTexCoord1sv); + QGL_invalidateExtensionFunc(table.m_glTexCoord2d); + QGL_invalidateExtensionFunc(table.m_glTexCoord2dv); + QGL_invalidateExtensionFunc(table.m_glTexCoord2f); + QGL_invalidateExtensionFunc(table.m_glTexCoord2fv); + QGL_invalidateExtensionFunc(table.m_glTexCoord2i); + QGL_invalidateExtensionFunc(table.m_glTexCoord2iv); + QGL_invalidateExtensionFunc(table.m_glTexCoord2s); + QGL_invalidateExtensionFunc(table.m_glTexCoord2sv); + QGL_invalidateExtensionFunc(table.m_glTexCoord3d); + QGL_invalidateExtensionFunc(table.m_glTexCoord3dv); + QGL_invalidateExtensionFunc(table.m_glTexCoord3f); + QGL_invalidateExtensionFunc(table.m_glTexCoord3fv); + QGL_invalidateExtensionFunc(table.m_glTexCoord3i); + QGL_invalidateExtensionFunc(table.m_glTexCoord3iv); + QGL_invalidateExtensionFunc(table.m_glTexCoord3s); + QGL_invalidateExtensionFunc(table.m_glTexCoord3sv); + QGL_invalidateExtensionFunc(table.m_glTexCoord4d); + QGL_invalidateExtensionFunc(table.m_glTexCoord4dv); + QGL_invalidateExtensionFunc(table.m_glTexCoord4f); + QGL_invalidateExtensionFunc(table.m_glTexCoord4fv); + QGL_invalidateExtensionFunc(table.m_glTexCoord4i); + QGL_invalidateExtensionFunc(table.m_glTexCoord4iv); + QGL_invalidateExtensionFunc(table.m_glTexCoord4s); + QGL_invalidateExtensionFunc(table.m_glTexCoord4sv); + QGL_invalidateExtensionFunc(table.m_glTexCoordPointer); + QGL_invalidateExtensionFunc(table.m_glTexEnvf); + QGL_invalidateExtensionFunc(table.m_glTexEnvfv); + QGL_invalidateExtensionFunc(table.m_glTexEnvi); + QGL_invalidateExtensionFunc(table.m_glTexEnviv); + QGL_invalidateExtensionFunc(table.m_glTexGend); + QGL_invalidateExtensionFunc(table.m_glTexGendv); + QGL_invalidateExtensionFunc(table.m_glTexGenf); + QGL_invalidateExtensionFunc(table.m_glTexGenfv); + QGL_invalidateExtensionFunc(table.m_glTexGeni); + QGL_invalidateExtensionFunc(table.m_glTexGeniv); + QGL_invalidateExtensionFunc(table.m_glTexImage1D); + QGL_invalidateExtensionFunc(table.m_glTexImage2D); + QGL_invalidateExtensionFunc(table.m_glTexParameterf); + QGL_invalidateExtensionFunc(table.m_glTexParameterfv); + QGL_invalidateExtensionFunc(table.m_glTexParameteri); + QGL_invalidateExtensionFunc(table.m_glTexParameteriv); + QGL_invalidateExtensionFunc(table.m_glTexSubImage1D); + QGL_invalidateExtensionFunc(table.m_glTexSubImage2D); + QGL_invalidateExtensionFunc(table.m_glTranslated); + QGL_invalidateExtensionFunc(table.m_glTranslatef); + QGL_invalidateExtensionFunc(table.m_glVertex2d); + QGL_invalidateExtensionFunc(table.m_glVertex2dv); + QGL_invalidateExtensionFunc(table.m_glVertex2f); + QGL_invalidateExtensionFunc(table.m_glVertex2fv); + QGL_invalidateExtensionFunc(table.m_glVertex2i); + QGL_invalidateExtensionFunc(table.m_glVertex2iv); + QGL_invalidateExtensionFunc(table.m_glVertex2s); + QGL_invalidateExtensionFunc(table.m_glVertex2sv); + QGL_invalidateExtensionFunc(table.m_glVertex3d); + QGL_invalidateExtensionFunc(table.m_glVertex3dv); + QGL_invalidateExtensionFunc(table.m_glVertex3f); + QGL_invalidateExtensionFunc(table.m_glVertex3fv); + QGL_invalidateExtensionFunc(table.m_glVertex3i); + QGL_invalidateExtensionFunc(table.m_glVertex3iv); + QGL_invalidateExtensionFunc(table.m_glVertex3s); + QGL_invalidateExtensionFunc(table.m_glVertex3sv); + QGL_invalidateExtensionFunc(table.m_glVertex4d); + QGL_invalidateExtensionFunc(table.m_glVertex4dv); + QGL_invalidateExtensionFunc(table.m_glVertex4f); + QGL_invalidateExtensionFunc(table.m_glVertex4fv); + QGL_invalidateExtensionFunc(table.m_glVertex4i); + QGL_invalidateExtensionFunc(table.m_glVertex4iv); + QGL_invalidateExtensionFunc(table.m_glVertex4s); + QGL_invalidateExtensionFunc(table.m_glVertex4sv); + QGL_invalidateExtensionFunc(table.m_glVertexPointer); + QGL_invalidateExtensionFunc(table.m_glViewport); } -int QGL_Init( OpenGLBinding& table ){ - QGL_clear( table ); +int QGL_Init(OpenGLBinding &table) +{ + QGL_clear(table); #if GDEF_OS_WINDOWS - qwglGetProcAddress = wglGetProcAddress; + qwglGetProcAddress = wglGetProcAddress; #elif defined( XWINDOWS ) - qglXGetProcAddressARB = (glXGetProcAddressARBProc)dlsym( RTLD_DEFAULT, "glXGetProcAddressARB" ); - if ( ( qglXQueryExtension == 0 ) || ( qglXQueryExtension(XOpenDisplay(nullptr), 0, 0) != True ) ) { - return 0; - } + qglXGetProcAddressARB = (glXGetProcAddressARBProc) dlsym(RTLD_DEFAULT, "glXGetProcAddressARB"); + if ((qglXQueryExtension == 0) || (qglXQueryExtension(XOpenDisplay(nullptr), 0, 0) != True)) { + return 0; + } #elif GDEF_OS_MACOS -#else + #else #error "unsupported platform" #endif - return 1; + return 1; } int g_qglMajorVersion = 0; int g_qglMinorVersion = 0; // requires a valid gl context -void QGL_InitVersion(){ +void QGL_InitVersion() +{ #if EXTENSIONS_ENABLED - const std::size_t versionSize = 256; - char version[versionSize]; - strncpy( version, reinterpret_cast( GlobalOpenGL().m_glGetString( GL_VERSION ) ), versionSize - 1 ); - version[versionSize - 1] = '\0'; - char* firstDot = strchr( version, '.' ); - ASSERT_NOTNULL( firstDot ); - *firstDot = '\0'; - g_qglMajorVersion = atoi( version ); - char* secondDot = strchr( firstDot + 1, '.' ); - if ( secondDot != 0 ) { - *secondDot = '\0'; - } - g_qglMinorVersion = atoi( firstDot + 1 ); + const std::size_t versionSize = 256; + char version[versionSize]; + strncpy(version, reinterpret_cast( GlobalOpenGL().m_glGetString(GL_VERSION)), versionSize - 1); + version[versionSize - 1] = '\0'; + char *firstDot = strchr(version, '.'); + ASSERT_NOTNULL(firstDot); + *firstDot = '\0'; + g_qglMajorVersion = atoi(version); + char *secondDot = strchr(firstDot + 1, '.'); + if (secondDot != 0) { + *secondDot = '\0'; + } + g_qglMinorVersion = atoi(firstDot + 1); #else - g_qglMajorVersion = 1; + g_qglMajorVersion = 1; g_qglMinorVersion = 1; #endif } -inline void extension_not_implemented( const char* extension ){ - globalErrorStream() << "WARNING: OpenGL driver reports support for " << extension << " but does not implement it\n"; +inline void extension_not_implemented(const char *extension) +{ + globalErrorStream() << "WARNING: OpenGL driver reports support for " << extension << " but does not implement it\n"; } float g_maxTextureAnisotropy; -float QGL_maxTextureAnisotropy(){ - return g_maxTextureAnisotropy; +float QGL_maxTextureAnisotropy() +{ + return g_maxTextureAnisotropy; } -void QGL_sharedContextCreated( OpenGLBinding& table ){ - QGL_InitVersion(); - - table.major_version = g_qglMajorVersion; - table.minor_version = g_qglMinorVersion; - - table.m_glAccum = glAccum; - table.m_glAlphaFunc = glAlphaFunc; - table.m_glAreTexturesResident = glAreTexturesResident; - table.m_glArrayElement = glArrayElement; - table.m_glBegin = glBegin; - table.m_glBindTexture = glBindTexture; - table.m_glBitmap = glBitmap; - table.m_glBlendFunc = glBlendFunc; - table.m_glCallList = glCallList; - table.m_glCallLists = glCallLists; - table.m_glClear = glClear; - table.m_glClearAccum = glClearAccum; - table.m_glClearColor = glClearColor; - table.m_glClearDepth = glClearDepth; - table.m_glClearIndex = glClearIndex; - table.m_glClearStencil = glClearStencil; - table.m_glClipPlane = glClipPlane; - table.m_glColor3b = glColor3b; - table.m_glColor3bv = glColor3bv; - table.m_glColor3d = glColor3d; - table.m_glColor3dv = glColor3dv; - table.m_glColor3f = glColor3f; - table.m_glColor3fv = glColor3fv; - table.m_glColor3i = glColor3i; - table.m_glColor3iv = glColor3iv; - table.m_glColor3s = glColor3s; - table.m_glColor3sv = glColor3sv; - table.m_glColor3ub = glColor3ub; - table.m_glColor3ubv = glColor3ubv; - table.m_glColor3ui = glColor3ui; - table.m_glColor3uiv = glColor3uiv; - table.m_glColor3us = glColor3us; - table.m_glColor3usv = glColor3usv; - table.m_glColor4b = glColor4b; - table.m_glColor4bv = glColor4bv; - table.m_glColor4d = glColor4d; - table.m_glColor4dv = glColor4dv; - table.m_glColor4f = glColor4f; - table.m_glColor4fv = glColor4fv; - table.m_glColor4i = glColor4i; - table.m_glColor4iv = glColor4iv; - table.m_glColor4s = glColor4s; - table.m_glColor4sv = glColor4sv; - table.m_glColor4ub = glColor4ub; - table.m_glColor4ubv = glColor4ubv; - table.m_glColor4ui = glColor4ui; - table.m_glColor4uiv = glColor4uiv; - table.m_glColor4us = glColor4us; - table.m_glColor4usv = glColor4usv; - table.m_glColorMask = glColorMask; - table.m_glColorMaterial = glColorMaterial; - table.m_glColorPointer = glColorPointer; - table.m_glCopyPixels = glCopyPixels; - table.m_glCopyTexImage1D = glCopyTexImage1D; - table.m_glCopyTexImage2D = glCopyTexImage2D; - table.m_glCopyTexSubImage1D = glCopyTexSubImage1D; - table.m_glCopyTexSubImage2D = glCopyTexSubImage2D; - table.m_glCullFace = glCullFace; - table.m_glDeleteLists = glDeleteLists; - table.m_glDeleteTextures = glDeleteTextures; - table.m_glDepthFunc = glDepthFunc; - table.m_glDepthMask = glDepthMask; - table.m_glDepthRange = glDepthRange; - table.m_glDisable = glDisable; - table.m_glDisableClientState = glDisableClientState; - table.m_glDrawArrays = glDrawArrays; - table.m_glDrawBuffer = glDrawBuffer; - table.m_glDrawElements = glDrawElements; - table.m_glDrawPixels = glDrawPixels; - table.m_glEdgeFlag = glEdgeFlag; - table.m_glEdgeFlagPointer = glEdgeFlagPointer; - table.m_glEdgeFlagv = glEdgeFlagv; - table.m_glEnable = glEnable; - table.m_glEnableClientState = glEnableClientState; - table.m_glEnd = glEnd; - table.m_glEndList = glEndList; - table.m_glEvalCoord1d = glEvalCoord1d; - table.m_glEvalCoord1dv = glEvalCoord1dv; - table.m_glEvalCoord1f = glEvalCoord1f; - table.m_glEvalCoord1fv = glEvalCoord1fv; - table.m_glEvalCoord2d = glEvalCoord2d; - table.m_glEvalCoord2dv = glEvalCoord2dv; - table.m_glEvalCoord2f = glEvalCoord2f; - table.m_glEvalCoord2fv = glEvalCoord2fv; - table.m_glEvalMesh1 = glEvalMesh1; - table.m_glEvalMesh2 = glEvalMesh2; - table.m_glEvalPoint1 = glEvalPoint1; - table.m_glEvalPoint2 = glEvalPoint2; - table.m_glFeedbackBuffer = glFeedbackBuffer; - table.m_glFinish = glFinish; - table.m_glFlush = glFlush; - table.m_glFogf = glFogf; - table.m_glFogfv = glFogfv; - table.m_glFogi = glFogi; - table.m_glFogiv = glFogiv; - table.m_glFrontFace = glFrontFace; - table.m_glFrustum = glFrustum; - table.m_glGenLists = glGenLists; - table.m_glGenTextures = glGenTextures; - table.m_glGetBooleanv = glGetBooleanv; - table.m_glGetClipPlane = glGetClipPlane; - table.m_glGetDoublev = glGetDoublev; - table.m_glGetError = glGetError; - table.m_glGetFloatv = glGetFloatv; - table.m_glGetIntegerv = glGetIntegerv; - table.m_glGetLightfv = glGetLightfv; - table.m_glGetLightiv = glGetLightiv; - table.m_glGetMapdv = glGetMapdv; - table.m_glGetMapfv = glGetMapfv; - table.m_glGetMapiv = glGetMapiv; - table.m_glGetMaterialfv = glGetMaterialfv; - table.m_glGetMaterialiv = glGetMaterialiv; - table.m_glGetPixelMapfv = glGetPixelMapfv; - table.m_glGetPixelMapuiv = glGetPixelMapuiv; - table.m_glGetPixelMapusv = glGetPixelMapusv; - table.m_glGetPointerv = glGetPointerv; - table.m_glGetPolygonStipple = glGetPolygonStipple; - table.m_glGetString = glGetString; - table.m_glGetTexEnvfv = glGetTexEnvfv; - table.m_glGetTexEnviv = glGetTexEnviv; - table.m_glGetTexGendv = glGetTexGendv; - table.m_glGetTexGenfv = glGetTexGenfv; - table.m_glGetTexGeniv = glGetTexGeniv; - table.m_glGetTexImage = glGetTexImage; - table.m_glGetTexLevelParameterfv = glGetTexLevelParameterfv; - table.m_glGetTexLevelParameteriv = glGetTexLevelParameteriv; - table.m_glGetTexParameterfv = glGetTexParameterfv; - table.m_glGetTexParameteriv = glGetTexParameteriv; - table.m_glHint = glHint; - table.m_glIndexMask = glIndexMask; - table.m_glIndexPointer = glIndexPointer; - table.m_glIndexd = glIndexd; - table.m_glIndexdv = glIndexdv; - table.m_glIndexf = glIndexf; - table.m_glIndexfv = glIndexfv; - table.m_glIndexi = glIndexi; - table.m_glIndexiv = glIndexiv; - table.m_glIndexs = glIndexs; - table.m_glIndexsv = glIndexsv; - table.m_glIndexub = glIndexub; - table.m_glIndexubv = glIndexubv; - table.m_glInitNames = glInitNames; - table.m_glInterleavedArrays = glInterleavedArrays; - table.m_glIsEnabled = glIsEnabled; - table.m_glIsList = glIsList; - table.m_glIsTexture = glIsTexture; - table.m_glLightModelf = glLightModelf; - table.m_glLightModelfv = glLightModelfv; - table.m_glLightModeli = glLightModeli; - table.m_glLightModeliv = glLightModeliv; - table.m_glLightf = glLightf; - table.m_glLightfv = glLightfv; - table.m_glLighti = glLighti; - table.m_glLightiv = glLightiv; - table.m_glLineStipple = glLineStipple; - table.m_glLineWidth = glLineWidth; - table.m_glListBase = glListBase; - table.m_glLoadIdentity = glLoadIdentity; - table.m_glLoadMatrixd = glLoadMatrixd; - table.m_glLoadMatrixf = glLoadMatrixf; - table.m_glLoadName = glLoadName; - table.m_glLogicOp = glLogicOp; - table.m_glMap1d = glMap1d; - table.m_glMap1f = glMap1f; - table.m_glMap2d = glMap2d; - table.m_glMap2f = glMap2f; - table.m_glMapGrid1d = glMapGrid1d; - table.m_glMapGrid1f = glMapGrid1f; - table.m_glMapGrid2d = glMapGrid2d; - table.m_glMapGrid2f = glMapGrid2f; - table.m_glMaterialf = glMaterialf; - table.m_glMaterialfv = glMaterialfv; - table.m_glMateriali = glMateriali; - table.m_glMaterialiv = glMaterialiv; - table.m_glMatrixMode = glMatrixMode; - table.m_glMultMatrixd = glMultMatrixd; - table.m_glMultMatrixf = glMultMatrixf; - table.m_glNewList = glNewList; - table.m_glNormal3b = glNormal3b; - table.m_glNormal3bv = glNormal3bv; - table.m_glNormal3d = glNormal3d; - table.m_glNormal3dv = glNormal3dv; - table.m_glNormal3f = glNormal3f; - table.m_glNormal3fv = glNormal3fv; - table.m_glNormal3i = glNormal3i; - table.m_glNormal3iv = glNormal3iv; - table.m_glNormal3s = glNormal3s; - table.m_glNormal3sv = glNormal3sv; - table.m_glNormalPointer = glNormalPointer; - table.m_glOrtho = glOrtho; - table.m_glPassThrough = glPassThrough; - table.m_glPixelMapfv = glPixelMapfv; - table.m_glPixelMapuiv = glPixelMapuiv; - table.m_glPixelMapusv = glPixelMapusv; - table.m_glPixelStoref = glPixelStoref; - table.m_glPixelStorei = glPixelStorei; - table.m_glPixelTransferf = glPixelTransferf; - table.m_glPixelTransferi = glPixelTransferi; - table.m_glPixelZoom = glPixelZoom; - table.m_glPointSize = glPointSize; - table.m_glPolygonMode = glPolygonMode; - table.m_glPolygonOffset = glPolygonOffset; - table.m_glPolygonStipple = glPolygonStipple; - table.m_glPopAttrib = glPopAttrib; - table.m_glPopClientAttrib = glPopClientAttrib; - table.m_glPopMatrix = glPopMatrix; - table.m_glPopName = glPopName; - table.m_glPrioritizeTextures = glPrioritizeTextures; - table.m_glPushAttrib = glPushAttrib; - table.m_glPushClientAttrib = glPushClientAttrib; - table.m_glPushMatrix = glPushMatrix; - table.m_glPushName = glPushName; - table.m_glRasterPos2d = glRasterPos2d; - table.m_glRasterPos2dv = glRasterPos2dv; - table.m_glRasterPos2f = glRasterPos2f; - table.m_glRasterPos2fv = glRasterPos2fv; - table.m_glRasterPos2i = glRasterPos2i; - table.m_glRasterPos2iv = glRasterPos2iv; - table.m_glRasterPos2s = glRasterPos2s; - table.m_glRasterPos2sv = glRasterPos2sv; - table.m_glRasterPos3d = glRasterPos3d; - table.m_glRasterPos3dv = glRasterPos3dv; - table.m_glRasterPos3f = glRasterPos3f; - table.m_glRasterPos3fv = glRasterPos3fv; - table.m_glRasterPos3i = glRasterPos3i; - table.m_glRasterPos3iv = glRasterPos3iv; - table.m_glRasterPos3s = glRasterPos3s; - table.m_glRasterPos3sv = glRasterPos3sv; - table.m_glRasterPos4d = glRasterPos4d; - table.m_glRasterPos4dv = glRasterPos4dv; - table.m_glRasterPos4f = glRasterPos4f; - table.m_glRasterPos4fv = glRasterPos4fv; - table.m_glRasterPos4i = glRasterPos4i; - table.m_glRasterPos4iv = glRasterPos4iv; - table.m_glRasterPos4s = glRasterPos4s; - table.m_glRasterPos4sv = glRasterPos4sv; - table.m_glReadBuffer = glReadBuffer; - table.m_glReadPixels = glReadPixels; - table.m_glRectd = glRectd; - table.m_glRectdv = glRectdv; - table.m_glRectf = glRectf; - table.m_glRectfv = glRectfv; - table.m_glRecti = glRecti; - table.m_glRectiv = glRectiv; - table.m_glRects = glRects; - table.m_glRectsv = glRectsv; - table.m_glRenderMode = glRenderMode; - table.m_glRotated = glRotated; - table.m_glRotatef = glRotatef; - table.m_glScaled = glScaled; - table.m_glScalef = glScalef; - table.m_glScissor = glScissor; - table.m_glSelectBuffer = glSelectBuffer; - table.m_glShadeModel = glShadeModel; - table.m_glStencilFunc = glStencilFunc; - table.m_glStencilMask = glStencilMask; - table.m_glStencilOp = glStencilOp; - table.m_glTexCoord1d = glTexCoord1d; - table.m_glTexCoord1dv = glTexCoord1dv; - table.m_glTexCoord1f = glTexCoord1f; - table.m_glTexCoord1fv = glTexCoord1fv; - table.m_glTexCoord1i = glTexCoord1i; - table.m_glTexCoord1iv = glTexCoord1iv; - table.m_glTexCoord1s = glTexCoord1s; - table.m_glTexCoord1sv = glTexCoord1sv; - table.m_glTexCoord2d = glTexCoord2d; - table.m_glTexCoord2dv = glTexCoord2dv; - table.m_glTexCoord2f = glTexCoord2f; - table.m_glTexCoord2fv = glTexCoord2fv; - table.m_glTexCoord2i = glTexCoord2i; - table.m_glTexCoord2iv = glTexCoord2iv; - table.m_glTexCoord2s = glTexCoord2s; - table.m_glTexCoord2sv = glTexCoord2sv; - table.m_glTexCoord3d = glTexCoord3d; - table.m_glTexCoord3dv = glTexCoord3dv; - table.m_glTexCoord3f = glTexCoord3f; - table.m_glTexCoord3fv = glTexCoord3fv; - table.m_glTexCoord3i = glTexCoord3i; - table.m_glTexCoord3iv = glTexCoord3iv; - table.m_glTexCoord3s = glTexCoord3s; - table.m_glTexCoord3sv = glTexCoord3sv; - table.m_glTexCoord4d = glTexCoord4d; - table.m_glTexCoord4dv = glTexCoord4dv; - table.m_glTexCoord4f = glTexCoord4f; - table.m_glTexCoord4fv = glTexCoord4fv; - table.m_glTexCoord4i = glTexCoord4i; - table.m_glTexCoord4iv = glTexCoord4iv; - table.m_glTexCoord4s = glTexCoord4s; - table.m_glTexCoord4sv = glTexCoord4sv; - table.m_glTexCoordPointer = glTexCoordPointer; - table.m_glTexEnvf = glTexEnvf; - table.m_glTexEnvfv = glTexEnvfv; - table.m_glTexEnvi = glTexEnvi; - table.m_glTexEnviv = glTexEnviv; - table.m_glTexGend = glTexGend; - table.m_glTexGendv = glTexGendv; - table.m_glTexGenf = glTexGenf; - table.m_glTexGenfv = glTexGenfv; - table.m_glTexGeni = glTexGeni; - table.m_glTexGeniv = glTexGeniv; - table.m_glTexImage1D = glTexImage1D; - table.m_glTexImage2D = glTexImage2D; - table.m_glTexParameterf = glTexParameterf; - table.m_glTexParameterfv = glTexParameterfv; - table.m_glTexParameteri = glTexParameteri; - table.m_glTexParameteriv = glTexParameteriv; - table.m_glTexSubImage1D = glTexSubImage1D; - table.m_glTexSubImage2D = glTexSubImage2D; - table.m_glTranslated = glTranslated; - table.m_glTranslatef = glTranslatef; - table.m_glVertex2d = glVertex2d; - table.m_glVertex2dv = glVertex2dv; - table.m_glVertex2f = glVertex2f; - table.m_glVertex2fv = glVertex2fv; - table.m_glVertex2i = glVertex2i; - table.m_glVertex2iv = glVertex2iv; - table.m_glVertex2s = glVertex2s; - table.m_glVertex2sv = glVertex2sv; - table.m_glVertex3d = glVertex3d; - table.m_glVertex3dv = glVertex3dv; - table.m_glVertex3f = glVertex3f; - table.m_glVertex3fv = glVertex3fv; - table.m_glVertex3i = glVertex3i; - table.m_glVertex3iv = glVertex3iv; - table.m_glVertex3s = glVertex3s; - table.m_glVertex3sv = glVertex3sv; - table.m_glVertex4d = glVertex4d; - table.m_glVertex4dv = glVertex4dv; - table.m_glVertex4f = glVertex4f; - table.m_glVertex4fv = glVertex4fv; - table.m_glVertex4i = glVertex4i; - table.m_glVertex4iv = glVertex4iv; - table.m_glVertex4s = glVertex4s; - table.m_glVertex4sv = glVertex4sv; - table.m_glVertexPointer = glVertexPointer; - table.m_glViewport = glViewport; - - if ( QGL_ExtensionSupported( "GL_ARB_multitexture" ) ) { - table.support_ARB_multitexture = - QGL_constructExtensionFunc( table.m_glActiveTextureARB, "glActiveTextureARB" ) - && QGL_constructExtensionFunc( table.m_glClientActiveTextureARB, "glClientActiveTextureARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1dARB, "glMultiTexCoord1dARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1fARB, "glMultiTexCoord1fARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1iARB, "glMultiTexCoord1iARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1sARB, "glMultiTexCoord1sARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1svARB, "glMultiTexCoord1svARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2dARB, "glMultiTexCoord2dARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2fARB, "glMultiTexCoord2fARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2iARB, "glMultiTexCoord2iARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2sARB, "glMultiTexCoord2sARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2svARB, "glMultiTexCoord2svARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3dARB, "glMultiTexCoord3dARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3fARB, "glMultiTexCoord3fARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3iARB, "glMultiTexCoord3iARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3sARB, "glMultiTexCoord3sARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3svARB, "glMultiTexCoord3svARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4dARB, "glMultiTexCoord4dARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4fARB, "glMultiTexCoord4fARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4iARB, "glMultiTexCoord4iARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4sARB, "glMultiTexCoord4sARB" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4svARB, "glMultiTexCoord4svARB" ); - - if ( !table.support_ARB_multitexture ) { - extension_not_implemented( "GL_ARB_multitexture" ); - } - } - else - { - table.support_ARB_multitexture = false; - } - - if ( QGL_ExtensionSupported( "GL_ARB_texture_compression" ) ) { - table.support_ARB_texture_compression = - QGL_constructExtensionFunc( table.m_glCompressedTexImage3DARB, "glCompressedTexImage3DARB" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexImage2DARB, "glCompressedTexImage2DARB" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexImage1DARB, "glCompressedTexImage1DARB" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexSubImage3DARB, "glCompressedTexSubImage3DARB" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexSubImage2DARB, "glCompressedTexSubImage2DARB" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexSubImage1DARB, "glCompressedTexSubImage1DARB" ) - && QGL_constructExtensionFunc( table.m_glGetCompressedTexImageARB, "glGetCompressedTexImageARB" ); - - if ( !table.support_ARB_texture_compression ) { - extension_not_implemented( "GL_ARB_texture_compression" ); - } - } - else - { - table.support_ARB_texture_compression = false; - } - - table.support_EXT_texture_compression_s3tc = QGL_ExtensionSupported( "GL_EXT_texture_compression_s3tc" ); - - // GL 1.2 - if ( table.major_version > 1 || table.minor_version >= 2 ) { - table.support_GL_1_2 = - QGL_constructExtensionFunc( table.m_glCopyTexSubImage3D, "glCopyTexSubImage3D" ) - && QGL_constructExtensionFunc( table.m_glDrawRangeElements, "glDrawRangeElements" ) - && QGL_constructExtensionFunc( table.m_glTexImage3D, "glTexImage3D" ) - && QGL_constructExtensionFunc( table.m_glTexSubImage3D, "glTexSubImage3D" ); - - if ( !table.support_GL_1_2 ) { - extension_not_implemented( "GL_VERSION_1_2" ); - } - } - else - { - table.support_GL_1_2 = false; - } - - // GL 1.3 - if ( table.major_version > 1 || table.minor_version >= 3 ) { - table.support_GL_1_3 = - QGL_constructExtensionFunc( table.m_glActiveTexture, "glActiveTexture" ) - && QGL_constructExtensionFunc( table.m_glClientActiveTexture, "glClientActiveTexture" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexImage1D, "glCompressedTexImage1D" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexImage2D, "glCompressedTexImage2D" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexImage3D, "glCompressedTexImage3D" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexSubImage1D, "glCompressedTexSubImage1D" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexSubImage2D, "glCompressedTexSubImage2D" ) - && QGL_constructExtensionFunc( table.m_glCompressedTexSubImage3D, "glCompressedTexSubImage3D" ) - && QGL_constructExtensionFunc( table.m_glGetCompressedTexImage, "glGetCompressedTexImage" ) - && QGL_constructExtensionFunc( table.m_glLoadTransposeMatrixd, "glLoadTransposeMatrixd" ) - && QGL_constructExtensionFunc( table.m_glLoadTransposeMatrixf, "glLoadTransposeMatrixf" ) - && QGL_constructExtensionFunc( table.m_glMultTransposeMatrixd, "glMultTransposeMatrixd" ) - && QGL_constructExtensionFunc( table.m_glMultTransposeMatrixf, "glMultTransposeMatrixf" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1d, "glMultiTexCoord1d" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1dv, "glMultiTexCoord1dv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1f, "glMultiTexCoord1f" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1fv, "glMultiTexCoord1fv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1i, "glMultiTexCoord1i" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1iv, "glMultiTexCoord1iv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1s, "glMultiTexCoord1s" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord1sv, "glMultiTexCoord1sv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2d, "glMultiTexCoord2d" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2dv, "glMultiTexCoord2dv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2f, "glMultiTexCoord2f" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2fv, "glMultiTexCoord2fv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2i, "glMultiTexCoord2i" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2iv, "glMultiTexCoord2iv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2s, "glMultiTexCoord2s" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord2sv, "glMultiTexCoord2sv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3d, "glMultiTexCoord3d" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3dv, "glMultiTexCoord3dv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3f, "glMultiTexCoord3f" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3fv, "glMultiTexCoord3fv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3i, "glMultiTexCoord3i" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3iv, "glMultiTexCoord3iv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3s, "glMultiTexCoord3s" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord3sv, "glMultiTexCoord3sv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4d, "glMultiTexCoord4d" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4dv, "glMultiTexCoord4dv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4f, "glMultiTexCoord4f" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4fv, "glMultiTexCoord4fv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4i, "glMultiTexCoord4i" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4iv, "glMultiTexCoord4iv" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4s, "glMultiTexCoord4s" ) - && QGL_constructExtensionFunc( table.m_glMultiTexCoord4sv, "glMultiTexCoord4sv" ) - && QGL_constructExtensionFunc( table.m_glSampleCoverage, "glSampleCoverage" ); - - if ( !table.support_GL_1_3 ) { - extension_not_implemented( "GL_VERSION_1_3" ); - } - } - else - { - table.support_GL_1_3 = false; - } - - // GL 1.4 - if ( table.major_version > 1 || table.minor_version >= 4 ) { - table.support_GL_1_4 = - QGL_constructExtensionFunc( table.m_glBlendColor, "glBlendColor" ) - && QGL_constructExtensionFunc( table.m_glBlendEquation, "glBlendEquation" ) - && QGL_constructExtensionFunc( table.m_glBlendFuncSeparate, "glBlendFuncSeparate" ) - && QGL_constructExtensionFunc( table.m_glFogCoordPointer, "glFogCoordPointer" ) - && QGL_constructExtensionFunc( table.m_glFogCoordd, "glFogCoordd" ) - && QGL_constructExtensionFunc( table.m_glFogCoorddv, "glFogCoorddv" ) - && QGL_constructExtensionFunc( table.m_glFogCoordf, "glFogCoordf" ) - && QGL_constructExtensionFunc( table.m_glFogCoordfv, "glFogCoordfv" ) - && QGL_constructExtensionFunc( table.m_glMultiDrawArrays, "glMultiDrawArrays" ) - && QGL_constructExtensionFunc( table.m_glMultiDrawElements, "glMultiDrawElements" ) - && QGL_constructExtensionFunc( table.m_glPointParameterf, "glPointParameterf" ) - && QGL_constructExtensionFunc( table.m_glPointParameterfv, "glPointParameterfv" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3b, "glSecondaryColor3b" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3bv, "glSecondaryColor3bv" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3d, "glSecondaryColor3d" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3dv, "glSecondaryColor3dv" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3f, "glSecondaryColor3f" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3fv, "glSecondaryColor3fv" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3i, "glSecondaryColor3i" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3iv, "glSecondaryColor3iv" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3s, "glSecondaryColor3s" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3sv, "glSecondaryColor3sv" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3ub, "glSecondaryColor3ub" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3ubv, "glSecondaryColor3ubv" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3ui, "glSecondaryColor3ui" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3uiv, "glSecondaryColor3uiv" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3us, "glSecondaryColor3us" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColor3usv, "glSecondaryColor3usv" ) - && QGL_constructExtensionFunc( table.m_glSecondaryColorPointer, "glSecondaryColorPointer" ) - && QGL_constructExtensionFunc( table.m_glWindowPos2d, "glWindowPos2d" ) - && QGL_constructExtensionFunc( table.m_glWindowPos2dv, "glWindowPos2dv" ) - && QGL_constructExtensionFunc( table.m_glWindowPos2f, "glWindowPos2f" ) - && QGL_constructExtensionFunc( table.m_glWindowPos2fv, "glWindowPos2fv" ) - && QGL_constructExtensionFunc( table.m_glWindowPos2i, "glWindowPos2i" ) - && QGL_constructExtensionFunc( table.m_glWindowPos2iv, "glWindowPos2iv" ) - && QGL_constructExtensionFunc( table.m_glWindowPos2s, "glWindowPos2s" ) - && QGL_constructExtensionFunc( table.m_glWindowPos2sv, "glWindowPos2sv" ) - && QGL_constructExtensionFunc( table.m_glWindowPos3d, "glWindowPos3d" ) - && QGL_constructExtensionFunc( table.m_glWindowPos3dv, "glWindowPos3dv" ) - && QGL_constructExtensionFunc( table.m_glWindowPos3f, "glWindowPos3f" ) - && QGL_constructExtensionFunc( table.m_glWindowPos3fv, "glWindowPos3fv" ) - && QGL_constructExtensionFunc( table.m_glWindowPos3i, "glWindowPos3i" ) - && QGL_constructExtensionFunc( table.m_glWindowPos3iv, "glWindowPos3iv" ) - && QGL_constructExtensionFunc( table.m_glWindowPos3s, "glWindowPos3s" ) - && QGL_constructExtensionFunc( table.m_glWindowPos3sv, "glWindowPos3sv" ); - - if ( !table.support_GL_1_4 ) { - extension_not_implemented( "GL_VERSION_1_4" ); - } - } - else - { - table.support_GL_1_4 = false; - } - - // GL 1.5 - if ( table.major_version > 1 || table.minor_version >= 5 ) { - table.support_GL_1_5 = - QGL_constructExtensionFunc( table.m_glBeginQuery, "glBeginQuery" ) - && QGL_constructExtensionFunc( table.m_glBindBuffer, "glBindBuffer" ) - && QGL_constructExtensionFunc( table.m_glBufferData, "glBufferData" ) - && QGL_constructExtensionFunc( table.m_glBufferSubData, "glBufferSubData" ) - && QGL_constructExtensionFunc( table.m_glDeleteBuffers, "glDeleteBuffers" ) - && QGL_constructExtensionFunc( table.m_glDeleteQueries, "glDeleteQueries" ) - && QGL_constructExtensionFunc( table.m_glEndQuery, "glEndQuery" ) - && QGL_constructExtensionFunc( table.m_glGenBuffers, "glGenBuffers" ) - && QGL_constructExtensionFunc( table.m_glGenQueries, "glGenQueries" ) - && QGL_constructExtensionFunc( table.m_glGetBufferParameteriv, "glGetBufferParameteriv" ) - && QGL_constructExtensionFunc( table.m_glGetBufferPointerv, "glGetBufferPointerv" ) - && QGL_constructExtensionFunc( table.m_glGetBufferSubData, "glGetBufferSubData" ) - && QGL_constructExtensionFunc( table.m_glGetQueryObjectiv, "glGetQueryObjectiv" ) - && QGL_constructExtensionFunc( table.m_glGetQueryObjectuiv, "glGetQueryObjectuiv" ) - && QGL_constructExtensionFunc( table.m_glGetQueryiv, "glGetQueryiv" ) - && QGL_constructExtensionFunc( table.m_glIsBuffer, "glIsBuffer" ) - && QGL_constructExtensionFunc( table.m_glIsQuery, "glIsQuery" ) - && QGL_constructExtensionFunc( table.m_glMapBuffer, "glMapBuffer" ) - && QGL_constructExtensionFunc( table.m_glUnmapBuffer, "glUnmapBuffer" ); - - if ( !table.support_GL_1_5 ) { - extension_not_implemented( "GL_VERSION_1_5" ); - } - } - else - { - table.support_GL_1_5 = false; - } - - - if ( QGL_ExtensionSupported( "GL_ARB_vertex_program" ) ) { - table.support_ARB_vertex_program = - QGL_constructExtensionFunc( table.m_glVertexAttrib1sARB, "glVertexAttrib1sARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1fARB, "glVertexAttrib1fARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1dARB, "glVertexAttrib1dARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2sARB, "glVertexAttrib2sARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2fARB, "glVertexAttrib2fARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2dARB, "glVertexAttrib2dARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3sARB, "glVertexAttrib3sARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3fARB, "glVertexAttrib3fARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3dARB, "glVertexAttrib3dARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4sARB, "glVertexAttrib4sARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4fARB, "glVertexAttrib4fARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4dARB, "glVertexAttrib4dARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NubARB, "glVertexAttrib4NubARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1svARB, "glVertexAttrib1svARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1fvARB, "glVertexAttrib1fvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1dvARB, "glVertexAttrib1dvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2svARB, "glVertexAttrib2svARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2fvARB, "glVertexAttrib2fvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2dvARB, "glVertexAttrib2dvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3svARB, "glVertexAttrib3svARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3fvARB, "glVertexAttrib3fvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3dvARB, "glVertexAttrib3dvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4bvARB, "glVertexAttrib4bvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4svARB, "glVertexAttrib4svARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4ivARB, "glVertexAttrib4ivARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4ubvARB, "glVertexAttrib4ubvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4usvARB, "glVertexAttrib4usvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4uivARB, "glVertexAttrib4uivARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4fvARB, "glVertexAttrib4fvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4dvARB, "glVertexAttrib4dvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NbvARB, "glVertexAttrib4NbvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NsvARB, "glVertexAttrib4NsvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NivARB, "glVertexAttrib4NivARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NubvARB, "glVertexAttrib4NubvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NusvARB, "glVertexAttrib4NusvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NuivARB, "glVertexAttrib4NuivARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttribPointerARB, "glVertexAttribPointerARB" ) - && QGL_constructExtensionFunc( table.m_glEnableVertexAttribArrayARB, "glEnableVertexAttribArrayARB" ) - && QGL_constructExtensionFunc( table.m_glDisableVertexAttribArrayARB, "glDisableVertexAttribArrayARB" ) - && QGL_constructExtensionFunc( table.m_glProgramStringARB, "glProgramStringARB" ) - && QGL_constructExtensionFunc( table.m_glBindProgramARB, "glBindProgramARB" ) - && QGL_constructExtensionFunc( table.m_glDeleteProgramsARB, "glDeleteProgramsARB" ) - && QGL_constructExtensionFunc( table.m_glGenProgramsARB, "glGenProgramsARB" ) - && QGL_constructExtensionFunc( table.m_glProgramEnvParameter4dARB, "glProgramEnvParameter4dARB" ) - && QGL_constructExtensionFunc( table.m_glProgramEnvParameter4dvARB, "glProgramEnvParameter4dvARB" ) - && QGL_constructExtensionFunc( table.m_glProgramEnvParameter4fARB, "glProgramEnvParameter4fARB" ) - && QGL_constructExtensionFunc( table.m_glProgramEnvParameter4fvARB, "glProgramEnvParameter4fvARB" ) - && QGL_constructExtensionFunc( table.m_glProgramLocalParameter4dARB, "glProgramLocalParameter4dARB" ) - && QGL_constructExtensionFunc( table.m_glProgramLocalParameter4dvARB, "glProgramLocalParameter4dvARB" ) - && QGL_constructExtensionFunc( table.m_glProgramLocalParameter4fARB, "glProgramLocalParameter4fARB" ) - && QGL_constructExtensionFunc( table.m_glProgramLocalParameter4fvARB, "glProgramLocalParameter4fvARB" ) - && QGL_constructExtensionFunc( table.m_glGetProgramEnvParameterdvARB, "glGetProgramEnvParameterdvARB" ) - && QGL_constructExtensionFunc( table.m_glGetProgramEnvParameterfvARB, "glGetProgramEnvParameterfvARB" ) - && QGL_constructExtensionFunc( table.m_glGetProgramLocalParameterdvARB, "glGetProgramLocalParameterdvARB" ) - && QGL_constructExtensionFunc( table.m_glGetProgramLocalParameterfvARB, "glGetProgramLocalParameterfvARB" ) - && QGL_constructExtensionFunc( table.m_glGetProgramivARB, "glGetProgramivARB" ) - && QGL_constructExtensionFunc( table.m_glGetProgramStringARB, "glGetProgramStringARB" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribdvARB, "glGetVertexAttribdvARB" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribfvARB, "glGetVertexAttribfvARB" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribivARB, "glGetVertexAttribivARB" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribPointervARB, "glGetVertexAttribPointervARB" ) - && QGL_constructExtensionFunc( table.m_glIsProgramARB, "glIsProgramARB" ); - - if ( !table.support_ARB_vertex_program ) { - extension_not_implemented( "GL_ARB_vertex_program" ); - } - } - else - { - table.support_ARB_vertex_program = false; - } - - - table.support_ARB_fragment_program = QGL_ExtensionSupported( "GL_ARB_fragment_program" ); - - if ( QGL_ExtensionSupported( "GL_ARB_shader_objects" ) ) { - table.support_ARB_shader_objects = - QGL_constructExtensionFunc( table.m_glDeleteObjectARB, "glDeleteObjectARB" ) - && QGL_constructExtensionFunc( table.m_glGetHandleARB, "glGetHandleARB" ) - && QGL_constructExtensionFunc( table.m_glDetachObjectARB, "glDetachObjectARB" ) - && QGL_constructExtensionFunc( table.m_glCreateShaderObjectARB, "glCreateShaderObjectARB" ) - && QGL_constructExtensionFunc( table.m_glShaderSourceARB, "glShaderSourceARB" ) - && QGL_constructExtensionFunc( table.m_glCompileShaderARB, "glCompileShaderARB" ) - && QGL_constructExtensionFunc( table.m_glCreateProgramObjectARB, "glCreateProgramObjectARB" ) - && QGL_constructExtensionFunc( table.m_glAttachObjectARB, "glAttachObjectARB" ) - && QGL_constructExtensionFunc( table.m_glLinkProgramARB, "glLinkProgramARB" ) - && QGL_constructExtensionFunc( table.m_glUseProgramObjectARB, "glUseProgramObjectARB" ) - && QGL_constructExtensionFunc( table.m_glValidateProgramARB, "glValidateProgramARB" ) - && QGL_constructExtensionFunc( table.m_glUniform1fARB, "glUniform1fARB" ) - && QGL_constructExtensionFunc( table.m_glUniform2fARB, "glUniform2fARB" ) - && QGL_constructExtensionFunc( table.m_glUniform3fARB, "glUniform3fARB" ) - && QGL_constructExtensionFunc( table.m_glUniform4fARB, "glUniform4fARB" ) - && QGL_constructExtensionFunc( table.m_glUniform1iARB, "glUniform1iARB" ) - && QGL_constructExtensionFunc( table.m_glUniform2iARB, "glUniform2iARB" ) - && QGL_constructExtensionFunc( table.m_glUniform3iARB, "glUniform3iARB" ) - && QGL_constructExtensionFunc( table.m_glUniform4iARB, "glUniform4iARB" ) - && QGL_constructExtensionFunc( table.m_glUniform1fvARB, "glUniform1fvARB" ) - && QGL_constructExtensionFunc( table.m_glUniform2fvARB, "glUniform2fvARB" ) - && QGL_constructExtensionFunc( table.m_glUniform3fvARB, "glUniform3fvARB" ) - && QGL_constructExtensionFunc( table.m_glUniform4fvARB, "glUniform4fvARB" ) - && QGL_constructExtensionFunc( table.m_glUniform1ivARB, "glUniform1ivARB" ) - && QGL_constructExtensionFunc( table.m_glUniform2ivARB, "glUniform2ivARB" ) - && QGL_constructExtensionFunc( table.m_glUniform3ivARB, "glUniform3ivARB" ) - && QGL_constructExtensionFunc( table.m_glUniform4ivARB, "glUniform4ivARB" ) - && QGL_constructExtensionFunc( table.m_glUniformMatrix2fvARB, "glUniformMatrix2fvARB" ) - && QGL_constructExtensionFunc( table.m_glUniformMatrix3fvARB, "glUniformMatrix3fvARB" ) - && QGL_constructExtensionFunc( table.m_glUniformMatrix4fvARB, "glUniformMatrix4fvARB" ) - && QGL_constructExtensionFunc( table.m_glGetObjectParameterfvARB, "glGetObjectParameterfvARB" ) - && QGL_constructExtensionFunc( table.m_glGetObjectParameterivARB, "glGetObjectParameterivARB" ) - && QGL_constructExtensionFunc( table.m_glGetInfoLogARB, "glGetInfoLogARB" ) - && QGL_constructExtensionFunc( table.m_glGetAttachedObjectsARB, "glGetAttachedObjectsARB" ) - && QGL_constructExtensionFunc( table.m_glGetUniformLocationARB, "glGetUniformLocationARB" ) - && QGL_constructExtensionFunc( table.m_glGetActiveUniformARB, "glGetActiveUniformARB" ) - && QGL_constructExtensionFunc( table.m_glGetUniformfvARB, "glGetUniformfvARB" ) - && QGL_constructExtensionFunc( table.m_glGetUniformivARB, "glGetUniformivARB" ) - && QGL_constructExtensionFunc( table.m_glGetShaderSourceARB, "glGetShaderSourceARB" ); - - if ( !table.support_ARB_shader_objects ) { - extension_not_implemented( "GL_ARB_shader_objects" ); - } - } - else - { - table.support_ARB_shader_objects = false; - } - - if ( QGL_ExtensionSupported( "GL_ARB_vertex_shader" ) ) { - table.support_ARB_vertex_shader = - QGL_constructExtensionFunc( table.m_glVertexAttrib1fARB, "glVertexAttrib1fARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1sARB, "glVertexAttrib1sARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1dARB, "glVertexAttrib1dARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2fARB, "glVertexAttrib2fARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2sARB, "glVertexAttrib2sARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2dARB, "glVertexAttrib2dARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3fARB, "glVertexAttrib3fARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3sARB, "glVertexAttrib3sARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3dARB, "glVertexAttrib3dARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4fARB, "glVertexAttrib4fARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4sARB, "glVertexAttrib4sARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4dARB, "glVertexAttrib4dARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NubARB, "glVertexAttrib4NubARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1fvARB, "glVertexAttrib1fvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1svARB, "glVertexAttrib1svARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1dvARB, "glVertexAttrib1dvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2fvARB, "glVertexAttrib2fvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2svARB, "glVertexAttrib2svARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2dvARB, "glVertexAttrib2dvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3fvARB, "glVertexAttrib3fvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3svARB, "glVertexAttrib3svARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3dvARB, "glVertexAttrib3dvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4fvARB, "glVertexAttrib4fvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4svARB, "glVertexAttrib4svARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4dvARB, "glVertexAttrib4dvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4ivARB, "glVertexAttrib4ivARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4bvARB, "glVertexAttrib4bvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4ubvARB, "glVertexAttrib4ubvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4usvARB, "glVertexAttrib4usvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4uivARB, "glVertexAttrib4uivARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NbvARB, "glVertexAttrib4NbvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NsvARB, "glVertexAttrib4NsvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NivARB, "glVertexAttrib4NivARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NubvARB, "glVertexAttrib4NubvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NusvARB, "glVertexAttrib4NusvARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4NuivARB, "glVertexAttrib4NuivARB" ) - && QGL_constructExtensionFunc( table.m_glVertexAttribPointerARB, "glVertexAttribPointerARB" ) - && QGL_constructExtensionFunc( table.m_glEnableVertexAttribArrayARB, "glEnableVertexAttribArrayARB" ) - && QGL_constructExtensionFunc( table.m_glDisableVertexAttribArrayARB, "glDisableVertexAttribArrayARB" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribdvARB, "glGetVertexAttribdvARB" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribfvARB, "glGetVertexAttribfvARB" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribivARB, "glGetVertexAttribivARB" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribPointervARB, "glGetVertexAttribPointervARB" ) - && QGL_constructExtensionFunc( table.m_glBindAttribLocationARB, "glBindAttribLocationARB" ) - && QGL_constructExtensionFunc( table.m_glGetActiveAttribARB, "glGetActiveAttribARB" ) - && QGL_constructExtensionFunc( table.m_glGetAttribLocationARB, "glGetAttribLocationARB" ); - - if ( !table.support_ARB_vertex_shader ) { - extension_not_implemented( "GL_ARB_vertex_shader" ); - } - } - else - { - table.support_ARB_vertex_shader = false; - } - - if ( QGL_ExtensionSupported( "GL_NV_vertex_program2" ) ) { - table.support_NV_vertex_program2 = - QGL_constructExtensionFunc( table.m_glAreProgramsResidentNV, "glAreProgramsResidentNV" ) - && QGL_constructExtensionFunc( table.m_glBindProgramNV, "glBindProgramNV" ) - && QGL_constructExtensionFunc( table.m_glDeleteProgramsNV, "glDeleteProgramsNV" ) - && QGL_constructExtensionFunc( table.m_glExecuteProgramNV, "glExecuteProgramNV" ) - && QGL_constructExtensionFunc( table.m_glGenProgramsNV, "glGenProgramsNV" ) - && QGL_constructExtensionFunc( table.m_glGetProgramParameterdvNV, "glGetProgramParameterdvNV" ) - && QGL_constructExtensionFunc( table.m_glGetProgramParameterfvNV, "glGetProgramParameterfvNV" ) - && QGL_constructExtensionFunc( table.m_glGetProgramivNV, "glGetProgramivNV" ) - && QGL_constructExtensionFunc( table.m_glGetProgramStringNV, "glGetProgramStringNV" ) - && QGL_constructExtensionFunc( table.m_glGetTrackMatrixivNV, "glGetTrackMatrixivNV" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribdvNV, "glGetVertexAttribdvNV" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribfvNV, "glGetVertexAttribfvNV" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribivNV, "glGetVertexAttribivNV" ) - && QGL_constructExtensionFunc( table.m_glGetVertexAttribPointervNV, "glGetVertexAttribPointervNV" ) - && QGL_constructExtensionFunc( table.m_glIsProgramNV, "glIsProgramNV" ) - && QGL_constructExtensionFunc( table.m_glLoadProgramNV, "glLoadProgramNV" ) - && QGL_constructExtensionFunc( table.m_glProgramParameter4fNV, "glProgramParameter4fNV" ) - && QGL_constructExtensionFunc( table.m_glProgramParameter4fvNV, "glProgramParameter4fvNV" ) - && QGL_constructExtensionFunc( table.m_glProgramParameters4fvNV, "glProgramParameters4fvNV" ) - && QGL_constructExtensionFunc( table.m_glRequestResidentProgramsNV, "glRequestResidentProgramsNV" ) - && QGL_constructExtensionFunc( table.m_glTrackMatrixNV, "glTrackMatrixNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttribPointerNV, "glVertexAttribPointerNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1fNV, "glVertexAttrib1fNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib1fvNV, "glVertexAttrib1fvNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2fNV, "glVertexAttrib2fNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib2fvNV, "glVertexAttrib2fvNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3fNV, "glVertexAttrib3fNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib3fvNV, "glVertexAttrib3fvNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4fNV, "glVertexAttrib4fNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttrib4fvNV, "glVertexAttrib4fvNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttribs1fvNV, "glVertexAttribs1fvNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttribs2fvNV, "glVertexAttribs2fvNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttribs3fvNV, "glVertexAttribs3fvNV" ) - && QGL_constructExtensionFunc( table.m_glVertexAttribs4fvNV, "glVertexAttribs4fvNV" ); - - if ( !table.support_NV_vertex_program2 ) { - extension_not_implemented( "GL_NV_vertex_program2" ); - } - } - else - { - table.support_NV_vertex_program2 = false; - QGL_invalidateExtensionFunc( table.m_glAreProgramsResidentNV ); - QGL_invalidateExtensionFunc( table.m_glBindProgramNV ); - QGL_invalidateExtensionFunc( table.m_glDeleteProgramsNV ); - QGL_invalidateExtensionFunc( table.m_glExecuteProgramNV ); - QGL_invalidateExtensionFunc( table.m_glGenProgramsNV ); - QGL_invalidateExtensionFunc( table.m_glGetProgramParameterdvNV ); - QGL_invalidateExtensionFunc( table.m_glGetProgramParameterfvNV ); - QGL_invalidateExtensionFunc( table.m_glGetProgramivNV ); - QGL_invalidateExtensionFunc( table.m_glGetProgramStringNV ); - QGL_invalidateExtensionFunc( table.m_glGetTrackMatrixivNV ); - QGL_invalidateExtensionFunc( table.m_glGetVertexAttribdvNV ); - QGL_invalidateExtensionFunc( table.m_glGetVertexAttribfvNV ); - QGL_invalidateExtensionFunc( table.m_glGetVertexAttribivNV ); - QGL_invalidateExtensionFunc( table.m_glGetVertexAttribPointervNV ); - QGL_invalidateExtensionFunc( table.m_glIsProgramNV ); - QGL_invalidateExtensionFunc( table.m_glLoadProgramNV ); - QGL_invalidateExtensionFunc( table.m_glProgramParameter4fNV ); - QGL_invalidateExtensionFunc( table.m_glProgramParameter4fvNV ); - QGL_invalidateExtensionFunc( table.m_glProgramParameters4fvNV ); - QGL_invalidateExtensionFunc( table.m_glRequestResidentProgramsNV ); - QGL_invalidateExtensionFunc( table.m_glTrackMatrixNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttribPointerNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttrib1fNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttrib1fvNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttrib2fNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttrib2fvNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttrib3fNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttrib3fvNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttrib4fNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttrib4fvNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttribs1fvNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttribs2fvNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttribs3fvNV ); - QGL_invalidateExtensionFunc( table.m_glVertexAttribs4fvNV ); - } - - if ( QGL_ExtensionSupported( "GL_NV_fragment_program" ) ) { - table.support_NV_fragment_program = - QGL_constructExtensionFunc( table.m_glProgramNamedParameter4fNV, "glProgramNamedParameter4fNV" ) - && QGL_constructExtensionFunc( table.m_glProgramNamedParameter4fvNV, "glProgramNamedParameter4fvNV" ) - && QGL_constructExtensionFunc( table.m_glGetProgramNamedParameterfvNV, "glGetProgramNamedParameterfvNV" ); - - if ( !table.support_NV_fragment_program ) { - extension_not_implemented( "GL_NV_fragment_program" ); - } - } - else - { - table.support_NV_fragment_program = false; - } - - table.support_ARB_fragment_shader = QGL_ExtensionSupported( "GL_ARB_fragment_shader" ); - table.support_ARB_shading_language_100 = QGL_ExtensionSupported( "GL_ARB_shading_language_100" ); - - if ( QGL_ExtensionSupported( "GL_EXT_texture_filter_anisotropic" ) ) { - glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &g_maxTextureAnisotropy ); - globalOutputStream() << "Anisotropic filtering possible (max " << g_maxTextureAnisotropy << "x)\n"; - } - else - { - globalOutputStream() << "No Anisotropic filtering available\n"; - g_maxTextureAnisotropy = 0; - } +void QGL_sharedContextCreated(OpenGLBinding &table) +{ + QGL_InitVersion(); + + table.major_version = g_qglMajorVersion; + table.minor_version = g_qglMinorVersion; + + table.m_glAccum = glAccum; + table.m_glAlphaFunc = glAlphaFunc; + table.m_glAreTexturesResident = glAreTexturesResident; + table.m_glArrayElement = glArrayElement; + table.m_glBegin = glBegin; + table.m_glBindTexture = glBindTexture; + table.m_glBitmap = glBitmap; + table.m_glBlendFunc = glBlendFunc; + table.m_glCallList = glCallList; + table.m_glCallLists = glCallLists; + table.m_glClear = glClear; + table.m_glClearAccum = glClearAccum; + table.m_glClearColor = glClearColor; + table.m_glClearDepth = glClearDepth; + table.m_glClearIndex = glClearIndex; + table.m_glClearStencil = glClearStencil; + table.m_glClipPlane = glClipPlane; + table.m_glColor3b = glColor3b; + table.m_glColor3bv = glColor3bv; + table.m_glColor3d = glColor3d; + table.m_glColor3dv = glColor3dv; + table.m_glColor3f = glColor3f; + table.m_glColor3fv = glColor3fv; + table.m_glColor3i = glColor3i; + table.m_glColor3iv = glColor3iv; + table.m_glColor3s = glColor3s; + table.m_glColor3sv = glColor3sv; + table.m_glColor3ub = glColor3ub; + table.m_glColor3ubv = glColor3ubv; + table.m_glColor3ui = glColor3ui; + table.m_glColor3uiv = glColor3uiv; + table.m_glColor3us = glColor3us; + table.m_glColor3usv = glColor3usv; + table.m_glColor4b = glColor4b; + table.m_glColor4bv = glColor4bv; + table.m_glColor4d = glColor4d; + table.m_glColor4dv = glColor4dv; + table.m_glColor4f = glColor4f; + table.m_glColor4fv = glColor4fv; + table.m_glColor4i = glColor4i; + table.m_glColor4iv = glColor4iv; + table.m_glColor4s = glColor4s; + table.m_glColor4sv = glColor4sv; + table.m_glColor4ub = glColor4ub; + table.m_glColor4ubv = glColor4ubv; + table.m_glColor4ui = glColor4ui; + table.m_glColor4uiv = glColor4uiv; + table.m_glColor4us = glColor4us; + table.m_glColor4usv = glColor4usv; + table.m_glColorMask = glColorMask; + table.m_glColorMaterial = glColorMaterial; + table.m_glColorPointer = glColorPointer; + table.m_glCopyPixels = glCopyPixels; + table.m_glCopyTexImage1D = glCopyTexImage1D; + table.m_glCopyTexImage2D = glCopyTexImage2D; + table.m_glCopyTexSubImage1D = glCopyTexSubImage1D; + table.m_glCopyTexSubImage2D = glCopyTexSubImage2D; + table.m_glCullFace = glCullFace; + table.m_glDeleteLists = glDeleteLists; + table.m_glDeleteTextures = glDeleteTextures; + table.m_glDepthFunc = glDepthFunc; + table.m_glDepthMask = glDepthMask; + table.m_glDepthRange = glDepthRange; + table.m_glDisable = glDisable; + table.m_glDisableClientState = glDisableClientState; + table.m_glDrawArrays = glDrawArrays; + table.m_glDrawBuffer = glDrawBuffer; + table.m_glDrawElements = glDrawElements; + table.m_glDrawPixels = glDrawPixels; + table.m_glEdgeFlag = glEdgeFlag; + table.m_glEdgeFlagPointer = glEdgeFlagPointer; + table.m_glEdgeFlagv = glEdgeFlagv; + table.m_glEnable = glEnable; + table.m_glEnableClientState = glEnableClientState; + table.m_glEnd = glEnd; + table.m_glEndList = glEndList; + table.m_glEvalCoord1d = glEvalCoord1d; + table.m_glEvalCoord1dv = glEvalCoord1dv; + table.m_glEvalCoord1f = glEvalCoord1f; + table.m_glEvalCoord1fv = glEvalCoord1fv; + table.m_glEvalCoord2d = glEvalCoord2d; + table.m_glEvalCoord2dv = glEvalCoord2dv; + table.m_glEvalCoord2f = glEvalCoord2f; + table.m_glEvalCoord2fv = glEvalCoord2fv; + table.m_glEvalMesh1 = glEvalMesh1; + table.m_glEvalMesh2 = glEvalMesh2; + table.m_glEvalPoint1 = glEvalPoint1; + table.m_glEvalPoint2 = glEvalPoint2; + table.m_glFeedbackBuffer = glFeedbackBuffer; + table.m_glFinish = glFinish; + table.m_glFlush = glFlush; + table.m_glFogf = glFogf; + table.m_glFogfv = glFogfv; + table.m_glFogi = glFogi; + table.m_glFogiv = glFogiv; + table.m_glFrontFace = glFrontFace; + table.m_glFrustum = glFrustum; + table.m_glGenLists = glGenLists; + table.m_glGenTextures = glGenTextures; + table.m_glGetBooleanv = glGetBooleanv; + table.m_glGetClipPlane = glGetClipPlane; + table.m_glGetDoublev = glGetDoublev; + table.m_glGetError = glGetError; + table.m_glGetFloatv = glGetFloatv; + table.m_glGetIntegerv = glGetIntegerv; + table.m_glGetLightfv = glGetLightfv; + table.m_glGetLightiv = glGetLightiv; + table.m_glGetMapdv = glGetMapdv; + table.m_glGetMapfv = glGetMapfv; + table.m_glGetMapiv = glGetMapiv; + table.m_glGetMaterialfv = glGetMaterialfv; + table.m_glGetMaterialiv = glGetMaterialiv; + table.m_glGetPixelMapfv = glGetPixelMapfv; + table.m_glGetPixelMapuiv = glGetPixelMapuiv; + table.m_glGetPixelMapusv = glGetPixelMapusv; + table.m_glGetPointerv = glGetPointerv; + table.m_glGetPolygonStipple = glGetPolygonStipple; + table.m_glGetString = glGetString; + table.m_glGetTexEnvfv = glGetTexEnvfv; + table.m_glGetTexEnviv = glGetTexEnviv; + table.m_glGetTexGendv = glGetTexGendv; + table.m_glGetTexGenfv = glGetTexGenfv; + table.m_glGetTexGeniv = glGetTexGeniv; + table.m_glGetTexImage = glGetTexImage; + table.m_glGetTexLevelParameterfv = glGetTexLevelParameterfv; + table.m_glGetTexLevelParameteriv = glGetTexLevelParameteriv; + table.m_glGetTexParameterfv = glGetTexParameterfv; + table.m_glGetTexParameteriv = glGetTexParameteriv; + table.m_glHint = glHint; + table.m_glIndexMask = glIndexMask; + table.m_glIndexPointer = glIndexPointer; + table.m_glIndexd = glIndexd; + table.m_glIndexdv = glIndexdv; + table.m_glIndexf = glIndexf; + table.m_glIndexfv = glIndexfv; + table.m_glIndexi = glIndexi; + table.m_glIndexiv = glIndexiv; + table.m_glIndexs = glIndexs; + table.m_glIndexsv = glIndexsv; + table.m_glIndexub = glIndexub; + table.m_glIndexubv = glIndexubv; + table.m_glInitNames = glInitNames; + table.m_glInterleavedArrays = glInterleavedArrays; + table.m_glIsEnabled = glIsEnabled; + table.m_glIsList = glIsList; + table.m_glIsTexture = glIsTexture; + table.m_glLightModelf = glLightModelf; + table.m_glLightModelfv = glLightModelfv; + table.m_glLightModeli = glLightModeli; + table.m_glLightModeliv = glLightModeliv; + table.m_glLightf = glLightf; + table.m_glLightfv = glLightfv; + table.m_glLighti = glLighti; + table.m_glLightiv = glLightiv; + table.m_glLineStipple = glLineStipple; + table.m_glLineWidth = glLineWidth; + table.m_glListBase = glListBase; + table.m_glLoadIdentity = glLoadIdentity; + table.m_glLoadMatrixd = glLoadMatrixd; + table.m_glLoadMatrixf = glLoadMatrixf; + table.m_glLoadName = glLoadName; + table.m_glLogicOp = glLogicOp; + table.m_glMap1d = glMap1d; + table.m_glMap1f = glMap1f; + table.m_glMap2d = glMap2d; + table.m_glMap2f = glMap2f; + table.m_glMapGrid1d = glMapGrid1d; + table.m_glMapGrid1f = glMapGrid1f; + table.m_glMapGrid2d = glMapGrid2d; + table.m_glMapGrid2f = glMapGrid2f; + table.m_glMaterialf = glMaterialf; + table.m_glMaterialfv = glMaterialfv; + table.m_glMateriali = glMateriali; + table.m_glMaterialiv = glMaterialiv; + table.m_glMatrixMode = glMatrixMode; + table.m_glMultMatrixd = glMultMatrixd; + table.m_glMultMatrixf = glMultMatrixf; + table.m_glNewList = glNewList; + table.m_glNormal3b = glNormal3b; + table.m_glNormal3bv = glNormal3bv; + table.m_glNormal3d = glNormal3d; + table.m_glNormal3dv = glNormal3dv; + table.m_glNormal3f = glNormal3f; + table.m_glNormal3fv = glNormal3fv; + table.m_glNormal3i = glNormal3i; + table.m_glNormal3iv = glNormal3iv; + table.m_glNormal3s = glNormal3s; + table.m_glNormal3sv = glNormal3sv; + table.m_glNormalPointer = glNormalPointer; + table.m_glOrtho = glOrtho; + table.m_glPassThrough = glPassThrough; + table.m_glPixelMapfv = glPixelMapfv; + table.m_glPixelMapuiv = glPixelMapuiv; + table.m_glPixelMapusv = glPixelMapusv; + table.m_glPixelStoref = glPixelStoref; + table.m_glPixelStorei = glPixelStorei; + table.m_glPixelTransferf = glPixelTransferf; + table.m_glPixelTransferi = glPixelTransferi; + table.m_glPixelZoom = glPixelZoom; + table.m_glPointSize = glPointSize; + table.m_glPolygonMode = glPolygonMode; + table.m_glPolygonOffset = glPolygonOffset; + table.m_glPolygonStipple = glPolygonStipple; + table.m_glPopAttrib = glPopAttrib; + table.m_glPopClientAttrib = glPopClientAttrib; + table.m_glPopMatrix = glPopMatrix; + table.m_glPopName = glPopName; + table.m_glPrioritizeTextures = glPrioritizeTextures; + table.m_glPushAttrib = glPushAttrib; + table.m_glPushClientAttrib = glPushClientAttrib; + table.m_glPushMatrix = glPushMatrix; + table.m_glPushName = glPushName; + table.m_glRasterPos2d = glRasterPos2d; + table.m_glRasterPos2dv = glRasterPos2dv; + table.m_glRasterPos2f = glRasterPos2f; + table.m_glRasterPos2fv = glRasterPos2fv; + table.m_glRasterPos2i = glRasterPos2i; + table.m_glRasterPos2iv = glRasterPos2iv; + table.m_glRasterPos2s = glRasterPos2s; + table.m_glRasterPos2sv = glRasterPos2sv; + table.m_glRasterPos3d = glRasterPos3d; + table.m_glRasterPos3dv = glRasterPos3dv; + table.m_glRasterPos3f = glRasterPos3f; + table.m_glRasterPos3fv = glRasterPos3fv; + table.m_glRasterPos3i = glRasterPos3i; + table.m_glRasterPos3iv = glRasterPos3iv; + table.m_glRasterPos3s = glRasterPos3s; + table.m_glRasterPos3sv = glRasterPos3sv; + table.m_glRasterPos4d = glRasterPos4d; + table.m_glRasterPos4dv = glRasterPos4dv; + table.m_glRasterPos4f = glRasterPos4f; + table.m_glRasterPos4fv = glRasterPos4fv; + table.m_glRasterPos4i = glRasterPos4i; + table.m_glRasterPos4iv = glRasterPos4iv; + table.m_glRasterPos4s = glRasterPos4s; + table.m_glRasterPos4sv = glRasterPos4sv; + table.m_glReadBuffer = glReadBuffer; + table.m_glReadPixels = glReadPixels; + table.m_glRectd = glRectd; + table.m_glRectdv = glRectdv; + table.m_glRectf = glRectf; + table.m_glRectfv = glRectfv; + table.m_glRecti = glRecti; + table.m_glRectiv = glRectiv; + table.m_glRects = glRects; + table.m_glRectsv = glRectsv; + table.m_glRenderMode = glRenderMode; + table.m_glRotated = glRotated; + table.m_glRotatef = glRotatef; + table.m_glScaled = glScaled; + table.m_glScalef = glScalef; + table.m_glScissor = glScissor; + table.m_glSelectBuffer = glSelectBuffer; + table.m_glShadeModel = glShadeModel; + table.m_glStencilFunc = glStencilFunc; + table.m_glStencilMask = glStencilMask; + table.m_glStencilOp = glStencilOp; + table.m_glTexCoord1d = glTexCoord1d; + table.m_glTexCoord1dv = glTexCoord1dv; + table.m_glTexCoord1f = glTexCoord1f; + table.m_glTexCoord1fv = glTexCoord1fv; + table.m_glTexCoord1i = glTexCoord1i; + table.m_glTexCoord1iv = glTexCoord1iv; + table.m_glTexCoord1s = glTexCoord1s; + table.m_glTexCoord1sv = glTexCoord1sv; + table.m_glTexCoord2d = glTexCoord2d; + table.m_glTexCoord2dv = glTexCoord2dv; + table.m_glTexCoord2f = glTexCoord2f; + table.m_glTexCoord2fv = glTexCoord2fv; + table.m_glTexCoord2i = glTexCoord2i; + table.m_glTexCoord2iv = glTexCoord2iv; + table.m_glTexCoord2s = glTexCoord2s; + table.m_glTexCoord2sv = glTexCoord2sv; + table.m_glTexCoord3d = glTexCoord3d; + table.m_glTexCoord3dv = glTexCoord3dv; + table.m_glTexCoord3f = glTexCoord3f; + table.m_glTexCoord3fv = glTexCoord3fv; + table.m_glTexCoord3i = glTexCoord3i; + table.m_glTexCoord3iv = glTexCoord3iv; + table.m_glTexCoord3s = glTexCoord3s; + table.m_glTexCoord3sv = glTexCoord3sv; + table.m_glTexCoord4d = glTexCoord4d; + table.m_glTexCoord4dv = glTexCoord4dv; + table.m_glTexCoord4f = glTexCoord4f; + table.m_glTexCoord4fv = glTexCoord4fv; + table.m_glTexCoord4i = glTexCoord4i; + table.m_glTexCoord4iv = glTexCoord4iv; + table.m_glTexCoord4s = glTexCoord4s; + table.m_glTexCoord4sv = glTexCoord4sv; + table.m_glTexCoordPointer = glTexCoordPointer; + table.m_glTexEnvf = glTexEnvf; + table.m_glTexEnvfv = glTexEnvfv; + table.m_glTexEnvi = glTexEnvi; + table.m_glTexEnviv = glTexEnviv; + table.m_glTexGend = glTexGend; + table.m_glTexGendv = glTexGendv; + table.m_glTexGenf = glTexGenf; + table.m_glTexGenfv = glTexGenfv; + table.m_glTexGeni = glTexGeni; + table.m_glTexGeniv = glTexGeniv; + table.m_glTexImage1D = glTexImage1D; + table.m_glTexImage2D = glTexImage2D; + table.m_glTexParameterf = glTexParameterf; + table.m_glTexParameterfv = glTexParameterfv; + table.m_glTexParameteri = glTexParameteri; + table.m_glTexParameteriv = glTexParameteriv; + table.m_glTexSubImage1D = glTexSubImage1D; + table.m_glTexSubImage2D = glTexSubImage2D; + table.m_glTranslated = glTranslated; + table.m_glTranslatef = glTranslatef; + table.m_glVertex2d = glVertex2d; + table.m_glVertex2dv = glVertex2dv; + table.m_glVertex2f = glVertex2f; + table.m_glVertex2fv = glVertex2fv; + table.m_glVertex2i = glVertex2i; + table.m_glVertex2iv = glVertex2iv; + table.m_glVertex2s = glVertex2s; + table.m_glVertex2sv = glVertex2sv; + table.m_glVertex3d = glVertex3d; + table.m_glVertex3dv = glVertex3dv; + table.m_glVertex3f = glVertex3f; + table.m_glVertex3fv = glVertex3fv; + table.m_glVertex3i = glVertex3i; + table.m_glVertex3iv = glVertex3iv; + table.m_glVertex3s = glVertex3s; + table.m_glVertex3sv = glVertex3sv; + table.m_glVertex4d = glVertex4d; + table.m_glVertex4dv = glVertex4dv; + table.m_glVertex4f = glVertex4f; + table.m_glVertex4fv = glVertex4fv; + table.m_glVertex4i = glVertex4i; + table.m_glVertex4iv = glVertex4iv; + table.m_glVertex4s = glVertex4s; + table.m_glVertex4sv = glVertex4sv; + table.m_glVertexPointer = glVertexPointer; + table.m_glViewport = glViewport; + + if (QGL_ExtensionSupported("GL_ARB_multitexture")) { + table.support_ARB_multitexture = + QGL_constructExtensionFunc(table.m_glActiveTextureARB, "glActiveTextureARB") + && QGL_constructExtensionFunc(table.m_glClientActiveTextureARB, "glClientActiveTextureARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1dARB, "glMultiTexCoord1dARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1fARB, "glMultiTexCoord1fARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1iARB, "glMultiTexCoord1iARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1sARB, "glMultiTexCoord1sARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1svARB, "glMultiTexCoord1svARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2dARB, "glMultiTexCoord2dARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2fARB, "glMultiTexCoord2fARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2iARB, "glMultiTexCoord2iARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2sARB, "glMultiTexCoord2sARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2svARB, "glMultiTexCoord2svARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3dARB, "glMultiTexCoord3dARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3fARB, "glMultiTexCoord3fARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3iARB, "glMultiTexCoord3iARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3sARB, "glMultiTexCoord3sARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3svARB, "glMultiTexCoord3svARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4dARB, "glMultiTexCoord4dARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4fARB, "glMultiTexCoord4fARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4iARB, "glMultiTexCoord4iARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4sARB, "glMultiTexCoord4sARB") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4svARB, "glMultiTexCoord4svARB"); + + if (!table.support_ARB_multitexture) { + extension_not_implemented("GL_ARB_multitexture"); + } + } else { + table.support_ARB_multitexture = false; + } + + if (QGL_ExtensionSupported("GL_ARB_texture_compression")) { + table.support_ARB_texture_compression = + QGL_constructExtensionFunc(table.m_glCompressedTexImage3DARB, "glCompressedTexImage3DARB") + && QGL_constructExtensionFunc(table.m_glCompressedTexImage2DARB, "glCompressedTexImage2DARB") + && QGL_constructExtensionFunc(table.m_glCompressedTexImage1DARB, "glCompressedTexImage1DARB") + && QGL_constructExtensionFunc(table.m_glCompressedTexSubImage3DARB, "glCompressedTexSubImage3DARB") + && QGL_constructExtensionFunc(table.m_glCompressedTexSubImage2DARB, "glCompressedTexSubImage2DARB") + && QGL_constructExtensionFunc(table.m_glCompressedTexSubImage1DARB, "glCompressedTexSubImage1DARB") + && QGL_constructExtensionFunc(table.m_glGetCompressedTexImageARB, "glGetCompressedTexImageARB"); + + if (!table.support_ARB_texture_compression) { + extension_not_implemented("GL_ARB_texture_compression"); + } + } else { + table.support_ARB_texture_compression = false; + } + + table.support_EXT_texture_compression_s3tc = QGL_ExtensionSupported("GL_EXT_texture_compression_s3tc"); + + // GL 1.2 + if (table.major_version > 1 || table.minor_version >= 2) { + table.support_GL_1_2 = + QGL_constructExtensionFunc(table.m_glCopyTexSubImage3D, "glCopyTexSubImage3D") + && QGL_constructExtensionFunc(table.m_glDrawRangeElements, "glDrawRangeElements") + && QGL_constructExtensionFunc(table.m_glTexImage3D, "glTexImage3D") + && QGL_constructExtensionFunc(table.m_glTexSubImage3D, "glTexSubImage3D"); + + if (!table.support_GL_1_2) { + extension_not_implemented("GL_VERSION_1_2"); + } + } else { + table.support_GL_1_2 = false; + } + + // GL 1.3 + if (table.major_version > 1 || table.minor_version >= 3) { + table.support_GL_1_3 = + QGL_constructExtensionFunc(table.m_glActiveTexture, "glActiveTexture") + && QGL_constructExtensionFunc(table.m_glClientActiveTexture, "glClientActiveTexture") + && QGL_constructExtensionFunc(table.m_glCompressedTexImage1D, "glCompressedTexImage1D") + && QGL_constructExtensionFunc(table.m_glCompressedTexImage2D, "glCompressedTexImage2D") + && QGL_constructExtensionFunc(table.m_glCompressedTexImage3D, "glCompressedTexImage3D") + && QGL_constructExtensionFunc(table.m_glCompressedTexSubImage1D, "glCompressedTexSubImage1D") + && QGL_constructExtensionFunc(table.m_glCompressedTexSubImage2D, "glCompressedTexSubImage2D") + && QGL_constructExtensionFunc(table.m_glCompressedTexSubImage3D, "glCompressedTexSubImage3D") + && QGL_constructExtensionFunc(table.m_glGetCompressedTexImage, "glGetCompressedTexImage") + && QGL_constructExtensionFunc(table.m_glLoadTransposeMatrixd, "glLoadTransposeMatrixd") + && QGL_constructExtensionFunc(table.m_glLoadTransposeMatrixf, "glLoadTransposeMatrixf") + && QGL_constructExtensionFunc(table.m_glMultTransposeMatrixd, "glMultTransposeMatrixd") + && QGL_constructExtensionFunc(table.m_glMultTransposeMatrixf, "glMultTransposeMatrixf") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1d, "glMultiTexCoord1d") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1dv, "glMultiTexCoord1dv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1f, "glMultiTexCoord1f") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1fv, "glMultiTexCoord1fv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1i, "glMultiTexCoord1i") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1iv, "glMultiTexCoord1iv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1s, "glMultiTexCoord1s") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord1sv, "glMultiTexCoord1sv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2d, "glMultiTexCoord2d") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2dv, "glMultiTexCoord2dv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2f, "glMultiTexCoord2f") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2fv, "glMultiTexCoord2fv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2i, "glMultiTexCoord2i") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2iv, "glMultiTexCoord2iv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2s, "glMultiTexCoord2s") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord2sv, "glMultiTexCoord2sv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3d, "glMultiTexCoord3d") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3dv, "glMultiTexCoord3dv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3f, "glMultiTexCoord3f") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3fv, "glMultiTexCoord3fv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3i, "glMultiTexCoord3i") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3iv, "glMultiTexCoord3iv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3s, "glMultiTexCoord3s") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord3sv, "glMultiTexCoord3sv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4d, "glMultiTexCoord4d") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4dv, "glMultiTexCoord4dv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4f, "glMultiTexCoord4f") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4fv, "glMultiTexCoord4fv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4i, "glMultiTexCoord4i") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4iv, "glMultiTexCoord4iv") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4s, "glMultiTexCoord4s") + && QGL_constructExtensionFunc(table.m_glMultiTexCoord4sv, "glMultiTexCoord4sv") + && QGL_constructExtensionFunc(table.m_glSampleCoverage, "glSampleCoverage"); + + if (!table.support_GL_1_3) { + extension_not_implemented("GL_VERSION_1_3"); + } + } else { + table.support_GL_1_3 = false; + } + + // GL 1.4 + if (table.major_version > 1 || table.minor_version >= 4) { + table.support_GL_1_4 = + QGL_constructExtensionFunc(table.m_glBlendColor, "glBlendColor") + && QGL_constructExtensionFunc(table.m_glBlendEquation, "glBlendEquation") + && QGL_constructExtensionFunc(table.m_glBlendFuncSeparate, "glBlendFuncSeparate") + && QGL_constructExtensionFunc(table.m_glFogCoordPointer, "glFogCoordPointer") + && QGL_constructExtensionFunc(table.m_glFogCoordd, "glFogCoordd") + && QGL_constructExtensionFunc(table.m_glFogCoorddv, "glFogCoorddv") + && QGL_constructExtensionFunc(table.m_glFogCoordf, "glFogCoordf") + && QGL_constructExtensionFunc(table.m_glFogCoordfv, "glFogCoordfv") + && QGL_constructExtensionFunc(table.m_glMultiDrawArrays, "glMultiDrawArrays") + && QGL_constructExtensionFunc(table.m_glMultiDrawElements, "glMultiDrawElements") + && QGL_constructExtensionFunc(table.m_glPointParameterf, "glPointParameterf") + && QGL_constructExtensionFunc(table.m_glPointParameterfv, "glPointParameterfv") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3b, "glSecondaryColor3b") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3bv, "glSecondaryColor3bv") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3d, "glSecondaryColor3d") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3dv, "glSecondaryColor3dv") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3f, "glSecondaryColor3f") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3fv, "glSecondaryColor3fv") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3i, "glSecondaryColor3i") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3iv, "glSecondaryColor3iv") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3s, "glSecondaryColor3s") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3sv, "glSecondaryColor3sv") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3ub, "glSecondaryColor3ub") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3ubv, "glSecondaryColor3ubv") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3ui, "glSecondaryColor3ui") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3uiv, "glSecondaryColor3uiv") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3us, "glSecondaryColor3us") + && QGL_constructExtensionFunc(table.m_glSecondaryColor3usv, "glSecondaryColor3usv") + && QGL_constructExtensionFunc(table.m_glSecondaryColorPointer, "glSecondaryColorPointer") + && QGL_constructExtensionFunc(table.m_glWindowPos2d, "glWindowPos2d") + && QGL_constructExtensionFunc(table.m_glWindowPos2dv, "glWindowPos2dv") + && QGL_constructExtensionFunc(table.m_glWindowPos2f, "glWindowPos2f") + && QGL_constructExtensionFunc(table.m_glWindowPos2fv, "glWindowPos2fv") + && QGL_constructExtensionFunc(table.m_glWindowPos2i, "glWindowPos2i") + && QGL_constructExtensionFunc(table.m_glWindowPos2iv, "glWindowPos2iv") + && QGL_constructExtensionFunc(table.m_glWindowPos2s, "glWindowPos2s") + && QGL_constructExtensionFunc(table.m_glWindowPos2sv, "glWindowPos2sv") + && QGL_constructExtensionFunc(table.m_glWindowPos3d, "glWindowPos3d") + && QGL_constructExtensionFunc(table.m_glWindowPos3dv, "glWindowPos3dv") + && QGL_constructExtensionFunc(table.m_glWindowPos3f, "glWindowPos3f") + && QGL_constructExtensionFunc(table.m_glWindowPos3fv, "glWindowPos3fv") + && QGL_constructExtensionFunc(table.m_glWindowPos3i, "glWindowPos3i") + && QGL_constructExtensionFunc(table.m_glWindowPos3iv, "glWindowPos3iv") + && QGL_constructExtensionFunc(table.m_glWindowPos3s, "glWindowPos3s") + && QGL_constructExtensionFunc(table.m_glWindowPos3sv, "glWindowPos3sv"); + + if (!table.support_GL_1_4) { + extension_not_implemented("GL_VERSION_1_4"); + } + } else { + table.support_GL_1_4 = false; + } + + // GL 1.5 + if (table.major_version > 1 || table.minor_version >= 5) { + table.support_GL_1_5 = + QGL_constructExtensionFunc(table.m_glBeginQuery, "glBeginQuery") + && QGL_constructExtensionFunc(table.m_glBindBuffer, "glBindBuffer") + && QGL_constructExtensionFunc(table.m_glBufferData, "glBufferData") + && QGL_constructExtensionFunc(table.m_glBufferSubData, "glBufferSubData") + && QGL_constructExtensionFunc(table.m_glDeleteBuffers, "glDeleteBuffers") + && QGL_constructExtensionFunc(table.m_glDeleteQueries, "glDeleteQueries") + && QGL_constructExtensionFunc(table.m_glEndQuery, "glEndQuery") + && QGL_constructExtensionFunc(table.m_glGenBuffers, "glGenBuffers") + && QGL_constructExtensionFunc(table.m_glGenQueries, "glGenQueries") + && QGL_constructExtensionFunc(table.m_glGetBufferParameteriv, "glGetBufferParameteriv") + && QGL_constructExtensionFunc(table.m_glGetBufferPointerv, "glGetBufferPointerv") + && QGL_constructExtensionFunc(table.m_glGetBufferSubData, "glGetBufferSubData") + && QGL_constructExtensionFunc(table.m_glGetQueryObjectiv, "glGetQueryObjectiv") + && QGL_constructExtensionFunc(table.m_glGetQueryObjectuiv, "glGetQueryObjectuiv") + && QGL_constructExtensionFunc(table.m_glGetQueryiv, "glGetQueryiv") + && QGL_constructExtensionFunc(table.m_glIsBuffer, "glIsBuffer") + && QGL_constructExtensionFunc(table.m_glIsQuery, "glIsQuery") + && QGL_constructExtensionFunc(table.m_glMapBuffer, "glMapBuffer") + && QGL_constructExtensionFunc(table.m_glUnmapBuffer, "glUnmapBuffer"); + + if (!table.support_GL_1_5) { + extension_not_implemented("GL_VERSION_1_5"); + } + } else { + table.support_GL_1_5 = false; + } + + + if (QGL_ExtensionSupported("GL_ARB_vertex_program")) { + table.support_ARB_vertex_program = + QGL_constructExtensionFunc(table.m_glVertexAttrib1sARB, "glVertexAttrib1sARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1fARB, "glVertexAttrib1fARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1dARB, "glVertexAttrib1dARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2sARB, "glVertexAttrib2sARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2fARB, "glVertexAttrib2fARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2dARB, "glVertexAttrib2dARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3sARB, "glVertexAttrib3sARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3fARB, "glVertexAttrib3fARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3dARB, "glVertexAttrib3dARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4sARB, "glVertexAttrib4sARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4fARB, "glVertexAttrib4fARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4dARB, "glVertexAttrib4dARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NubARB, "glVertexAttrib4NubARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1svARB, "glVertexAttrib1svARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1fvARB, "glVertexAttrib1fvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1dvARB, "glVertexAttrib1dvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2svARB, "glVertexAttrib2svARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2fvARB, "glVertexAttrib2fvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2dvARB, "glVertexAttrib2dvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3svARB, "glVertexAttrib3svARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3fvARB, "glVertexAttrib3fvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3dvARB, "glVertexAttrib3dvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4bvARB, "glVertexAttrib4bvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4svARB, "glVertexAttrib4svARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4ivARB, "glVertexAttrib4ivARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4ubvARB, "glVertexAttrib4ubvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4usvARB, "glVertexAttrib4usvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4uivARB, "glVertexAttrib4uivARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4fvARB, "glVertexAttrib4fvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4dvARB, "glVertexAttrib4dvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NbvARB, "glVertexAttrib4NbvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NsvARB, "glVertexAttrib4NsvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NivARB, "glVertexAttrib4NivARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NubvARB, "glVertexAttrib4NubvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NusvARB, "glVertexAttrib4NusvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NuivARB, "glVertexAttrib4NuivARB") + && QGL_constructExtensionFunc(table.m_glVertexAttribPointerARB, "glVertexAttribPointerARB") + && QGL_constructExtensionFunc(table.m_glEnableVertexAttribArrayARB, "glEnableVertexAttribArrayARB") + && QGL_constructExtensionFunc(table.m_glDisableVertexAttribArrayARB, "glDisableVertexAttribArrayARB") + && QGL_constructExtensionFunc(table.m_glProgramStringARB, "glProgramStringARB") + && QGL_constructExtensionFunc(table.m_glBindProgramARB, "glBindProgramARB") + && QGL_constructExtensionFunc(table.m_glDeleteProgramsARB, "glDeleteProgramsARB") + && QGL_constructExtensionFunc(table.m_glGenProgramsARB, "glGenProgramsARB") + && QGL_constructExtensionFunc(table.m_glProgramEnvParameter4dARB, "glProgramEnvParameter4dARB") + && QGL_constructExtensionFunc(table.m_glProgramEnvParameter4dvARB, "glProgramEnvParameter4dvARB") + && QGL_constructExtensionFunc(table.m_glProgramEnvParameter4fARB, "glProgramEnvParameter4fARB") + && QGL_constructExtensionFunc(table.m_glProgramEnvParameter4fvARB, "glProgramEnvParameter4fvARB") + && QGL_constructExtensionFunc(table.m_glProgramLocalParameter4dARB, "glProgramLocalParameter4dARB") + && QGL_constructExtensionFunc(table.m_glProgramLocalParameter4dvARB, "glProgramLocalParameter4dvARB") + && QGL_constructExtensionFunc(table.m_glProgramLocalParameter4fARB, "glProgramLocalParameter4fARB") + && QGL_constructExtensionFunc(table.m_glProgramLocalParameter4fvARB, "glProgramLocalParameter4fvARB") + && QGL_constructExtensionFunc(table.m_glGetProgramEnvParameterdvARB, "glGetProgramEnvParameterdvARB") + && QGL_constructExtensionFunc(table.m_glGetProgramEnvParameterfvARB, "glGetProgramEnvParameterfvARB") + && + QGL_constructExtensionFunc(table.m_glGetProgramLocalParameterdvARB, "glGetProgramLocalParameterdvARB") + && + QGL_constructExtensionFunc(table.m_glGetProgramLocalParameterfvARB, "glGetProgramLocalParameterfvARB") + && QGL_constructExtensionFunc(table.m_glGetProgramivARB, "glGetProgramivARB") + && QGL_constructExtensionFunc(table.m_glGetProgramStringARB, "glGetProgramStringARB") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribdvARB, "glGetVertexAttribdvARB") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribfvARB, "glGetVertexAttribfvARB") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribivARB, "glGetVertexAttribivARB") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribPointervARB, "glGetVertexAttribPointervARB") + && QGL_constructExtensionFunc(table.m_glIsProgramARB, "glIsProgramARB"); + + if (!table.support_ARB_vertex_program) { + extension_not_implemented("GL_ARB_vertex_program"); + } + } else { + table.support_ARB_vertex_program = false; + } + + + table.support_ARB_fragment_program = QGL_ExtensionSupported("GL_ARB_fragment_program"); + + if (QGL_ExtensionSupported("GL_ARB_shader_objects")) { + table.support_ARB_shader_objects = + QGL_constructExtensionFunc(table.m_glDeleteObjectARB, "glDeleteObjectARB") + && QGL_constructExtensionFunc(table.m_glGetHandleARB, "glGetHandleARB") + && QGL_constructExtensionFunc(table.m_glDetachObjectARB, "glDetachObjectARB") + && QGL_constructExtensionFunc(table.m_glCreateShaderObjectARB, "glCreateShaderObjectARB") + && QGL_constructExtensionFunc(table.m_glShaderSourceARB, "glShaderSourceARB") + && QGL_constructExtensionFunc(table.m_glCompileShaderARB, "glCompileShaderARB") + && QGL_constructExtensionFunc(table.m_glCreateProgramObjectARB, "glCreateProgramObjectARB") + && QGL_constructExtensionFunc(table.m_glAttachObjectARB, "glAttachObjectARB") + && QGL_constructExtensionFunc(table.m_glLinkProgramARB, "glLinkProgramARB") + && QGL_constructExtensionFunc(table.m_glUseProgramObjectARB, "glUseProgramObjectARB") + && QGL_constructExtensionFunc(table.m_glValidateProgramARB, "glValidateProgramARB") + && QGL_constructExtensionFunc(table.m_glUniform1fARB, "glUniform1fARB") + && QGL_constructExtensionFunc(table.m_glUniform2fARB, "glUniform2fARB") + && QGL_constructExtensionFunc(table.m_glUniform3fARB, "glUniform3fARB") + && QGL_constructExtensionFunc(table.m_glUniform4fARB, "glUniform4fARB") + && QGL_constructExtensionFunc(table.m_glUniform1iARB, "glUniform1iARB") + && QGL_constructExtensionFunc(table.m_glUniform2iARB, "glUniform2iARB") + && QGL_constructExtensionFunc(table.m_glUniform3iARB, "glUniform3iARB") + && QGL_constructExtensionFunc(table.m_glUniform4iARB, "glUniform4iARB") + && QGL_constructExtensionFunc(table.m_glUniform1fvARB, "glUniform1fvARB") + && QGL_constructExtensionFunc(table.m_glUniform2fvARB, "glUniform2fvARB") + && QGL_constructExtensionFunc(table.m_glUniform3fvARB, "glUniform3fvARB") + && QGL_constructExtensionFunc(table.m_glUniform4fvARB, "glUniform4fvARB") + && QGL_constructExtensionFunc(table.m_glUniform1ivARB, "glUniform1ivARB") + && QGL_constructExtensionFunc(table.m_glUniform2ivARB, "glUniform2ivARB") + && QGL_constructExtensionFunc(table.m_glUniform3ivARB, "glUniform3ivARB") + && QGL_constructExtensionFunc(table.m_glUniform4ivARB, "glUniform4ivARB") + && QGL_constructExtensionFunc(table.m_glUniformMatrix2fvARB, "glUniformMatrix2fvARB") + && QGL_constructExtensionFunc(table.m_glUniformMatrix3fvARB, "glUniformMatrix3fvARB") + && QGL_constructExtensionFunc(table.m_glUniformMatrix4fvARB, "glUniformMatrix4fvARB") + && QGL_constructExtensionFunc(table.m_glGetObjectParameterfvARB, "glGetObjectParameterfvARB") + && QGL_constructExtensionFunc(table.m_glGetObjectParameterivARB, "glGetObjectParameterivARB") + && QGL_constructExtensionFunc(table.m_glGetInfoLogARB, "glGetInfoLogARB") + && QGL_constructExtensionFunc(table.m_glGetAttachedObjectsARB, "glGetAttachedObjectsARB") + && QGL_constructExtensionFunc(table.m_glGetUniformLocationARB, "glGetUniformLocationARB") + && QGL_constructExtensionFunc(table.m_glGetActiveUniformARB, "glGetActiveUniformARB") + && QGL_constructExtensionFunc(table.m_glGetUniformfvARB, "glGetUniformfvARB") + && QGL_constructExtensionFunc(table.m_glGetUniformivARB, "glGetUniformivARB") + && QGL_constructExtensionFunc(table.m_glGetShaderSourceARB, "glGetShaderSourceARB"); + + if (!table.support_ARB_shader_objects) { + extension_not_implemented("GL_ARB_shader_objects"); + } + } else { + table.support_ARB_shader_objects = false; + } + + if (QGL_ExtensionSupported("GL_ARB_vertex_shader")) { + table.support_ARB_vertex_shader = + QGL_constructExtensionFunc(table.m_glVertexAttrib1fARB, "glVertexAttrib1fARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1sARB, "glVertexAttrib1sARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1dARB, "glVertexAttrib1dARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2fARB, "glVertexAttrib2fARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2sARB, "glVertexAttrib2sARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2dARB, "glVertexAttrib2dARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3fARB, "glVertexAttrib3fARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3sARB, "glVertexAttrib3sARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3dARB, "glVertexAttrib3dARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4fARB, "glVertexAttrib4fARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4sARB, "glVertexAttrib4sARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4dARB, "glVertexAttrib4dARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NubARB, "glVertexAttrib4NubARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1fvARB, "glVertexAttrib1fvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1svARB, "glVertexAttrib1svARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1dvARB, "glVertexAttrib1dvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2fvARB, "glVertexAttrib2fvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2svARB, "glVertexAttrib2svARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2dvARB, "glVertexAttrib2dvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3fvARB, "glVertexAttrib3fvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3svARB, "glVertexAttrib3svARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3dvARB, "glVertexAttrib3dvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4fvARB, "glVertexAttrib4fvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4svARB, "glVertexAttrib4svARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4dvARB, "glVertexAttrib4dvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4ivARB, "glVertexAttrib4ivARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4bvARB, "glVertexAttrib4bvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4ubvARB, "glVertexAttrib4ubvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4usvARB, "glVertexAttrib4usvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4uivARB, "glVertexAttrib4uivARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NbvARB, "glVertexAttrib4NbvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NsvARB, "glVertexAttrib4NsvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NivARB, "glVertexAttrib4NivARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NubvARB, "glVertexAttrib4NubvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NusvARB, "glVertexAttrib4NusvARB") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4NuivARB, "glVertexAttrib4NuivARB") + && QGL_constructExtensionFunc(table.m_glVertexAttribPointerARB, "glVertexAttribPointerARB") + && QGL_constructExtensionFunc(table.m_glEnableVertexAttribArrayARB, "glEnableVertexAttribArrayARB") + && QGL_constructExtensionFunc(table.m_glDisableVertexAttribArrayARB, "glDisableVertexAttribArrayARB") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribdvARB, "glGetVertexAttribdvARB") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribfvARB, "glGetVertexAttribfvARB") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribivARB, "glGetVertexAttribivARB") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribPointervARB, "glGetVertexAttribPointervARB") + && QGL_constructExtensionFunc(table.m_glBindAttribLocationARB, "glBindAttribLocationARB") + && QGL_constructExtensionFunc(table.m_glGetActiveAttribARB, "glGetActiveAttribARB") + && QGL_constructExtensionFunc(table.m_glGetAttribLocationARB, "glGetAttribLocationARB"); + + if (!table.support_ARB_vertex_shader) { + extension_not_implemented("GL_ARB_vertex_shader"); + } + } else { + table.support_ARB_vertex_shader = false; + } + + if (QGL_ExtensionSupported("GL_NV_vertex_program2")) { + table.support_NV_vertex_program2 = + QGL_constructExtensionFunc(table.m_glAreProgramsResidentNV, "glAreProgramsResidentNV") + && QGL_constructExtensionFunc(table.m_glBindProgramNV, "glBindProgramNV") + && QGL_constructExtensionFunc(table.m_glDeleteProgramsNV, "glDeleteProgramsNV") + && QGL_constructExtensionFunc(table.m_glExecuteProgramNV, "glExecuteProgramNV") + && QGL_constructExtensionFunc(table.m_glGenProgramsNV, "glGenProgramsNV") + && QGL_constructExtensionFunc(table.m_glGetProgramParameterdvNV, "glGetProgramParameterdvNV") + && QGL_constructExtensionFunc(table.m_glGetProgramParameterfvNV, "glGetProgramParameterfvNV") + && QGL_constructExtensionFunc(table.m_glGetProgramivNV, "glGetProgramivNV") + && QGL_constructExtensionFunc(table.m_glGetProgramStringNV, "glGetProgramStringNV") + && QGL_constructExtensionFunc(table.m_glGetTrackMatrixivNV, "glGetTrackMatrixivNV") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribdvNV, "glGetVertexAttribdvNV") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribfvNV, "glGetVertexAttribfvNV") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribivNV, "glGetVertexAttribivNV") + && QGL_constructExtensionFunc(table.m_glGetVertexAttribPointervNV, "glGetVertexAttribPointervNV") + && QGL_constructExtensionFunc(table.m_glIsProgramNV, "glIsProgramNV") + && QGL_constructExtensionFunc(table.m_glLoadProgramNV, "glLoadProgramNV") + && QGL_constructExtensionFunc(table.m_glProgramParameter4fNV, "glProgramParameter4fNV") + && QGL_constructExtensionFunc(table.m_glProgramParameter4fvNV, "glProgramParameter4fvNV") + && QGL_constructExtensionFunc(table.m_glProgramParameters4fvNV, "glProgramParameters4fvNV") + && QGL_constructExtensionFunc(table.m_glRequestResidentProgramsNV, "glRequestResidentProgramsNV") + && QGL_constructExtensionFunc(table.m_glTrackMatrixNV, "glTrackMatrixNV") + && QGL_constructExtensionFunc(table.m_glVertexAttribPointerNV, "glVertexAttribPointerNV") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1fNV, "glVertexAttrib1fNV") + && QGL_constructExtensionFunc(table.m_glVertexAttrib1fvNV, "glVertexAttrib1fvNV") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2fNV, "glVertexAttrib2fNV") + && QGL_constructExtensionFunc(table.m_glVertexAttrib2fvNV, "glVertexAttrib2fvNV") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3fNV, "glVertexAttrib3fNV") + && QGL_constructExtensionFunc(table.m_glVertexAttrib3fvNV, "glVertexAttrib3fvNV") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4fNV, "glVertexAttrib4fNV") + && QGL_constructExtensionFunc(table.m_glVertexAttrib4fvNV, "glVertexAttrib4fvNV") + && QGL_constructExtensionFunc(table.m_glVertexAttribs1fvNV, "glVertexAttribs1fvNV") + && QGL_constructExtensionFunc(table.m_glVertexAttribs2fvNV, "glVertexAttribs2fvNV") + && QGL_constructExtensionFunc(table.m_glVertexAttribs3fvNV, "glVertexAttribs3fvNV") + && QGL_constructExtensionFunc(table.m_glVertexAttribs4fvNV, "glVertexAttribs4fvNV"); + + if (!table.support_NV_vertex_program2) { + extension_not_implemented("GL_NV_vertex_program2"); + } + } else { + table.support_NV_vertex_program2 = false; + QGL_invalidateExtensionFunc(table.m_glAreProgramsResidentNV); + QGL_invalidateExtensionFunc(table.m_glBindProgramNV); + QGL_invalidateExtensionFunc(table.m_glDeleteProgramsNV); + QGL_invalidateExtensionFunc(table.m_glExecuteProgramNV); + QGL_invalidateExtensionFunc(table.m_glGenProgramsNV); + QGL_invalidateExtensionFunc(table.m_glGetProgramParameterdvNV); + QGL_invalidateExtensionFunc(table.m_glGetProgramParameterfvNV); + QGL_invalidateExtensionFunc(table.m_glGetProgramivNV); + QGL_invalidateExtensionFunc(table.m_glGetProgramStringNV); + QGL_invalidateExtensionFunc(table.m_glGetTrackMatrixivNV); + QGL_invalidateExtensionFunc(table.m_glGetVertexAttribdvNV); + QGL_invalidateExtensionFunc(table.m_glGetVertexAttribfvNV); + QGL_invalidateExtensionFunc(table.m_glGetVertexAttribivNV); + QGL_invalidateExtensionFunc(table.m_glGetVertexAttribPointervNV); + QGL_invalidateExtensionFunc(table.m_glIsProgramNV); + QGL_invalidateExtensionFunc(table.m_glLoadProgramNV); + QGL_invalidateExtensionFunc(table.m_glProgramParameter4fNV); + QGL_invalidateExtensionFunc(table.m_glProgramParameter4fvNV); + QGL_invalidateExtensionFunc(table.m_glProgramParameters4fvNV); + QGL_invalidateExtensionFunc(table.m_glRequestResidentProgramsNV); + QGL_invalidateExtensionFunc(table.m_glTrackMatrixNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttribPointerNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttrib1fNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttrib1fvNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttrib2fNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttrib2fvNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttrib3fNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttrib3fvNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttrib4fNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttrib4fvNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttribs1fvNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttribs2fvNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttribs3fvNV); + QGL_invalidateExtensionFunc(table.m_glVertexAttribs4fvNV); + } + + if (QGL_ExtensionSupported("GL_NV_fragment_program")) { + table.support_NV_fragment_program = + QGL_constructExtensionFunc(table.m_glProgramNamedParameter4fNV, "glProgramNamedParameter4fNV") + && QGL_constructExtensionFunc(table.m_glProgramNamedParameter4fvNV, "glProgramNamedParameter4fvNV") + && QGL_constructExtensionFunc(table.m_glGetProgramNamedParameterfvNV, "glGetProgramNamedParameterfvNV"); + + if (!table.support_NV_fragment_program) { + extension_not_implemented("GL_NV_fragment_program"); + } + } else { + table.support_NV_fragment_program = false; + } + + table.support_ARB_fragment_shader = QGL_ExtensionSupported("GL_ARB_fragment_shader"); + table.support_ARB_shading_language_100 = QGL_ExtensionSupported("GL_ARB_shading_language_100"); + + if (QGL_ExtensionSupported("GL_EXT_texture_filter_anisotropic")) { + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &g_maxTextureAnisotropy); + globalOutputStream() << "Anisotropic filtering possible (max " << g_maxTextureAnisotropy << "x)\n"; + } else { + globalOutputStream() << "No Anisotropic filtering available\n"; + g_maxTextureAnisotropy = 0; + } } -void QGL_sharedContextDestroyed( OpenGLBinding& table ){ - QGL_clear( table ); +void QGL_sharedContextDestroyed(OpenGLBinding &table) +{ + QGL_clear(table); } -void QGL_assertNoErrors( const char *file, int line ){ - GLenum error = GlobalOpenGL().m_glGetError(); - while ( error != GL_NO_ERROR ) - { - const char* errorString = reinterpret_cast( qgluErrorString( error ) ); - if ( error == GL_OUT_OF_MEMORY ) { - ERROR_MESSAGE( "OpenGL out of memory error at " << file << ":" << line << ": " << errorString ); - } - else - { - ERROR_MESSAGE( "OpenGL error at " << file << ":" << line << ": " << errorString ); - } - error = GlobalOpenGL().m_glGetError(); - } +void QGL_assertNoErrors(const char *file, int line) +{ + GLenum error = GlobalOpenGL().m_glGetError(); + while (error != GL_NO_ERROR) { + const char *errorString = reinterpret_cast( qgluErrorString(error)); + if (error == GL_OUT_OF_MEMORY) { + ERROR_MESSAGE("OpenGL out of memory error at " << file << ":" << line << ": " << errorString); + } else { + ERROR_MESSAGE("OpenGL error at " << file << ":" << line << ": " << errorString); + } + error = GlobalOpenGL().m_glGetError(); + } } -class QglAPI -{ -OpenGLBinding m_qgl; +class QglAPI { + OpenGLBinding m_qgl; public: -typedef OpenGLBinding Type; -STRING_CONSTANT( Name, "*" ); + typedef OpenGLBinding Type; -QglAPI(){ - QGL_Init( m_qgl ); + STRING_CONSTANT(Name, "*"); - m_qgl.assertNoErrors = &QGL_assertNoErrors; -} -~QglAPI(){ - QGL_Shutdown( m_qgl ); -} -OpenGLBinding* getTable(){ - return &m_qgl; -} + QglAPI() + { + QGL_Init(m_qgl); + + m_qgl.assertNoErrors = &QGL_assertNoErrors; + } + + ~QglAPI() + { + QGL_Shutdown(m_qgl); + } + + OpenGLBinding *getTable() + { + return &m_qgl; + } }; #include "modulesystem/singletonmodule.h" @@ -1521,4 +1513,4 @@ OpenGLBinding* getTable(){ typedef SingletonModule QglModule; typedef Static StaticQglModule; -StaticRegisterModule staticRegisterQgl( StaticQglModule::instance() ); +StaticRegisterModule staticRegisterQgl(StaticQglModule::instance()); diff --git a/radiant/qgl.h b/radiant/qgl.h index f7ef8a22..9d808528 100644 --- a/radiant/qgl.h +++ b/radiant/qgl.h @@ -23,10 +23,12 @@ #define INCLUDED_QGL_H struct OpenGLBinding; -void QGL_sharedContextCreated( OpenGLBinding& table ); -void QGL_sharedContextDestroyed( OpenGLBinding& table ); -bool QGL_ExtensionSupported( const char* extension ); +void QGL_sharedContextCreated(OpenGLBinding &table); + +void QGL_sharedContextDestroyed(OpenGLBinding &table); + +bool QGL_ExtensionSupported(const char *extension); float QGL_maxTextureAnisotropy(); diff --git a/radiant/radiant.rc b/radiant/radiant.rc index 51087c04..eb313af7 100644 --- a/radiant/radiant.rc +++ b/radiant/radiant.rc @@ -28,7 +28,9 @@ // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDI_RADIANT ICON DISCARDABLE "radiant.ico" +IDI_RADIANT +ICON DISCARDABLE +"radiant.ico" #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// diff --git a/radiant/referencecache.cpp b/radiant/referencecache.cpp index b1c34c8d..448cd913 100644 --- a/radiant/referencecache.cpp +++ b/radiant/referencecache.cpp @@ -28,9 +28,13 @@ #include "iselection.h" #include "iundo.h" #include "imap.h" -MapModules& ReferenceAPI_getMapModules(); + +MapModules &ReferenceAPI_getMapModules(); + #include "imodel.h" -ModelModules& ReferenceAPI_getModelModules(); + +ModelModules &ReferenceAPI_getModelModules(); + #include "ifilesystem.h" #include "iarchive.h" #include "ifiletypes.h" @@ -58,573 +62,631 @@ ModelModules& ReferenceAPI_getModelModules(); bool References_Saved(); -void MapChanged(){ - Map_SetModified( g_map, !References_Saved() ); +void MapChanged() +{ + Map_SetModified(g_map, !References_Saved()); } -EntityCreator* g_entityCreator = 0; - -bool MapResource_loadFile( const MapFormat& format, scene::Node& root, const char* filename ){ - globalOutputStream() << "Open file " << filename << " for read..."; - TextFileInputStream file( filename ); - if ( !file.failed() ) { - globalOutputStream() << "success\n"; - ScopeDisableScreenUpdates disableScreenUpdates( path_get_filename_start( filename ), "Loading Map" ); - ASSERT_NOTNULL( g_entityCreator ); - format.readGraph( root, file, *g_entityCreator ); - return true; - } - else - { - globalErrorStream() << "failure\n"; - return false; - } -} +EntityCreator *g_entityCreator = 0; -NodeSmartReference MapResource_load( const MapFormat& format, const char* path, const char* name ){ - NodeSmartReference root( NewMapRoot( name ) ); +bool MapResource_loadFile(const MapFormat &format, scene::Node &root, const char *filename) +{ + globalOutputStream() << "Open file " << filename << " for read..."; + TextFileInputStream file(filename); + if (!file.failed()) { + globalOutputStream() << "success\n"; + ScopeDisableScreenUpdates disableScreenUpdates(path_get_filename_start(filename), "Loading Map"); + ASSERT_NOTNULL(g_entityCreator); + format.readGraph(root, file, *g_entityCreator); + return true; + } else { + globalErrorStream() << "failure\n"; + return false; + } +} + +NodeSmartReference MapResource_load(const MapFormat &format, const char *path, const char *name) +{ + NodeSmartReference root(NewMapRoot(name)); - StringOutputStream fullpath( 256 ); - fullpath << path << name; + StringOutputStream fullpath(256); + fullpath << path << name; - if ( path_is_absolute( fullpath.c_str() ) ) { - MapResource_loadFile( format, root, fullpath.c_str() ); - } - else - { - globalErrorStream() << "map path is not fully qualified: " << makeQuoted( fullpath.c_str() ) << "\n"; - } + if (path_is_absolute(fullpath.c_str())) { + MapResource_loadFile(format, root, fullpath.c_str()); + } else { + globalErrorStream() << "map path is not fully qualified: " << makeQuoted(fullpath.c_str()) << "\n"; + } - return root; + return root; } -bool MapResource_saveFile( const MapFormat& format, scene::Node& root, GraphTraversalFunc traverse, const char* filename ){ - //ASSERT_MESSAGE(path_is_absolute(filename), "MapResource_saveFile: path is not absolute: " << makeQuoted(filename)); - globalOutputStream() << "Open file " << filename << " for write..."; - TextFileOutputStream file( filename ); - if ( !file.failed() ) { - globalOutputStream() << "success\n"; - ScopeDisableScreenUpdates disableScreenUpdates( path_get_filename_start( filename ), "Saving Map" ); - format.writeGraph( root, traverse, file ); - return true; - } - - globalErrorStream() << "failure\n"; - return false; +bool MapResource_saveFile(const MapFormat &format, scene::Node &root, GraphTraversalFunc traverse, const char *filename) +{ + //ASSERT_MESSAGE(path_is_absolute(filename), "MapResource_saveFile: path is not absolute: " << makeQuoted(filename)); + globalOutputStream() << "Open file " << filename << " for write..."; + TextFileOutputStream file(filename); + if (!file.failed()) { + globalOutputStream() << "success\n"; + ScopeDisableScreenUpdates disableScreenUpdates(path_get_filename_start(filename), "Saving Map"); + format.writeGraph(root, traverse, file); + return true; + } + + globalErrorStream() << "failure\n"; + return false; } -bool file_saveBackup( const char* path ){ - if ( file_writeable( path ) ) { - StringOutputStream backup( 256 ); - backup << StringRange( path, path_get_extension( path ) ) << "bak"; +bool file_saveBackup(const char *path) +{ + if (file_writeable(path)) { + StringOutputStream backup(256); + backup << StringRange(path, path_get_extension(path)) << "bak"; - return ( !file_exists( backup.c_str() ) || file_remove( backup.c_str() ) ) // remove backup - && file_move( path, backup.c_str() ); // rename current to backup - } + return (!file_exists(backup.c_str()) || file_remove(backup.c_str())) // remove backup + && file_move(path, backup.c_str()); // rename current to backup + } - globalErrorStream() << "map path is not writeable: " << makeQuoted( path ) << "\n"; - return false; + globalErrorStream() << "map path is not writeable: " << makeQuoted(path) << "\n"; + return false; } -bool MapResource_save( const MapFormat& format, scene::Node& root, const char* path, const char* name ){ - StringOutputStream fullpath( 256 ); - fullpath << path << name; +bool MapResource_save(const MapFormat &format, scene::Node &root, const char *path, const char *name) +{ + StringOutputStream fullpath(256); + fullpath << path << name; - if ( path_is_absolute( fullpath.c_str() ) ) { - if ( !file_exists( fullpath.c_str() ) || file_saveBackup( fullpath.c_str() ) ) { - return MapResource_saveFile( format, root, Map_Traverse, fullpath.c_str() ); - } + if (path_is_absolute(fullpath.c_str())) { + if (!file_exists(fullpath.c_str()) || file_saveBackup(fullpath.c_str())) { + return MapResource_saveFile(format, root, Map_Traverse, fullpath.c_str()); + } - globalErrorStream() << "failed to save a backup map file: " << makeQuoted( fullpath.c_str() ) << "\n"; - return false; - } + globalErrorStream() << "failed to save a backup map file: " << makeQuoted(fullpath.c_str()) << "\n"; + return false; + } - globalErrorStream() << "map path is not fully qualified: " << makeQuoted( fullpath.c_str() ) << "\n"; - return false; + globalErrorStream() << "map path is not fully qualified: " << makeQuoted(fullpath.c_str()) << "\n"; + return false; } -namespace -{ -NodeSmartReference g_nullNode( NewNullNode() ); -NodeSmartReference g_nullModel( g_nullNode ); +namespace { + NodeSmartReference g_nullNode(NewNullNode()); + NodeSmartReference g_nullModel(g_nullNode); } -class NullModelLoader : public ModelLoader -{ +class NullModelLoader : public ModelLoader { public: -scene::Node& loadModel( ArchiveFile& file ){ - return g_nullModel; -} + scene::Node &loadModel(ArchiveFile &file) + { + return g_nullModel; + } }; -namespace -{ -NullModelLoader g_NullModelLoader; +namespace { + NullModelLoader g_NullModelLoader; } /// \brief Returns the model loader for the model \p type or 0 if the model \p type has no loader module -ModelLoader* ModelLoader_forType( const char* type ){ - const char* moduleName = findModuleName( &GlobalFiletypes(), ModelLoader::Name(), type ); - if ( string_not_empty( moduleName ) ) { - ModelLoader* table = ReferenceAPI_getModelModules().findModule( moduleName ); - if ( table != 0 ) { - return table; - } - else - { - globalErrorStream() << "ERROR: Model type incorrectly registered: \"" << moduleName << "\"\n"; - return &g_NullModelLoader; - } - } - return 0; -} - -NodeSmartReference ModelResource_load( ModelLoader* loader, const char* name ){ - ScopeDisableScreenUpdates disableScreenUpdates( path_get_filename_start( name ), "Loading Model" ); +ModelLoader *ModelLoader_forType(const char *type) +{ + const char *moduleName = findModuleName(&GlobalFiletypes(), ModelLoader::Name(), type); + if (string_not_empty(moduleName)) { + ModelLoader *table = ReferenceAPI_getModelModules().findModule(moduleName); + if (table != 0) { + return table; + } else { + globalErrorStream() << "ERROR: Model type incorrectly registered: \"" << moduleName << "\"\n"; + return &g_NullModelLoader; + } + } + return 0; +} + +NodeSmartReference ModelResource_load(ModelLoader *loader, const char *name) +{ + ScopeDisableScreenUpdates disableScreenUpdates(path_get_filename_start(name), "Loading Model"); - NodeSmartReference model( g_nullModel ); + NodeSmartReference model(g_nullModel); - { - ArchiveFile* file = GlobalFileSystem().openFile( name ); + { + ArchiveFile *file = GlobalFileSystem().openFile(name); - if ( file != 0 ) { - globalOutputStream() << "Loaded Model: \"" << name << "\"\n"; - model = loader->loadModel( *file ); - file->release(); - } - else - { - globalErrorStream() << "Model load failed: \"" << name << "\"\n"; - } - } + if (file != 0) { + globalOutputStream() << "Loaded Model: \"" << name << "\"\n"; + model = loader->loadModel(*file); + file->release(); + } else { + globalErrorStream() << "Model load failed: \"" << name << "\"\n"; + } + } - model.get().m_isRoot = true; + model.get().m_isRoot = true; - return model; + return model; } -inline hash_t path_hash( const char* path, hash_t previous = 0 ){ +inline hash_t path_hash(const char *path, hash_t previous = 0) +{ #if GDEF_OS_WINDOWS - return string_hash_nocase( path, previous ); + return string_hash_nocase( path, previous ); #else // UNIX - return string_hash( path, previous ); + return string_hash(path, previous); #endif } -struct PathEqual -{ - bool operator()( const CopiedString& path, const CopiedString& other ) const { - return path_equal( path.c_str(), other.c_str() ); - } +struct PathEqual { + bool operator()(const CopiedString &path, const CopiedString &other) const + { + return path_equal(path.c_str(), other.c_str()); + } }; -struct PathHash -{ - typedef hash_t hash_type; - hash_type operator()( const CopiedString& path ) const { - return path_hash( path.c_str() ); - } +struct PathHash { + typedef hash_t hash_type; + + hash_type operator()(const CopiedString &path) const + { + return path_hash(path.c_str()); + } }; typedef std::pair ModelKey; -struct ModelKeyEqual -{ - bool operator()( const ModelKey& key, const ModelKey& other ) const { - return path_equal( key.first.c_str(), other.first.c_str() ) && path_equal( key.second.c_str(), other.second.c_str() ); - } +struct ModelKeyEqual { + bool operator()(const ModelKey &key, const ModelKey &other) const + { + return path_equal(key.first.c_str(), other.first.c_str()) && + path_equal(key.second.c_str(), other.second.c_str()); + } }; -struct ModelKeyHash -{ - typedef hash_t hash_type; - hash_type operator()( const ModelKey& key ) const { - return hash_combine( path_hash( key.first.c_str() ), path_hash( key.second.c_str() ) ); - } +struct ModelKeyHash { + typedef hash_t hash_type; + + hash_type operator()(const ModelKey &key) const + { + return hash_combine(path_hash(key.first.c_str()), path_hash(key.second.c_str())); + } }; typedef HashTable ModelCache; ModelCache g_modelCache; bool g_modelCache_enabled = true; -ModelCache::iterator ModelCache_find( const char* path, const char* name ){ - if ( g_modelCache_enabled ) { - return g_modelCache.find( ModelKey( path, name ) ); - } - return g_modelCache.end(); -} - -ModelCache::iterator ModelCache_insert( const char* path, const char* name, scene::Node& node ){ - if ( g_modelCache_enabled ) { - return g_modelCache.insert( ModelKey( path, name ), NodeSmartReference( node ) ); - } - return g_modelCache.insert( ModelKey( "", "" ), g_nullModel ); +ModelCache::iterator ModelCache_find(const char *path, const char *name) +{ + if (g_modelCache_enabled) { + return g_modelCache.find(ModelKey(path, name)); + } + return g_modelCache.end(); } -void ModelCache_flush( const char* path, const char* name ){ - ModelCache::iterator i = g_modelCache.find( ModelKey( path, name ) ); - if ( i != g_modelCache.end() ) { - //ASSERT_MESSAGE((*i).value.getCount() == 0, "resource flushed while still in use: " << (*i).key.first.c_str() << (*i).key.second.c_str()); - g_modelCache.erase( i ); - } +ModelCache::iterator ModelCache_insert(const char *path, const char *name, scene::Node &node) +{ + if (g_modelCache_enabled) { + return g_modelCache.insert(ModelKey(path, name), NodeSmartReference(node)); + } + return g_modelCache.insert(ModelKey("", ""), g_nullModel); } -void ModelCache_clear(){ - g_modelCache_enabled = false; - g_modelCache.clear(); - g_modelCache_enabled = true; +void ModelCache_flush(const char *path, const char *name) +{ + ModelCache::iterator i = g_modelCache.find(ModelKey(path, name)); + if (i != g_modelCache.end()) { + //ASSERT_MESSAGE((*i).value.getCount() == 0, "resource flushed while still in use: " << (*i).key.first.c_str() << (*i).key.second.c_str()); + g_modelCache.erase(i); + } } -NodeSmartReference Model_load( ModelLoader* loader, const char* path, const char* name, const char* type ){ - if ( loader != 0 ) { - return ModelResource_load( loader, name ); - } - else - { - const char* moduleName = findModuleName( &GlobalFiletypes(), MapFormat::Name(), type ); - if ( string_not_empty( moduleName ) ) { - const MapFormat* format = ReferenceAPI_getMapModules().findModule( moduleName ); - if ( format != 0 ) { - return MapResource_load( *format, path, name ); - } - else - { - globalErrorStream() << "ERROR: Map type incorrectly registered: \"" << moduleName << "\"\n"; - return g_nullModel; - } - } - else - { - if ( string_not_empty( type ) ) { - globalErrorStream() << "Model type not supported: \"" << name << "\"\n"; - } - return g_nullModel; - } - } +void ModelCache_clear() +{ + g_modelCache_enabled = false; + g_modelCache.clear(); + g_modelCache_enabled = true; } -namespace +NodeSmartReference Model_load(ModelLoader *loader, const char *path, const char *name, const char *type) { -bool g_realised = false; + if (loader != 0) { + return ModelResource_load(loader, name); + } else { + const char *moduleName = findModuleName(&GlobalFiletypes(), MapFormat::Name(), type); + if (string_not_empty(moduleName)) { + const MapFormat *format = ReferenceAPI_getMapModules().findModule(moduleName); + if (format != 0) { + return MapResource_load(*format, path, name); + } else { + globalErrorStream() << "ERROR: Map type incorrectly registered: \"" << moduleName << "\"\n"; + return g_nullModel; + } + } else { + if (string_not_empty(type)) { + globalErrorStream() << "Model type not supported: \"" << name << "\"\n"; + } + return g_nullModel; + } + } +} + +namespace { + bool g_realised = false; // name may be absolute or relative -const char* rootPath( const char* name ){ - return GlobalFileSystem().findRoot( - path_is_absolute( name ) - ? name - : GlobalFileSystem().findFile( name ) - ); -} -} - -struct ModelResource : public Resource -{ - NodeSmartReference m_model; - const CopiedString m_originalName; - CopiedString m_path; - CopiedString m_name; - CopiedString m_type; - ModelLoader* m_loader; - ModuleObservers m_observers; - std::time_t m_modified; - std::size_t m_unrealised; - - ModelResource( const CopiedString& name ) : - m_model( g_nullModel ), - m_originalName( name ), - m_type( path_get_extension( name.c_str() ) ), - m_loader( 0 ), - m_modified( 0 ), - m_unrealised( 1 ){ - m_loader = ModelLoader_forType( m_type.c_str() ); - - if ( g_realised ) { - realise(); - } - } - ~ModelResource(){ - if ( realised() ) { - unrealise(); - } - ASSERT_MESSAGE( !realised(), "ModelResource::~ModelResource: resource reference still realised: " << makeQuoted( m_name.c_str() ) ); - } - // NOT COPYABLE - ModelResource( const ModelResource& ); - // NOT ASSIGNABLE - ModelResource& operator=( const ModelResource& ); - - void setModel( const NodeSmartReference& model ){ - m_model = model; - } - void clearModel(){ - m_model = g_nullModel; - } - - void loadCached(){ - if ( g_modelCache_enabled ) { - // cache lookup - ModelCache::iterator i = ModelCache_find( m_path.c_str(), m_name.c_str() ); - if ( i == g_modelCache.end() ) { - i = ModelCache_insert( - m_path.c_str(), - m_name.c_str(), - Model_load( m_loader, m_path.c_str(), m_name.c_str(), m_type.c_str() ) - ); - } - - setModel( ( *i ).value ); - } - else - { - setModel( Model_load( m_loader, m_path.c_str(), m_name.c_str(), m_type.c_str() ) ); - } - } - - void loadModel(){ - loadCached(); - connectMap(); - mapSave(); - } - - bool load(){ - ASSERT_MESSAGE( realised(), "resource not realised" ); - if ( m_model == g_nullModel ) { - loadModel(); - } - - return m_model != g_nullModel; - } - bool save(){ - if ( !mapSaved() ) { - const char* moduleName = findModuleName( GetFileTypeRegistry(), MapFormat::Name(), m_type.c_str() ); - if ( string_not_empty( moduleName ) ) { - const MapFormat* format = ReferenceAPI_getMapModules().findModule( moduleName ); - if ( format != 0 && MapResource_save( *format, m_model.get(), m_path.c_str(), m_name.c_str() ) ) { - mapSave(); - return true; - } - } - } - return false; - } - void flush(){ - if ( realised() ) { - ModelCache_flush( m_path.c_str(), m_name.c_str() ); - } - } - scene::Node* getNode(){ - //if(m_model != g_nullModel) - { - return m_model.get_pointer(); - } - //return 0; - } - void setNode( scene::Node* node ){ - ModelCache::iterator i = ModelCache_find( m_path.c_str(), m_name.c_str() ); - if ( i != g_modelCache.end() ) { - ( *i ).value = NodeSmartReference( *node ); - } - setModel( NodeSmartReference( *node ) ); - - connectMap(); - } - void attach( ModuleObserver& observer ){ - if ( realised() ) { - observer.realise(); - } - m_observers.attach( observer ); - } - void detach( ModuleObserver& observer ){ - if ( realised() ) { - observer.unrealise(); - } - m_observers.detach( observer ); - } - bool realised(){ - return m_unrealised == 0; - } - void realise(){ - ASSERT_MESSAGE( m_unrealised != 0, "ModelResource::realise: already realised" ); - if ( --m_unrealised == 0 ) { - m_path = rootPath( m_originalName.c_str() ); - m_name = path_make_relative( m_originalName.c_str(), m_path.c_str() ); - - //globalOutputStream() << "ModelResource::realise: " << m_path.c_str() << m_name.c_str() << "\n"; - - m_observers.realise(); - } - } - void unrealise(){ - if ( ++m_unrealised == 1 ) { - m_observers.unrealise(); - - //globalOutputStream() << "ModelResource::unrealise: " << m_path.c_str() << m_name.c_str() << "\n"; - clearModel(); - } - } - bool isMap() const { - return Node_getMapFile( m_model ) != 0; - } - void connectMap(){ - MapFile* map = Node_getMapFile( m_model ); - if ( map != 0 ) { - map->setChangedCallback( makeCallbackF(MapChanged) ); - } - } - std::time_t modified() const { - StringOutputStream fullpath( 256 ); - fullpath << m_path.c_str() << m_name.c_str(); - return file_modified( fullpath.c_str() ); - } - void mapSave(){ - m_modified = modified(); - MapFile* map = Node_getMapFile( m_model ); - if ( map != 0 ) { - map->save(); - } - } - bool mapSaved() const { - MapFile* map = Node_getMapFile( m_model ); - if ( map != 0 ) { - return m_modified == modified() && map->saved(); - } - return true; - } - bool isModified() const { - return ( ( !string_empty( m_path.c_str() ) // had or has an absolute path - && m_modified != modified() ) // AND disk timestamp changed - || !path_equal( rootPath( m_originalName.c_str() ), m_path.c_str() ) ); // OR absolute vfs-root changed - } - void refresh(){ - if ( isModified() ) { - flush(); - unrealise(); - realise(); - } - } + const char *rootPath(const char *name) + { + return GlobalFileSystem().findRoot( + path_is_absolute(name) + ? name + : GlobalFileSystem().findFile(name) + ); + } +} + +struct ModelResource : public Resource { + NodeSmartReference m_model; + const CopiedString m_originalName; + CopiedString m_path; + CopiedString m_name; + CopiedString m_type; + ModelLoader *m_loader; + ModuleObservers m_observers; + std::time_t m_modified; + std::size_t m_unrealised; + + ModelResource(const CopiedString &name) : + m_model(g_nullModel), + m_originalName(name), + m_type(path_get_extension(name.c_str())), + m_loader(0), + m_modified(0), + m_unrealised(1) + { + m_loader = ModelLoader_forType(m_type.c_str()); + + if (g_realised) { + realise(); + } + } + + ~ModelResource() + { + if (realised()) { + unrealise(); + } + ASSERT_MESSAGE(!realised(), "ModelResource::~ModelResource: resource reference still realised: " + << makeQuoted(m_name.c_str())); + } + + // NOT COPYABLE + ModelResource(const ModelResource &); + + // NOT ASSIGNABLE + ModelResource &operator=(const ModelResource &); + + void setModel(const NodeSmartReference &model) + { + m_model = model; + } + + void clearModel() + { + m_model = g_nullModel; + } + + void loadCached() + { + if (g_modelCache_enabled) { + // cache lookup + ModelCache::iterator i = ModelCache_find(m_path.c_str(), m_name.c_str()); + if (i == g_modelCache.end()) { + i = ModelCache_insert( + m_path.c_str(), + m_name.c_str(), + Model_load(m_loader, m_path.c_str(), m_name.c_str(), m_type.c_str()) + ); + } + + setModel((*i).value); + } else { + setModel(Model_load(m_loader, m_path.c_str(), m_name.c_str(), m_type.c_str())); + } + } + + void loadModel() + { + loadCached(); + connectMap(); + mapSave(); + } + + bool load() + { + ASSERT_MESSAGE(realised(), "resource not realised"); + if (m_model == g_nullModel) { + loadModel(); + } + + return m_model != g_nullModel; + } + + bool save() + { + if (!mapSaved()) { + const char *moduleName = findModuleName(GetFileTypeRegistry(), MapFormat::Name(), m_type.c_str()); + if (string_not_empty(moduleName)) { + const MapFormat *format = ReferenceAPI_getMapModules().findModule(moduleName); + if (format != 0 && MapResource_save(*format, m_model.get(), m_path.c_str(), m_name.c_str())) { + mapSave(); + return true; + } + } + } + return false; + } + + void flush() + { + if (realised()) { + ModelCache_flush(m_path.c_str(), m_name.c_str()); + } + } + + scene::Node *getNode() + { + //if(m_model != g_nullModel) + { + return m_model.get_pointer(); + } + //return 0; + } + + void setNode(scene::Node *node) + { + ModelCache::iterator i = ModelCache_find(m_path.c_str(), m_name.c_str()); + if (i != g_modelCache.end()) { + (*i).value = NodeSmartReference(*node); + } + setModel(NodeSmartReference(*node)); + + connectMap(); + } + + void attach(ModuleObserver &observer) + { + if (realised()) { + observer.realise(); + } + m_observers.attach(observer); + } + + void detach(ModuleObserver &observer) + { + if (realised()) { + observer.unrealise(); + } + m_observers.detach(observer); + } + + bool realised() + { + return m_unrealised == 0; + } + + void realise() + { + ASSERT_MESSAGE(m_unrealised != 0, "ModelResource::realise: already realised"); + if (--m_unrealised == 0) { + m_path = rootPath(m_originalName.c_str()); + m_name = path_make_relative(m_originalName.c_str(), m_path.c_str()); + + //globalOutputStream() << "ModelResource::realise: " << m_path.c_str() << m_name.c_str() << "\n"; + + m_observers.realise(); + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + m_observers.unrealise(); + + //globalOutputStream() << "ModelResource::unrealise: " << m_path.c_str() << m_name.c_str() << "\n"; + clearModel(); + } + } + + bool isMap() const + { + return Node_getMapFile(m_model) != 0; + } + + void connectMap() + { + MapFile *map = Node_getMapFile(m_model); + if (map != 0) { + map->setChangedCallback(makeCallbackF(MapChanged)); + } + } + + std::time_t modified() const + { + StringOutputStream fullpath(256); + fullpath << m_path.c_str() << m_name.c_str(); + return file_modified(fullpath.c_str()); + } + + void mapSave() + { + m_modified = modified(); + MapFile *map = Node_getMapFile(m_model); + if (map != 0) { + map->save(); + } + } + + bool mapSaved() const + { + MapFile *map = Node_getMapFile(m_model); + if (map != 0) { + return m_modified == modified() && map->saved(); + } + return true; + } + + bool isModified() const + { + return ((!string_empty(m_path.c_str()) // had or has an absolute path + && m_modified != modified()) // AND disk timestamp changed + || !path_equal(rootPath(m_originalName.c_str()), m_path.c_str())); // OR absolute vfs-root changed + } + + void refresh() + { + if (isModified()) { + flush(); + unrealise(); + realise(); + } + } }; -class HashtableReferenceCache : public ReferenceCache, public ModuleObserver -{ -typedef HashedCache ModelReferences; -ModelReferences m_references; -std::size_t m_unrealised; - -class ModelReferencesSnapshot -{ -ModelReferences& m_references; -typedef std::list Iterators; -Iterators m_iterators; -public: -typedef Iterators::iterator iterator; -ModelReferencesSnapshot( ModelReferences& references ) : m_references( references ){ - for ( ModelReferences::iterator i = m_references.begin(); i != m_references.end(); ++i ) - { - m_references.capture( i ); - m_iterators.push_back( i ); - } -} -~ModelReferencesSnapshot(){ - for ( Iterators::iterator i = m_iterators.begin(); i != m_iterators.end(); ++i ) - { - m_references.release( *i ); - } -} -iterator begin(){ - return m_iterators.begin(); -} -iterator end(){ - return m_iterators.end(); -} -}; +class HashtableReferenceCache : public ReferenceCache, public ModuleObserver { + typedef HashedCache ModelReferences; + ModelReferences m_references; + std::size_t m_unrealised; + + class ModelReferencesSnapshot { + ModelReferences &m_references; + typedef std::list Iterators; + Iterators m_iterators; + public: + typedef Iterators::iterator iterator; + + ModelReferencesSnapshot(ModelReferences &references) : m_references(references) + { + for (ModelReferences::iterator i = m_references.begin(); i != m_references.end(); ++i) { + m_references.capture(i); + m_iterators.push_back(i); + } + } + + ~ModelReferencesSnapshot() + { + for (Iterators::iterator i = m_iterators.begin(); i != m_iterators.end(); ++i) { + m_references.release(*i); + } + } + + iterator begin() + { + return m_iterators.begin(); + } + + iterator end() + { + return m_iterators.end(); + } + }; public: -typedef ModelReferences::iterator iterator; - -HashtableReferenceCache() : m_unrealised( 1 ){ -} - -iterator begin(){ - return m_references.begin(); -} -iterator end(){ - return m_references.end(); -} - -void clear(){ - m_references.clear(); -} - -Resource* capture( const char* path ){ - //globalOutputStream() << "capture: \"" << path << "\"\n"; - return m_references.capture( CopiedString( path ) ).get(); -} -void release( const char* path ){ - m_references.release( CopiedString( path ) ); - //globalOutputStream() << "release: \"" << path << "\"\n"; -} - -void setEntityCreator( EntityCreator& entityCreator ){ - g_entityCreator = &entityCreator; -} - -bool realised() const { - return m_unrealised == 0; -} -void realise(){ - ASSERT_MESSAGE( m_unrealised != 0, "HashtableReferenceCache::realise: already realised" ); - if ( --m_unrealised == 0 ) { - g_realised = true; - - { - ModelReferencesSnapshot snapshot( m_references ); - for ( ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i ) - { - ModelReferences::value_type& value = *( *i ); - if ( value.value.count() != 1 ) { - value.value.get()->realise(); - } - } - } - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - g_realised = false; - - { - ModelReferencesSnapshot snapshot( m_references ); - for ( ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i ) - { - ModelReferences::value_type& value = *( *i ); - if ( value.value.count() != 1 ) { - value.value.get()->unrealise(); - } - } - } - - ModelCache_clear(); - } -} -void refresh(){ - ModelReferencesSnapshot snapshot( m_references ); - for ( ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i ) - { - ModelResource* resource = ( *( *i ) ).value.get(); - if ( !resource->isMap() ) { - resource->refresh(); - } - } -} + typedef ModelReferences::iterator iterator; + + HashtableReferenceCache() : m_unrealised(1) + { + } + + iterator begin() + { + return m_references.begin(); + } + + iterator end() + { + return m_references.end(); + } + + void clear() + { + m_references.clear(); + } + + Resource *capture(const char *path) + { + //globalOutputStream() << "capture: \"" << path << "\"\n"; + return m_references.capture(CopiedString(path)).get(); + } + + void release(const char *path) + { + m_references.release(CopiedString(path)); + //globalOutputStream() << "release: \"" << path << "\"\n"; + } + + void setEntityCreator(EntityCreator &entityCreator) + { + g_entityCreator = &entityCreator; + } + + bool realised() const + { + return m_unrealised == 0; + } + + void realise() + { + ASSERT_MESSAGE(m_unrealised != 0, "HashtableReferenceCache::realise: already realised"); + if (--m_unrealised == 0) { + g_realised = true; + + { + ModelReferencesSnapshot snapshot(m_references); + for (ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i) { + ModelReferences::value_type &value = *(*i); + if (value.value.count() != 1) { + value.value.get()->realise(); + } + } + } + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + g_realised = false; + + { + ModelReferencesSnapshot snapshot(m_references); + for (ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i) { + ModelReferences::value_type &value = *(*i); + if (value.value.count() != 1) { + value.value.get()->unrealise(); + } + } + } + + ModelCache_clear(); + } + } + + void refresh() + { + ModelReferencesSnapshot snapshot(m_references); + for (ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i) { + ModelResource *resource = (*(*i)).value.get(); + if (!resource->isMap()) { + resource->refresh(); + } + } + } }; -namespace -{ -HashtableReferenceCache g_referenceCache; +namespace { + HashtableReferenceCache g_referenceCache; } #if 0 @@ -632,46 +694,49 @@ class ResourceVisitor { public: virtual void visit( const char* name, const char* path, const - }; + }; #endif -void SaveReferences(){ - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Saving Map" ); - for ( HashtableReferenceCache::iterator i = g_referenceCache.begin(); i != g_referenceCache.end(); ++i ) - { - ( *i ).value->save(); - } - MapChanged(); -} - -bool References_Saved(){ - for ( HashtableReferenceCache::iterator i = g_referenceCache.begin(); i != g_referenceCache.end(); ++i ) - { - scene::Node* node = ( *i ).value->getNode(); - if ( node != 0 ) { - MapFile* map = Node_getMapFile( *node ); - if ( map != 0 && !map->saved() ) { - return false; - } - } - } - return true; +void SaveReferences() +{ + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Saving Map"); + for (HashtableReferenceCache::iterator i = g_referenceCache.begin(); i != g_referenceCache.end(); ++i) { + (*i).value->save(); + } + MapChanged(); } -void RefreshReferences(){ - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Refreshing Models" ); - g_referenceCache.refresh(); +bool References_Saved() +{ + for (HashtableReferenceCache::iterator i = g_referenceCache.begin(); i != g_referenceCache.end(); ++i) { + scene::Node *node = (*i).value->getNode(); + if (node != 0) { + MapFile *map = Node_getMapFile(*node); + if (map != 0 && !map->saved()) { + return false; + } + } + } + return true; +} + +void RefreshReferences() +{ + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Refreshing Models"); + g_referenceCache.refresh(); } -void FlushReferences(){ - ModelCache_clear(); +void FlushReferences() +{ + ModelCache_clear(); - g_referenceCache.clear(); + g_referenceCache.clear(); } -ReferenceCache& GetReferenceCache(){ - return g_referenceCache; +ReferenceCache &GetReferenceCache() +{ + return g_referenceCache; } @@ -680,57 +745,68 @@ ReferenceCache& GetReferenceCache(){ #include "modulesystem/moduleregistry.h" class ReferenceDependencies : - public GlobalRadiantModuleRef, - public GlobalFileSystemModuleRef, - public GlobalFiletypesModuleRef -{ -ModelModulesRef m_model_modules; -MapModulesRef m_map_modules; + public GlobalRadiantModuleRef, + public GlobalFileSystemModuleRef, + public GlobalFiletypesModuleRef { + ModelModulesRef m_model_modules; + MapModulesRef m_map_modules; public: -ReferenceDependencies() : - m_model_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "modeltypes" ) ), - m_map_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "maptypes" ) ) -{ -} -ModelModules& getModelModules(){ - return m_model_modules.get(); -} -MapModules& getMapModules(){ - return m_map_modules.get(); -} + ReferenceDependencies() : + m_model_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("modeltypes")), + m_map_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("maptypes")) + { + } + + ModelModules &getModelModules() + { + return m_model_modules.get(); + } + + MapModules &getMapModules() + { + return m_map_modules.get(); + } }; -class ReferenceAPI : public TypeSystemRef -{ -ReferenceCache* m_reference; +class ReferenceAPI : public TypeSystemRef { + ReferenceCache *m_reference; public: -typedef ReferenceCache Type; -STRING_CONSTANT( Name, "*" ); + typedef ReferenceCache Type; -ReferenceAPI(){ - g_nullModel = NewNullModel(); + STRING_CONSTANT(Name, "*"); - GlobalFileSystem().attach( g_referenceCache ); + ReferenceAPI() + { + g_nullModel = NewNullModel(); - m_reference = &GetReferenceCache(); -} -~ReferenceAPI(){ - GlobalFileSystem().detach( g_referenceCache ); + GlobalFileSystem().attach(g_referenceCache); - g_nullModel = g_nullNode; -} -ReferenceCache* getTable(){ - return m_reference; -} + m_reference = &GetReferenceCache(); + } + + ~ReferenceAPI() + { + GlobalFileSystem().detach(g_referenceCache); + + g_nullModel = g_nullNode; + } + + ReferenceCache *getTable() + { + return m_reference; + } }; typedef SingletonModule ReferenceModule; typedef Static StaticReferenceModule; -StaticRegisterModule staticRegisterReference( StaticReferenceModule::instance() ); +StaticRegisterModule staticRegisterReference(StaticReferenceModule::instance()); -ModelModules& ReferenceAPI_getModelModules(){ - return StaticReferenceModule::instance().getDependencies().getModelModules(); +ModelModules &ReferenceAPI_getModelModules() +{ + return StaticReferenceModule::instance().getDependencies().getModelModules(); } -MapModules& ReferenceAPI_getMapModules(){ - return StaticReferenceModule::instance().getDependencies().getMapModules( ); + +MapModules &ReferenceAPI_getMapModules() +{ + return StaticReferenceModule::instance().getDependencies().getMapModules(); } diff --git a/radiant/referencecache.h b/radiant/referencecache.h index eac4fc7c..92d5dc89 100644 --- a/radiant/referencecache.h +++ b/radiant/referencecache.h @@ -24,19 +24,23 @@ /// \brief Saves all open resource references if they differ from the version on disk. void SaveReferences(); + /// \brief Flushes the cache of resource references. All resource references must be released before calling this. void FlushReferences(); + /// \brief Reloads all resource references that differ from the version on disk. void RefreshReferences(); #include "iscenegraph.h" -namespace scene -{ -class Node; + +namespace scene { + class Node; } class MapFormat; -typedef void ( *GraphTraversalFunc )( scene::Node& root, const scene::Traversable::Walker& walker ); -bool MapResource_saveFile( const MapFormat& format, scene::Node& root, GraphTraversalFunc traverse, const char* filename ); +typedef void ( *GraphTraversalFunc )(scene::Node &root, const scene::Traversable::Walker &walker); + +bool +MapResource_saveFile(const MapFormat &format, scene::Node &root, GraphTraversalFunc traverse, const char *filename); #endif diff --git a/radiant/renderer.h b/radiant/renderer.h index c67cf0ea..4b14f33b 100644 --- a/radiant/renderer.h +++ b/radiant/renderer.h @@ -30,143 +30,159 @@ #include "math/frustum.h" #include -inline Cullable* Instance_getCullable( scene::Instance& instance ){ - return InstanceTypeCast::cast( instance ); +inline Cullable *Instance_getCullable(scene::Instance &instance) +{ + return InstanceTypeCast::cast(instance); } -inline Renderable* Instance_getRenderable( scene::Instance& instance ){ - return InstanceTypeCast::cast( instance ); +inline Renderable *Instance_getRenderable(scene::Instance &instance) +{ + return InstanceTypeCast::cast(instance); } -inline VolumeIntersectionValue Cullable_testVisible( scene::Instance& instance, const VolumeTest& volume, VolumeIntersectionValue parentVisible ){ - if ( parentVisible == c_volumePartial ) { - Cullable* cullable = Instance_getCullable( instance ); - if ( cullable != 0 ) { - return cullable->intersectVolume( volume, instance.localToWorld() ); - } - } - return parentVisible; +inline VolumeIntersectionValue +Cullable_testVisible(scene::Instance &instance, const VolumeTest &volume, VolumeIntersectionValue parentVisible) +{ + if (parentVisible == c_volumePartial) { + Cullable *cullable = Instance_getCullable(instance); + if (cullable != 0) { + return cullable->intersectVolume(volume, instance.localToWorld()); + } + } + return parentVisible; } template -class CullingWalker -{ -const VolumeTest& m_volume; -const _Walker& m_walker; +class CullingWalker { + const VolumeTest &m_volume; + const _Walker &m_walker; public: -CullingWalker( const VolumeTest& volume, const _Walker& walker ) - : m_volume( volume ), m_walker( walker ){ -} -bool pre( const scene::Path& path, scene::Instance& instance, VolumeIntersectionValue parentVisible ) const { - VolumeIntersectionValue visible = Cullable_testVisible( instance, m_volume, parentVisible ); - if ( visible != c_volumeOutside ) { - return m_walker.pre( path, instance ); - } - return true; -} -void post( const scene::Path& path, scene::Instance& instance, VolumeIntersectionValue parentVisible ) const { - return m_walker.post( path, instance ); -} + CullingWalker(const VolumeTest &volume, const _Walker &walker) + : m_volume(volume), m_walker(walker) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance, VolumeIntersectionValue parentVisible) const + { + VolumeIntersectionValue visible = Cullable_testVisible(instance, m_volume, parentVisible); + if (visible != c_volumeOutside) { + return m_walker.pre(path, instance); + } + return true; + } + + void post(const scene::Path &path, scene::Instance &instance, VolumeIntersectionValue parentVisible) const + { + return m_walker.post(path, instance); + } }; template -class ForEachVisible : public scene::Graph::Walker -{ -const VolumeTest& m_volume; -const Walker_& m_walker; -mutable std::vector m_state; +class ForEachVisible : public scene::Graph::Walker { + const VolumeTest &m_volume; + const Walker_ &m_walker; + mutable std::vector m_state; public: -ForEachVisible( const VolumeTest& volume, const Walker_& walker ) - : m_volume( volume ), m_walker( walker ){ - m_state.push_back( c_volumePartial ); -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - VolumeIntersectionValue visible = ( path.top().get().visible() ) ? m_state.back() : c_volumeOutside; - - if ( visible == c_volumePartial ) { - visible = m_volume.TestAABB( instance.worldAABB() ); - } - - m_state.push_back( visible ); - - if ( visible == c_volumeOutside ) { - return false; - } - else - { - return m_walker.pre( path, instance, m_state.back() ); - } -} -void post( const scene::Path& path, scene::Instance& instance ) const { - if ( m_state.back() != c_volumeOutside ) { - m_walker.post( path, instance, m_state.back() ); - } - - m_state.pop_back(); -} + ForEachVisible(const VolumeTest &volume, const Walker_ &walker) + : m_volume(volume), m_walker(walker) + { + m_state.push_back(c_volumePartial); + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + VolumeIntersectionValue visible = (path.top().get().visible()) ? m_state.back() : c_volumeOutside; + + if (visible == c_volumePartial) { + visible = m_volume.TestAABB(instance.worldAABB()); + } + + m_state.push_back(visible); + + if (visible == c_volumeOutside) { + return false; + } else { + return m_walker.pre(path, instance, m_state.back()); + } + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + if (m_state.back() != c_volumeOutside) { + m_walker.post(path, instance, m_state.back()); + } + + m_state.pop_back(); + } }; template -inline void Scene_forEachVisible( scene::Graph& graph, const VolumeTest& volume, const Functor& functor ){ - graph.traverse( ForEachVisible< CullingWalker >( volume, CullingWalker( volume, functor ) ) ); +inline void Scene_forEachVisible(scene::Graph &graph, const VolumeTest &volume, const Functor &functor) +{ + graph.traverse(ForEachVisible >(volume, CullingWalker(volume, functor))); } -class RenderHighlighted -{ -Renderer& m_renderer; -const VolumeTest& m_volume; +class RenderHighlighted { + Renderer &m_renderer; + const VolumeTest &m_volume; public: -RenderHighlighted( Renderer& renderer, const VolumeTest& volume ) - : m_renderer( renderer ), m_volume( volume ){ -} -void render( const Renderable& renderable ) const { - switch ( m_renderer.getStyle() ) - { - case Renderer::eFullMaterials: - renderable.renderSolid( m_renderer, m_volume ); - break; - case Renderer::eWireframeOnly: - renderable.renderWireframe( m_renderer, m_volume ); - break; - } -} -typedef ConstMemberCaller RenderCaller; - -bool pre( const scene::Path& path, scene::Instance& instance, VolumeIntersectionValue parentVisible ) const { - m_renderer.PushState(); - - if ( Cullable_testVisible( instance, m_volume, parentVisible ) != c_volumeOutside ) { - Renderable* renderable = Instance_getRenderable( instance ); - if ( renderable ) { - renderable->viewChanged(); - } - - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 && selectable->isSelected() ) { - if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { - m_renderer.Highlight( Renderer::eFace ); - } - else if ( renderable ) { - renderable->renderComponents( m_renderer, m_volume ); - } - m_renderer.Highlight( Renderer::ePrimitive ); - } - - if ( renderable ) { - render( *renderable ); - } - } - - return true; -} -void post( const scene::Path& path, scene::Instance& instance, VolumeIntersectionValue parentVisible ) const { - m_renderer.PopState(); -} + RenderHighlighted(Renderer &renderer, const VolumeTest &volume) + : m_renderer(renderer), m_volume(volume) + { + } + + void render(const Renderable &renderable) const + { + switch (m_renderer.getStyle()) { + case Renderer::eFullMaterials: + renderable.renderSolid(m_renderer, m_volume); + break; + case Renderer::eWireframeOnly: + renderable.renderWireframe(m_renderer, m_volume); + break; + } + } + + typedef ConstMemberCaller RenderCaller; + + bool pre(const scene::Path &path, scene::Instance &instance, VolumeIntersectionValue parentVisible) const + { + m_renderer.PushState(); + + if (Cullable_testVisible(instance, m_volume, parentVisible) != c_volumeOutside) { + Renderable *renderable = Instance_getRenderable(instance); + if (renderable) { + renderable->viewChanged(); + } + + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 && selectable->isSelected()) { + if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) { + m_renderer.Highlight(Renderer::eFace); + } else if (renderable) { + renderable->renderComponents(m_renderer, m_volume); + } + m_renderer.Highlight(Renderer::ePrimitive); + } + + if (renderable) { + render(*renderable); + } + } + + return true; + } + + void post(const scene::Path &path, scene::Instance &instance, VolumeIntersectionValue parentVisible) const + { + m_renderer.PopState(); + } }; -inline void Scene_Render( Renderer& renderer, const VolumeTest& volume ){ - GlobalSceneGraph().traverse( ForEachVisible( volume, RenderHighlighted( renderer, volume ) ) ); - GlobalShaderCache().forEachRenderable( RenderHighlighted::RenderCaller( RenderHighlighted( renderer, volume ) ) ); +inline void Scene_Render(Renderer &renderer, const VolumeTest &volume) +{ + GlobalSceneGraph().traverse(ForEachVisible(volume, RenderHighlighted(renderer, volume))); + GlobalShaderCache().forEachRenderable(RenderHighlighted::RenderCaller(RenderHighlighted(renderer, volume))); } #endif diff --git a/radiant/renderstate.cpp b/radiant/renderstate.cpp index 9dc8e2de..faa04502 100644 --- a/radiant/renderstate.cpp +++ b/radiant/renderstate.cpp @@ -54,24 +54,26 @@ #include "xywindow.h" - #define DEBUG_RENDER 0 -inline void debug_string( const char* string ){ +inline void debug_string(const char *string) +{ #if (DEBUG_RENDER) - globalOutputStream() << string << "\n"; + globalOutputStream() << string << "\n"; #endif } -inline void debug_int( const char* comment, int i ){ +inline void debug_int(const char *comment, int i) +{ #if (DEBUG_RENDER) - globalOutputStream() << comment << " " << i << "\n"; + globalOutputStream() << comment << " " << i << "\n"; #endif } -inline void debug_colour( const char* comment ){ -#if ( DEBUG_RENDER ) - Vector4 v; +inline void debug_colour(const char *comment) +{ +#if (DEBUG_RENDER) + Vector4 v; glGetFloatv( GL_CURRENT_COLOR, reinterpret_cast( &v ) ); globalOutputStream() << comment << " colour: " << v[0] << " " @@ -96,275 +98,298 @@ std::size_t g_count_states; std::size_t g_count_transforms; Timer g_timer; -inline void count_prim(){ - ++g_count_prims; +inline void count_prim() +{ + ++g_count_prims; } -inline void count_state(){ - ++g_count_states; +inline void count_state() +{ + ++g_count_states; } -inline void count_transform(){ - ++g_count_transforms; +inline void count_transform() +{ + ++g_count_transforms; } -void Renderer_ResetStats(){ - g_count_prims = 0; - g_count_states = 0; - g_count_transforms = 0; - g_timer.start(); +void Renderer_ResetStats() +{ + g_count_prims = 0; + g_count_states = 0; + g_count_transforms = 0; + g_timer.start(); } -const char* Renderer_GetStats(){ - g_renderer_stats.clear(); - g_renderer_stats << "prims: " << Unsigned( g_count_prims ) - << " | states: " << Unsigned( g_count_states ) - << " | transforms: " << Unsigned( g_count_transforms ) - << " | msec: " << g_timer.elapsed_msec(); - return g_renderer_stats.c_str(); +const char *Renderer_GetStats() +{ + g_renderer_stats.clear(); + g_renderer_stats << "prims: " << Unsigned(g_count_prims) + << " | states: " << Unsigned(g_count_states) + << " | transforms: " << Unsigned(g_count_transforms) + << " | msec: " << g_timer.elapsed_msec(); + return g_renderer_stats.c_str(); } -void printShaderLog( GLhandleARB object ){ - GLint log_length = 0; - glGetObjectParameterivARB( object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length ); +void printShaderLog(GLhandleARB object) +{ + GLint log_length = 0; + glGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length); - Array log( log_length ); - glGetInfoLogARB( object, log_length, &log_length, log.data() ); + Array log(log_length); + glGetInfoLogARB(object, log_length, &log_length, log.data()); - globalErrorStream() << StringRange( log.begin(), log.begin() + log_length ) << "\n"; + globalErrorStream() << StringRange(log.begin(), log.begin() + log_length) << "\n"; } -void createShader( GLhandleARB program, const char* filename, GLenum type ){ - GLhandleARB shader = glCreateShaderObjectARB( type ); - GlobalOpenGL_debugAssertNoErrors(); +void createShader(GLhandleARB program, const char *filename, GLenum type) +{ + GLhandleARB shader = glCreateShaderObjectARB(type); + GlobalOpenGL_debugAssertNoErrors(); - // load shader - { - std::size_t size = file_size( filename ); - FileInputStream file( filename ); - ASSERT_MESSAGE( !file.failed(), "failed to open " << makeQuoted( filename ) ); - Array buffer( size ); - size = file.read( reinterpret_cast( buffer.data() ), size ); - - const GLcharARB* string = buffer.data(); - GLint length = GLint( size ); - glShaderSourceARB( shader, 1, &string, &length ); - } + // load shader + { + std::size_t size = file_size(filename); + FileInputStream file(filename); + ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename)); + Array buffer(size); + size = file.read(reinterpret_cast( buffer.data()), size); - // compile shader - { - glCompileShaderARB( shader ); + const GLcharARB *string = buffer.data(); + GLint length = GLint(size); + glShaderSourceARB(shader, 1, &string, &length); + } - GLint compiled = 0; - glGetObjectParameterivARB( shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled ); + // compile shader + { + glCompileShaderARB(shader); - if ( !compiled ) { - printShaderLog( shader ); - } + GLint compiled = 0; + glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); - ASSERT_MESSAGE( compiled, "shader compile failed: " << makeQuoted( filename ) ); - } + if (!compiled) { + printShaderLog(shader); + } - // attach shader - glAttachObjectARB( program, shader ); + ASSERT_MESSAGE(compiled, "shader compile failed: " << makeQuoted(filename)); + } - glDeleteObjectARB( shader ); + // attach shader + glAttachObjectARB(program, shader); - GlobalOpenGL_debugAssertNoErrors(); + glDeleteObjectARB(shader); + + GlobalOpenGL_debugAssertNoErrors(); } -void GLSLProgram_link( GLhandleARB program ){ - glLinkProgramARB( program ); +void GLSLProgram_link(GLhandleARB program) +{ + glLinkProgramARB(program); - GLint linked = false; - glGetObjectParameterivARB( program, GL_OBJECT_LINK_STATUS_ARB, &linked ); + GLint linked = false; + glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked); - if ( !linked ) { - printShaderLog( program ); - } + if (!linked) { + printShaderLog(program); + } - ASSERT_MESSAGE( linked, "program link failed" ); + ASSERT_MESSAGE(linked, "program link failed"); } -void GLSLProgram_validate( GLhandleARB program ){ - glValidateProgramARB( program ); +void GLSLProgram_validate(GLhandleARB program) +{ + glValidateProgramARB(program); - GLint validated = false; - glGetObjectParameterivARB( program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated ); + GLint validated = false; + glGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated); - if ( !validated ) { - printShaderLog( program ); - } + if (!validated) { + printShaderLog(program); + } - ASSERT_MESSAGE( validated, "program validation failed" ); + ASSERT_MESSAGE(validated, "program validation failed"); } bool g_bumpGLSLPass_enabled = false; bool g_depthfillPass_enabled = false; -class GLSLBumpProgram : public GLProgram -{ +class GLSLBumpProgram : public GLProgram { public: -GLhandleARB m_program; -qtexture_t* m_light_attenuation_xy; -qtexture_t* m_light_attenuation_z; -GLint u_view_origin; -GLint u_light_origin; -GLint u_light_color; -GLint u_bump_scale; -GLint u_specular_exponent; - -GLSLBumpProgram() : m_program( 0 ), m_light_attenuation_xy( 0 ), m_light_attenuation_z( 0 ){ -} - -void create(){ - // create program - m_program = glCreateProgramObjectARB(); - - // create shader - { - StringOutputStream filename( 256 ); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl"; - createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB ); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl"; - createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB ); - } + GLhandleARB m_program; + qtexture_t *m_light_attenuation_xy; + qtexture_t *m_light_attenuation_z; + GLint u_view_origin; + GLint u_light_origin; + GLint u_light_color; + GLint u_bump_scale; + GLint u_specular_exponent; + + GLSLBumpProgram() : m_program(0), m_light_attenuation_xy(0), m_light_attenuation_z(0) + { + } + + void create() + { + // create program + m_program = glCreateProgramObjectARB(); + + // create shader + { + StringOutputStream filename(256); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl"; + createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl"; + createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB); + } + + GLSLProgram_link(m_program); + GLSLProgram_validate(m_program); + + glUseProgramObjectARB(m_program); + + glBindAttribLocationARB(m_program, c_attr_TexCoord0, "attr_TexCoord0"); + glBindAttribLocationARB(m_program, c_attr_Tangent, "attr_Tangent"); + glBindAttribLocationARB(m_program, c_attr_Binormal, "attr_Binormal"); + + glUniform1iARB(glGetUniformLocationARB(m_program, "u_diffusemap"), 0); + glUniform1iARB(glGetUniformLocationARB(m_program, "u_bumpmap"), 1); + glUniform1iARB(glGetUniformLocationARB(m_program, "u_specularmap"), 2); + glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_xy"), 3); + glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_z"), 4); + + u_view_origin = glGetUniformLocationARB(m_program, "u_view_origin"); + u_light_origin = glGetUniformLocationARB(m_program, "u_light_origin"); + u_light_color = glGetUniformLocationARB(m_program, "u_light_color"); + u_bump_scale = glGetUniformLocationARB(m_program, "u_bump_scale"); + u_specular_exponent = glGetUniformLocationARB(m_program, "u_specular_exponent"); + + glUseProgramObjectARB(0); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void destroy() + { + glDeleteObjectARB(m_program); + m_program = 0; + } + + void enable() + { + glUseProgramObjectARB(m_program); + + glEnableVertexAttribArrayARB(c_attr_TexCoord0); + glEnableVertexAttribArrayARB(c_attr_Tangent); + glEnableVertexAttribArrayARB(c_attr_Binormal); + + GlobalOpenGL_debugAssertNoErrors(); + + debug_string("enable bump"); + g_bumpGLSLPass_enabled = true; + } + + void disable() + { + glUseProgramObjectARB(0); + + glDisableVertexAttribArrayARB(c_attr_TexCoord0); + glDisableVertexAttribArrayARB(c_attr_Tangent); + glDisableVertexAttribArrayARB(c_attr_Binormal); + + GlobalOpenGL_debugAssertNoErrors(); + + debug_string("disable bump"); + g_bumpGLSLPass_enabled = false; + } + + void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, + const Matrix4 &world2light) + { + Matrix4 world2local(localToWorld); + matrix4_affine_invert(world2local); + + Vector3 localLight(origin); + matrix4_transform_point(world2local, localLight); + + Vector3 localViewer(viewer); + matrix4_transform_point(world2local, localViewer); + + Matrix4 local2light(world2light); + matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light + + glUniform3fARB(u_view_origin, localViewer.x(), localViewer.y(), localViewer.z()); + glUniform3fARB(u_light_origin, localLight.x(), localLight.y(), localLight.z()); + glUniform3fARB(u_light_color, colour.x(), colour.y(), colour.z()); + glUniform1fARB(u_bump_scale, 1.0); + glUniform1fARB(u_specular_exponent, 32.0); - GLSLProgram_link( m_program ); - GLSLProgram_validate( m_program ); + glActiveTexture(GL_TEXTURE3); + glClientActiveTexture(GL_TEXTURE3); - glUseProgramObjectARB( m_program ); - - glBindAttribLocationARB( m_program, c_attr_TexCoord0, "attr_TexCoord0" ); - glBindAttribLocationARB( m_program, c_attr_Tangent, "attr_Tangent" ); - glBindAttribLocationARB( m_program, c_attr_Binormal, "attr_Binormal" ); - - glUniform1iARB( glGetUniformLocationARB( m_program, "u_diffusemap" ), 0 ); - glUniform1iARB( glGetUniformLocationARB( m_program, "u_bumpmap" ), 1 ); - glUniform1iARB( glGetUniformLocationARB( m_program, "u_specularmap" ), 2 ); - glUniform1iARB( glGetUniformLocationARB( m_program, "u_attenuationmap_xy" ), 3 ); - glUniform1iARB( glGetUniformLocationARB( m_program, "u_attenuationmap_z" ), 4 ); - - u_view_origin = glGetUniformLocationARB( m_program, "u_view_origin" ); - u_light_origin = glGetUniformLocationARB( m_program, "u_light_origin" ); - u_light_color = glGetUniformLocationARB( m_program, "u_light_color" ); - u_bump_scale = glGetUniformLocationARB( m_program, "u_bump_scale" ); - u_specular_exponent = glGetUniformLocationARB( m_program, "u_specular_exponent" ); - - glUseProgramObjectARB( 0 ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void destroy(){ - glDeleteObjectARB( m_program ); - m_program = 0; -} - -void enable(){ - glUseProgramObjectARB( m_program ); - - glEnableVertexAttribArrayARB( c_attr_TexCoord0 ); - glEnableVertexAttribArrayARB( c_attr_Tangent ); - glEnableVertexAttribArrayARB( c_attr_Binormal ); - - GlobalOpenGL_debugAssertNoErrors(); - - debug_string( "enable bump" ); - g_bumpGLSLPass_enabled = true; -} - -void disable(){ - glUseProgramObjectARB( 0 ); - - glDisableVertexAttribArrayARB( c_attr_TexCoord0 ); - glDisableVertexAttribArrayARB( c_attr_Tangent ); - glDisableVertexAttribArrayARB( c_attr_Binormal ); - - GlobalOpenGL_debugAssertNoErrors(); - - debug_string( "disable bump" ); - g_bumpGLSLPass_enabled = false; -} - -void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ - Matrix4 world2local( localToWorld ); - matrix4_affine_invert( world2local ); - - Vector3 localLight( origin ); - matrix4_transform_point( world2local, localLight ); - - Vector3 localViewer( viewer ); - matrix4_transform_point( world2local, localViewer ); - - Matrix4 local2light( world2light ); - matrix4_multiply_by_matrix4( local2light, localToWorld ); // local->world->light - - glUniform3fARB( u_view_origin, localViewer.x(), localViewer.y(), localViewer.z() ); - glUniform3fARB( u_light_origin, localLight.x(), localLight.y(), localLight.z() ); - glUniform3fARB( u_light_color, colour.x(), colour.y(), colour.z() ); - glUniform1fARB( u_bump_scale, 1.0 ); - glUniform1fARB( u_specular_exponent, 32.0 ); - - glActiveTexture( GL_TEXTURE3 ); - glClientActiveTexture( GL_TEXTURE3 ); - - glMatrixMode( GL_TEXTURE ); - glLoadMatrixf( reinterpret_cast( &local2light ) ); - glMatrixMode( GL_MODELVIEW ); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(reinterpret_cast( &local2light )); + glMatrixMode(GL_MODELVIEW); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } }; GLSLBumpProgram g_bumpGLSL; -class GLSLDepthFillProgram : public GLProgram -{ +class GLSLDepthFillProgram : public GLProgram { public: -GLhandleARB m_program; - -void create(){ - // create program - m_program = glCreateProgramObjectARB(); - - // create shader - { - StringOutputStream filename( 256 ); - filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl"; - createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB ); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl"; - createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB ); - } - - GLSLProgram_link( m_program ); - GLSLProgram_validate( m_program ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void destroy(){ - glDeleteObjectARB( m_program ); - m_program = 0; -} -void enable(){ - glUseProgramObjectARB( m_program ); - GlobalOpenGL_debugAssertNoErrors(); - debug_string( "enable depthfill" ); - g_depthfillPass_enabled = true; -} -void disable(){ - glUseProgramObjectARB( 0 ); - GlobalOpenGL_debugAssertNoErrors(); - debug_string( "disable depthfill" ); - g_depthfillPass_enabled = false; -} -void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ -} + GLhandleARB m_program; + + void create() + { + // create program + m_program = glCreateProgramObjectARB(); + + // create shader + { + StringOutputStream filename(256); + filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl"; + createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl"; + createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB); + } + + GLSLProgram_link(m_program); + GLSLProgram_validate(m_program); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void destroy() + { + glDeleteObjectARB(m_program); + m_program = 0; + } + + void enable() + { + glUseProgramObjectARB(m_program); + GlobalOpenGL_debugAssertNoErrors(); + debug_string("enable depthfill"); + g_depthfillPass_enabled = true; + } + + void disable() + { + glUseProgramObjectARB(0); + GlobalOpenGL_debugAssertNoErrors(); + debug_string("disable depthfill"); + g_depthfillPass_enabled = false; + } + + void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, + const Matrix4 &world2light) + { + } }; GLSLDepthFillProgram g_depthFillGLSL; @@ -372,182 +397,194 @@ GLSLDepthFillProgram g_depthFillGLSL; // ARB path -void createProgram( const char* filename, GLenum type ){ - std::size_t size = file_size( filename ); - FileInputStream file( filename ); - ASSERT_MESSAGE( !file.failed(), "failed to open " << makeQuoted( filename ) ); - Array buffer( size ); - size = file.read( reinterpret_cast( buffer.data() ), size ); +void createProgram(const char *filename, GLenum type) +{ + std::size_t size = file_size(filename); + FileInputStream file(filename); + ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename)); + Array buffer(size); + size = file.read(reinterpret_cast( buffer.data()), size); - glProgramStringARB( type, GL_PROGRAM_FORMAT_ASCII_ARB, GLsizei( size ), buffer.data() ); + glProgramStringARB(type, GL_PROGRAM_FORMAT_ASCII_ARB, GLsizei(size), buffer.data()); - if ( GL_INVALID_OPERATION == glGetError() ) { - GLint errPos; - glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); - const GLubyte* errString = glGetString( GL_PROGRAM_ERROR_STRING_ARB ); + if (GL_INVALID_OPERATION == glGetError()) { + GLint errPos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); + const GLubyte *errString = glGetString(GL_PROGRAM_ERROR_STRING_ARB); - globalErrorStream() << reinterpret_cast( filename ) << ":" << errPos << "\n" << reinterpret_cast( errString ); + globalErrorStream() << reinterpret_cast( filename ) << ":" << errPos << "\n" + << reinterpret_cast( errString ); - ERROR_MESSAGE( "error in gl program" ); - } + ERROR_MESSAGE("error in gl program"); + } } -class ARBBumpProgram : public GLProgram -{ +class ARBBumpProgram : public GLProgram { public: -GLuint m_vertex_program; -GLuint m_fragment_program; + GLuint m_vertex_program; + GLuint m_fragment_program; -void create(){ - glEnable( GL_VERTEX_PROGRAM_ARB ); - glEnable( GL_FRAGMENT_PROGRAM_ARB ); + void create() + { + glEnable(GL_VERTEX_PROGRAM_ARB); + glEnable(GL_FRAGMENT_PROGRAM_ARB); - { - glGenProgramsARB( 1, &m_vertex_program ); - glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); - StringOutputStream filename( 256 ); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp"; - createProgram( filename.c_str(), GL_VERTEX_PROGRAM_ARB ); + { + glGenProgramsARB(1, &m_vertex_program); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); + StringOutputStream filename(256); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp"; + createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB); - glGenProgramsARB( 1, &m_fragment_program ); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp"; - createProgram( filename.c_str(), GL_FRAGMENT_PROGRAM_ARB ); - } + glGenProgramsARB(1, &m_fragment_program); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp"; + createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB); + } - glDisable( GL_VERTEX_PROGRAM_ARB ); - glDisable( GL_FRAGMENT_PROGRAM_ARB ); + glDisable(GL_VERTEX_PROGRAM_ARB); + glDisable(GL_FRAGMENT_PROGRAM_ARB); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } -void destroy(){ - glDeleteProgramsARB( 1, &m_vertex_program ); - glDeleteProgramsARB( 1, &m_fragment_program ); - GlobalOpenGL_debugAssertNoErrors(); -} + void destroy() + { + glDeleteProgramsARB(1, &m_vertex_program); + glDeleteProgramsARB(1, &m_fragment_program); + GlobalOpenGL_debugAssertNoErrors(); + } -void enable(){ - glEnable( GL_VERTEX_PROGRAM_ARB ); - glEnable( GL_FRAGMENT_PROGRAM_ARB ); - glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); + void enable() + { + glEnable(GL_VERTEX_PROGRAM_ARB); + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); - glEnableVertexAttribArrayARB( 8 ); - glEnableVertexAttribArrayARB( 9 ); - glEnableVertexAttribArrayARB( 10 ); - glEnableVertexAttribArrayARB( 11 ); + glEnableVertexAttribArrayARB(8); + glEnableVertexAttribArrayARB(9); + glEnableVertexAttribArrayARB(10); + glEnableVertexAttribArrayARB(11); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } -void disable(){ - glDisable( GL_VERTEX_PROGRAM_ARB ); - glDisable( GL_FRAGMENT_PROGRAM_ARB ); + void disable() + { + glDisable(GL_VERTEX_PROGRAM_ARB); + glDisable(GL_FRAGMENT_PROGRAM_ARB); - glDisableVertexAttribArrayARB( 8 ); - glDisableVertexAttribArrayARB( 9 ); - glDisableVertexAttribArrayARB( 10 ); - glDisableVertexAttribArrayARB( 11 ); + glDisableVertexAttribArrayARB(8); + glDisableVertexAttribArrayARB(9); + glDisableVertexAttribArrayARB(10); + glDisableVertexAttribArrayARB(11); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } -void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ - Matrix4 world2local( localToWorld ); - matrix4_affine_invert( world2local ); + void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, + const Matrix4 &world2light) + { + Matrix4 world2local(localToWorld); + matrix4_affine_invert(world2local); - Vector3 localLight( origin ); - matrix4_transform_point( world2local, localLight ); + Vector3 localLight(origin); + matrix4_transform_point(world2local, localLight); - Vector3 localViewer( viewer ); - matrix4_transform_point( world2local, localViewer ); + Vector3 localViewer(viewer); + matrix4_transform_point(world2local, localViewer); - Matrix4 local2light( world2light ); - matrix4_multiply_by_matrix4( local2light, localToWorld ); // local->world->light + Matrix4 local2light(world2light); + matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light - // view origin - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 4, localViewer.x(), localViewer.y(), localViewer.z(), 0 ); + // view origin + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4, localViewer.x(), localViewer.y(), localViewer.z(), 0); - // light origin - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 2, localLight.x(), localLight.y(), localLight.z(), 1 ); + // light origin + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, localLight.x(), localLight.y(), localLight.z(), 1); - // light colour - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 3, colour.x(), colour.y(), colour.z(), 0 ); + // light colour + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, colour.x(), colour.y(), colour.z(), 0); - // bump scale - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 1, 1, 0, 0, 0 ); + // bump scale + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1, 0, 0, 0); - // specular exponent - glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 5, 32, 0, 0, 0 ); + // specular exponent + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 5, 32, 0, 0, 0); - glActiveTexture( GL_TEXTURE3 ); - glClientActiveTexture( GL_TEXTURE3 ); + glActiveTexture(GL_TEXTURE3); + glClientActiveTexture(GL_TEXTURE3); - glMatrixMode( GL_TEXTURE ); - glLoadMatrixf( reinterpret_cast( &local2light ) ); - glMatrixMode( GL_MODELVIEW ); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(reinterpret_cast( &local2light )); + glMatrixMode(GL_MODELVIEW); - GlobalOpenGL_debugAssertNoErrors(); -} + GlobalOpenGL_debugAssertNoErrors(); + } }; -class ARBDepthFillProgram : public GLProgram -{ +class ARBDepthFillProgram : public GLProgram { public: -GLuint m_vertex_program; -GLuint m_fragment_program; - -void create(){ - glEnable( GL_VERTEX_PROGRAM_ARB ); - glEnable( GL_FRAGMENT_PROGRAM_ARB ); - - { - glGenProgramsARB( 1, &m_vertex_program ); - glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); - StringOutputStream filename( 256 ); - filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp"; - createProgram( filename.c_str(), GL_VERTEX_PROGRAM_ARB ); - - glGenProgramsARB( 1, &m_fragment_program ); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp"; - createProgram( filename.c_str(), GL_FRAGMENT_PROGRAM_ARB ); - } - - glDisable( GL_VERTEX_PROGRAM_ARB ); - glDisable( GL_FRAGMENT_PROGRAM_ARB ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void destroy(){ - glDeleteProgramsARB( 1, &m_vertex_program ); - glDeleteProgramsARB( 1, &m_fragment_program ); - GlobalOpenGL_debugAssertNoErrors(); -} - -void enable(){ - glEnable( GL_VERTEX_PROGRAM_ARB ); - glEnable( GL_FRAGMENT_PROGRAM_ARB ); - glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void disable(){ - glDisable( GL_VERTEX_PROGRAM_ARB ); - glDisable( GL_FRAGMENT_PROGRAM_ARB ); - - GlobalOpenGL_debugAssertNoErrors(); -} - -void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ -} + GLuint m_vertex_program; + GLuint m_fragment_program; + + void create() + { + glEnable(GL_VERTEX_PROGRAM_ARB); + glEnable(GL_FRAGMENT_PROGRAM_ARB); + + { + glGenProgramsARB(1, &m_vertex_program); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); + StringOutputStream filename(256); + filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp"; + createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB); + + glGenProgramsARB(1, &m_fragment_program); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp"; + createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB); + } + + glDisable(GL_VERTEX_PROGRAM_ARB); + glDisable(GL_FRAGMENT_PROGRAM_ARB); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void destroy() + { + glDeleteProgramsARB(1, &m_vertex_program); + glDeleteProgramsARB(1, &m_fragment_program); + GlobalOpenGL_debugAssertNoErrors(); + } + + void enable() + { + glEnable(GL_VERTEX_PROGRAM_ARB); + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void disable() + { + glDisable(GL_VERTEX_PROGRAM_ARB); + glDisable(GL_FRAGMENT_PROGRAM_ARB); + + GlobalOpenGL_debugAssertNoErrors(); + } + + void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, + const Matrix4 &world2light) + { + } }; ARBBumpProgram g_bumpARB; @@ -555,7 +592,7 @@ ARBDepthFillProgram g_depthFillARB; #if 0 -// NV20 path (unfinished) + // NV20 path (unfinished) void createProgram( GLint program, const char* filename, GLenum type ){ std::size_t size = file_size( filename ); @@ -771,199 +808,213 @@ bool g_normalArray_enabled = false; bool g_texcoordArray_enabled = false; bool g_colorArray_enabled = false; -inline bool OpenGLState_less( const OpenGLState& self, const OpenGLState& other ){ - //! Sort by sort-order override. - if ( self.m_sort != other.m_sort ) { - return self.m_sort < other.m_sort; - } - //! Sort by texture handle. - if ( self.m_texture != other.m_texture ) { - return self.m_texture < other.m_texture; - } - if ( self.m_texture1 != other.m_texture1 ) { - return self.m_texture1 < other.m_texture1; - } - if ( self.m_texture2 != other.m_texture2 ) { - return self.m_texture2 < other.m_texture2; - } - if ( self.m_texture3 != other.m_texture3 ) { - return self.m_texture3 < other.m_texture3; - } - if ( self.m_texture4 != other.m_texture4 ) { - return self.m_texture4 < other.m_texture4; - } - if ( self.m_texture5 != other.m_texture5 ) { - return self.m_texture5 < other.m_texture5; - } - if ( self.m_texture6 != other.m_texture6 ) { - return self.m_texture6 < other.m_texture6; - } - if ( self.m_texture7 != other.m_texture7 ) { - return self.m_texture7 < other.m_texture7; - } - //! Sort by state bit-vector. - if ( self.m_state != other.m_state ) { - return self.m_state < other.m_state; - } - //! Comparing address makes sure states are never equal. - return &self < &other; -} - -void OpenGLState_constructDefault( OpenGLState& state ){ - state.m_state = RENDER_DEFAULT; +inline bool OpenGLState_less(const OpenGLState &self, const OpenGLState &other) +{ + //! Sort by sort-order override. + if (self.m_sort != other.m_sort) { + return self.m_sort < other.m_sort; + } + //! Sort by texture handle. + if (self.m_texture != other.m_texture) { + return self.m_texture < other.m_texture; + } + if (self.m_texture1 != other.m_texture1) { + return self.m_texture1 < other.m_texture1; + } + if (self.m_texture2 != other.m_texture2) { + return self.m_texture2 < other.m_texture2; + } + if (self.m_texture3 != other.m_texture3) { + return self.m_texture3 < other.m_texture3; + } + if (self.m_texture4 != other.m_texture4) { + return self.m_texture4 < other.m_texture4; + } + if (self.m_texture5 != other.m_texture5) { + return self.m_texture5 < other.m_texture5; + } + if (self.m_texture6 != other.m_texture6) { + return self.m_texture6 < other.m_texture6; + } + if (self.m_texture7 != other.m_texture7) { + return self.m_texture7 < other.m_texture7; + } + //! Sort by state bit-vector. + if (self.m_state != other.m_state) { + return self.m_state < other.m_state; + } + //! Comparing address makes sure states are never equal. + return &self < &other; +} + +void OpenGLState_constructDefault(OpenGLState &state) +{ + state.m_state = RENDER_DEFAULT; - state.m_texture = 0; - state.m_texture1 = 0; - state.m_texture2 = 0; - state.m_texture3 = 0; - state.m_texture4 = 0; - state.m_texture5 = 0; - state.m_texture6 = 0; - state.m_texture7 = 0; + state.m_texture = 0; + state.m_texture1 = 0; + state.m_texture2 = 0; + state.m_texture3 = 0; + state.m_texture4 = 0; + state.m_texture5 = 0; + state.m_texture6 = 0; + state.m_texture7 = 0; - state.m_colour[0] = 1; - state.m_colour[1] = 1; - state.m_colour[2] = 1; - state.m_colour[3] = 1; + state.m_colour[0] = 1; + state.m_colour[1] = 1; + state.m_colour[2] = 1; + state.m_colour[3] = 1; - state.m_depthfunc = GL_LESS; + state.m_depthfunc = GL_LESS; - state.m_blend_src = GL_SRC_ALPHA; - state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA; + state.m_blend_src = GL_SRC_ALPHA; + state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA; - state.m_alphafunc = GL_ALWAYS; - state.m_alpharef = 0; + state.m_alphafunc = GL_ALWAYS; + state.m_alpharef = 0; - state.m_linewidth = 1; - state.m_pointsize = 1; + state.m_linewidth = 1; + state.m_pointsize = 1; - state.m_linestipple_factor = 1; - state.m_linestipple_pattern = 0xaaaa; + state.m_linestipple_factor = 1; + state.m_linestipple_pattern = 0xaaaa; - state.m_fog = OpenGLFogState(); + state.m_fog = OpenGLFogState(); } - - /// \brief A container of Renderable references. /// May contain the same Renderable multiple times, with different transforms. -class OpenGLStateBucket -{ +class OpenGLStateBucket { public: -struct RenderTransform -{ - const Matrix4* m_transform; - const OpenGLRenderable *m_renderable; - const RendererLight* m_light; + struct RenderTransform { + const Matrix4 *m_transform; + const OpenGLRenderable *m_renderable; + const RendererLight *m_light; - RenderTransform( const OpenGLRenderable& renderable, const Matrix4& transform, const RendererLight* light ) - : m_transform( &transform ), m_renderable( &renderable ), m_light( light ){ - } -}; + RenderTransform(const OpenGLRenderable &renderable, const Matrix4 &transform, const RendererLight *light) + : m_transform(&transform), m_renderable(&renderable), m_light(light) + { + } + }; -typedef std::vector Renderables; + typedef std::vector Renderables; private: -OpenGLState m_state; -Renderables m_renderables; + OpenGLState m_state; + Renderables m_renderables; public: -OpenGLStateBucket(){ -} -void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview, const RendererLight* light = 0 ){ - m_renderables.push_back( RenderTransform( renderable, modelview, light ) ); -} + OpenGLStateBucket() + { + } -OpenGLState& state(){ - return m_state; -} + void addRenderable(const OpenGLRenderable &renderable, const Matrix4 &modelview, const RendererLight *light = 0) + { + m_renderables.push_back(RenderTransform(renderable, modelview, light)); + } + + OpenGLState &state() + { + return m_state; + } -void render( OpenGLState& current, unsigned int globalstate, const Vector3& viewer ); + void render(OpenGLState ¤t, unsigned int globalstate, const Vector3 &viewer); }; #define LIGHT_SHADER_DEBUG 0 #if LIGHT_SHADER_DEBUG -typedef std::vector LightDebugShaders; + typedef std::vector LightDebugShaders; LightDebugShaders g_lightDebugShaders; #endif -class OpenGLStateLess -{ +class OpenGLStateLess { public: -bool operator()( const OpenGLState& self, const OpenGLState& other ) const { - return OpenGLState_less( self, other ); -} + bool operator()(const OpenGLState &self, const OpenGLState &other) const + { + return OpenGLState_less(self, other); + } }; typedef ConstReference OpenGLStateReference; -typedef std::map OpenGLStates; +typedef std::map OpenGLStates; OpenGLStates g_state_sorted; -class OpenGLStateBucketAdd -{ -OpenGLStateBucket& m_bucket; -const OpenGLRenderable& m_renderable; -const Matrix4& m_modelview; +class OpenGLStateBucketAdd { + OpenGLStateBucket &m_bucket; + const OpenGLRenderable &m_renderable; + const Matrix4 &m_modelview; public: -using func = void(const RendererLight&); + using func = void(const RendererLight &); -OpenGLStateBucketAdd( OpenGLStateBucket& bucket, const OpenGLRenderable& renderable, const Matrix4& modelview ) : - m_bucket( bucket ), m_renderable( renderable ), m_modelview( modelview ){ -} -void operator()( const RendererLight& light ){ - m_bucket.addRenderable( m_renderable, m_modelview, &light ); -} + OpenGLStateBucketAdd(OpenGLStateBucket &bucket, const OpenGLRenderable &renderable, const Matrix4 &modelview) : + m_bucket(bucket), m_renderable(renderable), m_modelview(modelview) + { + } + + void operator()(const RendererLight &light) + { + m_bucket.addRenderable(m_renderable, m_modelview, &light); + } }; -class CountLights -{ -std::size_t m_count; +class CountLights { + std::size_t m_count; public: -using func = void(RendererLight&); + using func = void(RendererLight &); -CountLights() : m_count( 0 ){ -} -void operator()( const RendererLight& light ){ - ++m_count; -} -std::size_t count() const { - return m_count; -} + CountLights() : m_count(0) + { + } + + void operator()(const RendererLight &light) + { + ++m_count; + } + + std::size_t count() const + { + return m_count; + } }; -class OpenGLShader : public Shader -{ -typedef std::list Passes; -Passes m_passes; -IShader* m_shader; -std::size_t m_used; -ModuleObservers m_observers; +class OpenGLShader : public Shader { + typedef std::list Passes; + Passes m_passes; + IShader *m_shader; + std::size_t m_used; + ModuleObservers m_observers; public: -OpenGLShader() : m_shader( 0 ), m_used( 0 ){ -} -~OpenGLShader(){ -} -void construct( const char* name ); -void destroy(){ - if ( m_shader ) { - m_shader->DecRef(); - } - m_shader = 0; - - for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) - { - delete *i; - } - m_passes.clear(); -} -void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview, const LightList* lights ){ - for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) - { + OpenGLShader() : m_shader(0), m_used(0) + { + } + + ~OpenGLShader() + { + } + + void construct(const char *name); + + void destroy() + { + if (m_shader) { + m_shader->DecRef(); + } + m_shader = 0; + + for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { + delete *i; + } + m_passes.clear(); + } + + void addRenderable(const OpenGLRenderable &renderable, const Matrix4 &modelview, const LightList *lights) + { + for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { #if LIGHT_SHADER_DEBUG - if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) { + if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) { if ( lights != 0 ) { CountLights counter; lights->forEachLight( makeCallback1( counter ) ); @@ -976,128 +1027,149 @@ void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview } else #else - if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) { - if ( lights != 0 ) { - OpenGLStateBucketAdd add( *( *i ), renderable, modelview ); - lights->forEachLight(makeCallback( add ) ); - } - } - else + if (((*i)->state().m_state & RENDER_BUMP) != 0) { + if (lights != 0) { + OpenGLStateBucketAdd add(*(*i), renderable, modelview); + lights->forEachLight(makeCallback(add)); + } + } else #endif - { - ( *i )->addRenderable( renderable, modelview ); - } - } -} -void incrementUsed(){ - if ( ++m_used == 1 && m_shader != 0 ) { - m_shader->SetInUse( true ); - } -} -void decrementUsed(){ - if ( --m_used == 0 && m_shader != 0 ) { - m_shader->SetInUse( false ); - } -} -bool realised() const { - return m_shader != 0; -} -void attach( ModuleObserver& observer ){ - if ( realised() ) { - observer.realise(); - } - m_observers.attach( observer ); -} -void detach( ModuleObserver& observer ){ - if ( realised() ) { - observer.unrealise(); - } - m_observers.detach( observer ); -} -void realise( const CopiedString& name ){ - construct( name.c_str() ); - - if ( m_used != 0 && m_shader != 0 ) { - m_shader->SetInUse( true ); - } - - for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) - { - g_state_sorted.insert( OpenGLStates::value_type( OpenGLStateReference( ( *i )->state() ), *i ) ); - } - - m_observers.realise(); -} -void unrealise(){ - m_observers.unrealise(); - - for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) - { - g_state_sorted.erase( OpenGLStateReference( ( *i )->state() ) ); - } - - destroy(); -} -qtexture_t& getTexture() const { - ASSERT_NOTNULL( m_shader ); - return *m_shader->getTexture(); -} -unsigned int getFlags() const { - ASSERT_NOTNULL( m_shader ); - return m_shader->getFlags(); -} -IShader& getShader() const { - ASSERT_NOTNULL( m_shader ); - return *m_shader; -} -OpenGLState& appendDefaultPass(){ - m_passes.push_back( new OpenGLStateBucket ); - OpenGLState& state = m_passes.back()->state(); - OpenGLState_constructDefault( state ); - return state; -} + { + (*i)->addRenderable(renderable, modelview); + } + } + } + + void incrementUsed() + { + if (++m_used == 1 && m_shader != 0) { + m_shader->SetInUse(true); + } + } + + void decrementUsed() + { + if (--m_used == 0 && m_shader != 0) { + m_shader->SetInUse(false); + } + } + + bool realised() const + { + return m_shader != 0; + } + + void attach(ModuleObserver &observer) + { + if (realised()) { + observer.realise(); + } + m_observers.attach(observer); + } + + void detach(ModuleObserver &observer) + { + if (realised()) { + observer.unrealise(); + } + m_observers.detach(observer); + } + + void realise(const CopiedString &name) + { + construct(name.c_str()); + + if (m_used != 0 && m_shader != 0) { + m_shader->SetInUse(true); + } + + for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { + g_state_sorted.insert(OpenGLStates::value_type(OpenGLStateReference((*i)->state()), *i)); + } + + m_observers.realise(); + } + + void unrealise() + { + m_observers.unrealise(); + + for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { + g_state_sorted.erase(OpenGLStateReference((*i)->state())); + } + + destroy(); + } + + qtexture_t &getTexture() const + { + ASSERT_NOTNULL(m_shader); + return *m_shader->getTexture(); + } + + unsigned int getFlags() const + { + ASSERT_NOTNULL(m_shader); + return m_shader->getFlags(); + } + + IShader &getShader() const + { + ASSERT_NOTNULL(m_shader); + return *m_shader; + } + + OpenGLState &appendDefaultPass() + { + m_passes.push_back(new OpenGLStateBucket); + OpenGLState &state = m_passes.back()->state(); + OpenGLState_constructDefault(state); + return state; + } }; -inline bool lightEnabled( const RendererLight& light, const LightCullable& cullable ){ - return cullable.testLight( light ); +inline bool lightEnabled(const RendererLight &light, const LightCullable &cullable) +{ + return cullable.testLight(light); } -typedef std::set RendererLights; +typedef std::set RendererLights; #define DEBUG_LIGHT_SYNC 0 -class LinearLightList : public LightList -{ -LightCullable& m_cullable; -RendererLights& m_allLights; -Callback m_evaluateChanged; +class LinearLightList : public LightList { + LightCullable &m_cullable; + RendererLights &m_allLights; + Callback m_evaluateChanged; -typedef std::list Lights; -mutable Lights m_lights; -mutable bool m_lightsChanged; + typedef std::list Lights; + mutable Lights m_lights; + mutable bool m_lightsChanged; public: -LinearLightList( LightCullable& cullable, RendererLights& lights, const Callback& evaluateChanged ) : - m_cullable( cullable ), m_allLights( lights ), m_evaluateChanged( evaluateChanged ){ - m_lightsChanged = true; -} -void evaluateLights() const { - m_evaluateChanged(); - if ( m_lightsChanged ) { - m_lightsChanged = false; - - m_lights.clear(); - m_cullable.clearLights(); - for ( RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i ) - { - if ( lightEnabled( *( *i ), m_cullable ) ) { - m_lights.push_back( *i ); - m_cullable.insertLight( *( *i ) ); - } - } - } -#if ( DEBUG_LIGHT_SYNC ) - else + LinearLightList(LightCullable &cullable, RendererLights &lights, const Callback &evaluateChanged) : + m_cullable(cullable), m_allLights(lights), m_evaluateChanged(evaluateChanged) + { + m_lightsChanged = true; + } + + void evaluateLights() const + { + m_evaluateChanged(); + if (m_lightsChanged) { + m_lightsChanged = false; + + m_lights.clear(); + m_cullable.clearLights(); + for (RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i) { + if (lightEnabled(*(*i), m_cullable)) { + m_lights.push_back(*i); + m_cullable.insertLight(*(*i)); + } + } + } +#if (DEBUG_LIGHT_SYNC) + else { Lights lights; for ( RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i ) @@ -1113,410 +1185,459 @@ void evaluateLights() const { ); } #endif -} -void forEachLight( const RendererLightCallback& callback ) const { - evaluateLights(); + } - for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i ) - { - callback( *( *i ) ); - } -} -void lightsChanged() const { - m_lightsChanged = true; -} -}; + void forEachLight(const RendererLightCallback &callback) const + { + evaluateLights(); -inline void setFogState( const OpenGLFogState& state ){ - glFogi( GL_FOG_MODE, state.mode ); - glFogf( GL_FOG_DENSITY, state.density ); - glFogf( GL_FOG_START, state.start ); - glFogf( GL_FOG_END, state.end ); - glFogi( GL_FOG_INDEX, state.index ); - glFogfv( GL_FOG_COLOR, vector4_to_array( state.colour ) ); -} + for (Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i) { + callback(*(*i)); + } + } -#define DEBUG_SHADERS 0 + void lightsChanged() const + { + m_lightsChanged = true; + } +}; -class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver -{ -class CreateOpenGLShader +inline void setFogState(const OpenGLFogState &state) { -OpenGLShaderCache* m_cache; -public: -explicit CreateOpenGLShader( OpenGLShaderCache* cache = 0 ) - : m_cache( cache ){ -} -OpenGLShader* construct( const CopiedString& name ){ - OpenGLShader* shader = new OpenGLShader; - if ( m_cache->realised() ) { - shader->realise( name ); - } - return shader; -} -void destroy( OpenGLShader* shader ){ - if ( m_cache->realised() ) { - shader->unrealise(); - } - delete shader; + glFogi(GL_FOG_MODE, state.mode); + glFogf(GL_FOG_DENSITY, state.density); + glFogf(GL_FOG_START, state.start); + glFogf(GL_FOG_END, state.end); + glFogi(GL_FOG_INDEX, state.index); + glFogfv(GL_FOG_COLOR, vector4_to_array(state.colour)); } -}; -typedef HashedCache, CreateOpenGLShader> Shaders; -Shaders m_shaders; -std::size_t m_unrealised; +#define DEBUG_SHADERS 0 -bool m_lightingEnabled; -bool m_lightingSupported; -bool m_useShaderLanguage; +class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver { + class CreateOpenGLShader { + OpenGLShaderCache *m_cache; + public: + explicit CreateOpenGLShader(OpenGLShaderCache *cache = 0) + : m_cache(cache) + { + } + + OpenGLShader *construct(const CopiedString &name) + { + OpenGLShader *shader = new OpenGLShader; + if (m_cache->realised()) { + shader->realise(name); + } + return shader; + } + + void destroy(OpenGLShader *shader) + { + if (m_cache->realised()) { + shader->unrealise(); + } + delete shader; + } + }; + + typedef HashedCache, CreateOpenGLShader> Shaders; + Shaders m_shaders; + std::size_t m_unrealised; + + bool m_lightingEnabled; + bool m_lightingSupported; + bool m_useShaderLanguage; public: -OpenGLShaderCache() - : m_shaders( CreateOpenGLShader( this ) ), - m_unrealised( 3 ), // wait until shaders, gl-context and textures are realised before creating any render-states - m_lightingEnabled( true ), - m_lightingSupported( false ), - m_useShaderLanguage( false ), - m_lightsChanged( true ), - m_traverseRenderablesMutex( false ){ -} -~OpenGLShaderCache(){ - for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) - { - globalOutputStream() << "leaked shader: " << makeQuoted( ( *i ).key.c_str() ) << "\n"; - } -} -Shader* capture( const char* name ){ - ASSERT_MESSAGE( name[0] == '$' - || *name == '[' - || *name == '<' - || *name == '(' - || strchr( name, '\\' ) == 0, "shader name contains invalid characters: \"" << name << "\"" ); + OpenGLShaderCache() + : m_shaders(CreateOpenGLShader(this)), + m_unrealised( + 3), // wait until shaders, gl-context and textures are realised before creating any render-states + m_lightingEnabled(true), + m_lightingSupported(false), + m_useShaderLanguage(false), + m_lightsChanged(true), + m_traverseRenderablesMutex(false) + { + } + + ~OpenGLShaderCache() + { + for (Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) { + globalOutputStream() << "leaked shader: " << makeQuoted((*i).key.c_str()) << "\n"; + } + } + + Shader *capture(const char *name) + { + ASSERT_MESSAGE(name[0] == '$' + || *name == '[' + || *name == '<' + || *name == '(' + || strchr(name, '\\') == 0, "shader name contains invalid characters: \"" << name << "\""); #if DEBUG_SHADERS - globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n'; + globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n'; #endif - return m_shaders.capture( name ).get(); -} -void release( const char *name ){ + return m_shaders.capture(name).get(); + } + + void release(const char *name) + { #if DEBUG_SHADERS - globalOutputStream() << "shaders release: " << makeQuoted( name ) << '\n'; + globalOutputStream() << "shaders release: " << makeQuoted( name ) << '\n'; +#endif + m_shaders.release(name); + } + + void + render(RenderStateFlags globalstate, const Matrix4 &modelview, const Matrix4 &projection, const Vector3 &viewer) + { + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(reinterpret_cast( &projection )); +#if 0 + //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast(&projection)); #endif - m_shaders.release( name ); -} -void render( RenderStateFlags globalstate, const Matrix4& modelview, const Matrix4& projection, const Vector3& viewer ){ - glMatrixMode( GL_PROJECTION ); - glLoadMatrixf( reinterpret_cast( &projection ) ); - #if 0 - //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast(&projection)); - #endif - - glMatrixMode( GL_MODELVIEW ); - glLoadMatrixf( reinterpret_cast( &modelview ) ); - #if 0 - //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast(&modelview)); - #endif - - ASSERT_MESSAGE( realised(), "render states are not realised" ); - - // global settings that are not set in renderstates - glFrontFace( GL_CW ); - glCullFace( GL_BACK ); - glPolygonOffset( -1, 1 ); - { - const GLubyte pattern[132] = { - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55 - }; - glPolygonStipple( pattern ); - } - glEnableClientState( GL_VERTEX_ARRAY ); - g_vertexArray_enabled = true; - glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); - - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - glClientActiveTexture( GL_TEXTURE0 ); - } - - if ( GlobalOpenGL().ARB_shader_objects() ) { - glUseProgramObjectARB( 0 ); - glDisableVertexAttribArrayARB( c_attr_TexCoord0 ); - glDisableVertexAttribArrayARB( c_attr_Tangent ); - glDisableVertexAttribArrayARB( c_attr_Binormal ); - } - - if ( globalstate & RENDER_TEXTURE ) { - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - } - - OpenGLState current; - OpenGLState_constructDefault( current ); - current.m_sort = OpenGLState::eSortFirst; - - // default renderstate settings - glLineStipple( current.m_linestipple_factor, current.m_linestipple_pattern ); - glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - glDisable( GL_LIGHTING ); - glDisable( GL_TEXTURE_2D ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - g_texcoordArray_enabled = false; - glDisableClientState( GL_COLOR_ARRAY ); - g_colorArray_enabled = false; - glDisableClientState( GL_NORMAL_ARRAY ); - g_normalArray_enabled = false; - glDisable( GL_BLEND ); - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - glDisable( GL_CULL_FACE ); - glShadeModel( GL_FLAT ); - glDisable( GL_DEPTH_TEST ); - glDepthMask( GL_FALSE ); - glDisable( GL_ALPHA_TEST ); - glDisable( GL_LINE_STIPPLE ); - glDisable( GL_POLYGON_STIPPLE ); - glDisable( GL_POLYGON_OFFSET_LINE ); - - glBindTexture( GL_TEXTURE_2D, 0 ); - glColor4f( 1,1,1,1 ); - glDepthFunc( GL_LESS ); - glAlphaFunc( GL_ALWAYS, 0 ); - glLineWidth( 1 ); - glPointSize( 1 ); - - glHint( GL_FOG_HINT, GL_NICEST ); - glDisable( GL_FOG ); - setFogState( OpenGLFogState() ); - - GlobalOpenGL_debugAssertNoErrors(); - - debug_string( "begin rendering" ); - for ( OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i ) - { - ( *i ).second->render( current, globalstate, viewer ); - } - debug_string( "end rendering" ); -} -void realise(){ - if ( --m_unrealised == 0 ) { - if ( lightingSupported() && lightingEnabled() ) { - if ( useShaderLanguage() ) { - g_bumpGLSL.create(); - g_depthFillGLSL.create(); - } - else - { - g_bumpARB.create(); - g_depthFillARB.create(); - } - } - - for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) - { - if ( !( *i ).value.empty() ) { - ( *i ).value->realise( i->key ); - } - } - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) - { - if ( !( *i ).value.empty() ) { - ( *i ).value->unrealise(); - } - } - if ( GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled() ) { - if ( useShaderLanguage() ) { - g_bumpGLSL.destroy(); - g_depthFillGLSL.destroy(); - } - else - { - g_bumpARB.destroy(); - g_depthFillARB.destroy(); - } - } - } -} -bool realised(){ - return m_unrealised == 0; -} - - -bool lightingEnabled() const { - return m_lightingEnabled; -} -bool lightingSupported() const { - return m_lightingSupported; -} -bool useShaderLanguage() const { - return m_useShaderLanguage; -} -void setLighting( bool supported, bool enabled ){ - bool refresh = ( m_lightingSupported && m_lightingEnabled ) != ( supported && enabled ); - if ( refresh ) { - unrealise(); - GlobalShaderSystem().setLightingEnabled( supported && enabled ); - } + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(reinterpret_cast( &modelview )); +#if 0 + //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast(&modelview)); +#endif - m_lightingSupported = supported; - m_lightingEnabled = enabled; - - if ( refresh ) { - realise(); - } -} -void extensionsInitialised(){ - setLighting( GlobalOpenGL().GL_1_3() - && GlobalOpenGL().ARB_vertex_program() - && GlobalOpenGL().ARB_fragment_program() - && GlobalOpenGL().ARB_shader_objects() - && GlobalOpenGL().ARB_vertex_shader() - && GlobalOpenGL().ARB_fragment_shader() - && GlobalOpenGL().ARB_shading_language_100(), - m_lightingEnabled - ); - - if ( !lightingSupported() ) { - globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n"; - if ( !GlobalOpenGL().GL_1_3() ) { - globalOutputStream() << " GL version 1.3 or better\n"; - } - if ( !GlobalOpenGL().ARB_vertex_program() ) { - globalOutputStream() << " GL_ARB_vertex_program\n"; - } - if ( !GlobalOpenGL().ARB_fragment_program() ) { - globalOutputStream() << " GL_ARB_fragment_program\n"; - } - if ( !GlobalOpenGL().ARB_shader_objects() ) { - globalOutputStream() << " GL_ARB_shader_objects\n"; - } - if ( !GlobalOpenGL().ARB_vertex_shader() ) { - globalOutputStream() << " GL_ARB_vertex_shader\n"; - } - if ( !GlobalOpenGL().ARB_fragment_shader() ) { - globalOutputStream() << " GL_ARB_fragment_shader\n"; - } - if ( !GlobalOpenGL().ARB_shading_language_100() ) { - globalOutputStream() << " GL_ARB_shading_language_100\n"; - } - } -} -void setLightingEnabled( bool enabled ){ - setLighting( m_lightingSupported, enabled ); -} + ASSERT_MESSAGE(realised(), "render states are not realised"); + + // global settings that are not set in renderstates + glFrontFace(GL_CW); + glCullFace(GL_BACK); + glPolygonOffset(-1, 1); + { + const GLubyte pattern[132] = { + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55 + }; + glPolygonStipple(pattern); + } + glEnableClientState(GL_VERTEX_ARRAY); + g_vertexArray_enabled = true; + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + } + + if (GlobalOpenGL().ARB_shader_objects()) { + glUseProgramObjectARB(0); + glDisableVertexAttribArrayARB(c_attr_TexCoord0); + glDisableVertexAttribArrayARB(c_attr_Tangent); + glDisableVertexAttribArrayARB(c_attr_Binormal); + } + + if (globalstate & RENDER_TEXTURE) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + + OpenGLState current; + OpenGLState_constructDefault(current); + current.m_sort = OpenGLState::eSortFirst; + + // default renderstate settings + glLineStipple(current.m_linestipple_factor, current.m_linestipple_pattern); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + g_texcoordArray_enabled = false; + glDisableClientState(GL_COLOR_ARRAY); + g_colorArray_enabled = false; + glDisableClientState(GL_NORMAL_ARRAY); + g_normalArray_enabled = false; + glDisable(GL_BLEND); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + glShadeModel(GL_FLAT); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_ALPHA_TEST); + glDisable(GL_LINE_STIPPLE); + glDisable(GL_POLYGON_STIPPLE); + glDisable(GL_POLYGON_OFFSET_LINE); + + glBindTexture(GL_TEXTURE_2D, 0); + glColor4f(1, 1, 1, 1); + glDepthFunc(GL_LESS); + glAlphaFunc(GL_ALWAYS, 0); + glLineWidth(1); + glPointSize(1); + + glHint(GL_FOG_HINT, GL_NICEST); + glDisable(GL_FOG); + setFogState(OpenGLFogState()); + + GlobalOpenGL_debugAssertNoErrors(); + + debug_string("begin rendering"); + for (OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i) { + (*i).second->render(current, globalstate, viewer); + } + debug_string("end rendering"); + } + + void realise() + { + if (--m_unrealised == 0) { + if (lightingSupported() && lightingEnabled()) { + if (useShaderLanguage()) { + g_bumpGLSL.create(); + g_depthFillGLSL.create(); + } else { + g_bumpARB.create(); + g_depthFillARB.create(); + } + } + + for (Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) { + if (!(*i).value.empty()) { + (*i).value->realise(i->key); + } + } + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + for (Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) { + if (!(*i).value.empty()) { + (*i).value->unrealise(); + } + } + if (GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled()) { + if (useShaderLanguage()) { + g_bumpGLSL.destroy(); + g_depthFillGLSL.destroy(); + } else { + g_bumpARB.destroy(); + g_depthFillARB.destroy(); + } + } + } + } + + bool realised() + { + return m_unrealised == 0; + } + + + bool lightingEnabled() const + { + return m_lightingEnabled; + } + + bool lightingSupported() const + { + return m_lightingSupported; + } + + bool useShaderLanguage() const + { + return m_useShaderLanguage; + } + + void setLighting(bool supported, bool enabled) + { + bool refresh = (m_lightingSupported && m_lightingEnabled) != (supported && enabled); + + if (refresh) { + unrealise(); + GlobalShaderSystem().setLightingEnabled(supported && enabled); + } + + m_lightingSupported = supported; + m_lightingEnabled = enabled; + + if (refresh) { + realise(); + } + } + + void extensionsInitialised() + { + setLighting(GlobalOpenGL().GL_1_3() + && GlobalOpenGL().ARB_vertex_program() + && GlobalOpenGL().ARB_fragment_program() + && GlobalOpenGL().ARB_shader_objects() + && GlobalOpenGL().ARB_vertex_shader() + && GlobalOpenGL().ARB_fragment_shader() + && GlobalOpenGL().ARB_shading_language_100(), + m_lightingEnabled + ); + + if (!lightingSupported()) { + globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n"; + if (!GlobalOpenGL().GL_1_3()) { + globalOutputStream() << " GL version 1.3 or better\n"; + } + if (!GlobalOpenGL().ARB_vertex_program()) { + globalOutputStream() << " GL_ARB_vertex_program\n"; + } + if (!GlobalOpenGL().ARB_fragment_program()) { + globalOutputStream() << " GL_ARB_fragment_program\n"; + } + if (!GlobalOpenGL().ARB_shader_objects()) { + globalOutputStream() << " GL_ARB_shader_objects\n"; + } + if (!GlobalOpenGL().ARB_vertex_shader()) { + globalOutputStream() << " GL_ARB_vertex_shader\n"; + } + if (!GlobalOpenGL().ARB_fragment_shader()) { + globalOutputStream() << " GL_ARB_fragment_shader\n"; + } + if (!GlobalOpenGL().ARB_shading_language_100()) { + globalOutputStream() << " GL_ARB_shading_language_100\n"; + } + } + } + + void setLightingEnabled(bool enabled) + { + setLighting(m_lightingSupported, enabled); + } // light culling -RendererLights m_lights; -bool m_lightsChanged; -typedef std::map LightLists; -LightLists m_lightLists; - -const LightList& attach( LightCullable& cullable ){ - return ( *m_lightLists.insert( LightLists::value_type( &cullable, LinearLightList( cullable, m_lights, EvaluateChangedCaller( *this ) ) ) ).first ).second; -} -void detach( LightCullable& cullable ){ - m_lightLists.erase( &cullable ); -} -void changed( LightCullable& cullable ){ - LightLists::iterator i = m_lightLists.find( &cullable ); - ASSERT_MESSAGE( i != m_lightLists.end(), "cullable not attached" ); - ( *i ).second.lightsChanged(); -} -void attach( RendererLight& light ){ - ASSERT_MESSAGE( m_lights.find( &light ) == m_lights.end(), "light could not be attached" ); - m_lights.insert( &light ); - changed( light ); -} -void detach( RendererLight& light ){ - ASSERT_MESSAGE( m_lights.find( &light ) != m_lights.end(), "light could not be detached" ); - m_lights.erase( &light ); - changed( light ); -} -void changed( RendererLight& light ){ - m_lightsChanged = true; -} -void evaluateChanged(){ - if ( m_lightsChanged ) { - m_lightsChanged = false; - for ( LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i ) - { - ( *i ).second.lightsChanged(); - } - } -} -typedef MemberCaller EvaluateChangedCaller; - -typedef std::set Renderables; -Renderables m_renderables; -mutable bool m_traverseRenderablesMutex; + RendererLights m_lights; + bool m_lightsChanged; + typedef std::map LightLists; + LightLists m_lightLists; + + const LightList &attach(LightCullable &cullable) + { + return (*m_lightLists.insert(LightLists::value_type(&cullable, LinearLightList(cullable, m_lights, + EvaluateChangedCaller( + *this)))).first).second; + } + + void detach(LightCullable &cullable) + { + m_lightLists.erase(&cullable); + } + + void changed(LightCullable &cullable) + { + LightLists::iterator i = m_lightLists.find(&cullable); + ASSERT_MESSAGE(i != m_lightLists.end(), "cullable not attached"); + (*i).second.lightsChanged(); + } + + void attach(RendererLight &light) + { + ASSERT_MESSAGE(m_lights.find(&light) == m_lights.end(), "light could not be attached"); + m_lights.insert(&light); + changed(light); + } + + void detach(RendererLight &light) + { + ASSERT_MESSAGE(m_lights.find(&light) != m_lights.end(), "light could not be detached"); + m_lights.erase(&light); + changed(light); + } + + void changed(RendererLight &light) + { + m_lightsChanged = true; + } + + void evaluateChanged() + { + if (m_lightsChanged) { + m_lightsChanged = false; + for (LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i) { + (*i).second.lightsChanged(); + } + } + } + + typedef MemberCaller EvaluateChangedCaller; + + typedef std::set Renderables; + Renderables m_renderables; + mutable bool m_traverseRenderablesMutex; // renderables -void attachRenderable( const Renderable& renderable ){ - ASSERT_MESSAGE( !m_traverseRenderablesMutex, "attaching renderable during traversal" ); - ASSERT_MESSAGE( m_renderables.find( &renderable ) == m_renderables.end(), "renderable could not be attached" ); - m_renderables.insert( &renderable ); -} -void detachRenderable( const Renderable& renderable ){ - ASSERT_MESSAGE( !m_traverseRenderablesMutex, "detaching renderable during traversal" ); - ASSERT_MESSAGE( m_renderables.find( &renderable ) != m_renderables.end(), "renderable could not be detached" ); - m_renderables.erase( &renderable ); -} -void forEachRenderable( const RenderableCallback& callback ) const { - ASSERT_MESSAGE( !m_traverseRenderablesMutex, "for-each during traversal" ); - m_traverseRenderablesMutex = true; - for ( Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i ) - { - callback( *( *i ) ); - } - m_traverseRenderablesMutex = false; -} + void attachRenderable(const Renderable &renderable) + { + ASSERT_MESSAGE(!m_traverseRenderablesMutex, "attaching renderable during traversal"); + ASSERT_MESSAGE(m_renderables.find(&renderable) == m_renderables.end(), "renderable could not be attached"); + m_renderables.insert(&renderable); + } + + void detachRenderable(const Renderable &renderable) + { + ASSERT_MESSAGE(!m_traverseRenderablesMutex, "detaching renderable during traversal"); + ASSERT_MESSAGE(m_renderables.find(&renderable) != m_renderables.end(), "renderable could not be detached"); + m_renderables.erase(&renderable); + } + + void forEachRenderable(const RenderableCallback &callback) const + { + ASSERT_MESSAGE(!m_traverseRenderablesMutex, "for-each during traversal"); + m_traverseRenderablesMutex = true; + for (Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i) { + callback(*(*i)); + } + m_traverseRenderablesMutex = false; + } }; -static OpenGLShaderCache* g_ShaderCache; +static OpenGLShaderCache *g_ShaderCache; -void ShaderCache_extensionsInitialised(){ - g_ShaderCache->extensionsInitialised(); +void ShaderCache_extensionsInitialised() +{ + g_ShaderCache->extensionsInitialised(); } -void ShaderCache_setBumpEnabled( bool enabled ){ - g_ShaderCache->setLightingEnabled( enabled ); +void ShaderCache_setBumpEnabled(bool enabled) +{ + g_ShaderCache->setLightingEnabled(enabled); } Vector3 g_DebugShaderColours[256]; -Shader* g_defaultPointLight = 0; +Shader *g_defaultPointLight = 0; -void ShaderCache_Construct(){ - g_ShaderCache = new OpenGLShaderCache; - GlobalTexturesCache().attach( *g_ShaderCache ); - GlobalShaderSystem().attach( *g_ShaderCache ); +void ShaderCache_Construct() +{ + g_ShaderCache = new OpenGLShaderCache; + GlobalTexturesCache().attach(*g_ShaderCache); + GlobalShaderSystem().attach(*g_ShaderCache); - if ( g_pGameDescription->mGameType == "doom3" ) { - g_defaultPointLight = g_ShaderCache->capture( "lights/defaultPointLight" ); - //Shader* overbright = - g_ShaderCache->capture( "$OVERBRIGHT" ); + if (g_pGameDescription->mGameType == "doom3") { + g_defaultPointLight = g_ShaderCache->capture("lights/defaultPointLight"); + //Shader* overbright = + g_ShaderCache->capture("$OVERBRIGHT"); #if LIGHT_SHADER_DEBUG - for ( std::size_t i = 0; i < 256; ++i ) + for ( std::size_t i = 0; i < 256; ++i ) { g_DebugShaderColours[i] = Vector3( i / 256.0, i / 256.0, i / 256.0 ); } @@ -1543,17 +1664,18 @@ void ShaderCache_Construct(){ buffer.clear(); } #endif - } + } } -void ShaderCache_Destroy(){ - if ( g_pGameDescription->mGameType == "doom3" ) { - g_ShaderCache->release( "lights/defaultPointLight" ); - g_ShaderCache->release( "$OVERBRIGHT" ); - g_defaultPointLight = 0; +void ShaderCache_Destroy() +{ + if (g_pGameDescription->mGameType == "doom3") { + g_ShaderCache->release("lights/defaultPointLight"); + g_ShaderCache->release("$OVERBRIGHT"); + g_defaultPointLight = 0; #if LIGHT_SHADER_DEBUG - g_lightDebugShaders.clear(); + g_lightDebugShaders.clear(); StringOutputStream buffer( 256 ); for ( std::size_t i = 0; i < 256; ++i ) { @@ -1561,875 +1683,884 @@ void ShaderCache_Destroy(){ g_ShaderCache->release( buffer.c_str() ); } #endif - } + } - GlobalShaderSystem().detach( *g_ShaderCache ); - GlobalTexturesCache().detach( *g_ShaderCache ); - delete g_ShaderCache; + GlobalShaderSystem().detach(*g_ShaderCache); + GlobalTexturesCache().detach(*g_ShaderCache); + delete g_ShaderCache; } -ShaderCache* GetShaderCache(){ - return g_ShaderCache; +ShaderCache *GetShaderCache() +{ + return g_ShaderCache; } -inline void setTextureState( GLint& current, const GLint& texture, GLenum textureUnit ){ - if ( texture != current ) { - glActiveTexture( textureUnit ); - glClientActiveTexture( textureUnit ); - glBindTexture( GL_TEXTURE_2D, texture ); - GlobalOpenGL_debugAssertNoErrors(); - current = texture; - } +inline void setTextureState(GLint ¤t, const GLint &texture, GLenum textureUnit) +{ + if (texture != current) { + glActiveTexture(textureUnit); + glClientActiveTexture(textureUnit); + glBindTexture(GL_TEXTURE_2D, texture); + GlobalOpenGL_debugAssertNoErrors(); + current = texture; + } } -inline void setTextureState( GLint& current, const GLint& texture ){ - if ( texture != current ) { - glBindTexture( GL_TEXTURE_2D, texture ); - GlobalOpenGL_debugAssertNoErrors(); - current = texture; - } +inline void setTextureState(GLint ¤t, const GLint &texture) +{ + if (texture != current) { + glBindTexture(GL_TEXTURE_2D, texture); + GlobalOpenGL_debugAssertNoErrors(); + current = texture; + } } -inline void setState( unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag ){ - if ( delta & state & flag ) { - glEnable( glflag ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & flag ) { - glDisable( glflag ); - GlobalOpenGL_debugAssertNoErrors(); - } +inline void setState(unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag) +{ + if (delta & state & flag) { + glEnable(glflag); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & flag) { + glDisable(glflag); + GlobalOpenGL_debugAssertNoErrors(); + } } -void OpenGLState_apply( const OpenGLState& self, OpenGLState& current, unsigned int globalstate ){ - debug_int( "sort", int(self.m_sort) ); - debug_int( "texture", self.m_texture ); - debug_int( "state", self.m_state ); - debug_int( "address", int(std::size_t( &self ) ) ); - - count_state(); - - if ( self.m_state & RENDER_OVERRIDE ) { - globalstate |= RENDER_FILL | RENDER_DEPTHWRITE; - } - - const unsigned int state = self.m_state & globalstate; - const unsigned int delta = state ^ current.m_state; - - GlobalOpenGL_debugAssertNoErrors(); - - GLProgram* program = ( state & RENDER_PROGRAM ) != 0 ? self.m_program : 0; - - if ( program != current.m_program ) { - if ( current.m_program != 0 ) { - current.m_program->disable(); - glColor4fv( vector4_to_array( current.m_colour ) ); - debug_colour( "cleaning program" ); - } - - current.m_program = program; - - if ( current.m_program != 0 ) { - current.m_program->enable(); - } - } - - if ( delta & state & RENDER_FILL ) { - //qglPolygonMode (GL_BACK, GL_LINE); - //qglPolygonMode (GL_FRONT, GL_FILL); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_FILL ) { - glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE ); - - if ( delta & state & RENDER_LIGHTING ) { - glEnable( GL_LIGHTING ); - glEnable( GL_COLOR_MATERIAL ); - glEnable( GL_RESCALE_NORMAL ); - glEnableClientState( GL_NORMAL_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - g_normalArray_enabled = true; - } - else if ( delta & ~state & RENDER_LIGHTING ) { - glDisable( GL_LIGHTING ); - glDisable( GL_COLOR_MATERIAL ); - glDisable( GL_RESCALE_NORMAL ); - glDisableClientState( GL_NORMAL_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - g_normalArray_enabled = false; - } - - if ( delta & state & RENDER_TEXTURE ) { - GlobalOpenGL_debugAssertNoErrors(); - - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - glClientActiveTexture( GL_TEXTURE0 ); - } - - glEnable( GL_TEXTURE_2D ); - - glColor4f( 1,1,1,self.m_colour[3] ); - debug_colour( "setting texture" ); - - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - g_texcoordArray_enabled = true; - } - else if ( delta & ~state & RENDER_TEXTURE ) { - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - glClientActiveTexture( GL_TEXTURE0 ); - } - - glDisable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, 0 ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - - GlobalOpenGL_debugAssertNoErrors(); - g_texcoordArray_enabled = false; - } - - if ( delta & state & RENDER_BLEND ) { +void OpenGLState_apply(const OpenGLState &self, OpenGLState ¤t, unsigned int globalstate) +{ + debug_int("sort", int(self.m_sort)); + debug_int("texture", self.m_texture); + debug_int("state", self.m_state); + debug_int("address", int(std::size_t(&self))); + + count_state(); + + if (self.m_state & RENDER_OVERRIDE) { + globalstate |= RENDER_FILL | RENDER_DEPTHWRITE; + } + + const unsigned int state = self.m_state & globalstate; + const unsigned int delta = state ^current.m_state; + + GlobalOpenGL_debugAssertNoErrors(); + + GLProgram *program = (state & RENDER_PROGRAM) != 0 ? self.m_program : 0; + + if (program != current.m_program) { + if (current.m_program != 0) { + current.m_program->disable(); + glColor4fv(vector4_to_array(current.m_colour)); + debug_colour("cleaning program"); + } + + current.m_program = program; + + if (current.m_program != 0) { + current.m_program->enable(); + } + } + + if (delta & state & RENDER_FILL) { + //qglPolygonMode (GL_BACK, GL_LINE); + //qglPolygonMode (GL_FRONT, GL_FILL); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_FILL) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE); + + if (delta & state & RENDER_LIGHTING) { + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_RESCALE_NORMAL); + glEnableClientState(GL_NORMAL_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + g_normalArray_enabled = true; + } else if (delta & ~state & RENDER_LIGHTING) { + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_RESCALE_NORMAL); + glDisableClientState(GL_NORMAL_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + g_normalArray_enabled = false; + } + + if (delta & state & RENDER_TEXTURE) { + GlobalOpenGL_debugAssertNoErrors(); + + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + } + + glEnable(GL_TEXTURE_2D); + + glColor4f(1, 1, 1, self.m_colour[3]); + debug_colour("setting texture"); + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + g_texcoordArray_enabled = true; + } else if (delta & ~state & RENDER_TEXTURE) { + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + } + + glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + GlobalOpenGL_debugAssertNoErrors(); + g_texcoordArray_enabled = false; + } + + if (delta & state & RENDER_BLEND) { // FIXME: some .TGA are buggy, have a completely empty alpha channel // if such brushes are rendered in this loop they would be totally transparent with GL_MODULATE // so I decided using GL_DECAL instead // if an empty-alpha-channel or nearly-empty texture is used. It will be blank-transparent. // this could get better if you can get glTexEnviv (GL_TEXTURE_ENV, to work .. patches are welcome - glEnable( GL_BLEND ); - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - } - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_BLEND ) { - glDisable( GL_BLEND ); - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - } - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_CULLFACE, GL_CULL_FACE ); - - if ( delta & state & RENDER_SMOOTH ) { - glShadeModel( GL_SMOOTH ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_SMOOTH ) { - glShadeModel( GL_FLAT ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_SCALED, GL_NORMALIZE ); // not GL_RESCALE_NORMAL - - setState( state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST ); - - if ( delta & state & RENDER_DEPTHWRITE ) { - glDepthMask( GL_TRUE ); + glEnable(GL_BLEND); + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + } + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_BLEND) { + glDisable(GL_BLEND); + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + } + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_CULLFACE, GL_CULL_FACE); + + if (delta & state & RENDER_SMOOTH) { + glShadeModel(GL_SMOOTH); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_SMOOTH) { + glShadeModel(GL_FLAT); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_SCALED, GL_NORMALIZE); // not GL_RESCALE_NORMAL + + setState(state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST); + + if (delta & state & RENDER_DEPTHWRITE) { + glDepthMask(GL_TRUE); #if DEBUG_RENDER - GLboolean depthEnabled; + GLboolean depthEnabled; glGetBooleanv( GL_DEPTH_WRITEMASK, &depthEnabled ); ASSERT_MESSAGE( depthEnabled, "failed to set depth buffer mask bit" ); #endif - debug_string( "enabled depth-buffer writing" ); + debug_string("enabled depth-buffer writing"); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_DEPTHWRITE ) { - glDepthMask( GL_FALSE ); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_DEPTHWRITE) { + glDepthMask(GL_FALSE); #if DEBUG_RENDER - GLboolean depthEnabled; + GLboolean depthEnabled; glGetBooleanv( GL_DEPTH_WRITEMASK, &depthEnabled ); ASSERT_MESSAGE( !depthEnabled, "failed to set depth buffer mask bit" ); #endif - debug_string( "disabled depth-buffer writing" ); - - GlobalOpenGL_debugAssertNoErrors(); - } - - if ( delta & state & RENDER_COLOURWRITE ) { - glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); - GlobalOpenGL_debugAssertNoErrors(); - } - else if ( delta & ~state & RENDER_COLOURWRITE ) { - glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST ); - - if ( delta & state & RENDER_COLOURARRAY ) { - glEnableClientState( GL_COLOR_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - debug_colour( "enabling color_array" ); - g_colorArray_enabled = true; - } - else if ( delta & ~state & RENDER_COLOURARRAY ) { - glDisableClientState( GL_COLOR_ARRAY ); - glColor4fv( vector4_to_array( self.m_colour ) ); - debug_colour( "cleaning color_array" ); - GlobalOpenGL_debugAssertNoErrors(); - g_colorArray_enabled = false; - } - - if ( delta & ~state & RENDER_COLOURCHANGE ) { - glColor4fv( vector4_to_array( self.m_colour ) ); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState( state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE ); - setState( state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH ); - - setState( state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE ); - setState( state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH ); - - setState( state, delta, RENDER_FOG, GL_FOG ); - - if ( ( state & RENDER_FOG ) != 0 ) { - setFogState( self.m_fog ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_fog = self.m_fog; - } - - if ( state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc ) { - glDepthFunc( self.m_depthfunc ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_depthfunc = self.m_depthfunc; - } - - if ( state & RENDER_LINESTIPPLE - && ( self.m_linestipple_factor != current.m_linestipple_factor - || self.m_linestipple_pattern != current.m_linestipple_pattern ) ) { - glLineStipple( self.m_linestipple_factor, self.m_linestipple_pattern ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_linestipple_factor = self.m_linestipple_factor; - current.m_linestipple_pattern = self.m_linestipple_pattern; - } - - - if ( state & RENDER_ALPHATEST - && ( self.m_alphafunc != current.m_alphafunc - || self.m_alpharef != current.m_alpharef ) ) { - glAlphaFunc( self.m_alphafunc, self.m_alpharef ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_alphafunc = self.m_alphafunc; - current.m_alpharef = self.m_alpharef; - } - - { - GLint texture0 = 0; - GLint texture1 = 0; - GLint texture2 = 0; - GLint texture3 = 0; - GLint texture4 = 0; - GLint texture5 = 0; - GLint texture6 = 0; - GLint texture7 = 0; - //if(state & RENDER_TEXTURE) != 0) - { - texture0 = self.m_texture; - texture1 = self.m_texture1; - texture2 = self.m_texture2; - texture3 = self.m_texture3; - texture4 = self.m_texture4; - texture5 = self.m_texture5; - texture6 = self.m_texture6; - texture7 = self.m_texture7; - } - - if ( GlobalOpenGL().GL_1_3() ) { - setTextureState( current.m_texture, texture0, GL_TEXTURE0 ); - setTextureState( current.m_texture1, texture1, GL_TEXTURE1 ); - setTextureState( current.m_texture2, texture2, GL_TEXTURE2 ); - setTextureState( current.m_texture3, texture3, GL_TEXTURE3 ); - setTextureState( current.m_texture4, texture4, GL_TEXTURE4 ); - setTextureState( current.m_texture5, texture5, GL_TEXTURE5 ); - setTextureState( current.m_texture6, texture6, GL_TEXTURE6 ); - setTextureState( current.m_texture7, texture7, GL_TEXTURE7 ); - } - else - { - setTextureState( current.m_texture, texture0 ); - } - } - - - if ( state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3] ) { - debug_colour( "setting alpha" ); - glColor4f( 1,1,1,self.m_colour[3] ); - GlobalOpenGL_debugAssertNoErrors(); - } - - if ( !( state & RENDER_TEXTURE ) - && ( self.m_colour[0] != current.m_colour[0] - || self.m_colour[1] != current.m_colour[1] - || self.m_colour[2] != current.m_colour[2] - || self.m_colour[3] != current.m_colour[3] ) ) { - glColor4fv( vector4_to_array( self.m_colour ) ); - debug_colour( "setting non-texture" ); - GlobalOpenGL_debugAssertNoErrors(); - } - current.m_colour = self.m_colour; - - if ( state & RENDER_BLEND - && ( self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst ) ) { - glBlendFunc( self.m_blend_src, self.m_blend_dst ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_blend_src = self.m_blend_src; - current.m_blend_dst = self.m_blend_dst; - } - - if ( !( state & RENDER_FILL ) - && self.m_linewidth != current.m_linewidth ) { - glLineWidth( self.m_linewidth ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_linewidth = self.m_linewidth; - } - - if ( !( state & RENDER_FILL ) - && self.m_pointsize != current.m_pointsize ) { - glPointSize( self.m_pointsize ); - GlobalOpenGL_debugAssertNoErrors(); - current.m_pointsize = self.m_pointsize; - } - - current.m_state = state; - - GlobalOpenGL_debugAssertNoErrors(); -} - -void Renderables_flush( OpenGLStateBucket::Renderables& renderables, OpenGLState& current, unsigned int globalstate, const Vector3& viewer ){ - const Matrix4* transform = 0; - glPushMatrix(); - for ( OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i ) - { - //qglLoadMatrixf(i->m_transform); - if ( !transform || ( transform != ( *i ).m_transform && !matrix4_affine_equal( *transform, *( *i ).m_transform ) ) ) { - count_transform(); - transform = ( *i ).m_transform; - glPopMatrix(); - glPushMatrix(); - glMultMatrixf( reinterpret_cast( transform ) ); - glFrontFace( ( ( current.m_state & RENDER_CULLFACE ) != 0 && matrix4_handedness( *transform ) == MATRIX4_RIGHTHANDED ) ? GL_CW : GL_CCW ); - } - - count_prim(); - - if ( current.m_program != 0 && ( *i ).m_light != 0 ) { - const IShader& lightShader = static_cast( ( *i ).m_light->getShader() )->getShader(); - if ( lightShader.firstLayer() != 0 ) { - GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number; - GLuint attenuation_z = lightShader.lightFalloffImage() != 0 - ? lightShader.lightFalloffImage()->texture_number - : static_cast( g_defaultPointLight )->getShader().lightFalloffImage()->texture_number; - - setTextureState( current.m_texture3, attenuation_xy, GL_TEXTURE3 ); - glActiveTexture( GL_TEXTURE3 ); - glBindTexture( GL_TEXTURE_2D, attenuation_xy ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER ); - - setTextureState( current.m_texture4, attenuation_z, GL_TEXTURE4 ); - glActiveTexture( GL_TEXTURE4 ); - glBindTexture( GL_TEXTURE_2D, attenuation_z ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - - - AABB lightBounds( ( *i ).m_light->aabb() ); - - Matrix4 world2light( g_matrix4_identity ); - - if ( ( *i ).m_light->isProjected() ) { - world2light = ( *i ).m_light->projection(); - matrix4_multiply_by_matrix4( world2light, matrix4_transposed( ( *i ).m_light->rotation() ) ); - matrix4_translate_by_vec3( world2light, vector3_negated( lightBounds.origin ) ); // world->lightBounds - } - if ( !( *i ).m_light->isProjected() ) { - matrix4_translate_by_vec3( world2light, Vector3( 0.5f, 0.5f, 0.5f ) ); - matrix4_scale_by_vec3( world2light, Vector3( 0.5f, 0.5f, 0.5f ) ); - matrix4_scale_by_vec3( world2light, Vector3( 1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), 1.0f / lightBounds.extents.z() ) ); - matrix4_multiply_by_matrix4( world2light, matrix4_transposed( ( *i ).m_light->rotation() ) ); - matrix4_translate_by_vec3( world2light, vector3_negated( lightBounds.origin ) ); // world->lightBounds - } - - current.m_program->setParameters( viewer, *( *i ).m_transform, lightBounds.origin + ( *i ).m_light->offset(), ( *i ).m_light->colour(), world2light ); - debug_string( "set lightBounds parameters" ); - } - } - - ( *i ).m_renderable->render( current.m_state ); - } - glPopMatrix(); - renderables.clear(); -} - -void OpenGLStateBucket::render( OpenGLState& current, unsigned int globalstate, const Vector3& viewer ){ - if ( ( globalstate & m_state.m_state & RENDER_SCREEN ) != 0 ) { - OpenGLState_apply( m_state, current, globalstate ); - debug_colour( "screen fill" ); + debug_string("disabled depth-buffer writing"); + + GlobalOpenGL_debugAssertNoErrors(); + } + + if (delta & state & RENDER_COLOURWRITE) { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + GlobalOpenGL_debugAssertNoErrors(); + } else if (delta & ~state & RENDER_COLOURWRITE) { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST); + + if (delta & state & RENDER_COLOURARRAY) { + glEnableClientState(GL_COLOR_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + debug_colour("enabling color_array"); + g_colorArray_enabled = true; + } else if (delta & ~state & RENDER_COLOURARRAY) { + glDisableClientState(GL_COLOR_ARRAY); + glColor4fv(vector4_to_array(self.m_colour)); + debug_colour("cleaning color_array"); + GlobalOpenGL_debugAssertNoErrors(); + g_colorArray_enabled = false; + } + + if (delta & ~state & RENDER_COLOURCHANGE) { + glColor4fv(vector4_to_array(self.m_colour)); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState(state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE); + setState(state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH); + + setState(state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE); + setState(state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH); + + setState(state, delta, RENDER_FOG, GL_FOG); + + if ((state & RENDER_FOG) != 0) { + setFogState(self.m_fog); + GlobalOpenGL_debugAssertNoErrors(); + current.m_fog = self.m_fog; + } + + if (state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc) { + glDepthFunc(self.m_depthfunc); + GlobalOpenGL_debugAssertNoErrors(); + current.m_depthfunc = self.m_depthfunc; + } + + if (state & RENDER_LINESTIPPLE + && (self.m_linestipple_factor != current.m_linestipple_factor + || self.m_linestipple_pattern != current.m_linestipple_pattern)) { + glLineStipple(self.m_linestipple_factor, self.m_linestipple_pattern); + GlobalOpenGL_debugAssertNoErrors(); + current.m_linestipple_factor = self.m_linestipple_factor; + current.m_linestipple_pattern = self.m_linestipple_pattern; + } + + + if (state & RENDER_ALPHATEST + && (self.m_alphafunc != current.m_alphafunc + || self.m_alpharef != current.m_alpharef)) { + glAlphaFunc(self.m_alphafunc, self.m_alpharef); + GlobalOpenGL_debugAssertNoErrors(); + current.m_alphafunc = self.m_alphafunc; + current.m_alpharef = self.m_alpharef; + } + + { + GLint texture0 = 0; + GLint texture1 = 0; + GLint texture2 = 0; + GLint texture3 = 0; + GLint texture4 = 0; + GLint texture5 = 0; + GLint texture6 = 0; + GLint texture7 = 0; + //if(state & RENDER_TEXTURE) != 0) + { + texture0 = self.m_texture; + texture1 = self.m_texture1; + texture2 = self.m_texture2; + texture3 = self.m_texture3; + texture4 = self.m_texture4; + texture5 = self.m_texture5; + texture6 = self.m_texture6; + texture7 = self.m_texture7; + } + + if (GlobalOpenGL().GL_1_3()) { + setTextureState(current.m_texture, texture0, GL_TEXTURE0); + setTextureState(current.m_texture1, texture1, GL_TEXTURE1); + setTextureState(current.m_texture2, texture2, GL_TEXTURE2); + setTextureState(current.m_texture3, texture3, GL_TEXTURE3); + setTextureState(current.m_texture4, texture4, GL_TEXTURE4); + setTextureState(current.m_texture5, texture5, GL_TEXTURE5); + setTextureState(current.m_texture6, texture6, GL_TEXTURE6); + setTextureState(current.m_texture7, texture7, GL_TEXTURE7); + } else { + setTextureState(current.m_texture, texture0); + } + } + + + if (state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3]) { + debug_colour("setting alpha"); + glColor4f(1, 1, 1, self.m_colour[3]); + GlobalOpenGL_debugAssertNoErrors(); + } + + if (!(state & RENDER_TEXTURE) + && (self.m_colour[0] != current.m_colour[0] + || self.m_colour[1] != current.m_colour[1] + || self.m_colour[2] != current.m_colour[2] + || self.m_colour[3] != current.m_colour[3])) { + glColor4fv(vector4_to_array(self.m_colour)); + debug_colour("setting non-texture"); + GlobalOpenGL_debugAssertNoErrors(); + } + current.m_colour = self.m_colour; + + if (state & RENDER_BLEND + && (self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst)) { + glBlendFunc(self.m_blend_src, self.m_blend_dst); + GlobalOpenGL_debugAssertNoErrors(); + current.m_blend_src = self.m_blend_src; + current.m_blend_dst = self.m_blend_dst; + } + + if (!(state & RENDER_FILL) + && self.m_linewidth != current.m_linewidth) { + glLineWidth(self.m_linewidth); + GlobalOpenGL_debugAssertNoErrors(); + current.m_linewidth = self.m_linewidth; + } + + if (!(state & RENDER_FILL) + && self.m_pointsize != current.m_pointsize) { + glPointSize(self.m_pointsize); + GlobalOpenGL_debugAssertNoErrors(); + current.m_pointsize = self.m_pointsize; + } + + current.m_state = state; + + GlobalOpenGL_debugAssertNoErrors(); +} + +void Renderables_flush(OpenGLStateBucket::Renderables &renderables, OpenGLState ¤t, unsigned int globalstate, + const Vector3 &viewer) +{ + const Matrix4 *transform = 0; + glPushMatrix(); + for (OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i) { + //qglLoadMatrixf(i->m_transform); + if (!transform || (transform != (*i).m_transform && !matrix4_affine_equal(*transform, *(*i).m_transform))) { + count_transform(); + transform = (*i).m_transform; + glPopMatrix(); + glPushMatrix(); + glMultMatrixf(reinterpret_cast( transform )); + glFrontFace( + ((current.m_state & RENDER_CULLFACE) != 0 && matrix4_handedness(*transform) == MATRIX4_RIGHTHANDED) + ? GL_CW : GL_CCW); + } + + count_prim(); + + if (current.m_program != 0 && (*i).m_light != 0) { + const IShader &lightShader = static_cast((*i).m_light->getShader())->getShader(); + if (lightShader.firstLayer() != 0) { + GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number; + GLuint attenuation_z = lightShader.lightFalloffImage() != 0 + ? lightShader.lightFalloffImage()->texture_number + : static_cast( g_defaultPointLight )->getShader().lightFalloffImage()->texture_number; + + setTextureState(current.m_texture3, attenuation_xy, GL_TEXTURE3); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, attenuation_xy); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + + setTextureState(current.m_texture4, attenuation_z, GL_TEXTURE4); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, attenuation_z); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + + AABB lightBounds((*i).m_light->aabb()); + + Matrix4 world2light(g_matrix4_identity); + + if ((*i).m_light->isProjected()) { + world2light = (*i).m_light->projection(); + matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation())); + matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds + } + if (!(*i).m_light->isProjected()) { + matrix4_translate_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f)); + matrix4_scale_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f)); + matrix4_scale_by_vec3(world2light, + Vector3(1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), + 1.0f / lightBounds.extents.z())); + matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation())); + matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds + } + + current.m_program->setParameters(viewer, *(*i).m_transform, lightBounds.origin + (*i).m_light->offset(), + (*i).m_light->colour(), world2light); + debug_string("set lightBounds parameters"); + } + } + + (*i).m_renderable->render(current.m_state); + } + glPopMatrix(); + renderables.clear(); +} + +void OpenGLStateBucket::render(OpenGLState ¤t, unsigned int globalstate, const Vector3 &viewer) +{ + if ((globalstate & m_state.m_state & RENDER_SCREEN) != 0) { + OpenGLState_apply(m_state, current, globalstate); + debug_colour("screen fill"); - glMatrixMode( GL_PROJECTION ); - glPushMatrix(); - glLoadMatrixf( reinterpret_cast( &g_matrix4_identity ) ); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(reinterpret_cast( &g_matrix4_identity )); - glMatrixMode( GL_MODELVIEW ); - glPushMatrix(); - glLoadMatrixf( reinterpret_cast( &g_matrix4_identity ) ); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(reinterpret_cast( &g_matrix4_identity )); - glBegin( GL_QUADS ); - glVertex3f( -1, -1, 0 ); - glVertex3f( 1, -1, 0 ); - glVertex3f( 1, 1, 0 ); - glVertex3f( -1, 1, 0 ); - glEnd(); + glBegin(GL_QUADS); + glVertex3f(-1, -1, 0); + glVertex3f(1, -1, 0); + glVertex3f(1, 1, 0); + glVertex3f(-1, 1, 0); + glEnd(); - glMatrixMode( GL_PROJECTION ); - glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); - glMatrixMode( GL_MODELVIEW ); - glPopMatrix(); - } - else if ( !m_renderables.empty() ) { - OpenGLState_apply( m_state, current, globalstate ); - Renderables_flush( m_renderables, current, globalstate, viewer ); - } + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } else if (!m_renderables.empty()) { + OpenGLState_apply(m_state, current, globalstate); + Renderables_flush(m_renderables, current, globalstate, viewer); + } } -class OpenGLStateMap : public OpenGLStateLibrary -{ -typedef std::map States; -States m_states; +class OpenGLStateMap : public OpenGLStateLibrary { + typedef std::map States; + States m_states; public: -~OpenGLStateMap(){ - ASSERT_MESSAGE( m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty" ); -} - -typedef States::iterator iterator; -iterator begin(){ - return m_states.begin(); -} -iterator end(){ - return m_states.end(); -} - -void getDefaultState( OpenGLState& state ) const { - OpenGLState_constructDefault( state ); -} - -void insert( const char* name, const OpenGLState& state ){ - bool inserted = m_states.insert( States::value_type( name, state ) ).second; - ASSERT_MESSAGE( inserted, "OpenGLStateMap::insert: " << name << " already exists" ); -} -void erase( const char* name ){ - std::size_t count = m_states.erase( name ); - ASSERT_MESSAGE( count == 1, "OpenGLStateMap::erase: " << name << " does not exist" ); -} - -iterator find( const char* name ){ - return m_states.find( name ); -} + ~OpenGLStateMap() + { + ASSERT_MESSAGE(m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty"); + } + + typedef States::iterator iterator; + + iterator begin() + { + return m_states.begin(); + } + + iterator end() + { + return m_states.end(); + } + + void getDefaultState(OpenGLState &state) const + { + OpenGLState_constructDefault(state); + } + + void insert(const char *name, const OpenGLState &state) + { + bool inserted = m_states.insert(States::value_type(name, state)).second; + ASSERT_MESSAGE(inserted, "OpenGLStateMap::insert: " << name << " already exists"); + } + + void erase(const char *name) + { + std::size_t count = m_states.erase(name); + ASSERT_MESSAGE(count == 1, "OpenGLStateMap::erase: " << name << " does not exist"); + } + + iterator find(const char *name) + { + return m_states.find(name); + } }; -OpenGLStateMap* g_openglStates = 0; +OpenGLStateMap *g_openglStates = 0; -inline GLenum convertBlendFactor( BlendFactor factor ){ - switch ( factor ) - { - case BLEND_ZERO: - return GL_ZERO; - case BLEND_ONE: - return GL_ONE; - case BLEND_SRC_COLOUR: - return GL_SRC_COLOR; - case BLEND_ONE_MINUS_SRC_COLOUR: - return GL_ONE_MINUS_SRC_COLOR; - case BLEND_SRC_ALPHA: - return GL_SRC_ALPHA; - case BLEND_ONE_MINUS_SRC_ALPHA: - return GL_ONE_MINUS_SRC_ALPHA; - case BLEND_DST_COLOUR: - return GL_DST_COLOR; - case BLEND_ONE_MINUS_DST_COLOUR: - return GL_ONE_MINUS_DST_COLOR; - case BLEND_DST_ALPHA: - return GL_DST_ALPHA; - case BLEND_ONE_MINUS_DST_ALPHA: - return GL_ONE_MINUS_DST_ALPHA; - case BLEND_SRC_ALPHA_SATURATE: - return GL_SRC_ALPHA_SATURATE; - } - return GL_ZERO; +inline GLenum convertBlendFactor(BlendFactor factor) +{ + switch (factor) { + case BLEND_ZERO: + return GL_ZERO; + case BLEND_ONE: + return GL_ONE; + case BLEND_SRC_COLOUR: + return GL_SRC_COLOR; + case BLEND_ONE_MINUS_SRC_COLOUR: + return GL_ONE_MINUS_SRC_COLOR; + case BLEND_SRC_ALPHA: + return GL_SRC_ALPHA; + case BLEND_ONE_MINUS_SRC_ALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + case BLEND_DST_COLOUR: + return GL_DST_COLOR; + case BLEND_ONE_MINUS_DST_COLOUR: + return GL_ONE_MINUS_DST_COLOR; + case BLEND_DST_ALPHA: + return GL_DST_ALPHA; + case BLEND_ONE_MINUS_DST_ALPHA: + return GL_ONE_MINUS_DST_ALPHA; + case BLEND_SRC_ALPHA_SATURATE: + return GL_SRC_ALPHA_SATURATE; + } + return GL_ZERO; } /// \todo Define special-case shaders in a data file. -void OpenGLShader::construct( const char* name ){ - OpenGLState& state = appendDefaultPass(); - switch ( name[0] ) - { - case '(': - sscanf( name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); - state.m_colour[3] = 1.0f; - state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - break; - - case '[': - sscanf( name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); - state.m_colour[3] = 0.5f; - state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND; - state.m_sort = OpenGLState::eSortTranslucent; - break; - - case '<': - sscanf( name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); - state.m_colour[3] = 1; - state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - state.m_depthfunc = GL_LESS; - state.m_linewidth = 1; - state.m_pointsize = 1; - break; - - case '$': - { - OpenGLStateMap::iterator i = g_openglStates->find( name ); - if ( i != g_openglStates->end() ) { - state = ( *i ).second; - break; - } - } - if ( string_equal( name + 1, "POINT" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst; - state.m_pointsize = 4; - } - else if ( string_equal( name + 1, "SELPOINT" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst + 1; - state.m_pointsize = 4; - } - else if ( string_equal( name + 1, "BIGPOINT" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst; - state.m_pointsize = 6; - } - else if ( string_equal( name + 1, "PIVOT" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortGUI1; - state.m_linewidth = 2; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState& hiddenLine = appendDefaultPass(); - hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_LINESTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortGUI0; - hiddenLine.m_linewidth = 2; - hiddenLine.m_depthfunc = GL_GREATER; - } - else if ( string_equal( name + 1, "LATTICE" ) ) { - state.m_colour[0] = 1; - state.m_colour[1] = 0.5; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst; - } - else if ( string_equal( name + 1, "WIREFRAME" ) ) { - state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - } - else if ( string_equal( name + 1, "CAM_HIGHLIGHT" ) ) { - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 0.3f; - state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortHighlight; - state.m_depthfunc = GL_LEQUAL; - } - else if ( string_equal( name + 1, "CAM_OVERLAY" ) ) { +void OpenGLShader::construct(const char *name) +{ + OpenGLState &state = appendDefaultPass(); + switch (name[0]) { + case '(': + sscanf(name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]); + state.m_colour[3] = 1.0f; + state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | + RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + break; + + case '[': + sscanf(name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]); + state.m_colour[3] = 0.5f; + state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | + RENDER_DEPTHWRITE | RENDER_BLEND; + state.m_sort = OpenGLState::eSortTranslucent; + break; + + case '<': + sscanf(name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]); + state.m_colour[3] = 1; + state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + state.m_depthfunc = GL_LESS; + state.m_linewidth = 1; + state.m_pointsize = 1; + break; + + case '$': { + OpenGLStateMap::iterator i = g_openglStates->find(name); + if (i != g_openglStates->end()) { + state = (*i).second; + break; + } + } + if (string_equal(name + 1, "POINT")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst; + state.m_pointsize = 4; + } else if (string_equal(name + 1, "SELPOINT")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst + 1; + state.m_pointsize = 4; + } else if (string_equal(name + 1, "BIGPOINT")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst; + state.m_pointsize = 6; + } else if (string_equal(name + 1, "PIVOT")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortGUI1; + state.m_linewidth = 2; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState &hiddenLine = appendDefaultPass(); + hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortGUI0; + hiddenLine.m_linewidth = 2; + hiddenLine.m_depthfunc = GL_GREATER; + } else if (string_equal(name + 1, "LATTICE")) { + state.m_colour[0] = 1; + state.m_colour[1] = 0.5; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst; + } else if (string_equal(name + 1, "WIREFRAME")) { + state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + } else if (string_equal(name + 1, "CAM_HIGHLIGHT")) { + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 0.3f; + state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE | + RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortHighlight; + state.m_depthfunc = GL_LEQUAL; + } else if (string_equal(name + 1, "CAM_OVERLAY")) { #if 0 - state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; state.m_sort = OpenGLState::eSortOverlayFirst; #else - state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_OFFSETLINE; - state.m_sort = OpenGLState::eSortOverlayFirst + 1; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState& hiddenLine = appendDefaultPass(); - hiddenLine.m_colour[0] = 0.75; - hiddenLine.m_colour[1] = 0.75; - hiddenLine.m_colour[2] = 0.75; - hiddenLine.m_colour[3] = 1; - hiddenLine.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_OFFSETLINE | RENDER_LINESTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortOverlayFirst; - hiddenLine.m_depthfunc = GL_GREATER; - hiddenLine.m_linestipple_factor = 2; + state.m_state = + RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_OFFSETLINE; + state.m_sort = OpenGLState::eSortOverlayFirst + 1; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState &hiddenLine = appendDefaultPass(); + hiddenLine.m_colour[0] = 0.75; + hiddenLine.m_colour[1] = 0.75; + hiddenLine.m_colour[2] = 0.75; + hiddenLine.m_colour[3] = 1; + hiddenLine.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_OFFSETLINE | + RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortOverlayFirst; + hiddenLine.m_depthfunc = GL_GREATER; + hiddenLine.m_linestipple_factor = 2; #endif - } - else if ( string_equal( name + 1, "XY_OVERLAY" ) ) { - state.m_colour[0] = g_xywindow_globals.color_selbrushes[0]; - state.m_colour[1] = g_xywindow_globals.color_selbrushes[1]; - state.m_colour[2] = g_xywindow_globals.color_selbrushes[2]; - state.m_colour[3] = 1; - state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE; - state.m_sort = OpenGLState::eSortOverlayFirst; - state.m_linewidth = 2; - state.m_linestipple_factor = 3; - } - else if ( string_equal( name + 1, "DEBUG_CLIPPED" ) ) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortLast; - } - else if ( string_equal( name + 1, "POINTFILE" ) ) { - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - state.m_linewidth = 4; - } - else if ( string_equal( name + 1, "LIGHT_SPHERE" ) ) { - state.m_colour[0] = .15f * .95f; - state.m_colour[1] = .15f * .95f; - state.m_colour[2] = .15f * .95f; - state.m_colour[3] = 1; - state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_blend_src = GL_ONE; - state.m_blend_dst = GL_ONE; - state.m_sort = OpenGLState::eSortTranslucent; - } - else if ( string_equal( name + 1, "Q3MAP2_LIGHT_SPHERE" ) ) { - state.m_colour[0] = .05f; - state.m_colour[1] = .05f; - state.m_colour[2] = .05f; - state.m_colour[3] = 1; - state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL; - state.m_blend_src = GL_ONE; - state.m_blend_dst = GL_ONE; - state.m_sort = OpenGLState::eSortTranslucent; - } - else if ( string_equal( name + 1, "WIRE_OVERLAY" ) ) { + } else if (string_equal(name + 1, "XY_OVERLAY")) { + state.m_colour[0] = g_xywindow_globals.color_selbrushes[0]; + state.m_colour[1] = g_xywindow_globals.color_selbrushes[1]; + state.m_colour[2] = g_xywindow_globals.color_selbrushes[2]; + state.m_colour[3] = 1; + state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE; + state.m_sort = OpenGLState::eSortOverlayFirst; + state.m_linewidth = 2; + state.m_linestipple_factor = 3; + } else if (string_equal(name + 1, "DEBUG_CLIPPED")) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortLast; + } else if (string_equal(name + 1, "POINTFILE")) { + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + state.m_linewidth = 4; + } else if (string_equal(name + 1, "LIGHT_SPHERE")) { + state.m_colour[0] = .15f * .95f; + state.m_colour[1] = .15f * .95f; + state.m_colour[2] = .15f * .95f; + state.m_colour[3] = 1; + state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | + RENDER_DEPTHWRITE; + state.m_blend_src = GL_ONE; + state.m_blend_dst = GL_ONE; + state.m_sort = OpenGLState::eSortTranslucent; + } else if (string_equal(name + 1, "Q3MAP2_LIGHT_SPHERE")) { + state.m_colour[0] = .05f; + state.m_colour[1] = .05f; + state.m_colour[2] = .05f; + state.m_colour[3] = 1; + state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL; + state.m_blend_src = GL_ONE; + state.m_blend_dst = GL_ONE; + state.m_sort = OpenGLState::eSortTranslucent; + } else if (string_equal(name + 1, "WIRE_OVERLAY")) { #if 0 - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; state.m_sort = OpenGLState::eSortOverlayFirst; #else - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; - state.m_sort = OpenGLState::eSortGUI1; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState& hiddenLine = appendDefaultPass(); - hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_LINESTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortGUI0; - hiddenLine.m_depthfunc = GL_GREATER; + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | + RENDER_OVERRIDE; + state.m_sort = OpenGLState::eSortGUI1; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState &hiddenLine = appendDefaultPass(); + hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | + RENDER_OVERRIDE | RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortGUI0; + hiddenLine.m_depthfunc = GL_GREATER; #endif - } - else if ( string_equal( name + 1, "FLATSHADE_OVERLAY" ) ) { - state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; - state.m_sort = OpenGLState::eSortGUI1; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState& hiddenLine = appendDefaultPass(); - hiddenLine.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_POLYGONSTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortGUI0; - hiddenLine.m_depthfunc = GL_GREATER; - } - else if ( string_equal( name + 1, "CLIPPER_OVERLAY" ) ) { - state.m_colour[0] = g_xywindow_globals.color_clipper[0]; - state.m_colour[1] = g_xywindow_globals.color_clipper[1]; - state.m_colour[2] = g_xywindow_globals.color_clipper[2]; - state.m_colour[3] = 1; - state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE; - state.m_sort = OpenGLState::eSortOverlayFirst; - } - else if ( string_equal( name + 1, "OVERBRIGHT" ) ) { - const float lightScale = 2; - state.m_colour[0] = lightScale * 0.5f; - state.m_colour[1] = lightScale * 0.5f; - state.m_colour[2] = lightScale * 0.5f; - state.m_colour[3] = 0.5; - state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_SCREEN; - state.m_sort = OpenGLState::eSortOverbrighten; - state.m_blend_src = GL_DST_COLOR; - state.m_blend_dst = GL_SRC_COLOR; - } - else - { - // default to something recognisable.. =) - ERROR_MESSAGE( "hardcoded renderstate not found" ); - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 1; - state.m_colour[3] = 1; - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFirst; - } - break; - default: - // construction from IShader - m_shader = QERApp_Shader_ForName( name ); - - if ( g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && m_shader->getBump()->texture_number != 0 ) { // is a bump shader - state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | RENDER_COLOURWRITE | RENDER_PROGRAM; - state.m_colour[0] = 0; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_sort = OpenGLState::eSortOpaque; - - if ( g_ShaderCache->useShaderLanguage() ) { - state.m_program = &g_depthFillGLSL; - } - else - { - state.m_program = &g_depthFillARB; - } - - OpenGLState& bumpPass = appendDefaultPass(); - bumpPass.m_texture = m_shader->getDiffuse()->texture_number; - bumpPass.m_texture1 = m_shader->getBump()->texture_number; - bumpPass.m_texture2 = m_shader->getSpecular()->texture_number; - - bumpPass.m_state = RENDER_BLEND | RENDER_FILL | RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_SMOOTH | RENDER_BUMP | RENDER_PROGRAM; - - if ( g_ShaderCache->useShaderLanguage() ) { - bumpPass.m_state |= RENDER_LIGHTING; - bumpPass.m_program = &g_bumpGLSL; - } - else - { - bumpPass.m_program = &g_bumpARB; - } - - bumpPass.m_depthfunc = GL_LEQUAL; - bumpPass.m_sort = OpenGLState::eSortMultiFirst; - bumpPass.m_blend_src = GL_ONE; - bumpPass.m_blend_dst = GL_ONE; - } - else - { - state.m_texture = m_shader->getTexture()->texture_number; - - state.m_state = RENDER_FILL | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_LIGHTING | RENDER_SMOOTH; - if ( ( m_shader->getFlags() & QER_CULL ) != 0 ) { - if ( m_shader->getCull() == IShader::eCullBack ) { - state.m_state |= RENDER_CULLFACE; - } - } - else - { - state.m_state |= RENDER_CULLFACE; - } - if ( ( m_shader->getFlags() & QER_ALPHATEST ) != 0 ) { - state.m_state |= RENDER_ALPHATEST; - IShader::EAlphaFunc alphafunc; - m_shader->getAlphaFunc( &alphafunc, &state.m_alpharef ); - switch ( alphafunc ) - { - case IShader::eAlways: - state.m_alphafunc = GL_ALWAYS; - case IShader::eEqual: - state.m_alphafunc = GL_EQUAL; - case IShader::eLess: - state.m_alphafunc = GL_LESS; - case IShader::eGreater: - state.m_alphafunc = GL_GREATER; - case IShader::eLEqual: - state.m_alphafunc = GL_LEQUAL; - case IShader::eGEqual: - state.m_alphafunc = GL_GEQUAL; - } - } - reinterpret_cast( state.m_colour ) = m_shader->getTexture()->color; - state.m_colour[3] = 1.0f; - - if ( ( m_shader->getFlags() & QER_TRANS ) != 0 ) { - state.m_state |= RENDER_BLEND; - state.m_colour[3] = m_shader->getTrans(); - state.m_sort = OpenGLState::eSortTranslucent; - BlendFunc blendFunc = m_shader->getBlendFunc(); - state.m_blend_src = convertBlendFactor( blendFunc.m_src ); - state.m_blend_dst = convertBlendFactor( blendFunc.m_dst ); - if ( state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA ) { - state.m_state |= RENDER_DEPTHWRITE; - } - } - else - { - state.m_state |= RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - } - } - } + } else if (string_equal(name + 1, "FLATSHADE_OVERLAY")) { + state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | + RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | + RENDER_OVERRIDE; + state.m_sort = OpenGLState::eSortGUI1; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState &hiddenLine = appendDefaultPass(); + hiddenLine.m_state = + RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | + RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | + RENDER_POLYGONSTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortGUI0; + hiddenLine.m_depthfunc = GL_GREATER; + } else if (string_equal(name + 1, "CLIPPER_OVERLAY")) { + state.m_colour[0] = g_xywindow_globals.color_clipper[0]; + state.m_colour[1] = g_xywindow_globals.color_clipper[1]; + state.m_colour[2] = g_xywindow_globals.color_clipper[2]; + state.m_colour[3] = 1; + state.m_state = + RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE; + state.m_sort = OpenGLState::eSortOverlayFirst; + } else if (string_equal(name + 1, "OVERBRIGHT")) { + const float lightScale = 2; + state.m_colour[0] = lightScale * 0.5f; + state.m_colour[1] = lightScale * 0.5f; + state.m_colour[2] = lightScale * 0.5f; + state.m_colour[3] = 0.5; + state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_SCREEN; + state.m_sort = OpenGLState::eSortOverbrighten; + state.m_blend_src = GL_DST_COLOR; + state.m_blend_dst = GL_SRC_COLOR; + } else { + // default to something recognisable.. =) + ERROR_MESSAGE("hardcoded renderstate not found"); + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 1; + state.m_colour[3] = 1; + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFirst; + } + break; + default: + // construction from IShader + m_shader = QERApp_Shader_ForName(name); + + if (g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && + m_shader->getBump()->texture_number != 0) { // is a bump shader + state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | + RENDER_COLOURWRITE | RENDER_PROGRAM; + state.m_colour[0] = 0; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_sort = OpenGLState::eSortOpaque; + + if (g_ShaderCache->useShaderLanguage()) { + state.m_program = &g_depthFillGLSL; + } else { + state.m_program = &g_depthFillARB; + } + + OpenGLState &bumpPass = appendDefaultPass(); + bumpPass.m_texture = m_shader->getDiffuse()->texture_number; + bumpPass.m_texture1 = m_shader->getBump()->texture_number; + bumpPass.m_texture2 = m_shader->getSpecular()->texture_number; + + bumpPass.m_state = + RENDER_BLEND | RENDER_FILL | RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | + RENDER_SMOOTH | RENDER_BUMP | RENDER_PROGRAM; + + if (g_ShaderCache->useShaderLanguage()) { + bumpPass.m_state |= RENDER_LIGHTING; + bumpPass.m_program = &g_bumpGLSL; + } else { + bumpPass.m_program = &g_bumpARB; + } + + bumpPass.m_depthfunc = GL_LEQUAL; + bumpPass.m_sort = OpenGLState::eSortMultiFirst; + bumpPass.m_blend_src = GL_ONE; + bumpPass.m_blend_dst = GL_ONE; + } else { + state.m_texture = m_shader->getTexture()->texture_number; + + state.m_state = RENDER_FILL | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_LIGHTING | + RENDER_SMOOTH; + if ((m_shader->getFlags() & QER_CULL) != 0) { + if (m_shader->getCull() == IShader::eCullBack) { + state.m_state |= RENDER_CULLFACE; + } + } else { + state.m_state |= RENDER_CULLFACE; + } + if ((m_shader->getFlags() & QER_ALPHATEST) != 0) { + state.m_state |= RENDER_ALPHATEST; + IShader::EAlphaFunc alphafunc; + m_shader->getAlphaFunc(&alphafunc, &state.m_alpharef); + switch (alphafunc) { + case IShader::eAlways: + state.m_alphafunc = GL_ALWAYS; + case IShader::eEqual: + state.m_alphafunc = GL_EQUAL; + case IShader::eLess: + state.m_alphafunc = GL_LESS; + case IShader::eGreater: + state.m_alphafunc = GL_GREATER; + case IShader::eLEqual: + state.m_alphafunc = GL_LEQUAL; + case IShader::eGEqual: + state.m_alphafunc = GL_GEQUAL; + } + } + reinterpret_cast( state.m_colour ) = m_shader->getTexture()->color; + state.m_colour[3] = 1.0f; + + if ((m_shader->getFlags() & QER_TRANS) != 0) { + state.m_state |= RENDER_BLEND; + state.m_colour[3] = m_shader->getTrans(); + state.m_sort = OpenGLState::eSortTranslucent; + BlendFunc blendFunc = m_shader->getBlendFunc(); + state.m_blend_src = convertBlendFactor(blendFunc.m_src); + state.m_blend_dst = convertBlendFactor(blendFunc.m_dst); + if (state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA) { + state.m_state |= RENDER_DEPTHWRITE; + } + } else { + state.m_state |= RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + } + } + } } #include "modulesystem/singletonmodule.h" #include "modulesystem/moduleregistry.h" -class OpenGLStateLibraryAPI -{ -OpenGLStateMap m_stateMap; +class OpenGLStateLibraryAPI { + OpenGLStateMap m_stateMap; public: -typedef OpenGLStateLibrary Type; -STRING_CONSTANT( Name, "*" ); + typedef OpenGLStateLibrary Type; -OpenGLStateLibraryAPI(){ - g_openglStates = &m_stateMap; -} -~OpenGLStateLibraryAPI(){ - g_openglStates = 0; -} -OpenGLStateLibrary* getTable(){ - return &m_stateMap; -} + STRING_CONSTANT(Name, "*"); + + OpenGLStateLibraryAPI() + { + g_openglStates = &m_stateMap; + } + + ~OpenGLStateLibraryAPI() + { + g_openglStates = 0; + } + + OpenGLStateLibrary *getTable() + { + return &m_stateMap; + } }; typedef SingletonModule OpenGLStateLibraryModule; typedef Static StaticOpenGLStateLibraryModule; -StaticRegisterModule staticRegisterOpenGLStateLibrary( StaticOpenGLStateLibraryModule::instance() ); +StaticRegisterModule staticRegisterOpenGLStateLibrary(StaticOpenGLStateLibraryModule::instance()); -class ShaderCacheDependencies : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef -{ +class ShaderCacheDependencies + : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef { public: -ShaderCacheDependencies() : - GlobalShadersModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "shaders" ) ){ -} + ShaderCacheDependencies() : + GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders")) + { + } }; -class ShaderCacheAPI -{ -ShaderCache* m_shaderCache; +class ShaderCacheAPI { + ShaderCache *m_shaderCache; public: -typedef ShaderCache Type; -STRING_CONSTANT( Name, "*" ); + typedef ShaderCache Type; -ShaderCacheAPI(){ - ShaderCache_Construct(); + STRING_CONSTANT(Name, "*"); - m_shaderCache = GetShaderCache(); -} -~ShaderCacheAPI(){ - ShaderCache_Destroy(); -} -ShaderCache* getTable(){ - return m_shaderCache; -} + ShaderCacheAPI() + { + ShaderCache_Construct(); + + m_shaderCache = GetShaderCache(); + } + + ~ShaderCacheAPI() + { + ShaderCache_Destroy(); + } + + ShaderCache *getTable() + { + return m_shaderCache; + } }; typedef SingletonModule ShaderCacheModule; typedef Static StaticShaderCacheModule; -StaticRegisterModule staticRegisterShaderCache( StaticShaderCacheModule::instance() ); +StaticRegisterModule staticRegisterShaderCache(StaticShaderCacheModule::instance()); diff --git a/radiant/renderstate.h b/radiant/renderstate.h index 26707d93..f4ba496b 100644 --- a/radiant/renderstate.h +++ b/radiant/renderstate.h @@ -22,7 +22,8 @@ #if !defined( INCLUDED_RENDERSTATE_H ) #define INCLUDED_RENDERSTATE_H -void ShaderCache_setBumpEnabled( bool enabled ); +void ShaderCache_setBumpEnabled(bool enabled); + void ShaderCache_extensionsInitialised(); #endif diff --git a/radiant/scenegraph.cpp b/radiant/scenegraph.cpp index c1730c33..9fd58c10 100644 --- a/radiant/scenegraph.cpp +++ b/radiant/scenegraph.cpp @@ -34,232 +34,263 @@ #include "treemodel.h" template -class TypeIdMap -{ -typedef const char* TypeName; -typedef TypeName TypeNames[SIZE]; -TypeNames m_typeNames; -TypeName* m_typeNamesEnd; +class TypeIdMap { + typedef const char *TypeName; + typedef TypeName TypeNames[SIZE]; + TypeNames m_typeNames; + TypeName *m_typeNamesEnd; public: -TypeIdMap() : m_typeNamesEnd( m_typeNames ){ -} -TypeId getTypeId( const char* name ){ - TypeName *i = std::find_if(m_typeNames, m_typeNamesEnd, [&](const char *other) { - return string_equal(name, other); - }); - if ( i == m_typeNamesEnd ) { - ASSERT_MESSAGE( m_typeNamesEnd != m_typeNames + SIZE, "reached maximum number of type names supported (" << Unsigned( SIZE ) << ")" ); - *m_typeNamesEnd++ = name; - } - return i - m_typeNames; -} + TypeIdMap() : m_typeNamesEnd(m_typeNames) + { + } + + TypeId getTypeId(const char *name) + { + TypeName *i = std::find_if(m_typeNames, m_typeNamesEnd, [&](const char *other) { + return string_equal(name, other); + }); + if (i == m_typeNamesEnd) { + ASSERT_MESSAGE(m_typeNamesEnd != m_typeNames + SIZE, + "reached maximum number of type names supported (" << Unsigned(SIZE) << ")"); + *m_typeNamesEnd++ = name; + } + return i - m_typeNames; + } }; -class CompiledGraph : public scene::Graph, public scene::Instantiable::Observer -{ -typedef std::map InstanceMap; +class CompiledGraph : public scene::Graph, public scene::Instantiable::Observer { + typedef std::map InstanceMap; -InstanceMap m_instances; -scene::Instantiable::Observer* m_observer; -Signal0 m_boundsChanged; -scene::Path m_rootpath; -Signal0 m_sceneChangedCallbacks; + InstanceMap m_instances; + scene::Instantiable::Observer *m_observer; + Signal0 m_boundsChanged; + scene::Path m_rootpath; + Signal0 m_sceneChangedCallbacks; -TypeIdMap m_nodeTypeIds; -TypeIdMap m_instanceTypeIds; + TypeIdMap m_nodeTypeIds; + TypeIdMap m_instanceTypeIds; public: -CompiledGraph( scene::Instantiable::Observer* observer ) - : m_observer( observer ){ -} + CompiledGraph(scene::Instantiable::Observer *observer) + : m_observer(observer) + { + } -void addSceneChangedCallback( const SignalHandler& handler ){ - m_sceneChangedCallbacks.connectLast( handler ); -} -void sceneChanged(){ - m_sceneChangedCallbacks(); -} + void addSceneChangedCallback(const SignalHandler &handler) + { + m_sceneChangedCallbacks.connectLast(handler); + } -scene::Node& root(){ - ASSERT_MESSAGE( !m_rootpath.empty(), "scenegraph root does not exist" ); - return m_rootpath.top(); -} -void insert_root( scene::Node& root ){ - //globalOutputStream() << "insert_root\n"; + void sceneChanged() + { + m_sceneChangedCallbacks(); + } - ASSERT_MESSAGE( m_rootpath.empty(), "scenegraph root already exists" ); + scene::Node &root() + { + ASSERT_MESSAGE(!m_rootpath.empty(), "scenegraph root does not exist"); + return m_rootpath.top(); + } - root.IncRef(); + void insert_root(scene::Node &root) + { + //globalOutputStream() << "insert_root\n"; - Node_traverseSubgraph( root, InstanceSubgraphWalker( this, scene::Path(), 0 ) ); + ASSERT_MESSAGE(m_rootpath.empty(), "scenegraph root already exists"); - m_rootpath.push( makeReference( root ) ); -} -void erase_root(){ - //globalOutputStream() << "erase_root\n"; + root.IncRef(); - ASSERT_MESSAGE( !m_rootpath.empty(), "scenegraph root does not exist" ); + Node_traverseSubgraph(root, InstanceSubgraphWalker(this, scene::Path(), 0)); - scene::Node& root = m_rootpath.top(); + m_rootpath.push(makeReference(root)); + } - m_rootpath.pop(); + void erase_root() + { + //globalOutputStream() << "erase_root\n"; - Node_traverseSubgraph( root, UninstanceSubgraphWalker( this, scene::Path() ) ); + ASSERT_MESSAGE(!m_rootpath.empty(), "scenegraph root does not exist"); - root.DecRef(); -} -void boundsChanged(){ - m_boundsChanged(); -} + scene::Node &root = m_rootpath.top(); -void traverse( const Walker& walker ){ - traverse_subgraph( walker, m_instances.begin() ); -} + m_rootpath.pop(); -void traverse_subgraph( const Walker& walker, const scene::Path& start ){ - if ( !m_instances.empty() ) { - traverse_subgraph( walker, m_instances.find( PathConstReference( start ) ) ); - } -} + Node_traverseSubgraph(root, UninstanceSubgraphWalker(this, scene::Path())); -scene::Instance* find( const scene::Path& path ){ - InstanceMap::iterator i = m_instances.find( PathConstReference( path ) ); - if ( i == m_instances.end() ) { - return 0; - } - return ( *i ).second; -} + root.DecRef(); + } -void insert( scene::Instance* instance ){ - m_instances.insert( InstanceMap::value_type( PathConstReference( instance->path() ), instance ) ); + void boundsChanged() + { + m_boundsChanged(); + } - m_observer->insert( instance ); -} -void erase( scene::Instance* instance ){ - m_observer->erase( instance ); + void traverse(const Walker &walker) + { + traverse_subgraph(walker, m_instances.begin()); + } - m_instances.erase( PathConstReference( instance->path() ) ); -} + void traverse_subgraph(const Walker &walker, const scene::Path &start) + { + if (!m_instances.empty()) { + traverse_subgraph(walker, m_instances.find(PathConstReference(start))); + } + } -SignalHandlerId addBoundsChangedCallback( const SignalHandler& boundsChanged ){ - return m_boundsChanged.connectLast( boundsChanged ); -} -void removeBoundsChangedCallback( SignalHandlerId id ){ - m_boundsChanged.disconnect( id ); -} + scene::Instance *find(const scene::Path &path) + { + InstanceMap::iterator i = m_instances.find(PathConstReference(path)); + if (i == m_instances.end()) { + return 0; + } + return (*i).second; + } -TypeId getNodeTypeId( const char* name ){ - return m_nodeTypeIds.getTypeId( name ); -} + void insert(scene::Instance *instance) + { + m_instances.insert(InstanceMap::value_type(PathConstReference(instance->path()), instance)); -TypeId getInstanceTypeId( const char* name ){ - return m_instanceTypeIds.getTypeId( name ); -} + m_observer->insert(instance); + } -private: + void erase(scene::Instance *instance) + { + m_observer->erase(instance); -bool pre( const Walker& walker, const InstanceMap::iterator& i ){ - return walker.pre( i->first, *i->second ); -} + m_instances.erase(PathConstReference(instance->path())); + } -void post( const Walker& walker, const InstanceMap::iterator& i ){ - walker.post( i->first, *i->second ); -} + SignalHandlerId addBoundsChangedCallback(const SignalHandler &boundsChanged) + { + return m_boundsChanged.connectLast(boundsChanged); + } -void traverse_subgraph( const Walker& walker, InstanceMap::iterator i ){ - Stack stack; - if ( i != m_instances.end() ) { - const std::size_t startSize = ( *i ).first.get().size(); - do - { - if ( i != m_instances.end() - && stack.size() < ( ( *i ).first.get().size() - startSize + 1 ) ) { - stack.push( i ); - ++i; - if ( !pre( walker, stack.top() ) ) { - // skip subgraph - while ( i != m_instances.end() - && stack.size() < ( ( *i ).first.get().size() - startSize + 1 ) ) - { - ++i; - } - } - } - else - { - post( walker, stack.top() ); - stack.pop(); - } - } - while ( !stack.empty() ); - } -} + void removeBoundsChangedCallback(SignalHandlerId id) + { + m_boundsChanged.disconnect(id); + } + + TypeId getNodeTypeId(const char *name) + { + return m_nodeTypeIds.getTypeId(name); + } + + TypeId getInstanceTypeId(const char *name) + { + return m_instanceTypeIds.getTypeId(name); + } + +private: + + bool pre(const Walker &walker, const InstanceMap::iterator &i) + { + return walker.pre(i->first, *i->second); + } + + void post(const Walker &walker, const InstanceMap::iterator &i) + { + walker.post(i->first, *i->second); + } + + void traverse_subgraph(const Walker &walker, InstanceMap::iterator i) + { + Stack stack; + if (i != m_instances.end()) { + const std::size_t startSize = (*i).first.get().size(); + do { + if (i != m_instances.end() + && stack.size() < ((*i).first.get().size() - startSize + 1)) { + stack.push(i); + ++i; + if (!pre(walker, stack.top())) { + // skip subgraph + while (i != m_instances.end() + && stack.size() < ((*i).first.get().size() - startSize + 1)) { + ++i; + } + } + } else { + post(walker, stack.top()); + stack.pop(); + } + } while (!stack.empty()); + } + } }; -namespace -{ -CompiledGraph* g_sceneGraph; -GraphTreeModel* g_tree_model; +namespace { + CompiledGraph *g_sceneGraph; + GraphTreeModel *g_tree_model; } -GraphTreeModel* scene_graph_get_tree_model(){ - return g_tree_model; +GraphTreeModel *scene_graph_get_tree_model() +{ + return g_tree_model; } -class SceneGraphObserver : public scene::Instantiable::Observer -{ +class SceneGraphObserver : public scene::Instantiable::Observer { public: -void insert( scene::Instance* instance ){ - g_sceneGraph->sceneChanged(); - graph_tree_model_insert( g_tree_model, *instance ); -} -void erase( scene::Instance* instance ){ - g_sceneGraph->sceneChanged(); - graph_tree_model_erase( g_tree_model, *instance ); -} + void insert(scene::Instance *instance) + { + g_sceneGraph->sceneChanged(); + graph_tree_model_insert(g_tree_model, *instance); + } + + void erase(scene::Instance *instance) + { + g_sceneGraph->sceneChanged(); + graph_tree_model_erase(g_tree_model, *instance); + } }; SceneGraphObserver g_SceneGraphObserver; -void SceneGraph_Construct(){ - g_tree_model = graph_tree_model_new(); +void SceneGraph_Construct() +{ + g_tree_model = graph_tree_model_new(); - g_sceneGraph = new CompiledGraph( &g_SceneGraphObserver ); + g_sceneGraph = new CompiledGraph(&g_SceneGraphObserver); } -void SceneGraph_Destroy(){ - delete g_sceneGraph; +void SceneGraph_Destroy() +{ + delete g_sceneGraph; - graph_tree_model_delete( g_tree_model ); + graph_tree_model_delete(g_tree_model); } #include "modulesystem/singletonmodule.h" #include "modulesystem/moduleregistry.h" -class SceneGraphAPI -{ -scene::Graph* m_scenegraph; +class SceneGraphAPI { + scene::Graph *m_scenegraph; public: -typedef scene::Graph Type; -STRING_CONSTANT( Name, "*" ); + typedef scene::Graph Type; -SceneGraphAPI(){ - SceneGraph_Construct(); + STRING_CONSTANT(Name, "*"); - m_scenegraph = g_sceneGraph; -} -~SceneGraphAPI(){ - SceneGraph_Destroy(); -} -scene::Graph* getTable(){ - return m_scenegraph; -} + SceneGraphAPI() + { + SceneGraph_Construct(); + + m_scenegraph = g_sceneGraph; + } + + ~SceneGraphAPI() + { + SceneGraph_Destroy(); + } + + scene::Graph *getTable() + { + return m_scenegraph; + } }; typedef SingletonModule SceneGraphModule; typedef Static StaticSceneGraphModule; -StaticRegisterModule staticRegisterSceneGraph( StaticSceneGraphModule::instance() ); +StaticRegisterModule staticRegisterSceneGraph(StaticSceneGraphModule::instance()); diff --git a/radiant/select.cpp b/radiant/select.cpp index 7a40bb35..578124c7 100644 --- a/radiant/select.cpp +++ b/radiant/select.cpp @@ -52,7 +52,6 @@ #include "entityinspector.h" - select_workzone_t g_select_workzone; @@ -60,38 +59,39 @@ select_workzone_t g_select_workzone; Loops over all selected brushes and stores their world AABBs in the specified array. */ -class CollectSelectedBrushesBounds : public SelectionSystem::Visitor -{ -AABB* m_bounds; // array of AABBs -Unsigned m_max; // max AABB-elements in array -Unsigned& m_count; // count of valid AABBs stored in array +class CollectSelectedBrushesBounds : public SelectionSystem::Visitor { + AABB *m_bounds; // array of AABBs + Unsigned m_max; // max AABB-elements in array + Unsigned &m_count; // count of valid AABBs stored in array public: -CollectSelectedBrushesBounds( AABB* bounds, Unsigned max, Unsigned& count ) - : m_bounds( bounds ), - m_max( max ), - m_count( count ){ - m_count = 0; -} - -void visit( scene::Instance& instance ) const { - ASSERT_MESSAGE( m_count <= m_max, "Invalid m_count in CollectSelectedBrushesBounds" ); - - // stop if the array is already full - if ( m_count == m_max ) { - return; - } - - Selectable* selectable = Instance_getSelectable( instance ); - if ( ( selectable != 0 ) - && instance.isSelected() ) { - // brushes only - if ( Instance_getBrush( instance ) != 0 ) { - m_bounds[m_count] = instance.worldAABB(); - ++m_count; - } - } -} + CollectSelectedBrushesBounds(AABB *bounds, Unsigned max, Unsigned &count) + : m_bounds(bounds), + m_max(max), + m_count(count) + { + m_count = 0; + } + + void visit(scene::Instance &instance) const + { + ASSERT_MESSAGE(m_count <= m_max, "Invalid m_count in CollectSelectedBrushesBounds"); + + // stop if the array is already full + if (m_count == m_max) { + return; + } + + Selectable *selectable = Instance_getSelectable(instance); + if ((selectable != 0) + && instance.isSelected()) { + // brushes only + if (Instance_getBrush(instance) != 0) { + m_bounds[m_count] = instance.worldAABB(); + ++m_count; + } + } + } }; /** @@ -99,735 +99,781 @@ void visit( scene::Instance& instance ) const { The exact intersection-method is specified through TSelectionPolicy */ template -class SelectByBounds : public scene::Graph::Walker -{ -AABB* m_aabbs; // selection aabbs -Unsigned m_count; // number of aabbs in m_aabbs -TSelectionPolicy policy; // type that contains a custom intersection method aabb<->aabb +class SelectByBounds : public scene::Graph::Walker { + AABB *m_aabbs; // selection aabbs + Unsigned m_count; // number of aabbs in m_aabbs + TSelectionPolicy policy; // type that contains a custom intersection method aabb<->aabb public: -SelectByBounds( AABB* aabbs, Unsigned count ) - : m_aabbs( aabbs ), - m_count( count ){ -} - -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - - // ignore worldspawn - Entity* entity = Node_getEntity( path.top() ); - if ( entity ) { - if ( string_equal( entity->getKeyValue( "classname" ), "worldspawn" ) ) { - return true; - } - } - - if ( ( path.size() > 1 ) && - ( !path.top().get().isRoot() ) && - ( selectable != 0 ) - ) { - for ( Unsigned i = 0; i < m_count; ++i ) - { - if ( policy.Evaluate( m_aabbs[i], instance ) ) { - selectable->setSelected( true ); - } - } - } - - return true; -} + SelectByBounds(AABB *aabbs, Unsigned count) + : m_aabbs(aabbs), + m_count(count) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + + // ignore worldspawn + Entity *entity = Node_getEntity(path.top()); + if (entity) { + if (string_equal(entity->getKeyValue("classname"), "worldspawn")) { + return true; + } + } + + if ((path.size() > 1) && + (!path.top().get().isRoot()) && + (selectable != 0) + ) { + for (Unsigned i = 0; i < m_count; ++i) { + if (policy.Evaluate(m_aabbs[i], instance)) { + selectable->setSelected(true); + } + } + } + + return true; + } /** Performs selection operation on the global scenegraph. If delete_bounds_src is true, then the objects which were used as source for the selection aabbs will be deleted. */ -static void DoSelection( bool delete_bounds_src = true ){ - if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) { - // we may not need all AABBs since not all selected objects have to be brushes - const Unsigned max = (Unsigned)GlobalSelectionSystem().countSelected(); - AABB* aabbs = new AABB[max]; - - Unsigned count; - CollectSelectedBrushesBounds collector( aabbs, max, count ); - GlobalSelectionSystem().foreachSelected( collector ); - - // nothing usable in selection - if ( !count ) { - delete[] aabbs; - return; - } - - // delete selected objects - if ( delete_bounds_src ) { // see deleteSelection - UndoableCommand undo( "deleteSelected" ); - Select_Delete(); - } - - // select objects with bounds - GlobalSceneGraph().traverse( SelectByBounds( aabbs, count ) ); - - SceneChangeNotify(); - delete[] aabbs; - } -} + static void DoSelection(bool delete_bounds_src = true) + { + if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) { + // we may not need all AABBs since not all selected objects have to be brushes + const Unsigned max = (Unsigned) GlobalSelectionSystem().countSelected(); + AABB *aabbs = new AABB[max]; + + Unsigned count; + CollectSelectedBrushesBounds collector(aabbs, max, count); + GlobalSelectionSystem().foreachSelected(collector); + + // nothing usable in selection + if (!count) { + delete[] aabbs; + return; + } + + // delete selected objects + if (delete_bounds_src) { // see deleteSelection + UndoableCommand undo("deleteSelected"); + Select_Delete(); + } + + // select objects with bounds + GlobalSceneGraph().traverse(SelectByBounds(aabbs, count)); + + SceneChangeNotify(); + delete[] aabbs; + } + } }; /** SelectionPolicy for SelectByBounds Returns true if box and the AABB of instance intersect */ -class SelectionPolicy_Touching -{ +class SelectionPolicy_Touching { public: -bool Evaluate( const AABB& box, scene::Instance& instance ) const { - const AABB& other( instance.worldAABB() ); - for ( Unsigned i = 0; i < 3; ++i ) - { - if ( fabsf( box.origin[i] - other.origin[i] ) > ( box.extents[i] + other.extents[i] ) ) { - return false; - } - } - return true; -} + bool Evaluate(const AABB &box, scene::Instance &instance) const + { + const AABB &other(instance.worldAABB()); + for (Unsigned i = 0; i < 3; ++i) { + if (fabsf(box.origin[i] - other.origin[i]) > (box.extents[i] + other.extents[i])) { + return false; + } + } + return true; + } }; /** SelectionPolicy for SelectByBounds Returns true if the AABB of instance is inside box */ -class SelectionPolicy_Inside -{ +class SelectionPolicy_Inside { public: -bool Evaluate( const AABB& box, scene::Instance& instance ) const { - const AABB& other( instance.worldAABB() ); - for ( Unsigned i = 0; i < 3; ++i ) - { - if ( fabsf( box.origin[i] - other.origin[i] ) > ( box.extents[i] - other.extents[i] ) ) { - return false; - } - } - return true; -} + bool Evaluate(const AABB &box, scene::Instance &instance) const + { + const AABB &other(instance.worldAABB()); + for (Unsigned i = 0; i < 3; ++i) { + if (fabsf(box.origin[i] - other.origin[i]) > (box.extents[i] - other.extents[i])) { + return false; + } + } + return true; + } }; -class DeleteSelected : public scene::Graph::Walker -{ -mutable bool m_remove; -mutable bool m_removedChild; +class DeleteSelected : public scene::Graph::Walker { + mutable bool m_remove; + mutable bool m_removedChild; public: -DeleteSelected() - : m_remove( false ), m_removedChild( false ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - m_removedChild = false; - - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() - && path.size() > 1 - && !path.top().get().isRoot() ) { - m_remove = true; - - return false; // dont traverse into child elements - } - return true; -} -void post( const scene::Path& path, scene::Instance& instance ) const { - - if ( m_removedChild ) { - m_removedChild = false; - - // delete empty entities - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 - && path.top().get_pointer() != Map_FindWorldspawn( g_map ) - && Node_getTraversable( path.top() )->empty() ) { - Path_deleteTop( path ); - } - } - - // node should be removed - if ( m_remove ) { - if ( Node_isEntity( path.parent() ) != 0 ) { - m_removedChild = true; - } - - m_remove = false; - Path_deleteTop( path ); - } -} + DeleteSelected() + : m_remove(false), m_removedChild(false) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + m_removedChild = false; + + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected() + && path.size() > 1 + && !path.top().get().isRoot()) { + m_remove = true; + + return false; // dont traverse into child elements + } + return true; + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + + if (m_removedChild) { + m_removedChild = false; + + // delete empty entities + Entity *entity = Node_getEntity(path.top()); + if (entity != 0 + && path.top().get_pointer() != Map_FindWorldspawn(g_map) + && Node_getTraversable(path.top())->empty()) { + Path_deleteTop(path); + } + } + + // node should be removed + if (m_remove) { + if (Node_isEntity(path.parent()) != 0) { + m_removedChild = true; + } + + m_remove = false; + Path_deleteTop(path); + } + } }; -void Scene_DeleteSelected( scene::Graph& graph ){ - graph.traverse( DeleteSelected() ); - SceneChangeNotify(); +void Scene_DeleteSelected(scene::Graph &graph) +{ + graph.traverse(DeleteSelected()); + SceneChangeNotify(); } -void Select_Delete( void ){ - Scene_DeleteSelected( GlobalSceneGraph() ); +void Select_Delete(void) +{ + Scene_DeleteSelected(GlobalSceneGraph()); } -class InvertSelectionWalker : public scene::Graph::Walker -{ -SelectionSystem::EMode m_mode; -mutable Selectable* m_selectable; +class InvertSelectionWalker : public scene::Graph::Walker { + SelectionSystem::EMode m_mode; + mutable Selectable *m_selectable; public: -InvertSelectionWalker( SelectionSystem::EMode mode ) - : m_mode( mode ), m_selectable( 0 ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable ) { - switch ( m_mode ) - { - case SelectionSystem::eEntity: - if ( Node_isEntity( path.top() ) != 0 ) { - m_selectable = path.top().get().visible() ? selectable : 0; - } - break; - case SelectionSystem::ePrimitive: - m_selectable = path.top().get().visible() ? selectable : 0; - break; - case SelectionSystem::eComponent: - break; - } - } - return true; -} -void post( const scene::Path& path, scene::Instance& instance ) const { - if ( m_selectable != 0 ) { - m_selectable->setSelected( !m_selectable->isSelected() ); - m_selectable = 0; - } -} + InvertSelectionWalker(SelectionSystem::EMode mode) + : m_mode(mode), m_selectable(0) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable) { + switch (m_mode) { + case SelectionSystem::eEntity: + if (Node_isEntity(path.top()) != 0) { + m_selectable = path.top().get().visible() ? selectable : 0; + } + break; + case SelectionSystem::ePrimitive: + m_selectable = path.top().get().visible() ? selectable : 0; + break; + case SelectionSystem::eComponent: + break; + } + } + return true; + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + if (m_selectable != 0) { + m_selectable->setSelected(!m_selectable->isSelected()); + m_selectable = 0; + } + } }; -void Scene_Invert_Selection( scene::Graph& graph ){ - graph.traverse( InvertSelectionWalker( GlobalSelectionSystem().Mode() ) ); +void Scene_Invert_Selection(scene::Graph &graph) +{ + graph.traverse(InvertSelectionWalker(GlobalSelectionSystem().Mode())); } -void Select_Invert(){ - Scene_Invert_Selection( GlobalSceneGraph() ); +void Select_Invert() +{ + Scene_Invert_Selection(GlobalSceneGraph()); } -class ExpandSelectionToEntitiesWalker : public scene::Graph::Walker -{ -mutable std::size_t m_depth; -NodeSmartReference worldspawn; +class ExpandSelectionToEntitiesWalker : public scene::Graph::Walker { + mutable std::size_t m_depth; + NodeSmartReference worldspawn; public: -ExpandSelectionToEntitiesWalker() : m_depth( 0 ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - ++m_depth; - - // ignore worldspawn - NodeSmartReference me( path.top().get() ); - if ( me == worldspawn ) { - return false; - } - - if ( m_depth == 2 ) { // entity depth - // traverse and select children if any one is selected - if ( instance.childSelected() ) { - Instance_setSelected( instance, true ); - } - return Node_getEntity( path.top() )->isContainer() && instance.isSelected(); - } - else if ( m_depth == 3 ) { // primitive depth - Instance_setSelected( instance, true ); - return false; - } - return true; -} -void post( const scene::Path& path, scene::Instance& instance ) const { - --m_depth; -} + ExpandSelectionToEntitiesWalker() : m_depth(0), worldspawn(Map_FindOrInsertWorldspawn(g_map)) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + ++m_depth; + + // ignore worldspawn + NodeSmartReference me(path.top().get()); + if (me == worldspawn) { + return false; + } + + if (m_depth == 2) { // entity depth + // traverse and select children if any one is selected + if (instance.childSelected()) { + Instance_setSelected(instance, true); + } + return Node_getEntity(path.top())->isContainer() && instance.isSelected(); + } else if (m_depth == 3) { // primitive depth + Instance_setSelected(instance, true); + return false; + } + return true; + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + --m_depth; + } }; -void Scene_ExpandSelectionToEntities(){ - GlobalSceneGraph().traverse( ExpandSelectionToEntitiesWalker() ); +void Scene_ExpandSelectionToEntities() +{ + GlobalSceneGraph().traverse(ExpandSelectionToEntitiesWalker()); } -namespace -{ -void Selection_UpdateWorkzone(){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - Select_GetBounds( g_select_workzone.d_work_min, g_select_workzone.d_work_max ); - } -} -typedef FreeCaller SelectionUpdateWorkzoneCaller; +namespace { + void Selection_UpdateWorkzone() + { + if (GlobalSelectionSystem().countSelected() != 0) { + Select_GetBounds(g_select_workzone.d_work_min, g_select_workzone.d_work_max); + } + } -IdleDraw g_idleWorkzone = IdleDraw( SelectionUpdateWorkzoneCaller() ); + typedef FreeCaller SelectionUpdateWorkzoneCaller; + + IdleDraw g_idleWorkzone = IdleDraw(SelectionUpdateWorkzoneCaller()); } -const select_workzone_t& Select_getWorkZone(){ - g_idleWorkzone.flush(); - return g_select_workzone; +const select_workzone_t &Select_getWorkZone() +{ + g_idleWorkzone.flush(); + return g_select_workzone; } -void UpdateWorkzone_ForSelection(){ - g_idleWorkzone.queueDraw(); +void UpdateWorkzone_ForSelection() +{ + g_idleWorkzone.queueDraw(); } // update the workzone to the current selection -void UpdateWorkzone_ForSelectionChanged( const Selectable& selectable ){ - if ( selectable.isSelected() ) { - UpdateWorkzone_ForSelection(); - } +void UpdateWorkzone_ForSelectionChanged(const Selectable &selectable) +{ + if (selectable.isSelected()) { + UpdateWorkzone_ForSelection(); + } } -void Select_SetShader( const char* shader ){ - if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { - Scene_BrushSetShader_Selected( GlobalSceneGraph(), shader ); - Scene_PatchSetShader_Selected( GlobalSceneGraph(), shader ); - } - Scene_BrushSetShader_Component_Selected( GlobalSceneGraph(), shader ); +void Select_SetShader(const char *shader) +{ + if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) { + Scene_BrushSetShader_Selected(GlobalSceneGraph(), shader); + Scene_PatchSetShader_Selected(GlobalSceneGraph(), shader); + } + Scene_BrushSetShader_Component_Selected(GlobalSceneGraph(), shader); } -void Select_SetTexdef( const TextureProjection& projection ){ - if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { - Scene_BrushSetTexdef_Selected( GlobalSceneGraph(), projection ); - } - Scene_BrushSetTexdef_Component_Selected( GlobalSceneGraph(), projection ); +void Select_SetTexdef(const TextureProjection &projection) +{ + if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) { + Scene_BrushSetTexdef_Selected(GlobalSceneGraph(), projection); + } + Scene_BrushSetTexdef_Component_Selected(GlobalSceneGraph(), projection); } -void Select_SetFlags( const ContentsFlagsValue& flags ){ - if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { - Scene_BrushSetFlags_Selected( GlobalSceneGraph(), flags ); - } - Scene_BrushSetFlags_Component_Selected( GlobalSceneGraph(), flags ); +void Select_SetFlags(const ContentsFlagsValue &flags) +{ + if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) { + Scene_BrushSetFlags_Selected(GlobalSceneGraph(), flags); + } + Scene_BrushSetFlags_Component_Selected(GlobalSceneGraph(), flags); } -void Select_GetBounds( Vector3& mins, Vector3& maxs ){ - AABB bounds; - Scene_BoundsSelected( GlobalSceneGraph(), bounds ); - maxs = vector3_added( bounds.origin, bounds.extents ); - mins = vector3_subtracted( bounds.origin, bounds.extents ); +void Select_GetBounds(Vector3 &mins, Vector3 &maxs) +{ + AABB bounds; + Scene_BoundsSelected(GlobalSceneGraph(), bounds); + maxs = vector3_added(bounds.origin, bounds.extents); + mins = vector3_subtracted(bounds.origin, bounds.extents); } -void Select_GetMid( Vector3& mid ){ - AABB bounds; - Scene_BoundsSelected( GlobalSceneGraph(), bounds ); - mid = vector3_snapped( bounds.origin ); +void Select_GetMid(Vector3 &mid) +{ + AABB bounds; + Scene_BoundsSelected(GlobalSceneGraph(), bounds); + mid = vector3_snapped(bounds.origin); } -void Select_FlipAxis( int axis ){ - Vector3 flip( 1, 1, 1 ); - flip[axis] = -1; - GlobalSelectionSystem().scaleSelected( flip ); +void Select_FlipAxis(int axis) +{ + Vector3 flip(1, 1, 1); + flip[axis] = -1; + GlobalSelectionSystem().scaleSelected(flip); } -void Select_Scale( float x, float y, float z ){ - GlobalSelectionSystem().scaleSelected( Vector3( x, y, z ) ); +void Select_Scale(float x, float y, float z) +{ + GlobalSelectionSystem().scaleSelected(Vector3(x, y, z)); } -enum axis_t -{ - eAxisX = 0, - eAxisY = 1, - eAxisZ = 2, +enum axis_t { + eAxisX = 0, + eAxisY = 1, + eAxisZ = 2, }; -enum sign_t -{ - eSignPositive = 1, - eSignNegative = -1, +enum sign_t { + eSignPositive = 1, + eSignNegative = -1, }; -inline Matrix4 matrix4_rotation_for_axis90( axis_t axis, sign_t sign ){ - switch ( axis ) - { - case eAxisX: - if ( sign == eSignPositive ) { - return matrix4_rotation_for_sincos_x( 1, 0 ); - } - else - { - return matrix4_rotation_for_sincos_x( -1, 0 ); - } - case eAxisY: - if ( sign == eSignPositive ) { - return matrix4_rotation_for_sincos_y( 1, 0 ); - } - else - { - return matrix4_rotation_for_sincos_y( -1, 0 ); - } - default: //case eAxisZ: - if ( sign == eSignPositive ) { - return matrix4_rotation_for_sincos_z( 1, 0 ); - } - else - { - return matrix4_rotation_for_sincos_z( -1, 0 ); - } - } -} - -inline void matrix4_rotate_by_axis90( Matrix4& matrix, axis_t axis, sign_t sign ){ - matrix4_multiply_by_matrix4( matrix, matrix4_rotation_for_axis90( axis, sign ) ); +inline Matrix4 matrix4_rotation_for_axis90(axis_t axis, sign_t sign) +{ + switch (axis) { + case eAxisX: + if (sign == eSignPositive) { + return matrix4_rotation_for_sincos_x(1, 0); + } else { + return matrix4_rotation_for_sincos_x(-1, 0); + } + case eAxisY: + if (sign == eSignPositive) { + return matrix4_rotation_for_sincos_y(1, 0); + } else { + return matrix4_rotation_for_sincos_y(-1, 0); + } + default: //case eAxisZ: + if (sign == eSignPositive) { + return matrix4_rotation_for_sincos_z(1, 0); + } else { + return matrix4_rotation_for_sincos_z(-1, 0); + } + } +} + +inline void matrix4_rotate_by_axis90(Matrix4 &matrix, axis_t axis, sign_t sign) +{ + matrix4_multiply_by_matrix4(matrix, matrix4_rotation_for_axis90(axis, sign)); } -inline void matrix4_pivoted_rotate_by_axis90( Matrix4& matrix, axis_t axis, sign_t sign, const Vector3& pivotpoint ){ - matrix4_translate_by_vec3( matrix, pivotpoint ); - matrix4_rotate_by_axis90( matrix, axis, sign ); - matrix4_translate_by_vec3( matrix, vector3_negated( pivotpoint ) ); +inline void matrix4_pivoted_rotate_by_axis90(Matrix4 &matrix, axis_t axis, sign_t sign, const Vector3 &pivotpoint) +{ + matrix4_translate_by_vec3(matrix, pivotpoint); + matrix4_rotate_by_axis90(matrix, axis, sign); + matrix4_translate_by_vec3(matrix, vector3_negated(pivotpoint)); } -inline Quaternion quaternion_for_axis90( axis_t axis, sign_t sign ){ +inline Quaternion quaternion_for_axis90(axis_t axis, sign_t sign) +{ #if 1 - switch ( axis ) - { - case eAxisX: - if ( sign == eSignPositive ) { - return Quaternion( c_half_sqrt2f, 0, 0, c_half_sqrt2f ); - } - else - { - return Quaternion( -c_half_sqrt2f, 0, 0, -c_half_sqrt2f ); - } - case eAxisY: - if ( sign == eSignPositive ) { - return Quaternion( 0, c_half_sqrt2f, 0, c_half_sqrt2f ); - } - else - { - return Quaternion( 0, -c_half_sqrt2f, 0, -c_half_sqrt2f ); - } - default: //case eAxisZ: - if ( sign == eSignPositive ) { - return Quaternion( 0, 0, c_half_sqrt2f, c_half_sqrt2f ); - } - else - { - return Quaternion( 0, 0, -c_half_sqrt2f, -c_half_sqrt2f ); - } - } + switch (axis) { + case eAxisX: + if (sign == eSignPositive) { + return Quaternion(c_half_sqrt2f, 0, 0, c_half_sqrt2f); + } else { + return Quaternion(-c_half_sqrt2f, 0, 0, -c_half_sqrt2f); + } + case eAxisY: + if (sign == eSignPositive) { + return Quaternion(0, c_half_sqrt2f, 0, c_half_sqrt2f); + } else { + return Quaternion(0, -c_half_sqrt2f, 0, -c_half_sqrt2f); + } + default: //case eAxisZ: + if (sign == eSignPositive) { + return Quaternion(0, 0, c_half_sqrt2f, c_half_sqrt2f); + } else { + return Quaternion(0, 0, -c_half_sqrt2f, -c_half_sqrt2f); + } + } #else - quaternion_for_matrix4_rotation( matrix4_rotation_for_axis90( (axis_t)axis, ( deg > 0 ) ? eSignPositive : eSignNegative ) ); + quaternion_for_matrix4_rotation( matrix4_rotation_for_axis90( (axis_t)axis, ( deg > 0 ) ? eSignPositive : eSignNegative ) ); #endif } -void Select_RotateAxis( int axis, float deg ){ - if ( fabs( deg ) == 90.f ) { - GlobalSelectionSystem().rotateSelected( quaternion_for_axis90( (axis_t)axis, ( deg > 0 ) ? eSignPositive : eSignNegative ) ); - } - else - { - switch ( axis ) - { - case 0: - GlobalSelectionSystem().rotateSelected( quaternion_for_matrix4_rotation( matrix4_rotation_for_x_degrees( deg ) ) ); - break; - case 1: - GlobalSelectionSystem().rotateSelected( quaternion_for_matrix4_rotation( matrix4_rotation_for_y_degrees( deg ) ) ); - break; - case 2: - GlobalSelectionSystem().rotateSelected( quaternion_for_matrix4_rotation( matrix4_rotation_for_z_degrees( deg ) ) ); - break; - } - } -} - - -void Select_ShiftTexture( float x, float y ){ - if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { - Scene_BrushShiftTexdef_Selected( GlobalSceneGraph(), x, y ); - Scene_PatchTranslateTexture_Selected( GlobalSceneGraph(), x, y ); - } - //globalOutputStream() << "shift selected face textures: s=" << x << " t=" << y << '\n'; - Scene_BrushShiftTexdef_Component_Selected( GlobalSceneGraph(), x, y ); +void Select_RotateAxis(int axis, float deg) +{ + if (fabs(deg) == 90.f) { + GlobalSelectionSystem().rotateSelected( + quaternion_for_axis90((axis_t) axis, (deg > 0) ? eSignPositive : eSignNegative)); + } else { + switch (axis) { + case 0: + GlobalSelectionSystem().rotateSelected( + quaternion_for_matrix4_rotation(matrix4_rotation_for_x_degrees(deg))); + break; + case 1: + GlobalSelectionSystem().rotateSelected( + quaternion_for_matrix4_rotation(matrix4_rotation_for_y_degrees(deg))); + break; + case 2: + GlobalSelectionSystem().rotateSelected( + quaternion_for_matrix4_rotation(matrix4_rotation_for_z_degrees(deg))); + break; + } + } +} + + +void Select_ShiftTexture(float x, float y) +{ + if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) { + Scene_BrushShiftTexdef_Selected(GlobalSceneGraph(), x, y); + Scene_PatchTranslateTexture_Selected(GlobalSceneGraph(), x, y); + } + //globalOutputStream() << "shift selected face textures: s=" << x << " t=" << y << '\n'; + Scene_BrushShiftTexdef_Component_Selected(GlobalSceneGraph(), x, y); } -void Select_ScaleTexture( float x, float y ){ - if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { - Scene_BrushScaleTexdef_Selected( GlobalSceneGraph(), x, y ); - Scene_PatchScaleTexture_Selected( GlobalSceneGraph(), x, y ); - } - Scene_BrushScaleTexdef_Component_Selected( GlobalSceneGraph(), x, y ); +void Select_ScaleTexture(float x, float y) +{ + if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) { + Scene_BrushScaleTexdef_Selected(GlobalSceneGraph(), x, y); + Scene_PatchScaleTexture_Selected(GlobalSceneGraph(), x, y); + } + Scene_BrushScaleTexdef_Component_Selected(GlobalSceneGraph(), x, y); } -void Select_RotateTexture( float amt ){ - if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { - Scene_BrushRotateTexdef_Selected( GlobalSceneGraph(), amt ); - Scene_PatchRotateTexture_Selected( GlobalSceneGraph(), amt ); - } - Scene_BrushRotateTexdef_Component_Selected( GlobalSceneGraph(), amt ); +void Select_RotateTexture(float amt) +{ + if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) { + Scene_BrushRotateTexdef_Selected(GlobalSceneGraph(), amt); + Scene_PatchRotateTexture_Selected(GlobalSceneGraph(), amt); + } + Scene_BrushRotateTexdef_Component_Selected(GlobalSceneGraph(), amt); } // TTimo modified to handle shader architecture: // expects shader names at input, comparison relies on shader names .. texture names no longer relevant -void FindReplaceTextures( const char* pFind, const char* pReplace, bool bSelected ){ - if ( !texdef_name_valid( pFind ) ) { - globalErrorStream() << "FindReplaceTextures: invalid texture name: '" << pFind << "', aborted\n"; - return; - } - if ( !texdef_name_valid( pReplace ) ) { - globalErrorStream() << "FindReplaceTextures: invalid texture name: '" << pReplace << "', aborted\n"; - return; - } - - StringOutputStream command; - command << "textureFindReplace -find " << pFind << " -replace " << pReplace; - UndoableCommand undo( command.c_str() ); - - if ( bSelected ) { - if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { - Scene_BrushFindReplaceShader_Selected( GlobalSceneGraph(), pFind, pReplace ); - Scene_PatchFindReplaceShader_Selected( GlobalSceneGraph(), pFind, pReplace ); - } - Scene_BrushFindReplaceShader_Component_Selected( GlobalSceneGraph(), pFind, pReplace ); - } - else - { - Scene_BrushFindReplaceShader( GlobalSceneGraph(), pFind, pReplace ); - Scene_PatchFindReplaceShader( GlobalSceneGraph(), pFind, pReplace ); - } -} - -typedef std::vector PropertyValues; - -bool propertyvalues_contain( const PropertyValues& propertyvalues, const char *str ){ - for ( PropertyValues::const_iterator i = propertyvalues.begin(); i != propertyvalues.end(); ++i ) - { - if ( string_equal( str, *i ) ) { - return true; - } - } - return false; +void FindReplaceTextures(const char *pFind, const char *pReplace, bool bSelected) +{ + if (!texdef_name_valid(pFind)) { + globalErrorStream() << "FindReplaceTextures: invalid texture name: '" << pFind << "', aborted\n"; + return; + } + if (!texdef_name_valid(pReplace)) { + globalErrorStream() << "FindReplaceTextures: invalid texture name: '" << pReplace << "', aborted\n"; + return; + } + + StringOutputStream command; + command << "textureFindReplace -find " << pFind << " -replace " << pReplace; + UndoableCommand undo(command.c_str()); + + if (bSelected) { + if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) { + Scene_BrushFindReplaceShader_Selected(GlobalSceneGraph(), pFind, pReplace); + Scene_PatchFindReplaceShader_Selected(GlobalSceneGraph(), pFind, pReplace); + } + Scene_BrushFindReplaceShader_Component_Selected(GlobalSceneGraph(), pFind, pReplace); + } else { + Scene_BrushFindReplaceShader(GlobalSceneGraph(), pFind, pReplace); + Scene_PatchFindReplaceShader(GlobalSceneGraph(), pFind, pReplace); + } +} + +typedef std::vector PropertyValues; + +bool propertyvalues_contain(const PropertyValues &propertyvalues, const char *str) +{ + for (PropertyValues::const_iterator i = propertyvalues.begin(); i != propertyvalues.end(); ++i) { + if (string_equal(str, *i)) { + return true; + } + } + return false; } -class EntityFindByPropertyValueWalker : public scene::Graph::Walker -{ -const PropertyValues& m_propertyvalues; -const char *m_prop; +class EntityFindByPropertyValueWalker : public scene::Graph::Walker { + const PropertyValues &m_propertyvalues; + const char *m_prop; public: -EntityFindByPropertyValueWalker( const char *prop, const PropertyValues& propertyvalues ) - : m_propertyvalues( propertyvalues ), m_prop( prop ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 - && propertyvalues_contain( m_propertyvalues, entity->getKeyValue( m_prop ) ) ) { - Instance_getSelectable( instance )->setSelected( true ); - } - return true; -} + EntityFindByPropertyValueWalker(const char *prop, const PropertyValues &propertyvalues) + : m_propertyvalues(propertyvalues), m_prop(prop) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Entity *entity = Node_getEntity(path.top()); + if (entity != 0 + && propertyvalues_contain(m_propertyvalues, entity->getKeyValue(m_prop))) { + Instance_getSelectable(instance)->setSelected(true); + } + return true; + } }; -void Scene_EntitySelectByPropertyValues( scene::Graph& graph, const char *prop, const PropertyValues& propertyvalues ){ - graph.traverse( EntityFindByPropertyValueWalker( prop, propertyvalues ) ); +void Scene_EntitySelectByPropertyValues(scene::Graph &graph, const char *prop, const PropertyValues &propertyvalues) +{ + graph.traverse(EntityFindByPropertyValueWalker(prop, propertyvalues)); } -class EntityGetSelectedPropertyValuesWalker : public scene::Graph::Walker -{ -PropertyValues& m_propertyvalues; -const char *m_prop; +class EntityGetSelectedPropertyValuesWalker : public scene::Graph::Walker { + PropertyValues &m_propertyvalues; + const char *m_prop; public: -EntityGetSelectedPropertyValuesWalker( const char *prop, PropertyValues& propertyvalues ) - : m_propertyvalues( propertyvalues ), m_prop( prop ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() ) { - Entity* entity = Node_getEntity( path.top() ); - if ( entity != 0 ) { - if ( !propertyvalues_contain( m_propertyvalues, entity->getKeyValue( m_prop ) ) ) { - m_propertyvalues.push_back( entity->getKeyValue( m_prop ) ); - } - } - } - return true; -} + EntityGetSelectedPropertyValuesWalker(const char *prop, PropertyValues &propertyvalues) + : m_propertyvalues(propertyvalues), m_prop(prop) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected()) { + Entity *entity = Node_getEntity(path.top()); + if (entity != 0) { + if (!propertyvalues_contain(m_propertyvalues, entity->getKeyValue(m_prop))) { + m_propertyvalues.push_back(entity->getKeyValue(m_prop)); + } + } + } + return true; + } }; -void Scene_EntityGetPropertyValues( scene::Graph& graph, const char *prop, PropertyValues& propertyvalues ){ - graph.traverse( EntityGetSelectedPropertyValuesWalker( prop, propertyvalues ) ); -} - -void Select_AllOfType(){ - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { - if ( GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace ) { - GlobalSelectionSystem().setSelectedAllComponents( false ); - Scene_BrushSelectByShader_Component( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); - } - } - else - { - PropertyValues propertyvalues; - const char *prop = EntityInspector_getCurrentKey(); - if ( !prop || !*prop ) { - prop = "classname"; - } - Scene_EntityGetPropertyValues( GlobalSceneGraph(), prop, propertyvalues ); - GlobalSelectionSystem().setSelectedAll( false ); - if ( !propertyvalues.empty() ) { - Scene_EntitySelectByPropertyValues( GlobalSceneGraph(), prop, propertyvalues ); - } - else - { - Scene_BrushSelectByShader( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); - Scene_PatchSelectByShader( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); - } - } +void Scene_EntityGetPropertyValues(scene::Graph &graph, const char *prop, PropertyValues &propertyvalues) +{ + graph.traverse(EntityGetSelectedPropertyValuesWalker(prop, propertyvalues)); } -void Select_Inside( void ){ - SelectByBounds::DoSelection(); +void Select_AllOfType() +{ + if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent) { + if (GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace) { + GlobalSelectionSystem().setSelectedAllComponents(false); + Scene_BrushSelectByShader_Component(GlobalSceneGraph(), + TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); + } + } else { + PropertyValues propertyvalues; + const char *prop = EntityInspector_getCurrentKey(); + if (!prop || !*prop) { + prop = "classname"; + } + Scene_EntityGetPropertyValues(GlobalSceneGraph(), prop, propertyvalues); + GlobalSelectionSystem().setSelectedAll(false); + if (!propertyvalues.empty()) { + Scene_EntitySelectByPropertyValues(GlobalSceneGraph(), prop, propertyvalues); + } else { + Scene_BrushSelectByShader(GlobalSceneGraph(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); + Scene_PatchSelectByShader(GlobalSceneGraph(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); + } + } +} + +void Select_Inside(void) +{ + SelectByBounds::DoSelection(); } -void Select_Touching( void ){ - SelectByBounds::DoSelection( false ); +void Select_Touching(void) +{ + SelectByBounds::DoSelection(false); } -void Select_FitTexture( float horizontal, float vertical ){ - if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) { - Scene_BrushFitTexture_Selected( GlobalSceneGraph(), horizontal, vertical ); - } - Scene_BrushFitTexture_Component_Selected( GlobalSceneGraph(), horizontal, vertical ); +void Select_FitTexture(float horizontal, float vertical) +{ + if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) { + Scene_BrushFitTexture_Selected(GlobalSceneGraph(), horizontal, vertical); + } + Scene_BrushFitTexture_Component_Selected(GlobalSceneGraph(), horizontal, vertical); - SceneChangeNotify(); + SceneChangeNotify(); } -inline void hide_node( scene::Node& node, bool hide ){ - hide - ? node.enable( scene::Node::eHidden ) - : node.disable( scene::Node::eHidden ); +inline void hide_node(scene::Node &node, bool hide) +{ + hide + ? node.enable(scene::Node::eHidden) + : node.disable(scene::Node::eHidden); } -class HideSelectedWalker : public scene::Graph::Walker -{ -bool m_hide; +class HideSelectedWalker : public scene::Graph::Walker { + bool m_hide; public: -HideSelectedWalker( bool hide ) - : m_hide( hide ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() ) { - hide_node( path.top(), m_hide ); - } - return true; -} + HideSelectedWalker(bool hide) + : m_hide(hide) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected()) { + hide_node(path.top(), m_hide); + } + return true; + } }; -void Scene_Hide_Selected( bool hide ){ - GlobalSceneGraph().traverse( HideSelectedWalker( hide ) ); +void Scene_Hide_Selected(bool hide) +{ + GlobalSceneGraph().traverse(HideSelectedWalker(hide)); } -void Select_Hide(){ - Scene_Hide_Selected( true ); - SceneChangeNotify(); +void Select_Hide() +{ + Scene_Hide_Selected(true); + SceneChangeNotify(); } -void HideSelected(){ - Select_Hide(); - GlobalSelectionSystem().setSelectedAll( false ); +void HideSelected() +{ + Select_Hide(); + GlobalSelectionSystem().setSelectedAll(false); } -class HideAllWalker : public scene::Graph::Walker -{ -bool m_hide; +class HideAllWalker : public scene::Graph::Walker { + bool m_hide; public: -HideAllWalker( bool hide ) - : m_hide( hide ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - hide_node( path.top(), m_hide ); - return true; -} + HideAllWalker(bool hide) + : m_hide(hide) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + hide_node(path.top(), m_hide); + return true; + } }; -void Scene_Hide_All( bool hide ){ - GlobalSceneGraph().traverse( HideAllWalker( hide ) ); +void Scene_Hide_All(bool hide) +{ + GlobalSceneGraph().traverse(HideAllWalker(hide)); } -void Select_ShowAllHidden(){ - Scene_Hide_All( false ); - SceneChangeNotify(); +void Select_ShowAllHidden() +{ + Scene_Hide_All(false); + SceneChangeNotify(); } - -void Selection_Flipx(){ - UndoableCommand undo( "mirrorSelected -axis x" ); - Select_FlipAxis( 0 ); +void Selection_Flipx() +{ + UndoableCommand undo("mirrorSelected -axis x"); + Select_FlipAxis(0); } -void Selection_Flipy(){ - UndoableCommand undo( "mirrorSelected -axis y" ); - Select_FlipAxis( 1 ); +void Selection_Flipy() +{ + UndoableCommand undo("mirrorSelected -axis y"); + Select_FlipAxis(1); } -void Selection_Flipz(){ - UndoableCommand undo( "mirrorSelected -axis z" ); - Select_FlipAxis( 2 ); +void Selection_Flipz() +{ + UndoableCommand undo("mirrorSelected -axis z"); + Select_FlipAxis(2); } -void Selection_Rotatex(){ - UndoableCommand undo( "rotateSelected -axis x -angle -90" ); - Select_RotateAxis( 0,-90 ); +void Selection_Rotatex() +{ + UndoableCommand undo("rotateSelected -axis x -angle -90"); + Select_RotateAxis(0, -90); } -void Selection_Rotatey(){ - UndoableCommand undo( "rotateSelected -axis y -angle 90" ); - Select_RotateAxis( 1, 90 ); +void Selection_Rotatey() +{ + UndoableCommand undo("rotateSelected -axis y -angle 90"); + Select_RotateAxis(1, 90); } -void Selection_Rotatez(){ - UndoableCommand undo( "rotateSelected -axis z -angle -90" ); - Select_RotateAxis( 2,-90 ); +void Selection_Rotatez() +{ + UndoableCommand undo("rotateSelected -axis z -angle -90"); + Select_RotateAxis(2, -90); } +void Nudge(int nDim, float fNudge) +{ + Vector3 translate(0, 0, 0); + translate[nDim] = fNudge; -void Nudge( int nDim, float fNudge ){ - Vector3 translate( 0, 0, 0 ); - translate[nDim] = fNudge; - - GlobalSelectionSystem().translateSelected( translate ); + GlobalSelectionSystem().translateSelected(translate); } -void Selection_NudgeZ( float amount ){ - StringOutputStream command; - command << "nudgeSelected -axis z -amount " << amount; - UndoableCommand undo( command.c_str() ); +void Selection_NudgeZ(float amount) +{ + StringOutputStream command; + command << "nudgeSelected -axis z -amount " << amount; + UndoableCommand undo(command.c_str()); - Nudge( 2, amount ); + Nudge(2, amount); } -void Selection_MoveDown(){ - Selection_NudgeZ( -GetGridSize() ); +void Selection_MoveDown() +{ + Selection_NudgeZ(-GetGridSize()); } -void Selection_MoveUp(){ - Selection_NudgeZ( GetGridSize() ); +void Selection_MoveUp() +{ + Selection_NudgeZ(GetGridSize()); } -void SceneSelectionChange( const Selectable& selectable ){ - SceneChangeNotify(); +void SceneSelectionChange(const Selectable &selectable) +{ + SceneChangeNotify(); } SignalHandlerId Selection_boundsChanged; -void Selection_construct(){ - typedef FreeCaller SceneSelectionChangeCaller; - GlobalSelectionSystem().addSelectionChangeCallback( SceneSelectionChangeCaller() ); - typedef FreeCaller UpdateWorkzoneForSelectionChangedCaller; - GlobalSelectionSystem().addSelectionChangeCallback( UpdateWorkzoneForSelectionChangedCaller() ); - typedef FreeCaller UpdateWorkzoneForSelectionCaller; - Selection_boundsChanged = GlobalSceneGraph().addBoundsChangedCallback( UpdateWorkzoneForSelectionCaller() ); +void Selection_construct() +{ + typedef FreeCaller SceneSelectionChangeCaller; + GlobalSelectionSystem().addSelectionChangeCallback(SceneSelectionChangeCaller()); + typedef FreeCaller UpdateWorkzoneForSelectionChangedCaller; + GlobalSelectionSystem().addSelectionChangeCallback(UpdateWorkzoneForSelectionChangedCaller()); + typedef FreeCaller UpdateWorkzoneForSelectionCaller; + Selection_boundsChanged = GlobalSceneGraph().addBoundsChangedCallback(UpdateWorkzoneForSelectionCaller()); } -void Selection_destroy(){ - GlobalSceneGraph().removeBoundsChangedCallback( Selection_boundsChanged ); +void Selection_destroy() +{ + GlobalSceneGraph().removeBoundsChangedCallback(Selection_boundsChanged); } @@ -835,294 +881,305 @@ void Selection_destroy(){ #include -inline Quaternion quaternion_for_euler_xyz_degrees( const Vector3& eulerXYZ ){ +inline Quaternion quaternion_for_euler_xyz_degrees(const Vector3 &eulerXYZ) +{ #if 0 - return quaternion_for_matrix4_rotation( matrix4_rotation_for_euler_xyz_degrees( eulerXYZ ) ); + return quaternion_for_matrix4_rotation( matrix4_rotation_for_euler_xyz_degrees( eulerXYZ ) ); #elif 0 - return quaternion_multiplied_by_quaternion( - quaternion_multiplied_by_quaternion( - quaternion_for_z( degrees_to_radians( eulerXYZ[2] ) ), - quaternion_for_y( degrees_to_radians( eulerXYZ[1] ) ) - ), - quaternion_for_x( degrees_to_radians( eulerXYZ[0] ) ) - ); + return quaternion_multiplied_by_quaternion( + quaternion_multiplied_by_quaternion( + quaternion_for_z( degrees_to_radians( eulerXYZ[2] ) ), + quaternion_for_y( degrees_to_radians( eulerXYZ[1] ) ) + ), + quaternion_for_x( degrees_to_radians( eulerXYZ[0] ) ) + ); #elif 1 - double cx = cos( degrees_to_radians( eulerXYZ[0] * 0.5 ) ); - double sx = sin( degrees_to_radians( eulerXYZ[0] * 0.5 ) ); - double cy = cos( degrees_to_radians( eulerXYZ[1] * 0.5 ) ); - double sy = sin( degrees_to_radians( eulerXYZ[1] * 0.5 ) ); - double cz = cos( degrees_to_radians( eulerXYZ[2] * 0.5 ) ); - double sz = sin( degrees_to_radians( eulerXYZ[2] * 0.5 ) ); - - return Quaternion( - cz * cy * sx - sz * sy * cx, - cz * sy * cx + sz * cy * sx, - sz * cy * cx - cz * sy * sx, - cz * cy * cx + sz * sy * sx - ); + double cx = cos(degrees_to_radians(eulerXYZ[0] * 0.5)); + double sx = sin(degrees_to_radians(eulerXYZ[0] * 0.5)); + double cy = cos(degrees_to_radians(eulerXYZ[1] * 0.5)); + double sy = sin(degrees_to_radians(eulerXYZ[1] * 0.5)); + double cz = cos(degrees_to_radians(eulerXYZ[2] * 0.5)); + double sz = sin(degrees_to_radians(eulerXYZ[2] * 0.5)); + + return Quaternion( + cz * cy * sx - sz * sy * cx, + cz * sy * cx + sz * cy * sx, + sz * cy * cx - cz * sy * sx, + cz * cy * cx + sz * sy * sx + ); #endif } -struct RotateDialog -{ - ui::SpinButton x{ui::null}; - ui::SpinButton y{ui::null}; - ui::SpinButton z{ui::null}; - ui::Window window{ui::null}; +struct RotateDialog { + ui::SpinButton x{ui::null}; + ui::SpinButton y{ui::null}; + ui::SpinButton z{ui::null}; + ui::Window window{ui::null}; }; -static gboolean rotatedlg_apply( ui::Widget widget, RotateDialog* rotateDialog ){ - Vector3 eulerXYZ; +static gboolean rotatedlg_apply(ui::Widget widget, RotateDialog *rotateDialog) +{ + Vector3 eulerXYZ; - eulerXYZ[0] = static_cast( gtk_spin_button_get_value( rotateDialog->x ) ); - eulerXYZ[1] = static_cast( gtk_spin_button_get_value( rotateDialog->y ) ); - eulerXYZ[2] = static_cast( gtk_spin_button_get_value( rotateDialog->z ) ); + eulerXYZ[0] = static_cast( gtk_spin_button_get_value(rotateDialog->x)); + eulerXYZ[1] = static_cast( gtk_spin_button_get_value(rotateDialog->y)); + eulerXYZ[2] = static_cast( gtk_spin_button_get_value(rotateDialog->z)); - StringOutputStream command; - command << "rotateSelectedEulerXYZ -x " << eulerXYZ[0] << " -y " << eulerXYZ[1] << " -z " << eulerXYZ[2]; - UndoableCommand undo( command.c_str() ); + StringOutputStream command; + command << "rotateSelectedEulerXYZ -x " << eulerXYZ[0] << " -y " << eulerXYZ[1] << " -z " << eulerXYZ[2]; + UndoableCommand undo(command.c_str()); - GlobalSelectionSystem().rotateSelected( quaternion_for_euler_xyz_degrees( eulerXYZ ) ); - return TRUE; + GlobalSelectionSystem().rotateSelected(quaternion_for_euler_xyz_degrees(eulerXYZ)); + return TRUE; } -static gboolean rotatedlg_cancel( ui::Widget widget, RotateDialog* rotateDialog ){ - rotateDialog->window.hide(); +static gboolean rotatedlg_cancel(ui::Widget widget, RotateDialog *rotateDialog) +{ + rotateDialog->window.hide(); - gtk_spin_button_set_value( rotateDialog->x, 0.0f ); // reset to 0 on close - gtk_spin_button_set_value( rotateDialog->y, 0.0f ); - gtk_spin_button_set_value( rotateDialog->z, 0.0f ); + gtk_spin_button_set_value(rotateDialog->x, 0.0f); // reset to 0 on close + gtk_spin_button_set_value(rotateDialog->y, 0.0f); + gtk_spin_button_set_value(rotateDialog->z, 0.0f); - return TRUE; + return TRUE; } -static gboolean rotatedlg_ok( ui::Widget widget, RotateDialog* rotateDialog ){ - rotatedlg_apply( widget, rotateDialog ); - rotateDialog->window.hide(); - return TRUE; +static gboolean rotatedlg_ok(ui::Widget widget, RotateDialog *rotateDialog) +{ + rotatedlg_apply(widget, rotateDialog); + rotateDialog->window.hide(); + return TRUE; } -static gboolean rotatedlg_delete( ui::Widget widget, GdkEventAny *event, RotateDialog* rotateDialog ){ - rotatedlg_cancel( widget, rotateDialog ); - return TRUE; +static gboolean rotatedlg_delete(ui::Widget widget, GdkEventAny *event, RotateDialog *rotateDialog) +{ + rotatedlg_cancel(widget, rotateDialog); + return TRUE; } RotateDialog g_rotate_dialog; -void DoRotateDlg(){ - if ( !g_rotate_dialog.window ) { - g_rotate_dialog.window = MainFrame_getWindow().create_dialog_window("Arbitrary rotation", G_CALLBACK(rotatedlg_delete ), &g_rotate_dialog ); - - auto accel = ui::AccelGroup(ui::New); - g_rotate_dialog.window.add_accel_group( accel ); - - { - auto hbox = create_dialog_hbox( 4, 4 ); - g_rotate_dialog.window.add(hbox); - { - auto table = create_dialog_table( 3, 2, 4, 4 ); - hbox.pack_start( table, TRUE, TRUE, 0 ); - { - ui::Widget label = ui::Label( " X " ); - label.show(); + +void DoRotateDlg() +{ + if (!g_rotate_dialog.window) { + g_rotate_dialog.window = MainFrame_getWindow().create_dialog_window("Arbitrary rotation", + G_CALLBACK(rotatedlg_delete), + &g_rotate_dialog); + + auto accel = ui::AccelGroup(ui::New); + g_rotate_dialog.window.add_accel_group(accel); + + { + auto hbox = create_dialog_hbox(4, 4); + g_rotate_dialog.window.add(hbox); + { + auto table = create_dialog_table(3, 2, 4, 4); + hbox.pack_start(table, TRUE, TRUE, 0); + { + ui::Widget label = ui::Label(" X "); + label.show(); table.attach(label, {0, 1, 0, 1}, {0, 0}); - } - { - ui::Widget label = ui::Label( " Y " ); - label.show(); + } + { + ui::Widget label = ui::Label(" Y "); + label.show(); table.attach(label, {0, 1, 1, 2}, {0, 0}); - } - { - ui::Widget label = ui::Label( " Z " ); - label.show(); + } + { + ui::Widget label = ui::Label(" Z "); + label.show(); table.attach(label, {0, 1, 2, 3}, {0, 0}); - } - { - auto adj = ui::Adjustment( 0, -359, 359, 1, 10, 0 ); - auto spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); + } + { + auto adj = ui::Adjustment(0, -359, 359, 1, 10, 0); + auto spin = ui::SpinButton(adj, 1, 0); + spin.show(); table.attach(spin, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); spin.dimensions(64, -1); - gtk_spin_button_set_wrap( spin, TRUE ); + gtk_spin_button_set_wrap(spin, TRUE); - gtk_widget_grab_focus( spin ); + gtk_widget_grab_focus(spin); - g_rotate_dialog.x = spin; - } - { - auto adj = ui::Adjustment( 0, -359, 359, 1, 10, 0 ); - auto spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); + g_rotate_dialog.x = spin; + } + { + auto adj = ui::Adjustment(0, -359, 359, 1, 10, 0); + auto spin = ui::SpinButton(adj, 1, 0); + spin.show(); table.attach(spin, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); spin.dimensions(64, -1); - gtk_spin_button_set_wrap( spin, TRUE ); - - g_rotate_dialog.y = spin; - } - { - auto adj = ui::Adjustment( 0, -359, 359, 1, 10, 0 ); - auto spin = ui::SpinButton( adj, 1, 0 ); - spin.show(); + gtk_spin_button_set_wrap(spin, TRUE); + + g_rotate_dialog.y = spin; + } + { + auto adj = ui::Adjustment(0, -359, 359, 1, 10, 0); + auto spin = ui::SpinButton(adj, 1, 0); + spin.show(); table.attach(spin, {1, 2, 2, 3}, {GTK_EXPAND | GTK_FILL, 0}); spin.dimensions(64, -1); - gtk_spin_button_set_wrap( spin, TRUE ); - - g_rotate_dialog.z = spin; - } - } - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, TRUE, TRUE, 0 ); - { - auto button = create_dialog_button( "OK", G_CALLBACK( rotatedlg_ok ), &g_rotate_dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - { - auto button = create_dialog_button( "Cancel", G_CALLBACK( rotatedlg_cancel ), &g_rotate_dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - { - auto button = create_dialog_button( "Apply", G_CALLBACK( rotatedlg_apply ), &g_rotate_dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - } - } - } - } - - g_rotate_dialog.window.show(); -} - - - - - - - - - -struct ScaleDialog -{ - ui::Entry x{ui::null}; - ui::Entry y{ui::null}; - ui::Entry z{ui::null}; - ui::Window window{ui::null}; + gtk_spin_button_set_wrap(spin, TRUE); + + g_rotate_dialog.z = spin; + } + } + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, TRUE, TRUE, 0); + { + auto button = create_dialog_button("OK", G_CALLBACK(rotatedlg_ok), &g_rotate_dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + { + auto button = create_dialog_button("Cancel", G_CALLBACK(rotatedlg_cancel), &g_rotate_dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + { + auto button = create_dialog_button("Apply", G_CALLBACK(rotatedlg_apply), &g_rotate_dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + } + } + } + } + + g_rotate_dialog.window.show(); +} + + +struct ScaleDialog { + ui::Entry x{ui::null}; + ui::Entry y{ui::null}; + ui::Entry z{ui::null}; + ui::Window window{ui::null}; }; -static gboolean scaledlg_apply( ui::Widget widget, ScaleDialog* scaleDialog ){ - float sx, sy, sz; +static gboolean scaledlg_apply(ui::Widget widget, ScaleDialog *scaleDialog) +{ + float sx, sy, sz; - sx = static_cast( atof( gtk_entry_get_text( GTK_ENTRY( scaleDialog->x ) ) ) ); - sy = static_cast( atof( gtk_entry_get_text( GTK_ENTRY( scaleDialog->y ) ) ) ); - sz = static_cast( atof( gtk_entry_get_text( GTK_ENTRY( scaleDialog->z ) ) ) ); + sx = static_cast( atof(gtk_entry_get_text(GTK_ENTRY(scaleDialog->x)))); + sy = static_cast( atof(gtk_entry_get_text(GTK_ENTRY(scaleDialog->y)))); + sz = static_cast( atof(gtk_entry_get_text(GTK_ENTRY(scaleDialog->z)))); - StringOutputStream command; - command << "scaleSelected -x " << sx << " -y " << sy << " -z " << sz; - UndoableCommand undo( command.c_str() ); + StringOutputStream command; + command << "scaleSelected -x " << sx << " -y " << sy << " -z " << sz; + UndoableCommand undo(command.c_str()); - Select_Scale( sx, sy, sz ); + Select_Scale(sx, sy, sz); - return TRUE; + return TRUE; } -static gboolean scaledlg_cancel( ui::Widget widget, ScaleDialog* scaleDialog ){ - scaleDialog->window.hide(); +static gboolean scaledlg_cancel(ui::Widget widget, ScaleDialog *scaleDialog) +{ + scaleDialog->window.hide(); - scaleDialog->x.text("1.0"); - scaleDialog->y.text("1.0"); - scaleDialog->z.text("1.0"); + scaleDialog->x.text("1.0"); + scaleDialog->y.text("1.0"); + scaleDialog->z.text("1.0"); - return TRUE; + return TRUE; } -static gboolean scaledlg_ok( ui::Widget widget, ScaleDialog* scaleDialog ){ - scaledlg_apply( widget, scaleDialog ); - scaleDialog->window.hide(); - return TRUE; +static gboolean scaledlg_ok(ui::Widget widget, ScaleDialog *scaleDialog) +{ + scaledlg_apply(widget, scaleDialog); + scaleDialog->window.hide(); + return TRUE; } -static gboolean scaledlg_delete( ui::Widget widget, GdkEventAny *event, ScaleDialog* scaleDialog ){ - scaledlg_cancel( widget, scaleDialog ); - return TRUE; +static gboolean scaledlg_delete(ui::Widget widget, GdkEventAny *event, ScaleDialog *scaleDialog) +{ + scaledlg_cancel(widget, scaleDialog); + return TRUE; } ScaleDialog g_scale_dialog; -void DoScaleDlg(){ - if ( !g_scale_dialog.window ) { - g_scale_dialog.window = MainFrame_getWindow().create_dialog_window("Arbitrary scale", G_CALLBACK(scaledlg_delete ), &g_scale_dialog ); - - auto accel = ui::AccelGroup(ui::New); - g_scale_dialog.window.add_accel_group( accel ); - - { - auto hbox = create_dialog_hbox( 4, 4 ); - g_scale_dialog.window.add(hbox); - { - auto table = create_dialog_table( 3, 2, 4, 4 ); - hbox.pack_start( table, TRUE, TRUE, 0 ); - { - ui::Widget label = ui::Label( " X " ); - label.show(); +void DoScaleDlg() +{ + if (!g_scale_dialog.window) { + g_scale_dialog.window = MainFrame_getWindow().create_dialog_window("Arbitrary scale", + G_CALLBACK(scaledlg_delete), + &g_scale_dialog); + + auto accel = ui::AccelGroup(ui::New); + g_scale_dialog.window.add_accel_group(accel); + + { + auto hbox = create_dialog_hbox(4, 4); + g_scale_dialog.window.add(hbox); + { + auto table = create_dialog_table(3, 2, 4, 4); + hbox.pack_start(table, TRUE, TRUE, 0); + { + ui::Widget label = ui::Label(" X "); + label.show(); table.attach(label, {0, 1, 0, 1}, {0, 0}); - } - { - ui::Widget label = ui::Label( " Y " ); - label.show(); + } + { + ui::Widget label = ui::Label(" Y "); + label.show(); table.attach(label, {0, 1, 1, 2}, {0, 0}); - } - { - ui::Widget label = ui::Label( " Z " ); - label.show(); + } + { + ui::Widget label = ui::Label(" Z "); + label.show(); table.attach(label, {0, 1, 2, 3}, {0, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.text("1.0"); - entry.show(); + } + { + auto entry = ui::Entry(ui::New); + entry.text("1.0"); + entry.show(); table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - g_scale_dialog.x = entry; - } - { - auto entry = ui::Entry(ui::New); - entry.text("1.0"); - entry.show(); + g_scale_dialog.x = entry; + } + { + auto entry = ui::Entry(ui::New); + entry.text("1.0"); + entry.show(); table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - g_scale_dialog.y = entry; - } - { - auto entry = ui::Entry(ui::New); - entry.text("1.0"); - entry.show(); + g_scale_dialog.y = entry; + } + { + auto entry = ui::Entry(ui::New); + entry.text("1.0"); + entry.show(); table.attach(entry, {1, 2, 2, 3}, {GTK_EXPAND | GTK_FILL, 0}); - g_scale_dialog.z = entry; - } - } - { - auto vbox = create_dialog_vbox( 4 ); - hbox.pack_start( vbox, TRUE, TRUE, 0 ); - { - auto button = create_dialog_button( "OK", G_CALLBACK( scaledlg_ok ), &g_scale_dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - widget_make_default( button ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - { - auto button = create_dialog_button( "Cancel", G_CALLBACK( scaledlg_cancel ), &g_scale_dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); - } - { - auto button = create_dialog_button( "Apply", G_CALLBACK( scaledlg_apply ), &g_scale_dialog ); - vbox.pack_start( button, FALSE, FALSE, 0 ); - } - } - } - } - - g_scale_dialog.window.show(); + g_scale_dialog.z = entry; + } + } + { + auto vbox = create_dialog_vbox(4); + hbox.pack_start(vbox, TRUE, TRUE, 0); + { + auto button = create_dialog_button("OK", G_CALLBACK(scaledlg_ok), &g_scale_dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + widget_make_default(button); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + { + auto button = create_dialog_button("Cancel", G_CALLBACK(scaledlg_cancel), &g_scale_dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, + (GtkAccelFlags) 0); + } + { + auto button = create_dialog_button("Apply", G_CALLBACK(scaledlg_apply), &g_scale_dialog); + vbox.pack_start(button, FALSE, FALSE, 0); + } + } + } + } + + g_scale_dialog.window.show(); } diff --git a/radiant/select.h b/radiant/select.h index 4a158fd4..89805881 100644 --- a/radiant/select.h +++ b/radiant/select.h @@ -24,67 +24,87 @@ #include "math/vector.h" -void Select_GetBounds( Vector3& mins, Vector3& maxs ); -void Select_GetMid( Vector3& mid ); +void Select_GetBounds(Vector3 &mins, Vector3 &maxs); + +void Select_GetMid(Vector3 &mid); void Select_Delete(); + void Select_Invert(); + void Select_Inside(); + void Select_Touching(); + void Scene_ExpandSelectionToEntities(); void Selection_Flipx(); + void Selection_Flipy(); + void Selection_Flipz(); + void Selection_Rotatex(); + void Selection_Rotatey(); + void Selection_Rotatez(); void Selection_MoveDown(); + void Selection_MoveUp(); void Select_AllOfType(); void DoRotateDlg(); + void DoScaleDlg(); -void Select_SetShader( const char* shader ); +void Select_SetShader(const char *shader); class TextureProjection; -void Select_SetTexdef( const TextureProjection& projection ); + +void Select_SetTexdef(const TextureProjection &projection); class ContentsFlagsValue; -void Select_SetFlags( const ContentsFlagsValue& flags ); -void Select_RotateTexture( float amt ); -void Select_ScaleTexture( float x, float y ); -void Select_ShiftTexture( float x, float y ); -void Select_FitTexture( float horizontal = 1, float vertical = 1 ); -void FindReplaceTextures( const char* pFind, const char* pReplace, bool bSelected ); +void Select_SetFlags(const ContentsFlagsValue &flags); + +void Select_RotateTexture(float amt); + +void Select_ScaleTexture(float x, float y); + +void Select_ShiftTexture(float x, float y); + +void Select_FitTexture(float horizontal = 1, float vertical = 1); + +void FindReplaceTextures(const char *pFind, const char *pReplace, bool bSelected); void HideSelected(); + void Select_ShowAllHidden(); // updating workzone to a given brush (depends on current view) void Selection_construct(); + void Selection_destroy(); -struct select_workzone_t -{ - // defines the boundaries of the current work area - // is used to guess brushes and drop points third coordinate when creating from 2D view - Vector3 d_work_min, d_work_max; +struct select_workzone_t { + // defines the boundaries of the current work area + // is used to guess brushes and drop points third coordinate when creating from 2D view + Vector3 d_work_min, d_work_max; - select_workzone_t() : - d_work_min( -64.0f,-64.0f,-64.0f ), - d_work_max( 64.0f, 64.0f, 64.0f ){ - } + select_workzone_t() : + d_work_min(-64.0f, -64.0f, -64.0f), + d_work_max(64.0f, 64.0f, 64.0f) + { + } }; -const select_workzone_t& Select_getWorkZone(); +const select_workzone_t &Select_getWorkZone(); #endif diff --git a/radiant/selection.cpp b/radiant/selection.cpp index df18daa9..9a409f27 100644 --- a/radiant/selection.cpp +++ b/radiant/selection.cpp @@ -53,418 +53,459 @@ #include "grid.h" -TextOutputStream& ostream_write( TextOutputStream& t, const Vector4& v ){ - return t << "[ " << v.x() << " " << v.y() << " " << v.z() << " " << v.w() << " ]"; +TextOutputStream &ostream_write(TextOutputStream &t, const Vector4 &v) +{ + return t << "[ " << v.x() << " " << v.y() << " " << v.z() << " " << v.w() << " ]"; } -TextOutputStream& ostream_write( TextOutputStream& t, const Matrix4& m ){ - return t << "[ " << m.x() << " " << m.y() << " " << m.z() << " " << m.t() << " ]"; +TextOutputStream &ostream_write(TextOutputStream &t, const Matrix4 &m) +{ + return t << "[ " << m.x() << " " << m.y() << " " << m.z() << " " << m.t() << " ]"; } -struct Pivot2World -{ - Matrix4 m_worldSpace; - Matrix4 m_viewpointSpace; - Matrix4 m_viewplaneSpace; - Vector3 m_axis_screen; +struct Pivot2World { + Matrix4 m_worldSpace; + Matrix4 m_viewpointSpace; + Matrix4 m_viewplaneSpace; + Vector3 m_axis_screen; - void update( const Matrix4& pivot2world, const Matrix4& modelview, const Matrix4& projection, const Matrix4& viewport ){ - Pivot2World_worldSpace( m_worldSpace, pivot2world, modelview, projection, viewport ); - Pivot2World_viewpointSpace( m_viewpointSpace, m_axis_screen, pivot2world, modelview, projection, viewport ); - Pivot2World_viewplaneSpace( m_viewplaneSpace, pivot2world, modelview, projection, viewport ); - } + void + update(const Matrix4 &pivot2world, const Matrix4 &modelview, const Matrix4 &projection, const Matrix4 &viewport) + { + Pivot2World_worldSpace(m_worldSpace, pivot2world, modelview, projection, viewport); + Pivot2World_viewpointSpace(m_viewpointSpace, m_axis_screen, pivot2world, modelview, projection, viewport); + Pivot2World_viewplaneSpace(m_viewplaneSpace, pivot2world, modelview, projection, viewport); + } }; -void point_for_device_point( Vector3& point, const Matrix4& device2object, const float x, const float y, const float z ){ - // transform from normalised device coords to object coords - point = vector4_projected( matrix4_transformed_vector4( device2object, Vector4( x, y, z, 1 ) ) ); +void point_for_device_point(Vector3 &point, const Matrix4 &device2object, const float x, const float y, const float z) +{ + // transform from normalised device coords to object coords + point = vector4_projected(matrix4_transformed_vector4(device2object, Vector4(x, y, z, 1))); } -void ray_for_device_point( Ray& ray, const Matrix4& device2object, const float x, const float y ){ - // point at x, y, zNear - point_for_device_point( ray.origin, device2object, x, y, -1 ); +void ray_for_device_point(Ray &ray, const Matrix4 &device2object, const float x, const float y) +{ + // point at x, y, zNear + point_for_device_point(ray.origin, device2object, x, y, -1); - // point at x, y, zFar - point_for_device_point( ray.direction, device2object, x, y, 1 ); + // point at x, y, zFar + point_for_device_point(ray.direction, device2object, x, y, 1); - // construct ray - vector3_subtract( ray.direction, ray.origin ); - vector3_normalise( ray.direction ); + // construct ray + vector3_subtract(ray.direction, ray.origin); + vector3_normalise(ray.direction); } -bool sphere_intersect_ray( const Vector3& origin, float radius, const Ray& ray, Vector3& intersection ){ - intersection = vector3_subtracted( origin, ray.origin ); - const double a = vector3_dot( intersection, ray.direction ); - const double d = radius * radius - ( vector3_dot( intersection, intersection ) - a * a ); +bool sphere_intersect_ray(const Vector3 &origin, float radius, const Ray &ray, Vector3 &intersection) +{ + intersection = vector3_subtracted(origin, ray.origin); + const double a = vector3_dot(intersection, ray.direction); + const double d = radius * radius - (vector3_dot(intersection, intersection) - a * a); - if ( d > 0 ) { - intersection = vector3_added( ray.origin, vector3_scaled( ray.direction, a - sqrt( d ) ) ); - return true; - } - else - { - intersection = vector3_added( ray.origin, vector3_scaled( ray.direction, a ) ); - return false; - } + if (d > 0) { + intersection = vector3_added(ray.origin, vector3_scaled(ray.direction, a - sqrt(d))); + return true; + } else { + intersection = vector3_added(ray.origin, vector3_scaled(ray.direction, a)); + return false; + } } -void ray_intersect_ray( const Ray& ray, const Ray& other, Vector3& intersection ){ - intersection = vector3_subtracted( ray.origin, other.origin ); - //float a = 1;//vector3_dot(ray.direction, ray.direction); // always >= 0 - double dot = vector3_dot( ray.direction, other.direction ); - //float c = 1;//vector3_dot(other.direction, other.direction); // always >= 0 - double d = vector3_dot( ray.direction, intersection ); - double e = vector3_dot( other.direction, intersection ); - double D = 1 - dot * dot; //a*c - dot*dot; // always >= 0 +void ray_intersect_ray(const Ray &ray, const Ray &other, Vector3 &intersection) +{ + intersection = vector3_subtracted(ray.origin, other.origin); + //float a = 1;//vector3_dot(ray.direction, ray.direction); // always >= 0 + double dot = vector3_dot(ray.direction, other.direction); + //float c = 1;//vector3_dot(other.direction, other.direction); // always >= 0 + double d = vector3_dot(ray.direction, intersection); + double e = vector3_dot(other.direction, intersection); + double D = 1 - dot * dot; //a*c - dot*dot; // always >= 0 - if ( D < 0.000001 ) { - // the lines are almost parallel - intersection = vector3_added( other.origin, vector3_scaled( other.direction, e ) ); - } - else - { - intersection = vector3_added( other.origin, vector3_scaled( other.direction, ( e - dot * d ) / D ) ); - } + if (D < 0.000001) { + // the lines are almost parallel + intersection = vector3_added(other.origin, vector3_scaled(other.direction, e)); + } else { + intersection = vector3_added(other.origin, vector3_scaled(other.direction, (e - dot * d) / D)); + } } -const Vector3 g_origin( 0, 0, 0 ); +const Vector3 g_origin(0, 0, 0); const float g_radius = 64; -void point_on_sphere( Vector3& point, const Matrix4& device2object, const float x, const float y ){ - Ray ray; - ray_for_device_point( ray, device2object, x, y ); - sphere_intersect_ray( g_origin, g_radius, ray, point ); +void point_on_sphere(Vector3 &point, const Matrix4 &device2object, const float x, const float y) +{ + Ray ray; + ray_for_device_point(ray, device2object, x, y); + sphere_intersect_ray(g_origin, g_radius, ray, point); } -void point_on_axis( Vector3& point, const Vector3& axis, const Matrix4& device2object, const float x, const float y ){ - Ray ray; - ray_for_device_point( ray, device2object, x, y ); - ray_intersect_ray( ray, Ray( Vector3( 0, 0, 0 ), axis ), point ); +void point_on_axis(Vector3 &point, const Vector3 &axis, const Matrix4 &device2object, const float x, const float y) +{ + Ray ray; + ray_for_device_point(ray, device2object, x, y); + ray_intersect_ray(ray, Ray(Vector3(0, 0, 0), axis), point); } -void point_on_plane( Vector3& point, const Matrix4& device2object, const float x, const float y ){ - Matrix4 object2device( matrix4_full_inverse( device2object ) ); - point = vector4_projected( matrix4_transformed_vector4( device2object, Vector4( x, y, object2device[14] / object2device[15], 1 ) ) ); +void point_on_plane(Vector3 &point, const Matrix4 &device2object, const float x, const float y) +{ + Matrix4 object2device(matrix4_full_inverse(device2object)); + point = vector4_projected( + matrix4_transformed_vector4(device2object, Vector4(x, y, object2device[14] / object2device[15], 1))); } //! a and b are unit vectors .. returns angle in radians -inline float angle_between( const Vector3& a, const Vector3& b ){ - return static_cast( 2.0 * atan2( - vector3_length( vector3_subtracted( a, b ) ), - vector3_length( vector3_added( a, b ) ) - ) ); +inline float angle_between(const Vector3 &a, const Vector3 &b) +{ + return static_cast( 2.0 * atan2( + vector3_length(vector3_subtracted(a, b)), + vector3_length(vector3_added(a, b)) + )); } #if GDEF_DEBUG -class test_quat -{ + +class test_quat { public: -test_quat( const Vector3& from, const Vector3& to ){ - Vector4 quaternion( quaternion_for_unit_vectors( from, to ) ); - Matrix4 matrix( matrix4_rotation_for_quaternion( quaternion_multiplied_by_quaternion( quaternion, c_quaternion_identity ) ) ); -} + test_quat(const Vector3 &from, const Vector3 &to) + { + Vector4 quaternion(quaternion_for_unit_vectors(from, to)); + Matrix4 matrix(matrix4_rotation_for_quaternion( + quaternion_multiplied_by_quaternion(quaternion, c_quaternion_identity))); + } + private: }; -static test_quat bleh( g_vector3_axis_x, g_vector3_axis_y ); +static test_quat bleh(g_vector3_axis_x, g_vector3_axis_y); #endif //! axis is a unit vector -inline void constrain_to_axis( Vector3& vec, const Vector3& axis ){ - vec = vector3_normalised( vector3_added( vec, vector3_scaled( axis, -vector3_dot( vec, axis ) ) ) ); +inline void constrain_to_axis(Vector3 &vec, const Vector3 &axis) +{ + vec = vector3_normalised(vector3_added(vec, vector3_scaled(axis, -vector3_dot(vec, axis)))); } //! a and b are unit vectors .. a and b must be orthogonal to axis .. returns angle in radians -float angle_for_axis( const Vector3& a, const Vector3& b, const Vector3& axis ){ - if ( vector3_dot( axis, vector3_cross( a, b ) ) > 0.0 ) { - return angle_between( a, b ); - } - else{ - return -angle_between( a, b ); - } -} - -float distance_for_axis( const Vector3& a, const Vector3& b, const Vector3& axis ){ - return static_cast( vector3_dot( b, axis ) - vector3_dot( a, axis ) ); +float angle_for_axis(const Vector3 &a, const Vector3 &b, const Vector3 &axis) +{ + if (vector3_dot(axis, vector3_cross(a, b)) > 0.0) { + return angle_between(a, b); + } else { + return -angle_between(a, b); + } } -class Manipulatable +float distance_for_axis(const Vector3 &a, const Vector3 &b, const Vector3 &axis) { -public: -virtual void Construct( const Matrix4& device2manip, const float x, const float y ) = 0; -virtual void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y ) = 0; -}; - -void transform_local2object( Matrix4& object, const Matrix4& local, const Matrix4& local2object ){ - object = matrix4_multiplied_by_matrix4( - matrix4_multiplied_by_matrix4( local2object, local ), - matrix4_full_inverse( local2object ) - ); + return static_cast( vector3_dot(b, axis) - vector3_dot(a, axis)); } -class Rotatable -{ +class Manipulatable { public: -virtual ~Rotatable() = default; -virtual void rotate( const Quaternion& rotation ) = 0; + virtual void Construct(const Matrix4 &device2manip, const float x, const float y) = 0; + + virtual void Transform(const Matrix4 &manip2object, const Matrix4 &device2manip, const float x, const float y) = 0; }; -class RotateFree : public Manipulatable +void transform_local2object(Matrix4 &object, const Matrix4 &local, const Matrix4 &local2object) { -Vector3 m_start; -Rotatable& m_rotatable; -public: -RotateFree( Rotatable& rotatable ) - : m_rotatable( rotatable ){ + object = matrix4_multiplied_by_matrix4( + matrix4_multiplied_by_matrix4(local2object, local), + matrix4_full_inverse(local2object) + ); } -void Construct( const Matrix4& device2manip, const float x, const float y ){ - point_on_sphere( m_start, device2manip, x, y ); - vector3_normalise( m_start ); -} -void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y ){ - Vector3 current; - point_on_sphere( current, device2manip, x, y ); - vector3_normalise( current ); +class Rotatable { +public: + virtual ~Rotatable() = default; - m_rotatable.rotate( quaternion_for_unit_vectors( m_start, current ) ); -} + virtual void rotate(const Quaternion &rotation) = 0; }; -class RotateAxis : public Manipulatable -{ -Vector3 m_axis; -Vector3 m_start; -Rotatable& m_rotatable; +class RotateFree : public Manipulatable { + Vector3 m_start; + Rotatable &m_rotatable; public: -RotateAxis( Rotatable& rotatable ) - : m_rotatable( rotatable ){ -} -void Construct( const Matrix4& device2manip, const float x, const float y ){ - point_on_sphere( m_start, device2manip, x, y ); - constrain_to_axis( m_start, m_axis ); -} -/// \brief Converts current position to a normalised vector orthogonal to axis. -void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y ){ - Vector3 current; - point_on_sphere( current, device2manip, x, y ); - constrain_to_axis( current, m_axis ); + RotateFree(Rotatable &rotatable) + : m_rotatable(rotatable) + { + } - m_rotatable.rotate( quaternion_for_axisangle( m_axis, angle_for_axis( m_start, current, m_axis ) ) ); -} + void Construct(const Matrix4 &device2manip, const float x, const float y) + { + point_on_sphere(m_start, device2manip, x, y); + vector3_normalise(m_start); + } -void SetAxis( const Vector3& axis ){ - m_axis = axis; -} -}; + void Transform(const Matrix4 &manip2object, const Matrix4 &device2manip, const float x, const float y) + { + Vector3 current; -void translation_local2object( Vector3& object, const Vector3& local, const Matrix4& local2object ){ - object = matrix4_get_translation_vec3( - matrix4_multiplied_by_matrix4( - matrix4_translated_by_vec3( local2object, local ), - matrix4_full_inverse( local2object ) - ) - ); -} + point_on_sphere(current, device2manip, x, y); + vector3_normalise(current); -class Translatable -{ -public: -virtual ~Translatable() = default; -virtual void translate( const Vector3& translation ) = 0; + m_rotatable.rotate(quaternion_for_unit_vectors(m_start, current)); + } }; -class TranslateAxis : public Manipulatable -{ -Vector3 m_start; -Vector3 m_axis; -Translatable& m_translatable; +class RotateAxis : public Manipulatable { + Vector3 m_axis; + Vector3 m_start; + Rotatable &m_rotatable; public: -TranslateAxis( Translatable& translatable ) - : m_translatable( translatable ){ -} -void Construct( const Matrix4& device2manip, const float x, const float y ){ - point_on_axis( m_start, m_axis, device2manip, x, y ); -} -void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y ){ - Vector3 current; - point_on_axis( current, m_axis, device2manip, x, y ); - current = vector3_scaled( m_axis, distance_for_axis( m_start, current, m_axis ) ); + RotateAxis(Rotatable &rotatable) + : m_rotatable(rotatable) + { + } - translation_local2object( current, current, manip2object ); - vector3_snap( current, GetSnapGridSize() ); + void Construct(const Matrix4 &device2manip, const float x, const float y) + { + point_on_sphere(m_start, device2manip, x, y); + constrain_to_axis(m_start, m_axis); + } - m_translatable.translate( current ); -} +/// \brief Converts current position to a normalised vector orthogonal to axis. + void Transform(const Matrix4 &manip2object, const Matrix4 &device2manip, const float x, const float y) + { + Vector3 current; + point_on_sphere(current, device2manip, x, y); + constrain_to_axis(current, m_axis); -void SetAxis( const Vector3& axis ){ - m_axis = axis; -} + m_rotatable.rotate(quaternion_for_axisangle(m_axis, angle_for_axis(m_start, current, m_axis))); + } + + void SetAxis(const Vector3 &axis) + { + m_axis = axis; + } }; -class TranslateFree : public Manipulatable +void translation_local2object(Vector3 &object, const Vector3 &local, const Matrix4 &local2object) { -private: -Vector3 m_start; -Translatable& m_translatable; -public: -TranslateFree( Translatable& translatable ) - : m_translatable( translatable ){ + object = matrix4_get_translation_vec3( + matrix4_multiplied_by_matrix4( + matrix4_translated_by_vec3(local2object, local), + matrix4_full_inverse(local2object) + ) + ); } -void Construct( const Matrix4& device2manip, const float x, const float y ){ - point_on_plane( m_start, device2manip, x, y ); -} -void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y ){ - Vector3 current; - point_on_plane( current, device2manip, x, y ); - current = vector3_subtracted( current, m_start ); - translation_local2object( current, current, manip2object ); - vector3_snap( current, GetSnapGridSize() ); +class Translatable { +public: + virtual ~Translatable() = default; - m_translatable.translate( current ); -} + virtual void translate(const Vector3 &translation) = 0; }; - -class Scalable -{ +class TranslateAxis : public Manipulatable { + Vector3 m_start; + Vector3 m_axis; + Translatable &m_translatable; public: -virtual ~Scalable() = default; -virtual void scale( const Vector3& scaling ) = 0; -}; + TranslateAxis(Translatable &translatable) + : m_translatable(translatable) + { + } + void Construct(const Matrix4 &device2manip, const float x, const float y) + { + point_on_axis(m_start, m_axis, device2manip, x, y); + } -class ScaleAxis : public Manipulatable -{ -private: -Vector3 m_start; -Vector3 m_axis; -Scalable& m_scalable; -public: -ScaleAxis( Scalable& scalable ) - : m_scalable( scalable ){ -} -void Construct( const Matrix4& device2manip, const float x, const float y ){ - point_on_axis( m_start, m_axis, device2manip, x, y ); -} -void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y ){ - Vector3 current; - point_on_axis( current, m_axis, device2manip, x, y ); - Vector3 delta = vector3_subtracted( current, m_start ); + void Transform(const Matrix4 &manip2object, const Matrix4 &device2manip, const float x, const float y) + { + Vector3 current; + point_on_axis(current, m_axis, device2manip, x, y); + current = vector3_scaled(m_axis, distance_for_axis(m_start, current, m_axis)); - translation_local2object( delta, delta, manip2object ); - vector3_snap( delta, GetSnapGridSize() ); + translation_local2object(current, current, manip2object); + vector3_snap(current, GetSnapGridSize()); - Vector3 start( vector3_snapped( m_start, GetSnapGridSize() ) ); - Vector3 scale( - start[0] == 0 ? 1 : 1 + delta[0] / start[0], - start[1] == 0 ? 1 : 1 + delta[1] / start[1], - start[2] == 0 ? 1 : 1 + delta[2] / start[2] - ); - m_scalable.scale( scale ); -} + m_translatable.translate(current); + } -void SetAxis( const Vector3& axis ){ - m_axis = axis; -} + void SetAxis(const Vector3 &axis) + { + m_axis = axis; + } }; -class ScaleFree : public Manipulatable -{ +class TranslateFree : public Manipulatable { private: -Vector3 m_start; -Scalable& m_scalable; + Vector3 m_start; + Translatable &m_translatable; public: -ScaleFree( Scalable& scalable ) - : m_scalable( scalable ){ -} -void Construct( const Matrix4& device2manip, const float x, const float y ){ - point_on_plane( m_start, device2manip, x, y ); -} -void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y ){ - Vector3 current; - point_on_plane( current, device2manip, x, y ); - Vector3 delta = vector3_subtracted( current, m_start ); - - translation_local2object( delta, delta, manip2object ); - vector3_snap( delta, GetSnapGridSize() ); - - Vector3 start( vector3_snapped( m_start, GetSnapGridSize() ) ); - Vector3 scale( - start[0] == 0 ? 1 : 1 + delta[0] / start[0], - start[1] == 0 ? 1 : 1 + delta[1] / start[1], - start[2] == 0 ? 1 : 1 + delta[2] / start[2] - ); - m_scalable.scale( scale ); -} -}; - - - - + TranslateFree(Translatable &translatable) + : m_translatable(translatable) + { + } + void Construct(const Matrix4 &device2manip, const float x, const float y) + { + point_on_plane(m_start, device2manip, x, y); + } + void Transform(const Matrix4 &manip2object, const Matrix4 &device2manip, const float x, const float y) + { + Vector3 current; + point_on_plane(current, device2manip, x, y); + current = vector3_subtracted(current, m_start); + translation_local2object(current, current, manip2object); + vector3_snap(current, GetSnapGridSize()); + m_translatable.translate(current); + } +}; -class RenderableClippedPrimitive : public OpenGLRenderable -{ -struct primitive_t -{ - PointVertex m_points[9]; - std::size_t m_count; -}; -Matrix4 m_inverse; -std::vector m_primitives; +class Scalable { public: -Matrix4 m_world; - -void render( RenderStateFlags state ) const { - for ( std::size_t i = 0; i < m_primitives.size(); ++i ) - { - glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_primitives[i].m_points[0].colour ); - glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_primitives[i].m_points[0].vertex ); - switch ( m_primitives[i].m_count ) - { - case 1: break; - case 2: glDrawArrays( GL_LINES, 0, GLsizei( m_primitives[i].m_count ) ); break; - default: glDrawArrays( GL_POLYGON, 0, GLsizei( m_primitives[i].m_count ) ); break; - } - } -} + virtual ~Scalable() = default; -void construct( const Matrix4& world2device ){ - m_inverse = matrix4_full_inverse( world2device ); - m_world = g_matrix4_identity; -} + virtual void scale(const Vector3 &scaling) = 0; +}; -void insert( const Vector4 clipped[9], std::size_t count ){ - add_one(); - m_primitives.back().m_count = count; - for ( std::size_t i = 0; i < count; ++i ) - { - Vector3 world_point( vector4_projected( matrix4_transformed_vector4( m_inverse, clipped[i] ) ) ); - m_primitives.back().m_points[i].vertex = vertex3f_for_vector3( world_point ); - } -} +class ScaleAxis : public Manipulatable { +private: + Vector3 m_start; + Vector3 m_axis; + Scalable &m_scalable; +public: + ScaleAxis(Scalable &scalable) + : m_scalable(scalable) + { + } + + void Construct(const Matrix4 &device2manip, const float x, const float y) + { + point_on_axis(m_start, m_axis, device2manip, x, y); + } + + void Transform(const Matrix4 &manip2object, const Matrix4 &device2manip, const float x, const float y) + { + Vector3 current; + point_on_axis(current, m_axis, device2manip, x, y); + Vector3 delta = vector3_subtracted(current, m_start); + + translation_local2object(delta, delta, manip2object); + vector3_snap(delta, GetSnapGridSize()); + + Vector3 start(vector3_snapped(m_start, GetSnapGridSize())); + Vector3 scale( + start[0] == 0 ? 1 : 1 + delta[0] / start[0], + start[1] == 0 ? 1 : 1 + delta[1] / start[1], + start[2] == 0 ? 1 : 1 + delta[2] / start[2] + ); + m_scalable.scale(scale); + } + + void SetAxis(const Vector3 &axis) + { + m_axis = axis; + } +}; + +class ScaleFree : public Manipulatable { +private: + Vector3 m_start; + Scalable &m_scalable; +public: + ScaleFree(Scalable &scalable) + : m_scalable(scalable) + { + } + + void Construct(const Matrix4 &device2manip, const float x, const float y) + { + point_on_plane(m_start, device2manip, x, y); + } + + void Transform(const Matrix4 &manip2object, const Matrix4 &device2manip, const float x, const float y) + { + Vector3 current; + point_on_plane(current, device2manip, x, y); + Vector3 delta = vector3_subtracted(current, m_start); + + translation_local2object(delta, delta, manip2object); + vector3_snap(delta, GetSnapGridSize()); + + Vector3 start(vector3_snapped(m_start, GetSnapGridSize())); + Vector3 scale( + start[0] == 0 ? 1 : 1 + delta[0] / start[0], + start[1] == 0 ? 1 : 1 + delta[1] / start[1], + start[2] == 0 ? 1 : 1 + delta[2] / start[2] + ); + m_scalable.scale(scale); + } +}; + + +class RenderableClippedPrimitive : public OpenGLRenderable { + struct primitive_t { + PointVertex m_points[9]; + std::size_t m_count; + }; + Matrix4 m_inverse; + std::vector m_primitives; +public: + Matrix4 m_world; + + void render(RenderStateFlags state) const + { + for (std::size_t i = 0; i < m_primitives.size(); ++i) { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_primitives[i].m_points[0].colour); + glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_primitives[i].m_points[0].vertex); + switch (m_primitives[i].m_count) { + case 1: + break; + case 2: + glDrawArrays(GL_LINES, 0, GLsizei(m_primitives[i].m_count)); + break; + default: + glDrawArrays(GL_POLYGON, 0, GLsizei(m_primitives[i].m_count)); + break; + } + } + } + + void construct(const Matrix4 &world2device) + { + m_inverse = matrix4_full_inverse(world2device); + m_world = g_matrix4_identity; + } + + void insert(const Vector4 clipped[9], std::size_t count) + { + add_one(); + + m_primitives.back().m_count = count; + for (std::size_t i = 0; i < count; ++i) { + Vector3 world_point(vector4_projected(matrix4_transformed_vector4(m_inverse, clipped[i]))); + m_primitives.back().m_points[i].vertex = vertex3f_for_vector3(world_point); + } + } + + void destroy() + { + m_primitives.clear(); + } -void destroy(){ - m_primitives.clear(); -} private: -void add_one(){ - m_primitives.push_back( primitive_t() ); + void add_one() + { + m_primitives.push_back(primitive_t()); - const Colour4b colour_clipped( 255, 127, 0, 255 ); + const Colour4b colour_clipped(255, 127, 0, 255); - for ( std::size_t i = 0; i < 9; ++i ) - m_primitives.back().m_points[i].colour = colour_clipped; -} + for (std::size_t i = 0; i < 9; ++i) { + m_primitives.back().m_points[i].colour = colour_clipped; + } + } }; #if GDEF_DEBUG @@ -472,13 +513,13 @@ void add_one(){ #endif #if defined( DEBUG_SELECTION ) -Shader* g_state_clipped; +Shader *g_state_clipped; RenderableClippedPrimitive g_render_clipped; #endif #if 0 -// dist_Point_to_Line(): get the distance of a point to a line. + // dist_Point_to_Line(): get the distance of a point to a line. // Input: a Point P and a Line L (in any dimension) // Return: the shortest distance from P to L float @@ -495,1649 +536,1806 @@ dist_Point_to_Line( Point P, Line L ){ } #endif -class Segment3D -{ -typedef Vector3 point_type; +class Segment3D { + typedef Vector3 point_type; public: -Segment3D( const point_type& _p0, const point_type& _p1 ) - : p0( _p0 ), p1( _p1 ){ -} + Segment3D(const point_type &_p0, const point_type &_p1) + : p0(_p0), p1(_p1) + { + } -point_type p0, p1; + point_type p0, p1; }; typedef Vector3 Point3D; -inline double vector3_distance_squared( const Point3D& a, const Point3D& b ){ - return vector3_length_squared( b - a ); +inline double vector3_distance_squared(const Point3D &a, const Point3D &b) +{ + return vector3_length_squared(b - a); } // get the distance of a point to a segment. -Point3D segment_closest_point_to_point( const Segment3D& segment, const Point3D& point ){ - Vector3 v = segment.p1 - segment.p0; - Vector3 w = point - segment.p0; +Point3D segment_closest_point_to_point(const Segment3D &segment, const Point3D &point) +{ + Vector3 v = segment.p1 - segment.p0; + Vector3 w = point - segment.p0; - double c1 = vector3_dot( w,v ); - if ( c1 <= 0 ) { - return segment.p0; - } + double c1 = vector3_dot(w, v); + if (c1 <= 0) { + return segment.p0; + } - double c2 = vector3_dot( v,v ); - if ( c2 <= c1 ) { - return segment.p1; - } + double c2 = vector3_dot(v, v); + if (c2 <= c1) { + return segment.p1; + } - return Point3D( segment.p0 + v * ( c1 / c2 ) ); + return Point3D(segment.p0 + v * (c1 / c2)); } -double segment_dist_to_point_3d( const Segment3D& segment, const Point3D& point ){ - return vector3_distance_squared( point, segment_closest_point_to_point( segment, point ) ); +double segment_dist_to_point_3d(const Segment3D &segment, const Point3D &point) +{ + return vector3_distance_squared(point, segment_closest_point_to_point(segment, point)); } typedef Vector3 point_t; -typedef const Vector3* point_iterator_t; +typedef const Vector3 *point_iterator_t; // crossing number test for a point in a polygon // This code is patterned after [Franklin, 2000] -bool point_test_polygon_2d( const point_t& P, point_iterator_t start, point_iterator_t finish ){ - std::size_t crossings = 0; - - // loop through all edges of the polygon - for ( point_iterator_t prev = finish - 1, cur = start; cur != finish; prev = cur, ++cur ) - { // edge from (*prev) to (*cur) - if ( ( ( ( *prev )[1] <= P[1] ) && ( ( *cur )[1] > P[1] ) ) // an upward crossing - || ( ( ( *prev )[1] > P[1] ) && ( ( *cur )[1] <= P[1] ) ) ) { // a downward crossing - // compute the actual edge-ray intersect x-coordinate - float vt = (float)( P[1] - ( *prev )[1] ) / ( ( *cur )[1] - ( *prev )[1] ); - if ( P[0] < ( *prev )[0] + vt * ( ( *cur )[0] - ( *prev )[0] ) ) { // P[0] < intersect - ++crossings; // a valid crossing of y=P[1] right of P[0] - } - } - } - return ( crossings & 0x1 ) != 0; // 0 if even (out), and 1 if odd (in) -} - -inline double triangle_signed_area_XY( const Vector3& p0, const Vector3& p1, const Vector3& p2 ){ - return ( ( p1[0] - p0[0] ) * ( p2[1] - p0[1] ) ) - ( ( p2[0] - p0[0] ) * ( p1[1] - p0[1] ) ); -} - -enum clipcull_t -{ - eClipCullNone, - eClipCullCW, - eClipCullCCW, -}; - - -inline SelectionIntersection select_point_from_clipped( Vector4& clipped ){ - return SelectionIntersection( clipped[2] / clipped[3], static_cast( vector3_length_squared( Vector3( clipped[0] / clipped[3], clipped[1] / clipped[3], 0 ) ) ) ); -} - -void BestPoint( std::size_t count, Vector4 clipped[9], SelectionIntersection& best, clipcull_t cull ){ - Vector3 normalised[9]; - - { - for ( std::size_t i = 0; i < count; ++i ) - { - normalised[i][0] = clipped[i][0] / clipped[i][3]; - normalised[i][1] = clipped[i][1] / clipped[i][3]; - normalised[i][2] = clipped[i][2] / clipped[i][3]; - } - } - - if ( cull != eClipCullNone && count > 2 ) { - double signed_area = triangle_signed_area_XY( normalised[0], normalised[1], normalised[2] ); - - if ( ( cull == eClipCullCW && signed_area > 0 ) - || ( cull == eClipCullCCW && signed_area < 0 ) ) { - return; - } - } - - if ( count == 2 ) { - Segment3D segment( normalised[0], normalised[1] ); - Point3D point = segment_closest_point_to_point( segment, Vector3( 0, 0, 0 ) ); - assign_if_closer( best, SelectionIntersection( point.z(), 0 ) ); - } - else if ( count > 2 && !point_test_polygon_2d( Vector3( 0, 0, 0 ), normalised, normalised + count ) ) { - point_iterator_t end = normalised + count; - for ( point_iterator_t previous = end - 1, current = normalised; current != end; previous = current, ++current ) - { - Segment3D segment( *previous, *current ); - Point3D point = segment_closest_point_to_point( segment, Vector3( 0, 0, 0 ) ); - float depth = point.z(); - point.z() = 0; - float distance = static_cast( vector3_length_squared( point ) ); - - assign_if_closer( best, SelectionIntersection( depth, distance ) ); - } - } - else if ( count > 2 ) { - assign_if_closer( - best, - SelectionIntersection( - static_cast( ray_distance_to_plane( - Ray( Vector3( 0, 0, 0 ), Vector3( 0, 0, 1 ) ), - plane3_for_points( normalised[0], normalised[1], normalised[2] ) - ) ), - 0 - ) - ); - } +bool point_test_polygon_2d(const point_t &P, point_iterator_t start, point_iterator_t finish) +{ + std::size_t crossings = 0; + + // loop through all edges of the polygon + for (point_iterator_t prev = finish - 1, cur = start; + cur != finish; prev = cur, ++cur) { // edge from (*prev) to (*cur) + if ((((*prev)[1] <= P[1]) && ((*cur)[1] > P[1])) // an upward crossing + || (((*prev)[1] > P[1]) && ((*cur)[1] <= P[1]))) { // a downward crossing + // compute the actual edge-ray intersect x-coordinate + float vt = (float) (P[1] - (*prev)[1]) / ((*cur)[1] - (*prev)[1]); + if (P[0] < (*prev)[0] + vt * ((*cur)[0] - (*prev)[0])) { // P[0] < intersect + ++crossings; // a valid crossing of y=P[1] right of P[0] + } + } + } + return (crossings & 0x1) != 0; // 0 if even (out), and 1 if odd (in) +} + +inline double triangle_signed_area_XY(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2) +{ + return ((p1[0] - p0[0]) * (p2[1] - p0[1])) - ((p2[0] - p0[0]) * (p1[1] - p0[1])); +} + +enum clipcull_t { + eClipCullNone, + eClipCullCW, + eClipCullCCW, +}; + + +inline SelectionIntersection select_point_from_clipped(Vector4 &clipped) +{ + return SelectionIntersection(clipped[2] / clipped[3], static_cast( vector3_length_squared( + Vector3(clipped[0] / clipped[3], clipped[1] / clipped[3], 0)))); +} + +void BestPoint(std::size_t count, Vector4 clipped[9], SelectionIntersection &best, clipcull_t cull) +{ + Vector3 normalised[9]; + + { + for (std::size_t i = 0; i < count; ++i) { + normalised[i][0] = clipped[i][0] / clipped[i][3]; + normalised[i][1] = clipped[i][1] / clipped[i][3]; + normalised[i][2] = clipped[i][2] / clipped[i][3]; + } + } + + if (cull != eClipCullNone && count > 2) { + double signed_area = triangle_signed_area_XY(normalised[0], normalised[1], normalised[2]); + + if ((cull == eClipCullCW && signed_area > 0) + || (cull == eClipCullCCW && signed_area < 0)) { + return; + } + } + + if (count == 2) { + Segment3D segment(normalised[0], normalised[1]); + Point3D point = segment_closest_point_to_point(segment, Vector3(0, 0, 0)); + assign_if_closer(best, SelectionIntersection(point.z(), 0)); + } else if (count > 2 && !point_test_polygon_2d(Vector3(0, 0, 0), normalised, normalised + count)) { + point_iterator_t end = normalised + count; + for (point_iterator_t previous = end - 1, current = normalised; current != end; previous = current, ++current) { + Segment3D segment(*previous, *current); + Point3D point = segment_closest_point_to_point(segment, Vector3(0, 0, 0)); + float depth = point.z(); + point.z() = 0; + float distance = static_cast( vector3_length_squared(point)); + + assign_if_closer(best, SelectionIntersection(depth, distance)); + } + } else if (count > 2) { + assign_if_closer( + best, + SelectionIntersection( + static_cast( ray_distance_to_plane( + Ray(Vector3(0, 0, 0), Vector3(0, 0, 1)), + plane3_for_points(normalised[0], normalised[1], normalised[2]) + )), + 0 + ) + ); + } #if defined( DEBUG_SELECTION ) - if ( count >= 2 ) { - g_render_clipped.insert( clipped, count ); - } + if (count >= 2) { + g_render_clipped.insert(clipped, count); + } #endif } -void LineStrip_BestPoint( const Matrix4& local2view, const PointVertex* vertices, const std::size_t size, SelectionIntersection& best ){ - Vector4 clipped[2]; - for ( std::size_t i = 0; ( i + 1 ) < size; ++i ) - { - const std::size_t count = matrix4_clip_line( local2view, vertex3f_to_vector3( vertices[i].vertex ), vertex3f_to_vector3( vertices[i + 1].vertex ), clipped ); - BestPoint( count, clipped, best, eClipCullNone ); - } +void LineStrip_BestPoint(const Matrix4 &local2view, const PointVertex *vertices, const std::size_t size, + SelectionIntersection &best) +{ + Vector4 clipped[2]; + for (std::size_t i = 0; (i + 1) < size; ++i) { + const std::size_t count = matrix4_clip_line(local2view, vertex3f_to_vector3(vertices[i].vertex), + vertex3f_to_vector3(vertices[i + 1].vertex), clipped); + BestPoint(count, clipped, best, eClipCullNone); + } } -void LineLoop_BestPoint( const Matrix4& local2view, const PointVertex* vertices, const std::size_t size, SelectionIntersection& best ){ - Vector4 clipped[2]; - for ( std::size_t i = 0; i < size; ++i ) - { - const std::size_t count = matrix4_clip_line( local2view, vertex3f_to_vector3( vertices[i].vertex ), vertex3f_to_vector3( vertices[( i + 1 ) % size].vertex ), clipped ); - BestPoint( count, clipped, best, eClipCullNone ); - } +void LineLoop_BestPoint(const Matrix4 &local2view, const PointVertex *vertices, const std::size_t size, + SelectionIntersection &best) +{ + Vector4 clipped[2]; + for (std::size_t i = 0; i < size; ++i) { + const std::size_t count = matrix4_clip_line(local2view, vertex3f_to_vector3(vertices[i].vertex), + vertex3f_to_vector3(vertices[(i + 1) % size].vertex), clipped); + BestPoint(count, clipped, best, eClipCullNone); + } } -void Line_BestPoint( const Matrix4& local2view, const PointVertex vertices[2], SelectionIntersection& best ){ - Vector4 clipped[2]; - const std::size_t count = matrix4_clip_line( local2view, vertex3f_to_vector3( vertices[0].vertex ), vertex3f_to_vector3( vertices[1].vertex ), clipped ); - BestPoint( count, clipped, best, eClipCullNone ); +void Line_BestPoint(const Matrix4 &local2view, const PointVertex vertices[2], SelectionIntersection &best) +{ + Vector4 clipped[2]; + const std::size_t count = matrix4_clip_line(local2view, vertex3f_to_vector3(vertices[0].vertex), + vertex3f_to_vector3(vertices[1].vertex), clipped); + BestPoint(count, clipped, best, eClipCullNone); } -void Circle_BestPoint( const Matrix4& local2view, clipcull_t cull, const PointVertex* vertices, const std::size_t size, SelectionIntersection& best ){ - Vector4 clipped[9]; - for ( std::size_t i = 0; i < size; ++i ) - { - const std::size_t count = matrix4_clip_triangle( local2view, g_vector3_identity, vertex3f_to_vector3( vertices[i].vertex ), vertex3f_to_vector3( vertices[( i + 1 ) % size].vertex ), clipped ); - BestPoint( count, clipped, best, cull ); - } +void Circle_BestPoint(const Matrix4 &local2view, clipcull_t cull, const PointVertex *vertices, const std::size_t size, + SelectionIntersection &best) +{ + Vector4 clipped[9]; + for (std::size_t i = 0; i < size; ++i) { + const std::size_t count = matrix4_clip_triangle(local2view, g_vector3_identity, + vertex3f_to_vector3(vertices[i].vertex), + vertex3f_to_vector3(vertices[(i + 1) % size].vertex), clipped); + BestPoint(count, clipped, best, cull); + } } -void Quad_BestPoint( const Matrix4& local2view, clipcull_t cull, const PointVertex* vertices, SelectionIntersection& best ){ - Vector4 clipped[9]; - { - const std::size_t count = matrix4_clip_triangle( local2view, vertex3f_to_vector3( vertices[0].vertex ), vertex3f_to_vector3( vertices[1].vertex ), vertex3f_to_vector3( vertices[3].vertex ), clipped ); - BestPoint( count, clipped, best, cull ); - } - { - const std::size_t count = matrix4_clip_triangle( local2view, vertex3f_to_vector3( vertices[1].vertex ), vertex3f_to_vector3( vertices[2].vertex ), vertex3f_to_vector3( vertices[3].vertex ), clipped ); - BestPoint( count, clipped, best, cull ); - } +void +Quad_BestPoint(const Matrix4 &local2view, clipcull_t cull, const PointVertex *vertices, SelectionIntersection &best) +{ + Vector4 clipped[9]; + { + const std::size_t count = matrix4_clip_triangle(local2view, vertex3f_to_vector3(vertices[0].vertex), + vertex3f_to_vector3(vertices[1].vertex), + vertex3f_to_vector3(vertices[3].vertex), clipped); + BestPoint(count, clipped, best, cull); + } + { + const std::size_t count = matrix4_clip_triangle(local2view, vertex3f_to_vector3(vertices[1].vertex), + vertex3f_to_vector3(vertices[2].vertex), + vertex3f_to_vector3(vertices[3].vertex), clipped); + BestPoint(count, clipped, best, cull); + } } -struct FlatShadedVertex -{ - Vertex3f vertex; - Colour4b colour; - Normal3f normal; +struct FlatShadedVertex { + Vertex3f vertex; + Colour4b colour; + Normal3f normal; - FlatShadedVertex(){ - } + FlatShadedVertex() + { + } }; -typedef FlatShadedVertex* FlatShadedVertexIterator; -void Triangles_BestPoint( const Matrix4& local2view, clipcull_t cull, FlatShadedVertexIterator first, FlatShadedVertexIterator last, SelectionIntersection& best ){ - for ( FlatShadedVertexIterator x( first ), y( first + 1 ), z( first + 2 ); x != last; x += 3, y += 3, z += 3 ) - { - Vector4 clipped[9]; - BestPoint( - matrix4_clip_triangle( - local2view, - reinterpret_cast( ( *x ).vertex ), - reinterpret_cast( ( *y ).vertex ), - reinterpret_cast( ( *z ).vertex ), - clipped - ), - clipped, - best, - cull - ); - } +typedef FlatShadedVertex *FlatShadedVertexIterator; + +void Triangles_BestPoint(const Matrix4 &local2view, clipcull_t cull, FlatShadedVertexIterator first, + FlatShadedVertexIterator last, SelectionIntersection &best) +{ + for (FlatShadedVertexIterator x(first), y(first + 1), z(first + 2); x != last; x += 3, y += 3, z += 3) { + Vector4 clipped[9]; + BestPoint( + matrix4_clip_triangle( + local2view, + reinterpret_cast((*x).vertex ), + reinterpret_cast((*y).vertex ), + reinterpret_cast((*z).vertex ), + clipped + ), + clipped, + best, + cull + ); + } } -typedef std::multimap SelectableSortedSet; +typedef std::multimap SelectableSortedSet; -class SelectionPool : public Selector -{ -SelectableSortedSet m_pool; -SelectionIntersection m_intersection; -Selectable* m_selectable; +class SelectionPool : public Selector { + SelectableSortedSet m_pool; + SelectionIntersection m_intersection; + Selectable *m_selectable; public: -void pushSelectable( Selectable& selectable ){ - m_intersection = SelectionIntersection(); - m_selectable = &selectable; -} -void popSelectable(){ - addSelectable( m_intersection, m_selectable ); - m_intersection = SelectionIntersection(); -} -void addIntersection( const SelectionIntersection& intersection ){ - assign_if_closer( m_intersection, intersection ); -} -void addSelectable( const SelectionIntersection& intersection, Selectable* selectable ){ - if ( intersection.valid() ) { - m_pool.insert( SelectableSortedSet::value_type( intersection, selectable ) ); - } -} + void pushSelectable(Selectable &selectable) + { + m_intersection = SelectionIntersection(); + m_selectable = &selectable; + } -typedef SelectableSortedSet::iterator iterator; + void popSelectable() + { + addSelectable(m_intersection, m_selectable); + m_intersection = SelectionIntersection(); + } -iterator begin(){ - return m_pool.begin(); -} -iterator end(){ - return m_pool.end(); -} + void addIntersection(const SelectionIntersection &intersection) + { + assign_if_closer(m_intersection, intersection); + } -bool failed(){ - return m_pool.empty(); -} + void addSelectable(const SelectionIntersection &intersection, Selectable *selectable) + { + if (intersection.valid()) { + m_pool.insert(SelectableSortedSet::value_type(intersection, selectable)); + } + } + + typedef SelectableSortedSet::iterator iterator; + + iterator begin() + { + return m_pool.begin(); + } + + iterator end() + { + return m_pool.end(); + } + + bool failed() + { + return m_pool.empty(); + } }; -const Colour4b g_colour_sphere( 0, 0, 0, 255 ); -const Colour4b g_colour_screen( 0, 255, 255, 255 ); -const Colour4b g_colour_selected( 255, 255, 0, 255 ); +const Colour4b g_colour_sphere(0, 0, 0, 255); +const Colour4b g_colour_screen(0, 255, 255, 255); +const Colour4b g_colour_selected(255, 255, 0, 255); -inline const Colour4b& colourSelected( const Colour4b& colour, bool selected ){ - return ( selected ) ? g_colour_selected : colour; +inline const Colour4b &colourSelected(const Colour4b &colour, bool selected) +{ + return (selected) ? g_colour_selected : colour; } template -inline void draw_semicircle( const std::size_t segments, const float radius, PointVertex* vertices, remap_policy remap ){ - const double increment = c_pi / double(segments << 2); - - std::size_t count = 0; - float x = radius; - float y = 0; - remap_policy::set( vertices[segments << 2].vertex, -radius, 0, 0 ); - while ( count < segments ) - { - PointVertex* i = vertices + count; - PointVertex* j = vertices + ( ( segments << 1 ) - ( count + 1 ) ); +inline void draw_semicircle(const std::size_t segments, const float radius, PointVertex *vertices, remap_policy remap) +{ + const double increment = c_pi / double(segments << 2); + + std::size_t count = 0; + float x = radius; + float y = 0; + remap_policy::set(vertices[segments << 2].vertex, -radius, 0, 0); + while (count < segments) { + PointVertex *i = vertices + count; + PointVertex *j = vertices + ((segments << 1) - (count + 1)); - PointVertex* k = i + ( segments << 1 ); - PointVertex* l = j + ( segments << 1 ); + PointVertex *k = i + (segments << 1); + PointVertex *l = j + (segments << 1); #if 0 - PointVertex* m = i + ( segments << 2 ); + PointVertex* m = i + ( segments << 2 ); PointVertex* n = j + ( segments << 2 ); PointVertex* o = k + ( segments << 2 ); PointVertex* p = l + ( segments << 2 ); #endif - remap_policy::set( i->vertex, x,-y, 0 ); - remap_policy::set( k->vertex,-y,-x, 0 ); + remap_policy::set(i->vertex, x, -y, 0); + remap_policy::set(k->vertex, -y, -x, 0); #if 0 - remap_policy::set( m->vertex,-x, y, 0 ); + remap_policy::set( m->vertex,-x, y, 0 ); remap_policy::set( o->vertex, y, x, 0 ); #endif - ++count; + ++count; - { - const double theta = increment * count; - x = static_cast( radius * cos( theta ) ); - y = static_cast( radius * sin( theta ) ); - } + { + const double theta = increment * count; + x = static_cast( radius * cos(theta)); + y = static_cast( radius * sin(theta)); + } - remap_policy::set( j->vertex, y,-x, 0 ); - remap_policy::set( l->vertex,-x,-y, 0 ); + remap_policy::set(j->vertex, y, -x, 0); + remap_policy::set(l->vertex, -x, -y, 0); #if 0 - remap_policy::set( n->vertex,-y, x, 0 ); + remap_policy::set( n->vertex,-y, x, 0 ); remap_policy::set( p->vertex, x, y, 0 ); #endif - } + } } -class Manipulator -{ +class Manipulator { public: -virtual Manipulatable* GetManipulatable() = 0; -virtual void testSelect( const View& view, const Matrix4& pivot2world ){ -} -virtual void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world ){ -} -virtual void setSelected( bool select ) = 0; -virtual bool isSelected() const = 0; -}; + virtual Manipulatable *GetManipulatable() = 0; + + virtual void testSelect(const View &view, const Matrix4 &pivot2world) + { + } + + virtual void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &pivot2world) + { + } + + virtual void setSelected(bool select) = 0; + + virtual bool isSelected() const = 0; +}; + + +inline Vector3 normalised_safe(const Vector3 &self) +{ + if (vector3_equal(self, g_vector3_identity)) { + return g_vector3_identity; + } + return vector3_normalised(self); +} + + +class RotateManipulator : public Manipulator { + struct RenderableCircle : public OpenGLRenderable { + Array m_vertices; + + RenderableCircle(std::size_t size) : m_vertices(size) + { + } + + void render(RenderStateFlags state) const + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_vertices.data()->colour); + glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_vertices.data()->vertex); + glDrawArrays(GL_LINE_LOOP, 0, GLsizei(m_vertices.size())); + } + + void setColour(const Colour4b &colour) + { + for (Array::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i) { + (*i).colour = colour; + } + } + }; + + struct RenderableSemiCircle : public OpenGLRenderable { + Array m_vertices; + + RenderableSemiCircle(std::size_t size) : m_vertices(size) + { + } + + void render(RenderStateFlags state) const + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_vertices.data()->colour); + glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_vertices.data()->vertex); + glDrawArrays(GL_LINE_STRIP, 0, GLsizei(m_vertices.size())); + } + + void setColour(const Colour4b &colour) + { + for (Array::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i) { + (*i).colour = colour; + } + } + }; + + RotateFree m_free; + RotateAxis m_axis; + Vector3 m_axis_screen; + RenderableSemiCircle m_circle_x; + RenderableSemiCircle m_circle_y; + RenderableSemiCircle m_circle_z; + RenderableCircle m_circle_screen; + RenderableCircle m_circle_sphere; + SelectableBool m_selectable_x; + SelectableBool m_selectable_y; + SelectableBool m_selectable_z; + SelectableBool m_selectable_screen; + SelectableBool m_selectable_sphere; + Pivot2World m_pivot; + Matrix4 m_local2world_x; + Matrix4 m_local2world_y; + Matrix4 m_local2world_z; + bool m_circle_x_visible; + bool m_circle_y_visible; + bool m_circle_z_visible; +public: + static Shader *m_state_outer; + + RotateManipulator(Rotatable &rotatable, std::size_t segments, float radius) : + m_free(rotatable), + m_axis(rotatable), + m_circle_x((segments << 2) + 1), + m_circle_y((segments << 2) + 1), + m_circle_z((segments << 2) + 1), + m_circle_screen(segments << 3), + m_circle_sphere(segments << 3) + { + draw_semicircle(segments, radius, m_circle_x.m_vertices.data(), RemapYZX()); + draw_semicircle(segments, radius, m_circle_y.m_vertices.data(), RemapZXY()); + draw_semicircle(segments, radius, m_circle_z.m_vertices.data(), RemapXYZ()); + + draw_circle(segments, radius * 1.15f, m_circle_screen.m_vertices.data(), RemapXYZ()); + draw_circle(segments, radius, m_circle_sphere.m_vertices.data(), RemapXYZ()); + } + + + void UpdateColours() + { + m_circle_x.setColour(colourSelected(g_colour_x, m_selectable_x.isSelected())); + m_circle_y.setColour(colourSelected(g_colour_y, m_selectable_y.isSelected())); + m_circle_z.setColour(colourSelected(g_colour_z, m_selectable_z.isSelected())); + m_circle_screen.setColour(colourSelected(g_colour_screen, m_selectable_screen.isSelected())); + m_circle_sphere.setColour(colourSelected(g_colour_sphere, false)); + } + + void updateCircleTransforms() + { + Vector3 localViewpoint(matrix4_transformed_direction(matrix4_transposed(m_pivot.m_worldSpace), + vector4_to_vector3(m_pivot.m_viewpointSpace.z()))); + + m_circle_x_visible = !vector3_equal_epsilon(g_vector3_axis_x, localViewpoint, 1e-6f); + if (m_circle_x_visible) { + m_local2world_x = g_matrix4_identity; + vector4_to_vector3(m_local2world_x.y()) = normalised_safe( + vector3_cross(g_vector3_axis_x, localViewpoint) + ); + vector4_to_vector3(m_local2world_x.z()) = normalised_safe( + vector3_cross(vector4_to_vector3(m_local2world_x.x()), vector4_to_vector3(m_local2world_x.y())) + ); + matrix4_premultiply_by_matrix4(m_local2world_x, m_pivot.m_worldSpace); + } + + m_circle_y_visible = !vector3_equal_epsilon(g_vector3_axis_y, localViewpoint, 1e-6f); + if (m_circle_y_visible) { + m_local2world_y = g_matrix4_identity; + vector4_to_vector3(m_local2world_y.z()) = normalised_safe( + vector3_cross(g_vector3_axis_y, localViewpoint) + ); + vector4_to_vector3(m_local2world_y.x()) = normalised_safe( + vector3_cross(vector4_to_vector3(m_local2world_y.y()), vector4_to_vector3(m_local2world_y.z())) + ); + matrix4_premultiply_by_matrix4(m_local2world_y, m_pivot.m_worldSpace); + } + + m_circle_z_visible = !vector3_equal_epsilon(g_vector3_axis_z, localViewpoint, 1e-6f); + if (m_circle_z_visible) { + m_local2world_z = g_matrix4_identity; + vector4_to_vector3(m_local2world_z.x()) = normalised_safe( + vector3_cross(g_vector3_axis_z, localViewpoint) + ); + vector4_to_vector3(m_local2world_z.y()) = normalised_safe( + vector3_cross(vector4_to_vector3(m_local2world_z.z()), vector4_to_vector3(m_local2world_z.x())) + ); + matrix4_premultiply_by_matrix4(m_local2world_z, m_pivot.m_worldSpace); + } + } + + void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &pivot2world) + { + m_pivot.update(pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport()); + updateCircleTransforms(); + + // temp hack + UpdateColours(); + + renderer.SetState(m_state_outer, Renderer::eWireframeOnly); + renderer.SetState(m_state_outer, Renderer::eFullMaterials); + + renderer.addRenderable(m_circle_screen, m_pivot.m_viewpointSpace); + renderer.addRenderable(m_circle_sphere, m_pivot.m_viewpointSpace); + + if (m_circle_x_visible) { + renderer.addRenderable(m_circle_x, m_local2world_x); + } + if (m_circle_y_visible) { + renderer.addRenderable(m_circle_y, m_local2world_y); + } + if (m_circle_z_visible) { + renderer.addRenderable(m_circle_z, m_local2world_z); + } + } + + void testSelect(const View &view, const Matrix4 &pivot2world) + { + m_pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport()); + updateCircleTransforms(); + + SelectionPool selector; + + { + { + Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_local2world_x)); +#if defined( DEBUG_SELECTION ) + g_render_clipped.construct(view.GetViewMatrix()); +#endif -inline Vector3 normalised_safe( const Vector3& self ){ - if ( vector3_equal( self, g_vector3_identity ) ) { - return g_vector3_identity; - } - return vector3_normalised( self ); -} + SelectionIntersection best; + LineStrip_BestPoint(local2view, m_circle_x.m_vertices.data(), m_circle_x.m_vertices.size(), best); + selector.addSelectable(best, &m_selectable_x); + } + { + Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_local2world_y)); -class RotateManipulator : public Manipulator -{ -struct RenderableCircle : public OpenGLRenderable -{ - Array m_vertices; +#if defined( DEBUG_SELECTION ) + g_render_clipped.construct(view.GetViewMatrix()); +#endif - RenderableCircle( std::size_t size ) : m_vertices( size ){ - } - void render( RenderStateFlags state ) const { - glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_vertices.data()->colour ); - glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_vertices.data()->vertex ); - glDrawArrays( GL_LINE_LOOP, 0, GLsizei( m_vertices.size() ) ); - } - void setColour( const Colour4b& colour ){ - for ( Array::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i ) - { - ( *i ).colour = colour; - } - } -}; + SelectionIntersection best; + LineStrip_BestPoint(local2view, m_circle_y.m_vertices.data(), m_circle_y.m_vertices.size(), best); + selector.addSelectable(best, &m_selectable_y); + } -struct RenderableSemiCircle : public OpenGLRenderable -{ - Array m_vertices; + { + Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_local2world_z)); - RenderableSemiCircle( std::size_t size ) : m_vertices( size ){ - } - void render( RenderStateFlags state ) const { - glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_vertices.data()->colour ); - glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_vertices.data()->vertex ); - glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_vertices.size() ) ); - } - void setColour( const Colour4b& colour ){ - for ( Array::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i ) - { - ( *i ).colour = colour; - } - } -}; +#if defined( DEBUG_SELECTION ) + g_render_clipped.construct(view.GetViewMatrix()); +#endif -RotateFree m_free; -RotateAxis m_axis; -Vector3 m_axis_screen; -RenderableSemiCircle m_circle_x; -RenderableSemiCircle m_circle_y; -RenderableSemiCircle m_circle_z; -RenderableCircle m_circle_screen; -RenderableCircle m_circle_sphere; -SelectableBool m_selectable_x; -SelectableBool m_selectable_y; -SelectableBool m_selectable_z; -SelectableBool m_selectable_screen; -SelectableBool m_selectable_sphere; -Pivot2World m_pivot; -Matrix4 m_local2world_x; -Matrix4 m_local2world_y; -Matrix4 m_local2world_z; -bool m_circle_x_visible; -bool m_circle_y_visible; -bool m_circle_z_visible; -public: -static Shader* m_state_outer; - -RotateManipulator( Rotatable& rotatable, std::size_t segments, float radius ) : - m_free( rotatable ), - m_axis( rotatable ), - m_circle_x( ( segments << 2 ) + 1 ), - m_circle_y( ( segments << 2 ) + 1 ), - m_circle_z( ( segments << 2 ) + 1 ), - m_circle_screen( segments << 3 ), - m_circle_sphere( segments << 3 ){ - draw_semicircle( segments, radius, m_circle_x.m_vertices.data(), RemapYZX() ); - draw_semicircle( segments, radius, m_circle_y.m_vertices.data(), RemapZXY() ); - draw_semicircle( segments, radius, m_circle_z.m_vertices.data(), RemapXYZ() ); - - draw_circle( segments, radius * 1.15f, m_circle_screen.m_vertices.data(), RemapXYZ() ); - draw_circle( segments, radius, m_circle_sphere.m_vertices.data(), RemapXYZ() ); -} - - -void UpdateColours(){ - m_circle_x.setColour( colourSelected( g_colour_x, m_selectable_x.isSelected() ) ); - m_circle_y.setColour( colourSelected( g_colour_y, m_selectable_y.isSelected() ) ); - m_circle_z.setColour( colourSelected( g_colour_z, m_selectable_z.isSelected() ) ); - m_circle_screen.setColour( colourSelected( g_colour_screen, m_selectable_screen.isSelected() ) ); - m_circle_sphere.setColour( colourSelected( g_colour_sphere, false ) ); -} - -void updateCircleTransforms(){ - Vector3 localViewpoint( matrix4_transformed_direction( matrix4_transposed( m_pivot.m_worldSpace ), vector4_to_vector3( m_pivot.m_viewpointSpace.z() ) ) ); - - m_circle_x_visible = !vector3_equal_epsilon( g_vector3_axis_x, localViewpoint, 1e-6f ); - if ( m_circle_x_visible ) { - m_local2world_x = g_matrix4_identity; - vector4_to_vector3( m_local2world_x.y() ) = normalised_safe( - vector3_cross( g_vector3_axis_x, localViewpoint ) - ); - vector4_to_vector3( m_local2world_x.z() ) = normalised_safe( - vector3_cross( vector4_to_vector3( m_local2world_x.x() ), vector4_to_vector3( m_local2world_x.y() ) ) - ); - matrix4_premultiply_by_matrix4( m_local2world_x, m_pivot.m_worldSpace ); - } + SelectionIntersection best; + LineStrip_BestPoint(local2view, m_circle_z.m_vertices.data(), m_circle_z.m_vertices.size(), best); + selector.addSelectable(best, &m_selectable_z); + } + } + + { + Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_viewpointSpace)); + + { + SelectionIntersection best; + LineLoop_BestPoint(local2view, m_circle_screen.m_vertices.data(), m_circle_screen.m_vertices.size(), + best); + selector.addSelectable(best, &m_selectable_screen); + } + + { + SelectionIntersection best; + Circle_BestPoint(local2view, eClipCullCW, m_circle_sphere.m_vertices.data(), + m_circle_sphere.m_vertices.size(), best); + selector.addSelectable(best, &m_selectable_sphere); + } + } + + m_axis_screen = m_pivot.m_axis_screen; + + if (!selector.failed()) { + (*selector.begin()).second->setSelected(true); + } + } + + Manipulatable *GetManipulatable() + { + if (m_selectable_x.isSelected()) { + m_axis.SetAxis(g_vector3_axis_x); + return &m_axis; + } else if (m_selectable_y.isSelected()) { + m_axis.SetAxis(g_vector3_axis_y); + return &m_axis; + } else if (m_selectable_z.isSelected()) { + m_axis.SetAxis(g_vector3_axis_z); + return &m_axis; + } else if (m_selectable_screen.isSelected()) { + m_axis.SetAxis(m_axis_screen); + return &m_axis; + } else { + return &m_free; + } + } + + void setSelected(bool select) + { + m_selectable_x.setSelected(select); + m_selectable_y.setSelected(select); + m_selectable_z.setSelected(select); + m_selectable_screen.setSelected(select); + } + + bool isSelected() const + { + return m_selectable_x.isSelected() + | m_selectable_y.isSelected() + | m_selectable_z.isSelected() + | m_selectable_screen.isSelected() + | m_selectable_sphere.isSelected(); + } +}; + +Shader *RotateManipulator::m_state_outer; - m_circle_y_visible = !vector3_equal_epsilon( g_vector3_axis_y, localViewpoint, 1e-6f ); - if ( m_circle_y_visible ) { - m_local2world_y = g_matrix4_identity; - vector4_to_vector3( m_local2world_y.z() ) = normalised_safe( - vector3_cross( g_vector3_axis_y, localViewpoint ) - ); - vector4_to_vector3( m_local2world_y.x() ) = normalised_safe( - vector3_cross( vector4_to_vector3( m_local2world_y.y() ), vector4_to_vector3( m_local2world_y.z() ) ) - ); - matrix4_premultiply_by_matrix4( m_local2world_y, m_pivot.m_worldSpace ); - } - m_circle_z_visible = !vector3_equal_epsilon( g_vector3_axis_z, localViewpoint, 1e-6f ); - if ( m_circle_z_visible ) { - m_local2world_z = g_matrix4_identity; - vector4_to_vector3( m_local2world_z.x() ) = normalised_safe( - vector3_cross( g_vector3_axis_z, localViewpoint ) - ); - vector4_to_vector3( m_local2world_z.y() ) = normalised_safe( - vector3_cross( vector4_to_vector3( m_local2world_z.z() ), vector4_to_vector3( m_local2world_z.x() ) ) - ); - matrix4_premultiply_by_matrix4( m_local2world_z, m_pivot.m_worldSpace ); - } +const float arrowhead_length = 16; +const float arrowhead_radius = 4; + +inline void draw_arrowline(const float length, PointVertex *line, const std::size_t axis) +{ + (*line++).vertex = vertex3f_identity; + (*line).vertex = vertex3f_identity; + vertex3f_to_array((*line).vertex)[axis] = length - arrowhead_length; } -void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world ){ - m_pivot.update( pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport() ); - updateCircleTransforms(); +template +inline void +draw_arrowhead(const std::size_t segments, const float length, FlatShadedVertex *vertices, VertexRemap, NormalRemap) +{ + std::size_t head_tris = (segments << 3); + const double head_segment = c_2pi / head_tris; + for (std::size_t i = 0; i < head_tris; ++i) { + { + FlatShadedVertex &point = vertices[i * 6 + 0]; + VertexRemap::x(point.vertex) = length - arrowhead_length; + VertexRemap::y(point.vertex) = arrowhead_radius * static_cast( cos(i * head_segment)); + VertexRemap::z(point.vertex) = arrowhead_radius * static_cast( sin(i * head_segment)); + NormalRemap::x(point.normal) = arrowhead_radius / arrowhead_length; + NormalRemap::y(point.normal) = static_cast( cos(i * head_segment)); + NormalRemap::z(point.normal) = static_cast( sin(i * head_segment)); + } + { + FlatShadedVertex &point = vertices[i * 6 + 1]; + VertexRemap::x(point.vertex) = length; + VertexRemap::y(point.vertex) = 0; + VertexRemap::z(point.vertex) = 0; + NormalRemap::x(point.normal) = arrowhead_radius / arrowhead_length; + NormalRemap::y(point.normal) = static_cast( cos((i + 0.5) * head_segment)); + NormalRemap::z(point.normal) = static_cast( sin((i + 0.5) * head_segment)); + } + { + FlatShadedVertex &point = vertices[i * 6 + 2]; + VertexRemap::x(point.vertex) = length - arrowhead_length; + VertexRemap::y(point.vertex) = arrowhead_radius * static_cast( cos((i + 1) * head_segment)); + VertexRemap::z(point.vertex) = arrowhead_radius * static_cast( sin((i + 1) * head_segment)); + NormalRemap::x(point.normal) = arrowhead_radius / arrowhead_length; + NormalRemap::y(point.normal) = static_cast( cos((i + 1) * head_segment)); + NormalRemap::z(point.normal) = static_cast( sin((i + 1) * head_segment)); + } + + { + FlatShadedVertex &point = vertices[i * 6 + 3]; + VertexRemap::x(point.vertex) = length - arrowhead_length; + VertexRemap::y(point.vertex) = 0; + VertexRemap::z(point.vertex) = 0; + NormalRemap::x(point.normal) = -1; + NormalRemap::y(point.normal) = 0; + NormalRemap::z(point.normal) = 0; + } + { + FlatShadedVertex &point = vertices[i * 6 + 4]; + VertexRemap::x(point.vertex) = length - arrowhead_length; + VertexRemap::y(point.vertex) = arrowhead_radius * static_cast( cos(i * head_segment)); + VertexRemap::z(point.vertex) = arrowhead_radius * static_cast( sin(i * head_segment)); + NormalRemap::x(point.normal) = -1; + NormalRemap::y(point.normal) = 0; + NormalRemap::z(point.normal) = 0; + } + { + FlatShadedVertex &point = vertices[i * 6 + 5]; + VertexRemap::x(point.vertex) = length - arrowhead_length; + VertexRemap::y(point.vertex) = arrowhead_radius * static_cast( cos((i + 1) * head_segment)); + VertexRemap::z(point.vertex) = arrowhead_radius * static_cast( sin((i + 1) * head_segment)); + NormalRemap::x(point.normal) = -1; + NormalRemap::y(point.normal) = 0; + NormalRemap::z(point.normal) = 0; + } + } +} - // temp hack - UpdateColours(); +template +class TripleRemapXYZ { +public: + static float &x(Triple &triple) + { + return triple.x(); + } - renderer.SetState( m_state_outer, Renderer::eWireframeOnly ); - renderer.SetState( m_state_outer, Renderer::eFullMaterials ); + static float &y(Triple &triple) + { + return triple.y(); + } - renderer.addRenderable( m_circle_screen, m_pivot.m_viewpointSpace ); - renderer.addRenderable( m_circle_sphere, m_pivot.m_viewpointSpace ); + static float &z(Triple &triple) + { + return triple.z(); + } +}; - if ( m_circle_x_visible ) { - renderer.addRenderable( m_circle_x, m_local2world_x ); - } - if ( m_circle_y_visible ) { - renderer.addRenderable( m_circle_y, m_local2world_y ); - } - if ( m_circle_z_visible ) { - renderer.addRenderable( m_circle_z, m_local2world_z ); - } -} -void testSelect( const View& view, const Matrix4& pivot2world ){ - m_pivot.update( pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport() ); - updateCircleTransforms(); +template +class TripleRemapYZX { +public: + static float &x(Triple &triple) + { + return triple.y(); + } - SelectionPool selector; + static float &y(Triple &triple) + { + return triple.z(); + } - { - { - Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_local2world_x ) ); + static float &z(Triple &triple) + { + return triple.x(); + } +}; + +template +class TripleRemapZXY { +public: + static float &x(Triple &triple) + { + return triple.z(); + } + + static float &y(Triple &triple) + { + return triple.x(); + } + + static float &z(Triple &triple) + { + return triple.y(); + } +}; + +void vector3_print(const Vector3 &v) +{ + globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )"; +} + +class TranslateManipulator : public Manipulator { + struct RenderableArrowLine : public OpenGLRenderable { + PointVertex m_line[2]; + + RenderableArrowLine() + { + } + + void render(RenderStateFlags state) const + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_line[0].colour); + glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_line[0].vertex); + glDrawArrays(GL_LINES, 0, 2); + } + + void setColour(const Colour4b &colour) + { + m_line[0].colour = colour; + m_line[1].colour = colour; + } + }; + + struct RenderableArrowHead : public OpenGLRenderable { + Array m_vertices; + + RenderableArrowHead(std::size_t size) + : m_vertices(size) + { + } + + void render(RenderStateFlags state) const + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(FlatShadedVertex), &m_vertices.data()->colour); + glVertexPointer(3, GL_FLOAT, sizeof(FlatShadedVertex), &m_vertices.data()->vertex); + glNormalPointer(GL_FLOAT, sizeof(FlatShadedVertex), &m_vertices.data()->normal); + glDrawArrays(GL_TRIANGLES, 0, GLsizei(m_vertices.size())); + } + + void setColour(const Colour4b &colour) + { + for (Array::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i) { + (*i).colour = colour; + } + } + }; + + struct RenderableQuad : public OpenGLRenderable { + PointVertex m_quad[4]; + + void render(RenderStateFlags state) const + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_quad[0].colour); + glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_quad[0].vertex); + glDrawArrays(GL_LINE_LOOP, 0, 4); + } + + void setColour(const Colour4b &colour) + { + m_quad[0].colour = colour; + m_quad[1].colour = colour; + m_quad[2].colour = colour; + m_quad[3].colour = colour; + } + }; + + TranslateFree m_free; + TranslateAxis m_axis; + RenderableArrowLine m_arrow_x; + RenderableArrowLine m_arrow_y; + RenderableArrowLine m_arrow_z; + RenderableArrowHead m_arrow_head_x; + RenderableArrowHead m_arrow_head_y; + RenderableArrowHead m_arrow_head_z; + RenderableQuad m_quad_screen; + SelectableBool m_selectable_x; + SelectableBool m_selectable_y; + SelectableBool m_selectable_z; + SelectableBool m_selectable_screen; + Pivot2World m_pivot; +public: + static Shader *m_state_wire; + static Shader *m_state_fill; + + TranslateManipulator(Translatable &translatable, std::size_t segments, float length) : + m_free(translatable), + m_axis(translatable), + m_arrow_head_x(3 * 2 * (segments << 3)), + m_arrow_head_y(3 * 2 * (segments << 3)), + m_arrow_head_z(3 * 2 * (segments << 3)) + { + draw_arrowline(length, m_arrow_x.m_line, 0); + draw_arrowhead(segments, length, m_arrow_head_x.m_vertices.data(), TripleRemapXYZ(), + TripleRemapXYZ()); + draw_arrowline(length, m_arrow_y.m_line, 1); + draw_arrowhead(segments, length, m_arrow_head_y.m_vertices.data(), TripleRemapYZX(), + TripleRemapYZX()); + draw_arrowline(length, m_arrow_z.m_line, 2); + draw_arrowhead(segments, length, m_arrow_head_z.m_vertices.data(), TripleRemapZXY(), + TripleRemapZXY()); + + draw_quad(16, m_quad_screen.m_quad); + } + + void UpdateColours() + { + m_arrow_x.setColour(colourSelected(g_colour_x, m_selectable_x.isSelected())); + m_arrow_head_x.setColour(colourSelected(g_colour_x, m_selectable_x.isSelected())); + m_arrow_y.setColour(colourSelected(g_colour_y, m_selectable_y.isSelected())); + m_arrow_head_y.setColour(colourSelected(g_colour_y, m_selectable_y.isSelected())); + m_arrow_z.setColour(colourSelected(g_colour_z, m_selectable_z.isSelected())); + m_arrow_head_z.setColour(colourSelected(g_colour_z, m_selectable_z.isSelected())); + m_quad_screen.setColour(colourSelected(g_colour_screen, m_selectable_screen.isSelected())); + } + + bool manipulator_show_axis(const Pivot2World &pivot, const Vector3 &axis) + { + return fabs(vector3_dot(pivot.m_axis_screen, axis)) < 0.95; + } + + void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &pivot2world) + { + m_pivot.update(pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport()); + + // temp hack + UpdateColours(); + + Vector3 x = vector3_normalised(vector4_to_vector3(m_pivot.m_worldSpace.x())); + bool show_x = manipulator_show_axis(m_pivot, x); + + Vector3 y = vector3_normalised(vector4_to_vector3(m_pivot.m_worldSpace.y())); + bool show_y = manipulator_show_axis(m_pivot, y); + + Vector3 z = vector3_normalised(vector4_to_vector3(m_pivot.m_worldSpace.z())); + bool show_z = manipulator_show_axis(m_pivot, z); + + renderer.SetState(m_state_wire, Renderer::eWireframeOnly); + renderer.SetState(m_state_wire, Renderer::eFullMaterials); + + if (show_x) { + renderer.addRenderable(m_arrow_x, m_pivot.m_worldSpace); + } + if (show_y) { + renderer.addRenderable(m_arrow_y, m_pivot.m_worldSpace); + } + if (show_z) { + renderer.addRenderable(m_arrow_z, m_pivot.m_worldSpace); + } + + renderer.addRenderable(m_quad_screen, m_pivot.m_viewplaneSpace); + + renderer.SetState(m_state_fill, Renderer::eWireframeOnly); + renderer.SetState(m_state_fill, Renderer::eFullMaterials); + + if (show_x) { + renderer.addRenderable(m_arrow_head_x, m_pivot.m_worldSpace); + } + if (show_y) { + renderer.addRenderable(m_arrow_head_y, m_pivot.m_worldSpace); + } + if (show_z) { + renderer.addRenderable(m_arrow_head_z, m_pivot.m_worldSpace); + } + } + + void testSelect(const View &view, const Matrix4 &pivot2world) + { + m_pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport()); + + SelectionPool selector; + + Vector3 x = vector3_normalised(vector4_to_vector3(m_pivot.m_worldSpace.x())); + bool show_x = manipulator_show_axis(m_pivot, x); + + Vector3 y = vector3_normalised(vector4_to_vector3(m_pivot.m_worldSpace.y())); + bool show_y = manipulator_show_axis(m_pivot, y); + + Vector3 z = vector3_normalised(vector4_to_vector3(m_pivot.m_worldSpace.z())); + bool show_z = manipulator_show_axis(m_pivot, z); + + { + Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_viewpointSpace)); + + { + SelectionIntersection best; + Quad_BestPoint(local2view, eClipCullCW, m_quad_screen.m_quad, best); + if (best.valid()) { + best = SelectionIntersection(0, 0); + selector.addSelectable(best, &m_selectable_screen); + } + } + } + + { + Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_worldSpace)); #if defined( DEBUG_SELECTION ) - g_render_clipped.construct( view.GetViewMatrix() ); + g_render_clipped.construct(view.GetViewMatrix()); #endif - SelectionIntersection best; - LineStrip_BestPoint( local2view, m_circle_x.m_vertices.data(), m_circle_x.m_vertices.size(), best ); - selector.addSelectable( best, &m_selectable_x ); - } + if (show_x) { + SelectionIntersection best; + Line_BestPoint(local2view, m_arrow_x.m_line, best); + Triangles_BestPoint(local2view, eClipCullCW, m_arrow_head_x.m_vertices.begin(), + m_arrow_head_x.m_vertices.end(), best); + selector.addSelectable(best, &m_selectable_x); + } + + if (show_y) { + SelectionIntersection best; + Line_BestPoint(local2view, m_arrow_y.m_line, best); + Triangles_BestPoint(local2view, eClipCullCW, m_arrow_head_y.m_vertices.begin(), + m_arrow_head_y.m_vertices.end(), best); + selector.addSelectable(best, &m_selectable_y); + } + + if (show_z) { + SelectionIntersection best; + Line_BestPoint(local2view, m_arrow_z.m_line, best); + Triangles_BestPoint(local2view, eClipCullCW, m_arrow_head_z.m_vertices.begin(), + m_arrow_head_z.m_vertices.end(), best); + selector.addSelectable(best, &m_selectable_z); + } + } + + if (!selector.failed()) { + (*selector.begin()).second->setSelected(true); + } + } + + Manipulatable *GetManipulatable() + { + if (m_selectable_x.isSelected()) { + m_axis.SetAxis(g_vector3_axis_x); + return &m_axis; + } else if (m_selectable_y.isSelected()) { + m_axis.SetAxis(g_vector3_axis_y); + return &m_axis; + } else if (m_selectable_z.isSelected()) { + m_axis.SetAxis(g_vector3_axis_z); + return &m_axis; + } else { + return &m_free; + } + } + + void setSelected(bool select) + { + m_selectable_x.setSelected(select); + m_selectable_y.setSelected(select); + m_selectable_z.setSelected(select); + m_selectable_screen.setSelected(select); + } + + bool isSelected() const + { + return m_selectable_x.isSelected() + | m_selectable_y.isSelected() + | m_selectable_z.isSelected() + | m_selectable_screen.isSelected(); + } +}; + +Shader *TranslateManipulator::m_state_wire; +Shader *TranslateManipulator::m_state_fill; + +class ScaleManipulator : public Manipulator { + struct RenderableArrow : public OpenGLRenderable { + PointVertex m_line[2]; + + void render(RenderStateFlags state) const + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_line[0].colour); + glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_line[0].vertex); + glDrawArrays(GL_LINES, 0, 2); + } + + void setColour(const Colour4b &colour) + { + m_line[0].colour = colour; + m_line[1].colour = colour; + } + }; + + struct RenderableQuad : public OpenGLRenderable { + PointVertex m_quad[4]; + + void render(RenderStateFlags state) const + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_quad[0].colour); + glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_quad[0].vertex); + glDrawArrays(GL_QUADS, 0, 4); + } + + void setColour(const Colour4b &colour) + { + m_quad[0].colour = colour; + m_quad[1].colour = colour; + m_quad[2].colour = colour; + m_quad[3].colour = colour; + } + }; + + ScaleFree m_free; + ScaleAxis m_axis; + RenderableArrow m_arrow_x; + RenderableArrow m_arrow_y; + RenderableArrow m_arrow_z; + RenderableQuad m_quad_screen; + SelectableBool m_selectable_x; + SelectableBool m_selectable_y; + SelectableBool m_selectable_z; + SelectableBool m_selectable_screen; + Pivot2World m_pivot; +public: + ScaleManipulator(Scalable &scalable, std::size_t segments, float length) : + m_free(scalable), + m_axis(scalable) + { + draw_arrowline(length, m_arrow_x.m_line, 0); + draw_arrowline(length, m_arrow_y.m_line, 1); + draw_arrowline(length, m_arrow_z.m_line, 2); - { - Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_local2world_y ) ); + draw_quad(16, m_quad_screen.m_quad); + } -#if defined( DEBUG_SELECTION ) - g_render_clipped.construct( view.GetViewMatrix() ); -#endif + Pivot2World &getPivot() + { + return m_pivot; + } - SelectionIntersection best; - LineStrip_BestPoint( local2view, m_circle_y.m_vertices.data(), m_circle_y.m_vertices.size(), best ); - selector.addSelectable( best, &m_selectable_y ); - } + void UpdateColours() + { + m_arrow_x.setColour(colourSelected(g_colour_x, m_selectable_x.isSelected())); + m_arrow_y.setColour(colourSelected(g_colour_y, m_selectable_y.isSelected())); + m_arrow_z.setColour(colourSelected(g_colour_z, m_selectable_z.isSelected())); + m_quad_screen.setColour(colourSelected(g_colour_screen, m_selectable_screen.isSelected())); + } - { - Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_local2world_z ) ); + void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &pivot2world) + { + m_pivot.update(pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport()); -#if defined( DEBUG_SELECTION ) - g_render_clipped.construct( view.GetViewMatrix() ); -#endif + // temp hack + UpdateColours(); - SelectionIntersection best; - LineStrip_BestPoint( local2view, m_circle_z.m_vertices.data(), m_circle_z.m_vertices.size(), best ); - selector.addSelectable( best, &m_selectable_z ); - } - } + renderer.addRenderable(m_arrow_x, m_pivot.m_worldSpace); + renderer.addRenderable(m_arrow_y, m_pivot.m_worldSpace); + renderer.addRenderable(m_arrow_z, m_pivot.m_worldSpace); - { - Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_viewpointSpace ) ); + renderer.addRenderable(m_quad_screen, m_pivot.m_viewpointSpace); + } - { - SelectionIntersection best; - LineLoop_BestPoint( local2view, m_circle_screen.m_vertices.data(), m_circle_screen.m_vertices.size(), best ); - selector.addSelectable( best, &m_selectable_screen ); - } + void testSelect(const View &view, const Matrix4 &pivot2world) + { + m_pivot.update(pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport()); - { - SelectionIntersection best; - Circle_BestPoint( local2view, eClipCullCW, m_circle_sphere.m_vertices.data(), m_circle_sphere.m_vertices.size(), best ); - selector.addSelectable( best, &m_selectable_sphere ); - } - } + SelectionPool selector; - m_axis_screen = m_pivot.m_axis_screen; + { + Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_worldSpace)); - if ( !selector.failed() ) { - ( *selector.begin() ).second->setSelected( true ); - } -} +#if defined( DEBUG_SELECTION ) + g_render_clipped.construct(view.GetViewMatrix()); +#endif -Manipulatable* GetManipulatable(){ - if ( m_selectable_x.isSelected() ) { - m_axis.SetAxis( g_vector3_axis_x ); - return &m_axis; - } - else if ( m_selectable_y.isSelected() ) { - m_axis.SetAxis( g_vector3_axis_y ); - return &m_axis; - } - else if ( m_selectable_z.isSelected() ) { - m_axis.SetAxis( g_vector3_axis_z ); - return &m_axis; - } - else if ( m_selectable_screen.isSelected() ) { - m_axis.SetAxis( m_axis_screen ); - return &m_axis; - } - else{ - return &m_free; - } -} + { + SelectionIntersection best; + Line_BestPoint(local2view, m_arrow_x.m_line, best); + selector.addSelectable(best, &m_selectable_x); + } + + { + SelectionIntersection best; + Line_BestPoint(local2view, m_arrow_y.m_line, best); + selector.addSelectable(best, &m_selectable_y); + } + + { + SelectionIntersection best; + Line_BestPoint(local2view, m_arrow_z.m_line, best); + selector.addSelectable(best, &m_selectable_z); + } + } + + { + Matrix4 local2view(matrix4_multiplied_by_matrix4(view.GetViewMatrix(), m_pivot.m_viewpointSpace)); + + { + SelectionIntersection best; + Quad_BestPoint(local2view, eClipCullCW, m_quad_screen.m_quad, best); + selector.addSelectable(best, &m_selectable_screen); + } + } + + if (!selector.failed()) { + (*selector.begin()).second->setSelected(true); + } + } + + Manipulatable *GetManipulatable() + { + if (m_selectable_x.isSelected()) { + m_axis.SetAxis(g_vector3_axis_x); + return &m_axis; + } else if (m_selectable_y.isSelected()) { + m_axis.SetAxis(g_vector3_axis_y); + return &m_axis; + } else if (m_selectable_z.isSelected()) { + m_axis.SetAxis(g_vector3_axis_z); + return &m_axis; + } else { + return &m_free; + } + } + + void setSelected(bool select) + { + m_selectable_x.setSelected(select); + m_selectable_y.setSelected(select); + m_selectable_z.setSelected(select); + m_selectable_screen.setSelected(select); + } + + bool isSelected() const + { + return m_selectable_x.isSelected() + | m_selectable_y.isSelected() + | m_selectable_z.isSelected() + | m_selectable_screen.isSelected(); + } +}; + + +inline PlaneSelectable *Instance_getPlaneSelectable(scene::Instance &instance) +{ + return InstanceTypeCast::cast(instance); +} + +class PlaneSelectableSelectPlanes : public scene::Graph::Walker { + Selector &m_selector; + SelectionTest &m_test; + PlaneCallback m_selectedPlaneCallback; +public: + PlaneSelectableSelectPlanes(Selector &selector, SelectionTest &test, const PlaneCallback &selectedPlaneCallback) + : m_selector(selector), m_test(test), m_selectedPlaneCallback(selectedPlaneCallback) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 && selectable->isSelected()) { + PlaneSelectable *planeSelectable = Instance_getPlaneSelectable(instance); + if (planeSelectable != 0) { + planeSelectable->selectPlanes(m_selector, m_test, m_selectedPlaneCallback); + } + } + } + return true; + } +}; + +class PlaneSelectableSelectReversedPlanes : public scene::Graph::Walker { + Selector &m_selector; + const SelectedPlanes &m_selectedPlanes; +public: + PlaneSelectableSelectReversedPlanes(Selector &selector, const SelectedPlanes &selectedPlanes) + : m_selector(selector), m_selectedPlanes(selectedPlanes) + { + } -void setSelected( bool select ){ - m_selectable_x.setSelected( select ); - m_selectable_y.setSelected( select ); - m_selectable_z.setSelected( select ); - m_selectable_screen.setSelected( select ); -} -bool isSelected() const { - return m_selectable_x.isSelected() - | m_selectable_y.isSelected() - | m_selectable_z.isSelected() - | m_selectable_screen.isSelected() - | m_selectable_sphere.isSelected(); -} + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 && selectable->isSelected()) { + PlaneSelectable *planeSelectable = Instance_getPlaneSelectable(instance); + if (planeSelectable != 0) { + planeSelectable->selectReversedPlanes(m_selector, m_selectedPlanes); + } + } + } + return true; + } }; -Shader* RotateManipulator::m_state_outer; - - -const float arrowhead_length = 16; -const float arrowhead_radius = 4; - -inline void draw_arrowline( const float length, PointVertex* line, const std::size_t axis ){ - ( *line++ ).vertex = vertex3f_identity; - ( *line ).vertex = vertex3f_identity; - vertex3f_to_array( ( *line ).vertex )[axis] = length - arrowhead_length; -} - -template -inline void draw_arrowhead( const std::size_t segments, const float length, FlatShadedVertex* vertices, VertexRemap, NormalRemap ){ - std::size_t head_tris = ( segments << 3 ); - const double head_segment = c_2pi / head_tris; - for ( std::size_t i = 0; i < head_tris; ++i ) - { - { - FlatShadedVertex& point = vertices[i * 6 + 0]; - VertexRemap::x( point.vertex ) = length - arrowhead_length; - VertexRemap::y( point.vertex ) = arrowhead_radius * static_cast( cos( i * head_segment ) ); - VertexRemap::z( point.vertex ) = arrowhead_radius * static_cast( sin( i * head_segment ) ); - NormalRemap::x( point.normal ) = arrowhead_radius / arrowhead_length; - NormalRemap::y( point.normal ) = static_cast( cos( i * head_segment ) ); - NormalRemap::z( point.normal ) = static_cast( sin( i * head_segment ) ); - } - { - FlatShadedVertex& point = vertices[i * 6 + 1]; - VertexRemap::x( point.vertex ) = length; - VertexRemap::y( point.vertex ) = 0; - VertexRemap::z( point.vertex ) = 0; - NormalRemap::x( point.normal ) = arrowhead_radius / arrowhead_length; - NormalRemap::y( point.normal ) = static_cast( cos( ( i + 0.5 ) * head_segment ) ); - NormalRemap::z( point.normal ) = static_cast( sin( ( i + 0.5 ) * head_segment ) ); - } - { - FlatShadedVertex& point = vertices[i * 6 + 2]; - VertexRemap::x( point.vertex ) = length - arrowhead_length; - VertexRemap::y( point.vertex ) = arrowhead_radius * static_cast( cos( ( i + 1 ) * head_segment ) ); - VertexRemap::z( point.vertex ) = arrowhead_radius * static_cast( sin( ( i + 1 ) * head_segment ) ); - NormalRemap::x( point.normal ) = arrowhead_radius / arrowhead_length; - NormalRemap::y( point.normal ) = static_cast( cos( ( i + 1 ) * head_segment ) ); - NormalRemap::z( point.normal ) = static_cast( sin( ( i + 1 ) * head_segment ) ); - } - - { - FlatShadedVertex& point = vertices[i * 6 + 3]; - VertexRemap::x( point.vertex ) = length - arrowhead_length; - VertexRemap::y( point.vertex ) = 0; - VertexRemap::z( point.vertex ) = 0; - NormalRemap::x( point.normal ) = -1; - NormalRemap::y( point.normal ) = 0; - NormalRemap::z( point.normal ) = 0; - } - { - FlatShadedVertex& point = vertices[i * 6 + 4]; - VertexRemap::x( point.vertex ) = length - arrowhead_length; - VertexRemap::y( point.vertex ) = arrowhead_radius * static_cast( cos( i * head_segment ) ); - VertexRemap::z( point.vertex ) = arrowhead_radius * static_cast( sin( i * head_segment ) ); - NormalRemap::x( point.normal ) = -1; - NormalRemap::y( point.normal ) = 0; - NormalRemap::z( point.normal ) = 0; - } - { - FlatShadedVertex& point = vertices[i * 6 + 5]; - VertexRemap::x( point.vertex ) = length - arrowhead_length; - VertexRemap::y( point.vertex ) = arrowhead_radius * static_cast( cos( ( i + 1 ) * head_segment ) ); - VertexRemap::z( point.vertex ) = arrowhead_radius * static_cast( sin( ( i + 1 ) * head_segment ) ); - NormalRemap::x( point.normal ) = -1; - NormalRemap::y( point.normal ) = 0; - NormalRemap::z( point.normal ) = 0; - } - } -} - -template -class TripleRemapXYZ +void Scene_forEachPlaneSelectable_selectPlanes(scene::Graph &graph, Selector &selector, SelectionTest &test, + const PlaneCallback &selectedPlaneCallback) { -public: -static float& x( Triple& triple ){ - return triple.x(); -} -static float& y( Triple& triple ){ - return triple.y(); + graph.traverse(PlaneSelectableSelectPlanes(selector, test, selectedPlaneCallback)); } -static float& z( Triple& triple ){ - return triple.z(); -} -}; -template -class TripleRemapYZX +void Scene_forEachPlaneSelectable_selectReversedPlanes(scene::Graph &graph, Selector &selector, + const SelectedPlanes &selectedPlanes) { -public: -static float& x( Triple& triple ){ - return triple.y(); -} -static float& y( Triple& triple ){ - return triple.z(); -} -static float& z( Triple& triple ){ - return triple.x(); + graph.traverse(PlaneSelectableSelectReversedPlanes(selector, selectedPlanes)); } -}; -template -class TripleRemapZXY -{ + +class PlaneLess { public: -static float& x( Triple& triple ){ - return triple.z(); -} -static float& y( Triple& triple ){ - return triple.x(); -} -static float& z( Triple& triple ){ - return triple.y(); -} + bool operator()(const Plane3 &plane, const Plane3 &other) const + { + if (plane.a < other.a) { + return true; + } + if (other.a < plane.a) { + return false; + } + + if (plane.b < other.b) { + return true; + } + if (other.b < plane.b) { + return false; + } + + if (plane.c < other.c) { + return true; + } + if (other.c < plane.c) { + return false; + } + + if (plane.d < other.d) { + return true; + } + if (other.d < plane.d) { + return false; + } + + return false; + } }; -void vector3_print( const Vector3& v ){ - globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )"; -} - -class TranslateManipulator : public Manipulator -{ -struct RenderableArrowLine : public OpenGLRenderable -{ - PointVertex m_line[2]; - - RenderableArrowLine(){ - } - void render( RenderStateFlags state ) const { - glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_line[0].colour ); - glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_line[0].vertex ); - glDrawArrays( GL_LINES, 0, 2 ); - } - void setColour( const Colour4b& colour ){ - m_line[0].colour = colour; - m_line[1].colour = colour; - } -}; -struct RenderableArrowHead : public OpenGLRenderable -{ - Array m_vertices; +typedef std::set PlaneSet; - RenderableArrowHead( std::size_t size ) - : m_vertices( size ){ - } - void render( RenderStateFlags state ) const { - glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( FlatShadedVertex ), &m_vertices.data()->colour ); - glVertexPointer( 3, GL_FLOAT, sizeof( FlatShadedVertex ), &m_vertices.data()->vertex ); - glNormalPointer( GL_FLOAT, sizeof( FlatShadedVertex ), &m_vertices.data()->normal ); - glDrawArrays( GL_TRIANGLES, 0, GLsizei( m_vertices.size() ) ); - } - void setColour( const Colour4b& colour ){ - for ( Array::iterator i = m_vertices.begin(); i != m_vertices.end(); ++i ) - { - ( *i ).colour = colour; - } - } -}; -struct RenderableQuad : public OpenGLRenderable +inline void PlaneSet_insert(PlaneSet &self, const Plane3 &plane) { - PointVertex m_quad[4]; - void render( RenderStateFlags state ) const { - glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_quad[0].colour ); - glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_quad[0].vertex ); - glDrawArrays( GL_LINE_LOOP, 0, 4 ); - } - void setColour( const Colour4b& colour ){ - m_quad[0].colour = colour; - m_quad[1].colour = colour; - m_quad[2].colour = colour; - m_quad[3].colour = colour; - } -}; - -TranslateFree m_free; -TranslateAxis m_axis; -RenderableArrowLine m_arrow_x; -RenderableArrowLine m_arrow_y; -RenderableArrowLine m_arrow_z; -RenderableArrowHead m_arrow_head_x; -RenderableArrowHead m_arrow_head_y; -RenderableArrowHead m_arrow_head_z; -RenderableQuad m_quad_screen; -SelectableBool m_selectable_x; -SelectableBool m_selectable_y; -SelectableBool m_selectable_z; -SelectableBool m_selectable_screen; -Pivot2World m_pivot; -public: -static Shader* m_state_wire; -static Shader* m_state_fill; - -TranslateManipulator( Translatable& translatable, std::size_t segments, float length ) : - m_free( translatable ), - m_axis( translatable ), - m_arrow_head_x( 3 * 2 * ( segments << 3 ) ), - m_arrow_head_y( 3 * 2 * ( segments << 3 ) ), - m_arrow_head_z( 3 * 2 * ( segments << 3 ) ){ - draw_arrowline( length, m_arrow_x.m_line, 0 ); - draw_arrowhead( segments, length, m_arrow_head_x.m_vertices.data(), TripleRemapXYZ(), TripleRemapXYZ() ); - draw_arrowline( length, m_arrow_y.m_line, 1 ); - draw_arrowhead( segments, length, m_arrow_head_y.m_vertices.data(), TripleRemapYZX(), TripleRemapYZX() ); - draw_arrowline( length, m_arrow_z.m_line, 2 ); - draw_arrowhead( segments, length, m_arrow_head_z.m_vertices.data(), TripleRemapZXY(), TripleRemapZXY() ); - - draw_quad( 16, m_quad_screen.m_quad ); + self.insert(plane); } -void UpdateColours(){ - m_arrow_x.setColour( colourSelected( g_colour_x, m_selectable_x.isSelected() ) ); - m_arrow_head_x.setColour( colourSelected( g_colour_x, m_selectable_x.isSelected() ) ); - m_arrow_y.setColour( colourSelected( g_colour_y, m_selectable_y.isSelected() ) ); - m_arrow_head_y.setColour( colourSelected( g_colour_y, m_selectable_y.isSelected() ) ); - m_arrow_z.setColour( colourSelected( g_colour_z, m_selectable_z.isSelected() ) ); - m_arrow_head_z.setColour( colourSelected( g_colour_z, m_selectable_z.isSelected() ) ); - m_quad_screen.setColour( colourSelected( g_colour_screen, m_selectable_screen.isSelected() ) ); -} - -bool manipulator_show_axis( const Pivot2World& pivot, const Vector3& axis ){ - return fabs( vector3_dot( pivot.m_axis_screen, axis ) ) < 0.95; +inline bool PlaneSet_contains(const PlaneSet &self, const Plane3 &plane) +{ + return self.find(plane) != self.end(); } -void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world ){ - m_pivot.update( pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport() ); - - // temp hack - UpdateColours(); - Vector3 x = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.x() ) ); - bool show_x = manipulator_show_axis( m_pivot, x ); +class SelectedPlaneSet : public SelectedPlanes { + PlaneSet m_selectedPlanes; +public: + bool empty() const + { + return m_selectedPlanes.empty(); + } - Vector3 y = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.y() ) ); - bool show_y = manipulator_show_axis( m_pivot, y ); + void insert(const Plane3 &plane) + { + PlaneSet_insert(m_selectedPlanes, plane); + } - Vector3 z = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.z() ) ); - bool show_z = manipulator_show_axis( m_pivot, z ); + bool contains(const Plane3 &plane) const + { + return PlaneSet_contains(m_selectedPlanes, plane); + } - renderer.SetState( m_state_wire, Renderer::eWireframeOnly ); - renderer.SetState( m_state_wire, Renderer::eFullMaterials ); + typedef MemberCaller InsertCaller; +}; - if ( show_x ) { - renderer.addRenderable( m_arrow_x, m_pivot.m_worldSpace ); - } - if ( show_y ) { - renderer.addRenderable( m_arrow_y, m_pivot.m_worldSpace ); - } - if ( show_z ) { - renderer.addRenderable( m_arrow_z, m_pivot.m_worldSpace ); - } - renderer.addRenderable( m_quad_screen, m_pivot.m_viewplaneSpace ); +bool Scene_forEachPlaneSelectable_selectPlanes(scene::Graph &graph, Selector &selector, SelectionTest &test) +{ + SelectedPlaneSet selectedPlanes; - renderer.SetState( m_state_fill, Renderer::eWireframeOnly ); - renderer.SetState( m_state_fill, Renderer::eFullMaterials ); + Scene_forEachPlaneSelectable_selectPlanes(graph, selector, test, SelectedPlaneSet::InsertCaller(selectedPlanes)); + Scene_forEachPlaneSelectable_selectReversedPlanes(graph, selector, selectedPlanes); - if ( show_x ) { - renderer.addRenderable( m_arrow_head_x, m_pivot.m_worldSpace ); - } - if ( show_y ) { - renderer.addRenderable( m_arrow_head_y, m_pivot.m_worldSpace ); - } - if ( show_z ) { - renderer.addRenderable( m_arrow_head_z, m_pivot.m_worldSpace ); - } + return !selectedPlanes.empty(); } -void testSelect( const View& view, const Matrix4& pivot2world ){ - m_pivot.update( pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport() ); - - SelectionPool selector; - Vector3 x = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.x() ) ); - bool show_x = manipulator_show_axis( m_pivot, x ); +void Scene_Translate_Component_Selected(scene::Graph &graph, const Vector3 &translation); - Vector3 y = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.y() ) ); - bool show_y = manipulator_show_axis( m_pivot, y ); +void Scene_Translate_Selected(scene::Graph &graph, const Vector3 &translation); - Vector3 z = vector3_normalised( vector4_to_vector3( m_pivot.m_worldSpace.z() ) ); - bool show_z = manipulator_show_axis( m_pivot, z ); +void Scene_TestSelect_Primitive(Selector &selector, SelectionTest &test, const VolumeTest &volume); - { - Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_viewpointSpace ) ); +void Scene_TestSelect_Component(Selector &selector, SelectionTest &test, const VolumeTest &volume, + SelectionSystem::EComponentMode componentMode); - { - SelectionIntersection best; - Quad_BestPoint( local2view, eClipCullCW, m_quad_screen.m_quad, best ); - if ( best.valid() ) { - best = SelectionIntersection( 0, 0 ); - selector.addSelectable( best, &m_selectable_screen ); - } - } - } +void Scene_TestSelect_Component_Selected(Selector &selector, SelectionTest &test, const VolumeTest &volume, + SelectionSystem::EComponentMode componentMode); - { - Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_worldSpace ) ); +void Scene_SelectAll_Component(bool select, SelectionSystem::EComponentMode componentMode); -#if defined( DEBUG_SELECTION ) - g_render_clipped.construct( view.GetViewMatrix() ); -#endif - - if ( show_x ) { - SelectionIntersection best; - Line_BestPoint( local2view, m_arrow_x.m_line, best ); - Triangles_BestPoint( local2view, eClipCullCW, m_arrow_head_x.m_vertices.begin(), m_arrow_head_x.m_vertices.end(), best ); - selector.addSelectable( best, &m_selectable_x ); - } - - if ( show_y ) { - SelectionIntersection best; - Line_BestPoint( local2view, m_arrow_y.m_line, best ); - Triangles_BestPoint( local2view, eClipCullCW, m_arrow_head_y.m_vertices.begin(), m_arrow_head_y.m_vertices.end(), best ); - selector.addSelectable( best, &m_selectable_y ); - } - - if ( show_z ) { - SelectionIntersection best; - Line_BestPoint( local2view, m_arrow_z.m_line, best ); - Triangles_BestPoint( local2view, eClipCullCW, m_arrow_head_z.m_vertices.begin(), m_arrow_head_z.m_vertices.end(), best ); - selector.addSelectable( best, &m_selectable_z ); - } - } - - if ( !selector.failed() ) { - ( *selector.begin() ).second->setSelected( true ); - } -} - -Manipulatable* GetManipulatable(){ - if ( m_selectable_x.isSelected() ) { - m_axis.SetAxis( g_vector3_axis_x ); - return &m_axis; - } - else if ( m_selectable_y.isSelected() ) { - m_axis.SetAxis( g_vector3_axis_y ); - return &m_axis; - } - else if ( m_selectable_z.isSelected() ) { - m_axis.SetAxis( g_vector3_axis_z ); - return &m_axis; - } - else - { - return &m_free; - } -} - -void setSelected( bool select ){ - m_selectable_x.setSelected( select ); - m_selectable_y.setSelected( select ); - m_selectable_z.setSelected( select ); - m_selectable_screen.setSelected( select ); -} -bool isSelected() const { - return m_selectable_x.isSelected() - | m_selectable_y.isSelected() - | m_selectable_z.isSelected() - | m_selectable_screen.isSelected(); -} +class ResizeTranslatable : public Translatable { + void translate(const Vector3 &translation) + { + Scene_Translate_Component_Selected(GlobalSceneGraph(), translation); + } }; -Shader* TranslateManipulator::m_state_wire; -Shader* TranslateManipulator::m_state_fill; - -class ScaleManipulator : public Manipulator -{ -struct RenderableArrow : public OpenGLRenderable -{ - PointVertex m_line[2]; - - void render( RenderStateFlags state ) const { - glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_line[0].colour ); - glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_line[0].vertex ); - glDrawArrays( GL_LINES, 0, 2 ); - } - void setColour( const Colour4b& colour ){ - m_line[0].colour = colour; - m_line[1].colour = colour; - } -}; -struct RenderableQuad : public OpenGLRenderable -{ - PointVertex m_quad[4]; - void render( RenderStateFlags state ) const { - glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_quad[0].colour ); - glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_quad[0].vertex ); - glDrawArrays( GL_QUADS, 0, 4 ); - } - void setColour( const Colour4b& colour ){ - m_quad[0].colour = colour; - m_quad[1].colour = colour; - m_quad[2].colour = colour; - m_quad[3].colour = colour; - } +class DragTranslatable : public Translatable { + void translate(const Vector3 &translation) + { + if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent) { + Scene_Translate_Component_Selected(GlobalSceneGraph(), translation); + } else { + Scene_Translate_Selected(GlobalSceneGraph(), translation); + } + } }; -ScaleFree m_free; -ScaleAxis m_axis; -RenderableArrow m_arrow_x; -RenderableArrow m_arrow_y; -RenderableArrow m_arrow_z; -RenderableQuad m_quad_screen; -SelectableBool m_selectable_x; -SelectableBool m_selectable_y; -SelectableBool m_selectable_z; -SelectableBool m_selectable_screen; -Pivot2World m_pivot; +class SelectionVolume : public SelectionTest { + Matrix4 m_local2view; + const View &m_view; + clipcull_t m_cull; + Vector3 m_near; + Vector3 m_far; public: -ScaleManipulator( Scalable& scalable, std::size_t segments, float length ) : - m_free( scalable ), - m_axis( scalable ){ - draw_arrowline( length, m_arrow_x.m_line, 0 ); - draw_arrowline( length, m_arrow_y.m_line, 1 ); - draw_arrowline( length, m_arrow_z.m_line, 2 ); - - draw_quad( 16, m_quad_screen.m_quad ); -} - -Pivot2World& getPivot(){ - return m_pivot; -} - -void UpdateColours(){ - m_arrow_x.setColour( colourSelected( g_colour_x, m_selectable_x.isSelected() ) ); - m_arrow_y.setColour( colourSelected( g_colour_y, m_selectable_y.isSelected() ) ); - m_arrow_z.setColour( colourSelected( g_colour_z, m_selectable_z.isSelected() ) ); - m_quad_screen.setColour( colourSelected( g_colour_screen, m_selectable_screen.isSelected() ) ); -} - -void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& pivot2world ){ - m_pivot.update( pivot2world, volume.GetModelview(), volume.GetProjection(), volume.GetViewport() ); - - // temp hack - UpdateColours(); - - renderer.addRenderable( m_arrow_x, m_pivot.m_worldSpace ); - renderer.addRenderable( m_arrow_y, m_pivot.m_worldSpace ); - renderer.addRenderable( m_arrow_z, m_pivot.m_worldSpace ); - - renderer.addRenderable( m_quad_screen, m_pivot.m_viewpointSpace ); -} -void testSelect( const View& view, const Matrix4& pivot2world ){ - m_pivot.update( pivot2world, view.GetModelview(), view.GetProjection(), view.GetViewport() ); - - SelectionPool selector; - - { - Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_worldSpace ) ); + SelectionVolume(const View &view) + : m_view(view) + { + } + + const VolumeTest &getVolume() const + { + return m_view; + } + + const Vector3 &getNear() const + { + return m_near; + } + + const Vector3 &getFar() const + { + return m_far; + } + + void BeginMesh(const Matrix4 &localToWorld, bool twoSided) + { + m_local2view = matrix4_multiplied_by_matrix4(m_view.GetViewMatrix(), localToWorld); + + // Cull back-facing polygons based on winding being clockwise or counter-clockwise. + // Don't cull if the view is wireframe and the polygons are two-sided. + m_cull = twoSided && !m_view.fill() ? eClipCullNone : (matrix4_handedness(localToWorld) == MATRIX4_RIGHTHANDED) + ? eClipCullCW : eClipCullCCW; + + { + Matrix4 screen2world(matrix4_full_inverse(m_local2view)); + + m_near = vector4_projected( + matrix4_transformed_vector4( + screen2world, + Vector4(0, 0, -1, 1) + ) + ); + + m_far = vector4_projected( + matrix4_transformed_vector4( + screen2world, + Vector4(0, 0, 1, 1) + ) + ); + } #if defined( DEBUG_SELECTION ) - g_render_clipped.construct( view.GetViewMatrix() ); + g_render_clipped.construct(m_view.GetViewMatrix()); #endif - - { - SelectionIntersection best; - Line_BestPoint( local2view, m_arrow_x.m_line, best ); - selector.addSelectable( best, &m_selectable_x ); - } - - { - SelectionIntersection best; - Line_BestPoint( local2view, m_arrow_y.m_line, best ); - selector.addSelectable( best, &m_selectable_y ); - } - - { - SelectionIntersection best; - Line_BestPoint( local2view, m_arrow_z.m_line, best ); - selector.addSelectable( best, &m_selectable_z ); - } - } - - { - Matrix4 local2view( matrix4_multiplied_by_matrix4( view.GetViewMatrix(), m_pivot.m_viewpointSpace ) ); - - { - SelectionIntersection best; - Quad_BestPoint( local2view, eClipCullCW, m_quad_screen.m_quad, best ); - selector.addSelectable( best, &m_selectable_screen ); - } - } - - if ( !selector.failed() ) { - ( *selector.begin() ).second->setSelected( true ); - } -} - -Manipulatable* GetManipulatable(){ - if ( m_selectable_x.isSelected() ) { - m_axis.SetAxis( g_vector3_axis_x ); - return &m_axis; - } - else if ( m_selectable_y.isSelected() ) { - m_axis.SetAxis( g_vector3_axis_y ); - return &m_axis; - } - else if ( m_selectable_z.isSelected() ) { - m_axis.SetAxis( g_vector3_axis_z ); - return &m_axis; - } - else{ - return &m_free; - } -} - -void setSelected( bool select ){ - m_selectable_x.setSelected( select ); - m_selectable_y.setSelected( select ); - m_selectable_z.setSelected( select ); - m_selectable_screen.setSelected( select ); -} -bool isSelected() const { - return m_selectable_x.isSelected() - | m_selectable_y.isSelected() - | m_selectable_z.isSelected() - | m_selectable_screen.isSelected(); -} -}; - - -inline PlaneSelectable* Instance_getPlaneSelectable( scene::Instance& instance ){ - return InstanceTypeCast::cast( instance ); -} - -class PlaneSelectableSelectPlanes : public scene::Graph::Walker -{ -Selector& m_selector; -SelectionTest& m_test; -PlaneCallback m_selectedPlaneCallback; + } + + void TestPoint(const Vector3 &point, SelectionIntersection &best) + { + Vector4 clipped; + if (matrix4_clip_point(m_local2view, point, clipped) == c_CLIP_PASS) { + best = select_point_from_clipped(clipped); + } + } + + void TestPolygon(const VertexPointer &vertices, std::size_t count, SelectionIntersection &best) + { + Vector4 clipped[9]; + for (std::size_t i = 0; i + 2 < count; ++i) { + BestPoint( + matrix4_clip_triangle( + m_local2view, + reinterpret_cast( vertices[0] ), + reinterpret_cast( vertices[i + 1] ), + reinterpret_cast( vertices[i + 2] ), + clipped + ), + clipped, + best, + m_cull + ); + } + } + + void TestLineLoop(const VertexPointer &vertices, std::size_t count, SelectionIntersection &best) + { + if (count == 0) { + return; + } + Vector4 clipped[9]; + for (VertexPointer::iterator i = vertices.begin(), end = i + count, prev = i + (count - 1); + i != end; prev = i, ++i) { + BestPoint( + matrix4_clip_line( + m_local2view, + reinterpret_cast((*prev)), + reinterpret_cast((*i)), + clipped + ), + clipped, + best, + m_cull + ); + } + } + + void TestLineStrip(const VertexPointer &vertices, std::size_t count, SelectionIntersection &best) + { + if (count == 0) { + return; + } + Vector4 clipped[9]; + for (VertexPointer::iterator i = vertices.begin(), end = i + count, next = i + 1; + next != end; i = next, ++next) { + BestPoint( + matrix4_clip_line( + m_local2view, + reinterpret_cast((*i)), + reinterpret_cast((*next)), + clipped + ), + clipped, + best, + m_cull + ); + } + } + + void TestLines(const VertexPointer &vertices, std::size_t count, SelectionIntersection &best) + { + if (count == 0) { + return; + } + Vector4 clipped[9]; + for (VertexPointer::iterator i = vertices.begin(), end = i + count; i != end; i += 2) { + BestPoint( + matrix4_clip_line( + m_local2view, + reinterpret_cast((*i)), + reinterpret_cast((*(i + 1))), + clipped + ), + clipped, + best, + m_cull + ); + } + } + + void TestTriangles(const VertexPointer &vertices, const IndexPointer &indices, SelectionIntersection &best) + { + Vector4 clipped[9]; + for (IndexPointer::iterator i(indices.begin()); i != indices.end(); i += 3) { + BestPoint( + matrix4_clip_triangle( + m_local2view, + reinterpret_cast( vertices[*i] ), + reinterpret_cast( vertices[*(i + 1)] ), + reinterpret_cast( vertices[*(i + 2)] ), + clipped + ), + clipped, + best, + m_cull + ); + } + } + + void TestQuads(const VertexPointer &vertices, const IndexPointer &indices, SelectionIntersection &best) + { + Vector4 clipped[9]; + for (IndexPointer::iterator i(indices.begin()); i != indices.end(); i += 4) { + BestPoint( + matrix4_clip_triangle( + m_local2view, + reinterpret_cast( vertices[*i] ), + reinterpret_cast( vertices[*(i + 1)] ), + reinterpret_cast( vertices[*(i + 3)] ), + clipped + ), + clipped, + best, + m_cull + ); + BestPoint( + matrix4_clip_triangle( + m_local2view, + reinterpret_cast( vertices[*(i + 1)] ), + reinterpret_cast( vertices[*(i + 2)] ), + reinterpret_cast( vertices[*(i + 3)] ), + clipped + ), + clipped, + best, + m_cull + ); + } + } + + void TestQuadStrip(const VertexPointer &vertices, const IndexPointer &indices, SelectionIntersection &best) + { + Vector4 clipped[9]; + for (IndexPointer::iterator i(indices.begin()); i + 2 != indices.end(); i += 2) { + BestPoint( + matrix4_clip_triangle( + m_local2view, + reinterpret_cast( vertices[*i] ), + reinterpret_cast( vertices[*(i + 1)] ), + reinterpret_cast( vertices[*(i + 2)] ), + clipped + ), + clipped, + best, + m_cull + ); + BestPoint( + matrix4_clip_triangle( + m_local2view, + reinterpret_cast( vertices[*(i + 2)] ), + reinterpret_cast( vertices[*(i + 1)] ), + reinterpret_cast( vertices[*(i + 3)] ), + clipped + ), + clipped, + best, + m_cull + ); + } + } +}; + +class SelectionCounter { public: -PlaneSelectableSelectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ) - : m_selector( selector ), m_test( test ), m_selectedPlaneCallback( selectedPlaneCallback ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 && selectable->isSelected() ) { - PlaneSelectable* planeSelectable = Instance_getPlaneSelectable( instance ); - if ( planeSelectable != 0 ) { - planeSelectable->selectPlanes( m_selector, m_test, m_selectedPlaneCallback ); - } - } - } - return true; -} -}; + using func = void(const Selectable &); + + SelectionCounter(const SelectionChangeCallback &onchanged) + : m_count(0), m_onchanged(onchanged) + { + } + + void operator()(const Selectable &selectable) + { + if (selectable.isSelected()) { + ++m_count; + } else { + ASSERT_MESSAGE(m_count != 0, "selection counter underflow"); + --m_count; + } + + m_onchanged(selectable); + } + + bool empty() const + { + return m_count == 0; + } + + std::size_t size() const + { + return m_count; + } -class PlaneSelectableSelectReversedPlanes : public scene::Graph::Walker -{ -Selector& m_selector; -const SelectedPlanes& m_selectedPlanes; -public: -PlaneSelectableSelectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ) - : m_selector( selector ), m_selectedPlanes( selectedPlanes ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 && selectable->isSelected() ) { - PlaneSelectable* planeSelectable = Instance_getPlaneSelectable( instance ); - if ( planeSelectable != 0 ) { - planeSelectable->selectReversedPlanes( m_selector, m_selectedPlanes ); - } - } - } - return true; -} +private: + std::size_t m_count; + SelectionChangeCallback m_onchanged; }; -void Scene_forEachPlaneSelectable_selectPlanes( scene::Graph& graph, Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){ - graph.traverse( PlaneSelectableSelectPlanes( selector, test, selectedPlaneCallback ) ); -} - -void Scene_forEachPlaneSelectable_selectReversedPlanes( scene::Graph& graph, Selector& selector, const SelectedPlanes& selectedPlanes ){ - graph.traverse( PlaneSelectableSelectReversedPlanes( selector, selectedPlanes ) ); -} - - -class PlaneLess +inline void ConstructSelectionTest(View &view, const rect_t selection_box) { -public: -bool operator()( const Plane3& plane, const Plane3& other ) const { - if ( plane.a < other.a ) { - return true; - } - if ( other.a < plane.a ) { - return false; - } - - if ( plane.b < other.b ) { - return true; - } - if ( other.b < plane.b ) { - return false; - } - - if ( plane.c < other.c ) { - return true; - } - if ( other.c < plane.c ) { - return false; - } - - if ( plane.d < other.d ) { - return true; - } - if ( other.d < plane.d ) { - return false; - } - - return false; -} -}; - -typedef std::set PlaneSet; - -inline void PlaneSet_insert( PlaneSet& self, const Plane3& plane ){ - self.insert( plane ); -} - -inline bool PlaneSet_contains( const PlaneSet& self, const Plane3& plane ){ - return self.find( plane ) != self.end(); + view.EnableScissor(selection_box.min[0], selection_box.max[0], selection_box.min[1], selection_box.max[1]); } - -class SelectedPlaneSet : public SelectedPlanes +inline const rect_t SelectionBoxForPoint(const float device_point[2], const float device_epsilon[2]) { -PlaneSet m_selectedPlanes; -public: -bool empty() const { - return m_selectedPlanes.empty(); -} - -void insert( const Plane3& plane ){ - PlaneSet_insert( m_selectedPlanes, plane ); -} -bool contains( const Plane3& plane ) const { - return PlaneSet_contains( m_selectedPlanes, plane ); -} -typedef MemberCaller InsertCaller; -}; - - -bool Scene_forEachPlaneSelectable_selectPlanes( scene::Graph& graph, Selector& selector, SelectionTest& test ){ - SelectedPlaneSet selectedPlanes; - - Scene_forEachPlaneSelectable_selectPlanes( graph, selector, test, SelectedPlaneSet::InsertCaller( selectedPlanes ) ); - Scene_forEachPlaneSelectable_selectReversedPlanes( graph, selector, selectedPlanes ); - - return !selectedPlanes.empty(); + rect_t selection_box; + selection_box.min[0] = device_point[0] - device_epsilon[0]; + selection_box.min[1] = device_point[1] - device_epsilon[1]; + selection_box.max[0] = device_point[0] + device_epsilon[0]; + selection_box.max[1] = device_point[1] + device_epsilon[1]; + return selection_box; } -void Scene_Translate_Component_Selected( scene::Graph& graph, const Vector3& translation ); -void Scene_Translate_Selected( scene::Graph& graph, const Vector3& translation ); -void Scene_TestSelect_Primitive( Selector& selector, SelectionTest& test, const VolumeTest& volume ); -void Scene_TestSelect_Component( Selector& selector, SelectionTest& test, const VolumeTest& volume, SelectionSystem::EComponentMode componentMode ); -void Scene_TestSelect_Component_Selected( Selector& selector, SelectionTest& test, const VolumeTest& volume, SelectionSystem::EComponentMode componentMode ); -void Scene_SelectAll_Component( bool select, SelectionSystem::EComponentMode componentMode ); - -class ResizeTranslatable : public Translatable +inline const rect_t SelectionBoxForArea(const float device_point[2], const float device_delta[2]) { -void translate( const Vector3& translation ){ - Scene_Translate_Component_Selected( GlobalSceneGraph(), translation ); + rect_t selection_box; + selection_box.min[0] = (device_delta[0] < 0) ? (device_point[0] + device_delta[0]) : (device_point[0]); + selection_box.min[1] = (device_delta[1] < 0) ? (device_point[1] + device_delta[1]) : (device_point[1]); + selection_box.max[0] = (device_delta[0] > 0) ? (device_point[0] + device_delta[0]) : (device_point[0]); + selection_box.max[1] = (device_delta[1] > 0) ? (device_point[1] + device_delta[1]) : (device_point[1]); + return selection_box; } -}; -class DragTranslatable : public Translatable +Quaternion construct_local_rotation(const Quaternion &world, const Quaternion &localToWorld) { -void translate( const Vector3& translation ){ - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { - Scene_Translate_Component_Selected( GlobalSceneGraph(), translation ); - } - else - { - Scene_Translate_Selected( GlobalSceneGraph(), translation ); - } + return quaternion_normalised(quaternion_multiplied_by_quaternion( + quaternion_normalised(quaternion_multiplied_by_quaternion( + quaternion_inverse(localToWorld), + world + )), + localToWorld + )); } -}; -class SelectionVolume : public SelectionTest +inline void matrix4_assign_rotation(Matrix4 &matrix, const Matrix4 &other) { -Matrix4 m_local2view; -const View& m_view; -clipcull_t m_cull; -Vector3 m_near; -Vector3 m_far; -public: -SelectionVolume( const View& view ) - : m_view( view ){ + matrix[0] = other[0]; + matrix[1] = other[1]; + matrix[2] = other[2]; + matrix[4] = other[4]; + matrix[5] = other[5]; + matrix[6] = other[6]; + matrix[8] = other[8]; + matrix[9] = other[9]; + matrix[10] = other[10]; } -const VolumeTest& getVolume() const { - return m_view; -} - -const Vector3& getNear() const { - return m_near; -} -const Vector3& getFar() const { - return m_far; -} - -void BeginMesh( const Matrix4& localToWorld, bool twoSided ){ - m_local2view = matrix4_multiplied_by_matrix4( m_view.GetViewMatrix(), localToWorld ); - - // Cull back-facing polygons based on winding being clockwise or counter-clockwise. - // Don't cull if the view is wireframe and the polygons are two-sided. - m_cull = twoSided && !m_view.fill() ? eClipCullNone : ( matrix4_handedness( localToWorld ) == MATRIX4_RIGHTHANDED ) ? eClipCullCW : eClipCullCCW; - - { - Matrix4 screen2world( matrix4_full_inverse( m_local2view ) ); - - m_near = vector4_projected( - matrix4_transformed_vector4( - screen2world, - Vector4( 0, 0, -1, 1 ) - ) - ); - - m_far = vector4_projected( - matrix4_transformed_vector4( - screen2world, - Vector4( 0, 0, 1, 1 ) - ) - ); - } - -#if defined( DEBUG_SELECTION ) - g_render_clipped.construct( m_view.GetViewMatrix() ); -#endif -} -void TestPoint( const Vector3& point, SelectionIntersection& best ){ - Vector4 clipped; - if ( matrix4_clip_point( m_local2view, point, clipped ) == c_CLIP_PASS ) { - best = select_point_from_clipped( clipped ); - } -} -void TestPolygon( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ){ - Vector4 clipped[9]; - for ( std::size_t i = 0; i + 2 < count; ++i ) - { - BestPoint( - matrix4_clip_triangle( - m_local2view, - reinterpret_cast( vertices[0] ), - reinterpret_cast( vertices[i + 1] ), - reinterpret_cast( vertices[i + 2] ), - clipped - ), - clipped, - best, - m_cull - ); - } -} -void TestLineLoop( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ){ - if ( count == 0 ) { - return; - } - Vector4 clipped[9]; - for ( VertexPointer::iterator i = vertices.begin(), end = i + count, prev = i + ( count - 1 ); i != end; prev = i, ++i ) - { - BestPoint( - matrix4_clip_line( - m_local2view, - reinterpret_cast( ( *prev ) ), - reinterpret_cast( ( *i ) ), - clipped - ), - clipped, - best, - m_cull - ); - } -} -void TestLineStrip( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ){ - if ( count == 0 ) { - return; - } - Vector4 clipped[9]; - for ( VertexPointer::iterator i = vertices.begin(), end = i + count, next = i + 1; next != end; i = next, ++next ) - { - BestPoint( - matrix4_clip_line( - m_local2view, - reinterpret_cast( ( *i ) ), - reinterpret_cast( ( *next ) ), - clipped - ), - clipped, - best, - m_cull - ); - } -} -void TestLines( const VertexPointer& vertices, std::size_t count, SelectionIntersection& best ){ - if ( count == 0 ) { - return; - } - Vector4 clipped[9]; - for ( VertexPointer::iterator i = vertices.begin(), end = i + count; i != end; i += 2 ) - { - BestPoint( - matrix4_clip_line( - m_local2view, - reinterpret_cast( ( *i ) ), - reinterpret_cast( ( *( i + 1 ) ) ), - clipped - ), - clipped, - best, - m_cull - ); - } -} -void TestTriangles( const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best ){ - Vector4 clipped[9]; - for ( IndexPointer::iterator i( indices.begin() ); i != indices.end(); i += 3 ) - { - BestPoint( - matrix4_clip_triangle( - m_local2view, - reinterpret_cast( vertices[*i] ), - reinterpret_cast( vertices[*( i + 1 )] ), - reinterpret_cast( vertices[*( i + 2 )] ), - clipped - ), - clipped, - best, - m_cull - ); - } -} -void TestQuads( const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best ){ - Vector4 clipped[9]; - for ( IndexPointer::iterator i( indices.begin() ); i != indices.end(); i += 4 ) - { - BestPoint( - matrix4_clip_triangle( - m_local2view, - reinterpret_cast( vertices[*i] ), - reinterpret_cast( vertices[*( i + 1 )] ), - reinterpret_cast( vertices[*( i + 3 )] ), - clipped - ), - clipped, - best, - m_cull - ); - BestPoint( - matrix4_clip_triangle( - m_local2view, - reinterpret_cast( vertices[*( i + 1 )] ), - reinterpret_cast( vertices[*( i + 2 )] ), - reinterpret_cast( vertices[*( i + 3 )] ), - clipped - ), - clipped, - best, - m_cull - ); - } -} -void TestQuadStrip( const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best ){ - Vector4 clipped[9]; - for ( IndexPointer::iterator i( indices.begin() ); i + 2 != indices.end(); i += 2 ) - { - BestPoint( - matrix4_clip_triangle( - m_local2view, - reinterpret_cast( vertices[*i] ), - reinterpret_cast( vertices[*( i + 1 )] ), - reinterpret_cast( vertices[*( i + 2 )] ), - clipped - ), - clipped, - best, - m_cull - ); - BestPoint( - matrix4_clip_triangle( - m_local2view, - reinterpret_cast( vertices[*( i + 2 )] ), - reinterpret_cast( vertices[*( i + 1 )] ), - reinterpret_cast( vertices[*( i + 3 )] ), - clipped - ), - clipped, - best, - m_cull - ); - } -} -}; - -class SelectionCounter +void matrix4_assign_rotation_for_pivot(Matrix4 &matrix, scene::Instance &instance) { -public: -using func = void(const Selectable &); - -SelectionCounter( const SelectionChangeCallback& onchanged ) - : m_count( 0 ), m_onchanged( onchanged ){ -} -void operator()( const Selectable& selectable ){ - if ( selectable.isSelected() ) { - ++m_count; - } - else - { - ASSERT_MESSAGE( m_count != 0, "selection counter underflow" ); - --m_count; - } - - m_onchanged( selectable ); -} -bool empty() const { - return m_count == 0; -} -std::size_t size() const { - return m_count; + Editable *editable = Node_getEditable(instance.path().top()); + if (editable != 0) { + matrix4_assign_rotation(matrix, + matrix4_multiplied_by_matrix4(instance.localToWorld(), editable->getLocalPivot())); + } else { + matrix4_assign_rotation(matrix, instance.localToWorld()); + } } -private: -std::size_t m_count; -SelectionChangeCallback m_onchanged; -}; -inline void ConstructSelectionTest( View& view, const rect_t selection_box ){ - view.EnableScissor( selection_box.min[0], selection_box.max[0], selection_box.min[1], selection_box.max[1] ); -} - -inline const rect_t SelectionBoxForPoint( const float device_point[2], const float device_epsilon[2] ){ - rect_t selection_box; - selection_box.min[0] = device_point[0] - device_epsilon[0]; - selection_box.min[1] = device_point[1] - device_epsilon[1]; - selection_box.max[0] = device_point[0] + device_epsilon[0]; - selection_box.max[1] = device_point[1] + device_epsilon[1]; - return selection_box; -} - -inline const rect_t SelectionBoxForArea( const float device_point[2], const float device_delta[2] ){ - rect_t selection_box; - selection_box.min[0] = ( device_delta[0] < 0 ) ? ( device_point[0] + device_delta[0] ) : ( device_point[0] ); - selection_box.min[1] = ( device_delta[1] < 0 ) ? ( device_point[1] + device_delta[1] ) : ( device_point[1] ); - selection_box.max[0] = ( device_delta[0] > 0 ) ? ( device_point[0] + device_delta[0] ) : ( device_point[0] ); - selection_box.max[1] = ( device_delta[1] > 0 ) ? ( device_point[1] + device_delta[1] ) : ( device_point[1] ); - return selection_box; -} - -Quaternion construct_local_rotation( const Quaternion& world, const Quaternion& localToWorld ){ - return quaternion_normalised( quaternion_multiplied_by_quaternion( - quaternion_normalised( quaternion_multiplied_by_quaternion( - quaternion_inverse( localToWorld ), - world - ) ), - localToWorld - ) ); -} - -inline void matrix4_assign_rotation( Matrix4& matrix, const Matrix4& other ){ - matrix[0] = other[0]; - matrix[1] = other[1]; - matrix[2] = other[2]; - matrix[4] = other[4]; - matrix[5] = other[5]; - matrix[6] = other[6]; - matrix[8] = other[8]; - matrix[9] = other[9]; - matrix[10] = other[10]; -} - -void matrix4_assign_rotation_for_pivot( Matrix4& matrix, scene::Instance& instance ){ - Editable* editable = Node_getEditable( instance.path().top() ); - if ( editable != 0 ) { - matrix4_assign_rotation( matrix, matrix4_multiplied_by_matrix4( instance.localToWorld(), editable->getLocalPivot() ) ); - } - else - { - matrix4_assign_rotation( matrix, instance.localToWorld() ); - } -} - -inline bool Instance_isSelectedComponents( scene::Instance& instance ){ - ComponentSelectionTestable* componentSelectionTestable = Instance_getComponentSelectionTestable( instance ); - return componentSelectionTestable != 0 - && componentSelectionTestable->isSelectedComponents(); -} - -class TranslateSelected : public SelectionSystem::Visitor +inline bool Instance_isSelectedComponents(scene::Instance &instance) { -const Vector3& m_translate; -public: -TranslateSelected( const Vector3& translate ) - : m_translate( translate ){ -} -void visit( scene::Instance& instance ) const { - Transformable* transform = Instance_getTransformable( instance ); - if ( transform != 0 ) { - transform->setType( TRANSFORM_PRIMITIVE ); - transform->setTranslation( m_translate ); - } -} -}; - -void Scene_Translate_Selected( scene::Graph& graph, const Vector3& translation ){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - GlobalSelectionSystem().foreachSelected( TranslateSelected( translation ) ); - } + ComponentSelectionTestable *componentSelectionTestable = Instance_getComponentSelectionTestable(instance); + return componentSelectionTestable != 0 + && componentSelectionTestable->isSelectedComponents(); } -Vector3 get_local_pivot( const Vector3& world_pivot, const Matrix4& localToWorld ){ - return Vector3( - matrix4_transformed_point( - matrix4_full_inverse( localToWorld ), - world_pivot - ) - ); -} - -void translation_for_pivoted_matrix_transform( Vector3& parent_translation, const Matrix4& local_transform, const Vector3& world_pivot, const Matrix4& localToWorld, const Matrix4& localToParent ){ - // we need a translation inside the parent system to move the origin of this object to the right place - - // mathematically, it must fulfill: - // - // local_translation local_transform local_pivot = local_pivot - // local_translation = local_pivot - local_transform local_pivot - // - // or maybe? - // local_transform local_translation local_pivot = local_pivot - // local_translation local_pivot = local_transform^-1 local_pivot - // local_translation + local_pivot = local_transform^-1 local_pivot - // local_translation = local_transform^-1 local_pivot - local_pivot - - Vector3 local_pivot( get_local_pivot( world_pivot, localToWorld ) ); - - Vector3 local_translation( - vector3_subtracted( - local_pivot, - matrix4_transformed_point( - local_transform, - local_pivot - ) - /* +class TranslateSelected : public SelectionSystem::Visitor { + const Vector3 &m_translate; +public: + TranslateSelected(const Vector3 &translate) + : m_translate(translate) + { + } + + void visit(scene::Instance &instance) const + { + Transformable *transform = Instance_getTransformable(instance); + if (transform != 0) { + transform->setType(TRANSFORM_PRIMITIVE); + transform->setTranslation(m_translate); + } + } +}; + +void Scene_Translate_Selected(scene::Graph &graph, const Vector3 &translation) +{ + if (GlobalSelectionSystem().countSelected() != 0) { + GlobalSelectionSystem().foreachSelected(TranslateSelected(translation)); + } +} + +Vector3 get_local_pivot(const Vector3 &world_pivot, const Matrix4 &localToWorld) +{ + return Vector3( + matrix4_transformed_point( + matrix4_full_inverse(localToWorld), + world_pivot + ) + ); +} + +void translation_for_pivoted_matrix_transform(Vector3 &parent_translation, const Matrix4 &local_transform, + const Vector3 &world_pivot, const Matrix4 &localToWorld, + const Matrix4 &localToParent) +{ + // we need a translation inside the parent system to move the origin of this object to the right place + + // mathematically, it must fulfill: + // + // local_translation local_transform local_pivot = local_pivot + // local_translation = local_pivot - local_transform local_pivot + // + // or maybe? + // local_transform local_translation local_pivot = local_pivot + // local_translation local_pivot = local_transform^-1 local_pivot + // local_translation + local_pivot = local_transform^-1 local_pivot + // local_translation = local_transform^-1 local_pivot - local_pivot + + Vector3 local_pivot(get_local_pivot(world_pivot, localToWorld)); + + Vector3 local_translation( + vector3_subtracted( + local_pivot, + matrix4_transformed_point( + local_transform, + local_pivot + ) + /* matrix4_transformed_point( matrix4_full_inverse(local_transform), local_pivot ), local_pivot */ - ) - ); + ) + ); - translation_local2object( parent_translation, local_translation, localToParent ); + translation_local2object(parent_translation, local_translation, localToParent); - /* + /* // verify it! globalOutputStream() << "World pivot is at " << world_pivot << "\n"; globalOutputStream() << "Local pivot is at " << local_pivot << "\n"; @@ -2147,1154 +2345,1280 @@ void translation_for_pivoted_matrix_transform( Vector3& parent_translation, cons */ } -void translation_for_pivoted_rotation( Vector3& parent_translation, const Quaternion& local_rotation, const Vector3& world_pivot, const Matrix4& localToWorld, const Matrix4& localToParent ){ - translation_for_pivoted_matrix_transform( parent_translation, matrix4_rotation_for_quaternion_quantised( local_rotation ), world_pivot, localToWorld, localToParent ); -} - -void translation_for_pivoted_scale( Vector3& parent_translation, const Vector3& world_scale, const Vector3& world_pivot, const Matrix4& localToWorld, const Matrix4& localToParent ){ - Matrix4 local_transform( - matrix4_multiplied_by_matrix4( - matrix4_full_inverse( localToWorld ), - matrix4_multiplied_by_matrix4( - matrix4_scale_for_vec3( world_scale ), - localToWorld - ) - ) - ); - local_transform.tx() = local_transform.ty() = local_transform.tz() = 0; // cancel translation parts - translation_for_pivoted_matrix_transform( parent_translation, local_transform, world_pivot, localToWorld, localToParent ); -} - -class rotate_selected : public SelectionSystem::Visitor +void translation_for_pivoted_rotation(Vector3 &parent_translation, const Quaternion &local_rotation, + const Vector3 &world_pivot, const Matrix4 &localToWorld, + const Matrix4 &localToParent) { -const Quaternion& m_rotate; -const Vector3& m_world_pivot; -public: -rotate_selected( const Quaternion& rotation, const Vector3& world_pivot ) - : m_rotate( rotation ), m_world_pivot( world_pivot ){ -} -void visit( scene::Instance& instance ) const { - TransformNode* transformNode = Node_getTransformNode( instance.path().top() ); - if ( transformNode != 0 ) { - Transformable* transform = Instance_getTransformable( instance ); - if ( transform != 0 ) { - transform->setType( TRANSFORM_PRIMITIVE ); - transform->setScale( c_scale_identity ); - transform->setTranslation( c_translation_identity ); - - transform->setType( TRANSFORM_PRIMITIVE ); - transform->setRotation( m_rotate ); - - { - Editable* editable = Node_getEditable( instance.path().top() ); - const Matrix4& localPivot = editable != 0 ? editable->getLocalPivot() : g_matrix4_identity; - - Vector3 parent_translation; - translation_for_pivoted_rotation( - parent_translation, - m_rotate, - m_world_pivot, - matrix4_multiplied_by_matrix4( instance.localToWorld(), localPivot ), - matrix4_multiplied_by_matrix4( transformNode->localToParent(), localPivot ) - ); - - transform->setTranslation( parent_translation ); - } - } - } -} -}; - -void Scene_Rotate_Selected( scene::Graph& graph, const Quaternion& rotation, const Vector3& world_pivot ){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - GlobalSelectionSystem().foreachSelected( rotate_selected( rotation, world_pivot ) ); - } + translation_for_pivoted_matrix_transform(parent_translation, + matrix4_rotation_for_quaternion_quantised(local_rotation), world_pivot, + localToWorld, localToParent); } -class scale_selected : public SelectionSystem::Visitor +void translation_for_pivoted_scale(Vector3 &parent_translation, const Vector3 &world_scale, const Vector3 &world_pivot, + const Matrix4 &localToWorld, const Matrix4 &localToParent) { -const Vector3& m_scale; -const Vector3& m_world_pivot; -public: -scale_selected( const Vector3& scaling, const Vector3& world_pivot ) - : m_scale( scaling ), m_world_pivot( world_pivot ){ -} -void visit( scene::Instance& instance ) const { - TransformNode* transformNode = Node_getTransformNode( instance.path().top() ); - if ( transformNode != 0 ) { - Transformable* transform = Instance_getTransformable( instance ); - if ( transform != 0 ) { - transform->setType( TRANSFORM_PRIMITIVE ); - transform->setScale( c_scale_identity ); - transform->setTranslation( c_translation_identity ); - - transform->setType( TRANSFORM_PRIMITIVE ); - transform->setScale( m_scale ); - { - Editable* editable = Node_getEditable( instance.path().top() ); - const Matrix4& localPivot = editable != 0 ? editable->getLocalPivot() : g_matrix4_identity; - - Vector3 parent_translation; - translation_for_pivoted_scale( - parent_translation, - m_scale, - m_world_pivot, - matrix4_multiplied_by_matrix4( instance.localToWorld(), localPivot ), - matrix4_multiplied_by_matrix4( transformNode->localToParent(), localPivot ) - ); - - transform->setTranslation( parent_translation ); - } - } - } -} -}; - -void Scene_Scale_Selected( scene::Graph& graph, const Vector3& scaling, const Vector3& world_pivot ){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - GlobalSelectionSystem().foreachSelected( scale_selected( scaling, world_pivot ) ); - } + Matrix4 local_transform( + matrix4_multiplied_by_matrix4( + matrix4_full_inverse(localToWorld), + matrix4_multiplied_by_matrix4( + matrix4_scale_for_vec3(world_scale), + localToWorld + ) + ) + ); + local_transform.tx() = local_transform.ty() = local_transform.tz() = 0; // cancel translation parts + translation_for_pivoted_matrix_transform(parent_translation, local_transform, world_pivot, localToWorld, + localToParent); } - -class translate_component_selected : public SelectionSystem::Visitor -{ -const Vector3& m_translate; +class rotate_selected : public SelectionSystem::Visitor { + const Quaternion &m_rotate; + const Vector3 &m_world_pivot; public: -translate_component_selected( const Vector3& translate ) - : m_translate( translate ){ -} -void visit( scene::Instance& instance ) const { - Transformable* transform = Instance_getTransformable( instance ); - if ( transform != 0 ) { - transform->setType( TRANSFORM_COMPONENT ); - transform->setTranslation( m_translate ); - } -} -}; - -void Scene_Translate_Component_Selected( scene::Graph& graph, const Vector3& translation ){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - GlobalSelectionSystem().foreachSelectedComponent( translate_component_selected( translation ) ); - } -} - -class rotate_component_selected : public SelectionSystem::Visitor -{ -const Quaternion& m_rotate; -const Vector3& m_world_pivot; + rotate_selected(const Quaternion &rotation, const Vector3 &world_pivot) + : m_rotate(rotation), m_world_pivot(world_pivot) + { + } + + void visit(scene::Instance &instance) const + { + TransformNode *transformNode = Node_getTransformNode(instance.path().top()); + if (transformNode != 0) { + Transformable *transform = Instance_getTransformable(instance); + if (transform != 0) { + transform->setType(TRANSFORM_PRIMITIVE); + transform->setScale(c_scale_identity); + transform->setTranslation(c_translation_identity); + + transform->setType(TRANSFORM_PRIMITIVE); + transform->setRotation(m_rotate); + + { + Editable *editable = Node_getEditable(instance.path().top()); + const Matrix4 &localPivot = editable != 0 ? editable->getLocalPivot() : g_matrix4_identity; + + Vector3 parent_translation; + translation_for_pivoted_rotation( + parent_translation, + m_rotate, + m_world_pivot, + matrix4_multiplied_by_matrix4(instance.localToWorld(), localPivot), + matrix4_multiplied_by_matrix4(transformNode->localToParent(), localPivot) + ); + + transform->setTranslation(parent_translation); + } + } + } + } +}; + +void Scene_Rotate_Selected(scene::Graph &graph, const Quaternion &rotation, const Vector3 &world_pivot) +{ + if (GlobalSelectionSystem().countSelected() != 0) { + GlobalSelectionSystem().foreachSelected(rotate_selected(rotation, world_pivot)); + } +} + +class scale_selected : public SelectionSystem::Visitor { + const Vector3 &m_scale; + const Vector3 &m_world_pivot; public: -rotate_component_selected( const Quaternion& rotation, const Vector3& world_pivot ) - : m_rotate( rotation ), m_world_pivot( world_pivot ){ -} -void visit( scene::Instance& instance ) const { - Transformable* transform = Instance_getTransformable( instance ); - if ( transform != 0 ) { - Vector3 parent_translation; - translation_for_pivoted_rotation( parent_translation, m_rotate, m_world_pivot, instance.localToWorld(), Node_getTransformNode( instance.path().top() )->localToParent() ); - - transform->setType( TRANSFORM_COMPONENT ); - transform->setRotation( m_rotate ); - transform->setTranslation( parent_translation ); - } -} -}; - -void Scene_Rotate_Component_Selected( scene::Graph& graph, const Quaternion& rotation, const Vector3& world_pivot ){ - if ( GlobalSelectionSystem().countSelectedComponents() != 0 ) { - GlobalSelectionSystem().foreachSelectedComponent( rotate_component_selected( rotation, world_pivot ) ); - } -} - -class scale_component_selected : public SelectionSystem::Visitor -{ -const Vector3& m_scale; -const Vector3& m_world_pivot; + scale_selected(const Vector3 &scaling, const Vector3 &world_pivot) + : m_scale(scaling), m_world_pivot(world_pivot) + { + } + + void visit(scene::Instance &instance) const + { + TransformNode *transformNode = Node_getTransformNode(instance.path().top()); + if (transformNode != 0) { + Transformable *transform = Instance_getTransformable(instance); + if (transform != 0) { + transform->setType(TRANSFORM_PRIMITIVE); + transform->setScale(c_scale_identity); + transform->setTranslation(c_translation_identity); + + transform->setType(TRANSFORM_PRIMITIVE); + transform->setScale(m_scale); + { + Editable *editable = Node_getEditable(instance.path().top()); + const Matrix4 &localPivot = editable != 0 ? editable->getLocalPivot() : g_matrix4_identity; + + Vector3 parent_translation; + translation_for_pivoted_scale( + parent_translation, + m_scale, + m_world_pivot, + matrix4_multiplied_by_matrix4(instance.localToWorld(), localPivot), + matrix4_multiplied_by_matrix4(transformNode->localToParent(), localPivot) + ); + + transform->setTranslation(parent_translation); + } + } + } + } +}; + +void Scene_Scale_Selected(scene::Graph &graph, const Vector3 &scaling, const Vector3 &world_pivot) +{ + if (GlobalSelectionSystem().countSelected() != 0) { + GlobalSelectionSystem().foreachSelected(scale_selected(scaling, world_pivot)); + } +} + + +class translate_component_selected : public SelectionSystem::Visitor { + const Vector3 &m_translate; public: -scale_component_selected( const Vector3& scaling, const Vector3& world_pivot ) - : m_scale( scaling ), m_world_pivot( world_pivot ){ -} -void visit( scene::Instance& instance ) const { - Transformable* transform = Instance_getTransformable( instance ); - if ( transform != 0 ) { - Vector3 parent_translation; - translation_for_pivoted_scale( parent_translation, m_scale, m_world_pivot, instance.localToWorld(), Node_getTransformNode( instance.path().top() )->localToParent() ); - - transform->setType( TRANSFORM_COMPONENT ); - transform->setScale( m_scale ); - transform->setTranslation( parent_translation ); - } -} -}; - -void Scene_Scale_Component_Selected( scene::Graph& graph, const Vector3& scaling, const Vector3& world_pivot ){ - if ( GlobalSelectionSystem().countSelectedComponents() != 0 ) { - GlobalSelectionSystem().foreachSelectedComponent( scale_component_selected( scaling, world_pivot ) ); - } -} + translate_component_selected(const Vector3 &translate) + : m_translate(translate) + { + } + void visit(scene::Instance &instance) const + { + Transformable *transform = Instance_getTransformable(instance); + if (transform != 0) { + transform->setType(TRANSFORM_COMPONENT); + transform->setTranslation(m_translate); + } + } +}; -class BooleanSelector : public Selector +void Scene_Translate_Component_Selected(scene::Graph &graph, const Vector3 &translation) { -bool m_selected; -SelectionIntersection m_intersection; -Selectable* m_selectable; -public: -BooleanSelector() : m_selected( false ){ -} - -void pushSelectable( Selectable& selectable ){ - m_intersection = SelectionIntersection(); - m_selectable = &selectable; -} -void popSelectable(){ - if ( m_intersection.valid() ) { - m_selected = true; - } - m_intersection = SelectionIntersection(); -} -void addIntersection( const SelectionIntersection& intersection ){ - if ( m_selectable->isSelected() ) { - assign_if_closer( m_intersection, intersection ); - } + if (GlobalSelectionSystem().countSelected() != 0) { + GlobalSelectionSystem().foreachSelectedComponent(translate_component_selected(translation)); + } } -bool isSelected(){ - return m_selected; -} -}; - -class BestSelector : public Selector -{ -SelectionIntersection m_intersection; -Selectable* m_selectable; -SelectionIntersection m_bestIntersection; -std::list m_bestSelectable; +class rotate_component_selected : public SelectionSystem::Visitor { + const Quaternion &m_rotate; + const Vector3 &m_world_pivot; public: -BestSelector() : m_bestIntersection( SelectionIntersection() ), m_bestSelectable( 0 ){ -} + rotate_component_selected(const Quaternion &rotation, const Vector3 &world_pivot) + : m_rotate(rotation), m_world_pivot(world_pivot) + { + } -void pushSelectable( Selectable& selectable ){ - m_intersection = SelectionIntersection(); - m_selectable = &selectable; -} -void popSelectable(){ - if ( m_intersection.equalEpsilon( m_bestIntersection, 0.25f, 0.001f ) ) { - m_bestSelectable.push_back( m_selectable ); - m_bestIntersection = m_intersection; - } - else if ( m_intersection < m_bestIntersection ) { - m_bestSelectable.clear(); - m_bestSelectable.push_back( m_selectable ); - m_bestIntersection = m_intersection; - } - m_intersection = SelectionIntersection(); -} -void addIntersection( const SelectionIntersection& intersection ){ - assign_if_closer( m_intersection, intersection ); -} + void visit(scene::Instance &instance) const + { + Transformable *transform = Instance_getTransformable(instance); + if (transform != 0) { + Vector3 parent_translation; + translation_for_pivoted_rotation(parent_translation, m_rotate, m_world_pivot, instance.localToWorld(), + Node_getTransformNode(instance.path().top())->localToParent()); -std::list& best(){ - return m_bestSelectable; -} + transform->setType(TRANSFORM_COMPONENT); + transform->setRotation(m_rotate); + transform->setTranslation(parent_translation); + } + } }; -class DragManipulator : public Manipulator +void Scene_Rotate_Component_Selected(scene::Graph &graph, const Quaternion &rotation, const Vector3 &world_pivot) { -TranslateFree m_freeResize; -TranslateFree m_freeDrag; -ResizeTranslatable m_resize; -DragTranslatable m_drag; -SelectableBool m_dragSelectable; -public: - -bool m_selected; - -DragManipulator() : m_freeResize( m_resize ), m_freeDrag( m_drag ), m_selected( false ){ -} - -Manipulatable* GetManipulatable(){ - return m_dragSelectable.isSelected() ? &m_freeDrag : &m_freeResize; + if (GlobalSelectionSystem().countSelectedComponents() != 0) { + GlobalSelectionSystem().foreachSelectedComponent(rotate_component_selected(rotation, world_pivot)); + } } -void testSelect( const View& view, const Matrix4& pivot2world ){ - SelectionPool selector; - - SelectionVolume test( view ); - - if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) { - BooleanSelector booleanSelector; +class scale_component_selected : public SelectionSystem::Visitor { + const Vector3 &m_scale; + const Vector3 &m_world_pivot; +public: + scale_component_selected(const Vector3 &scaling, const Vector3 &world_pivot) + : m_scale(scaling), m_world_pivot(world_pivot) + { + } - Scene_TestSelect_Primitive( booleanSelector, test, view ); + void visit(scene::Instance &instance) const + { + Transformable *transform = Instance_getTransformable(instance); + if (transform != 0) { + Vector3 parent_translation; + translation_for_pivoted_scale(parent_translation, m_scale, m_world_pivot, instance.localToWorld(), + Node_getTransformNode(instance.path().top())->localToParent()); - if ( booleanSelector.isSelected() ) { - selector.addSelectable( SelectionIntersection( 0, 0 ), &m_dragSelectable ); - m_selected = false; - } - else - { - m_selected = Scene_forEachPlaneSelectable_selectPlanes( GlobalSceneGraph(), selector, test ); - } - } - else - { - BestSelector bestSelector; - Scene_TestSelect_Component_Selected( bestSelector, test, view, GlobalSelectionSystem().ComponentMode() ); - for ( std::list::iterator i = bestSelector.best().begin(); i != bestSelector.best().end(); ++i ) - { - if ( !( *i )->isSelected() ) { - GlobalSelectionSystem().setSelectedAllComponents( false ); - } - m_selected = false; - selector.addSelectable( SelectionIntersection( 0, 0 ), ( *i ) ); - m_dragSelectable.setSelected( true ); - } - } - - for ( SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i ) - { - ( *i ).second->setSelected( true ); - } -} - -void setSelected( bool select ){ - m_selected = select; - m_dragSelectable.setSelected( select ); -} -bool isSelected() const { - return m_selected || m_dragSelectable.isSelected(); -} + transform->setType(TRANSFORM_COMPONENT); + transform->setScale(m_scale); + transform->setTranslation(parent_translation); + } + } }; -class ClipManipulator : public Manipulator +void Scene_Scale_Component_Selected(scene::Graph &graph, const Vector3 &scaling, const Vector3 &world_pivot) { -public: - -Manipulatable* GetManipulatable(){ - ERROR_MESSAGE( "clipper is not manipulatable" ); - return 0; + if (GlobalSelectionSystem().countSelectedComponents() != 0) { + GlobalSelectionSystem().foreachSelectedComponent(scale_component_selected(scaling, world_pivot)); + } } -void setSelected( bool select ){ -} -bool isSelected() const { - return false; -} -}; -class select_all : public scene::Graph::Walker -{ -bool m_select; +class BooleanSelector : public Selector { + bool m_selected; + SelectionIntersection m_intersection; + Selectable *m_selectable; public: -select_all( bool select ) - : m_select( select ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 ) { - selectable->setSelected( m_select ); - } - return true; -} -}; - -class select_all_component : public scene::Graph::Walker -{ -bool m_select; -SelectionSystem::EComponentMode m_mode; + BooleanSelector() : m_selected(false) + { + } + + void pushSelectable(Selectable &selectable) + { + m_intersection = SelectionIntersection(); + m_selectable = &selectable; + } + + void popSelectable() + { + if (m_intersection.valid()) { + m_selected = true; + } + m_intersection = SelectionIntersection(); + } + + void addIntersection(const SelectionIntersection &intersection) + { + if (m_selectable->isSelected()) { + assign_if_closer(m_intersection, intersection); + } + } + + bool isSelected() + { + return m_selected; + } +}; + +class BestSelector : public Selector { + SelectionIntersection m_intersection; + Selectable *m_selectable; + SelectionIntersection m_bestIntersection; + std::list m_bestSelectable; public: -select_all_component( bool select, SelectionSystem::EComponentMode mode ) - : m_select( select ), m_mode( mode ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - ComponentSelectionTestable* componentSelectionTestable = Instance_getComponentSelectionTestable( instance ); - if ( componentSelectionTestable ) { - componentSelectionTestable->setSelectedComponents( m_select, m_mode ); - } - return true; -} -}; - -void Scene_SelectAll_Component( bool select, SelectionSystem::EComponentMode componentMode ){ - GlobalSceneGraph().traverse( select_all_component( select, componentMode ) ); -} - - -// RadiantSelectionSystem -class RadiantSelectionSystem : - public SelectionSystem, - public Translatable, - public Rotatable, - public Scalable, - public Renderable -{ -mutable Matrix4 m_pivot2world; -Matrix4 m_pivot2world_start; -Matrix4 m_manip2pivot_start; -Translation m_translation; -Rotation m_rotation; -Scale m_scale; + BestSelector() : m_bestIntersection(SelectionIntersection()), m_bestSelectable(0) + { + } + + void pushSelectable(Selectable &selectable) + { + m_intersection = SelectionIntersection(); + m_selectable = &selectable; + } + + void popSelectable() + { + if (m_intersection.equalEpsilon(m_bestIntersection, 0.25f, 0.001f)) { + m_bestSelectable.push_back(m_selectable); + m_bestIntersection = m_intersection; + } else if (m_intersection < m_bestIntersection) { + m_bestSelectable.clear(); + m_bestSelectable.push_back(m_selectable); + m_bestIntersection = m_intersection; + } + m_intersection = SelectionIntersection(); + } + + void addIntersection(const SelectionIntersection &intersection) + { + assign_if_closer(m_intersection, intersection); + } + + std::list &best() + { + return m_bestSelectable; + } +}; + +class DragManipulator : public Manipulator { + TranslateFree m_freeResize; + TranslateFree m_freeDrag; + ResizeTranslatable m_resize; + DragTranslatable m_drag; + SelectableBool m_dragSelectable; public: -static Shader* m_state; -private: -EManipulatorMode m_manipulator_mode; -Manipulator* m_manipulator; - -// state -bool m_undo_begun; -EMode m_mode; -EComponentMode m_componentmode; - -SelectionCounter m_count_primitive; -SelectionCounter m_count_component; - -TranslateManipulator m_translate_manipulator; -RotateManipulator m_rotate_manipulator; -ScaleManipulator m_scale_manipulator; -DragManipulator m_drag_manipulator; -ClipManipulator m_clip_manipulator; - -typedef SelectionList selection_t; -selection_t m_selection; -selection_t m_component_selection; - -Signal1 m_selectionChanged_callbacks; - -void ConstructPivot() const; -mutable bool m_pivotChanged; -bool m_pivot_moving; - -void Scene_TestSelect( Selector& selector, SelectionTest& test, const View& view, SelectionSystem::EMode mode, SelectionSystem::EComponentMode componentMode ); - -bool nothingSelected() const { - return ( Mode() == eComponent && m_count_component.empty() ) - || ( Mode() == ePrimitive && m_count_primitive.empty() ); -} - + bool m_selected; + + DragManipulator() : m_freeResize(m_resize), m_freeDrag(m_drag), m_selected(false) + { + } + + Manipulatable *GetManipulatable() + { + return m_dragSelectable.isSelected() ? &m_freeDrag : &m_freeResize; + } + + void testSelect(const View &view, const Matrix4 &pivot2world) + { + SelectionPool selector; + + SelectionVolume test(view); + + if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) { + BooleanSelector booleanSelector; + + Scene_TestSelect_Primitive(booleanSelector, test, view); + + if (booleanSelector.isSelected()) { + selector.addSelectable(SelectionIntersection(0, 0), &m_dragSelectable); + m_selected = false; + } else { + m_selected = Scene_forEachPlaneSelectable_selectPlanes(GlobalSceneGraph(), selector, test); + } + } else { + BestSelector bestSelector; + Scene_TestSelect_Component_Selected(bestSelector, test, view, GlobalSelectionSystem().ComponentMode()); + for (std::list::iterator i = bestSelector.best().begin(); + i != bestSelector.best().end(); ++i) { + if (!(*i)->isSelected()) { + GlobalSelectionSystem().setSelectedAllComponents(false); + } + m_selected = false; + selector.addSelectable(SelectionIntersection(0, 0), (*i)); + m_dragSelectable.setSelected(true); + } + } + + for (SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i) { + (*i).second->setSelected(true); + } + } + + void setSelected(bool select) + { + m_selected = select; + m_dragSelectable.setSelected(select); + } + + bool isSelected() const + { + return m_selected || m_dragSelectable.isSelected(); + } +}; + +class ClipManipulator : public Manipulator { public: -enum EModifier -{ - eManipulator, - eToggle, - eReplace, - eCycle, -}; -RadiantSelectionSystem() : - m_undo_begun( false ), - m_mode( ePrimitive ), - m_componentmode( eDefault ), - m_count_primitive( SelectionChangedCaller( *this ) ), - m_count_component( SelectionChangedCaller( *this ) ), - m_translate_manipulator( *this, 2, 64 ), - m_rotate_manipulator( *this, 8, 64 ), - m_scale_manipulator( *this, 0, 64 ), - m_pivotChanged( false ), - m_pivot_moving( false ){ - SetManipulatorMode( eTranslate ); - pivotChanged(); - addSelectionChangeCallback( PivotChangedSelectionCaller( *this ) ); - AddGridChangeCallback( PivotChangedCaller( *this ) ); -} -void pivotChanged() const { - m_pivotChanged = true; - SceneChangeNotify(); -} -typedef ConstMemberCaller PivotChangedCaller; -void pivotChangedSelection( const Selectable& selectable ){ - pivotChanged(); -} -typedef MemberCaller PivotChangedSelectionCaller; - -void SetMode( EMode mode ){ - if ( m_mode != mode ) { - m_mode = mode; - pivotChanged(); - } -} -EMode Mode() const { - return m_mode; -} -void SetComponentMode( EComponentMode mode ){ - m_componentmode = mode; -} -EComponentMode ComponentMode() const { - return m_componentmode; -} -void SetManipulatorMode( EManipulatorMode mode ){ - m_manipulator_mode = mode; - switch ( m_manipulator_mode ) - { - case eTranslate: m_manipulator = &m_translate_manipulator; break; - case eRotate: m_manipulator = &m_rotate_manipulator; break; - case eScale: m_manipulator = &m_scale_manipulator; break; - case eDrag: m_manipulator = &m_drag_manipulator; break; - case eClip: m_manipulator = &m_clip_manipulator; break; - } - pivotChanged(); -} -EManipulatorMode ManipulatorMode() const { - return m_manipulator_mode; -} + Manipulatable *GetManipulatable() + { + ERROR_MESSAGE("clipper is not manipulatable"); + return 0; + } -SelectionChangeCallback getObserver( EMode mode ){ - if ( mode == ePrimitive ) { - return makeCallback( m_count_primitive ); - } - else - { - return makeCallback( m_count_component ); - } -} -std::size_t countSelected() const { - return m_count_primitive.size(); -} -std::size_t countSelectedComponents() const { - return m_count_component.size(); -} -void onSelectedChanged( scene::Instance& instance, const Selectable& selectable ){ - if ( selectable.isSelected() ) { - m_selection.append( instance ); - } - else - { - m_selection.erase( instance ); - } + void setSelected(bool select) + { + } - ASSERT_MESSAGE( m_selection.size() == m_count_primitive.size(), "selection-tracking error" ); -} -void onComponentSelection( scene::Instance& instance, const Selectable& selectable ){ - if ( selectable.isSelected() ) { - m_component_selection.append( instance ); - } - else - { - m_component_selection.erase( instance ); - } - - ASSERT_MESSAGE( m_component_selection.size() == m_count_component.size(), "selection-tracking error" ); -} -scene::Instance& ultimateSelected() const { - ASSERT_MESSAGE( m_selection.size() > 0, "no instance selected" ); - return m_selection.back(); -} -scene::Instance& penultimateSelected() const { - ASSERT_MESSAGE( m_selection.size() > 1, "only one instance selected" ); - return *( *( --( --m_selection.end() ) ) ); -} -void setSelectedAll( bool selected ){ - GlobalSceneGraph().traverse( select_all( selected ) ); - - m_manipulator->setSelected( selected ); -} -void setSelectedAllComponents( bool selected ){ - Scene_SelectAll_Component( selected, SelectionSystem::eVertex ); - Scene_SelectAll_Component( selected, SelectionSystem::eEdge ); - Scene_SelectAll_Component( selected, SelectionSystem::eFace ); - - m_manipulator->setSelected( selected ); -} - -void foreachSelected( const Visitor& visitor ) const { - selection_t::const_iterator i = m_selection.begin(); - while ( i != m_selection.end() ) - { - visitor.visit( *( *( i++ ) ) ); - } -} -void foreachSelectedComponent( const Visitor& visitor ) const { - selection_t::const_iterator i = m_component_selection.begin(); - while ( i != m_component_selection.end() ) - { - visitor.visit( *( *( i++ ) ) ); - } -} - -void addSelectionChangeCallback( const SelectionChangeHandler& handler ){ - m_selectionChanged_callbacks.connectLast( handler ); -} -void selectionChanged( const Selectable& selectable ){ - m_selectionChanged_callbacks( selectable ); -} -typedef MemberCaller SelectionChangedCaller; - - -void startMove(){ - m_pivot2world_start = GetPivot2World(); -} - -bool SelectManipulator( const View& view, const float device_point[2], const float device_epsilon[2] ){ - if ( !nothingSelected() || ( ManipulatorMode() == eDrag && Mode() == eComponent ) ) { -#if defined ( DEBUG_SELECTION ) - g_render_clipped.destroy(); -#endif - - m_manipulator->setSelected( false ); - - if ( !nothingSelected() || ( ManipulatorMode() == eDrag && Mode() == eComponent ) ) { - View scissored( view ); - ConstructSelectionTest( scissored, SelectionBoxForPoint( device_point, device_epsilon ) ); - m_manipulator->testSelect( scissored, GetPivot2World() ); - } - - startMove(); - - m_pivot_moving = m_manipulator->isSelected(); - - if ( m_pivot_moving ) { - Pivot2World pivot; - pivot.update( GetPivot2World(), view.GetModelview(), view.GetProjection(), view.GetViewport() ); - - m_manip2pivot_start = matrix4_multiplied_by_matrix4( matrix4_full_inverse( m_pivot2world_start ), pivot.m_worldSpace ); - - Matrix4 device2manip; - ConstructDevice2Manip( device2manip, m_pivot2world_start, view.GetModelview(), view.GetProjection(), view.GetViewport() ); - m_manipulator->GetManipulatable()->Construct( device2manip, device_point[0], device_point[1] ); - - m_undo_begun = false; - } - - SceneChangeNotify(); - } - - return m_pivot_moving; -} - -void deselectAll(){ - if ( Mode() == eComponent ) { - setSelectedAllComponents( false ); - } - else - { - setSelectedAll( false ); - } -} - -void SelectPoint( const View& view, const float device_point[2], const float device_epsilon[2], RadiantSelectionSystem::EModifier modifier, bool face ){ - ASSERT_MESSAGE( fabs( device_point[0] ) <= 1.0f && fabs( device_point[1] ) <= 1.0f, "point-selection error" ); - if ( modifier == eReplace ) { - if ( face ) { - setSelectedAllComponents( false ); - } - else - { - deselectAll(); - } - } - - #if defined ( DEBUG_SELECTION ) - g_render_clipped.destroy(); - #endif + bool isSelected() const + { + return false; + } +}; - { - View scissored( view ); - ConstructSelectionTest( scissored, SelectionBoxForPoint( device_point, device_epsilon ) ); +class select_all : public scene::Graph::Walker { + bool m_select; +public: + select_all(bool select) + : m_select(select) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0) { + selectable->setSelected(m_select); + } + return true; + } +}; + +class select_all_component : public scene::Graph::Walker { + bool m_select; + SelectionSystem::EComponentMode m_mode; +public: + select_all_component(bool select, SelectionSystem::EComponentMode mode) + : m_select(select), m_mode(mode) + { + } - SelectionVolume volume( scissored ); - SelectionPool selector; - if ( face ) { - Scene_TestSelect_Component( selector, volume, scissored, eFace ); - } - else - { - Scene_TestSelect( selector, volume, scissored, Mode(), ComponentMode() ); - } + bool pre(const scene::Path &path, scene::Instance &instance) const + { + ComponentSelectionTestable *componentSelectionTestable = Instance_getComponentSelectionTestable(instance); + if (componentSelectionTestable) { + componentSelectionTestable->setSelectedComponents(m_select, m_mode); + } + return true; + } +}; - if ( !selector.failed() ) { - switch ( modifier ) - { - case RadiantSelectionSystem::eToggle: - { - SelectableSortedSet::iterator best = selector.begin(); - // toggle selection of the object with least depth - if ( ( *best ).second->isSelected() ) { - ( *best ).second->setSelected( false ); - } - else{ - ( *best ).second->setSelected( true ); - } - } - break; - // if cycle mode not enabled, enable it - case RadiantSelectionSystem::eReplace: - { - // select closest - ( *selector.begin() ).second->setSelected( true ); - } - break; - // select the next object in the list from the one already selected - case RadiantSelectionSystem::eCycle: - { - SelectionPool::iterator i = selector.begin(); - while ( i != selector.end() ) - { - if ( ( *i ).second->isSelected() ) { - ( *i ).second->setSelected( false ); - ++i; - if ( i != selector.end() ) { - i->second->setSelected( true ); - } - else - { - selector.begin()->second->setSelected( true ); - } - break; - } - ++i; - } - } - break; - default: - break; - } - } - } +void Scene_SelectAll_Component(bool select, SelectionSystem::EComponentMode componentMode) +{ + GlobalSceneGraph().traverse(select_all_component(select, componentMode)); } -void SelectArea( const View& view, const float device_point[2], const float device_delta[2], RadiantSelectionSystem::EModifier modifier, bool face ){ - if ( modifier == eReplace ) { - if ( face ) { - setSelectedAllComponents( false ); - } - else - { - deselectAll(); - } - } - #if defined ( DEBUG_SELECTION ) - g_render_clipped.destroy(); - #endif +// RadiantSelectionSystem +class RadiantSelectionSystem : + public SelectionSystem, + public Translatable, + public Rotatable, + public Scalable, + public Renderable { + mutable Matrix4 m_pivot2world; + Matrix4 m_pivot2world_start; + Matrix4 m_manip2pivot_start; + Translation m_translation; + Rotation m_rotation; + Scale m_scale; +public: + static Shader *m_state; +private: + EManipulatorMode m_manipulator_mode; + Manipulator *m_manipulator; - { - View scissored( view ); - ConstructSelectionTest( scissored, SelectionBoxForArea( device_point, device_delta ) ); +// state + bool m_undo_begun; + EMode m_mode; + EComponentMode m_componentmode; - SelectionVolume volume( scissored ); - SelectionPool pool; - if ( face ) { - Scene_TestSelect_Component( pool, volume, scissored, eFace ); - } - else - { - Scene_TestSelect( pool, volume, scissored, Mode(), ComponentMode() ); - } + SelectionCounter m_count_primitive; + SelectionCounter m_count_component; - for ( SelectionPool::iterator i = pool.begin(); i != pool.end(); ++i ) - { - ( *i ).second->setSelected( !( modifier == RadiantSelectionSystem::eToggle && ( *i ).second->isSelected() ) ); - } - } -} + TranslateManipulator m_translate_manipulator; + RotateManipulator m_rotate_manipulator; + ScaleManipulator m_scale_manipulator; + DragManipulator m_drag_manipulator; + ClipManipulator m_clip_manipulator; + typedef SelectionList selection_t; + selection_t m_selection; + selection_t m_component_selection; -void translate( const Vector3& translation ){ - if ( !nothingSelected() ) { - //ASSERT_MESSAGE(!m_pivotChanged, "pivot is invalid"); + Signal1 m_selectionChanged_callbacks; - m_translation = translation; + void ConstructPivot() const; - m_pivot2world = m_pivot2world_start; - matrix4_translate_by_vec3( m_pivot2world, translation ); + mutable bool m_pivotChanged; + bool m_pivot_moving; - if ( Mode() == eComponent ) { - Scene_Translate_Component_Selected( GlobalSceneGraph(), m_translation ); - } - else - { - Scene_Translate_Selected( GlobalSceneGraph(), m_translation ); - } + void Scene_TestSelect(Selector &selector, SelectionTest &test, const View &view, SelectionSystem::EMode mode, + SelectionSystem::EComponentMode componentMode); - SceneChangeNotify(); - } -} -void outputTranslation( TextOutputStream& ostream ){ - ostream << " -xyz " << m_translation.x() << " " << m_translation.y() << " " << m_translation.z(); -} -void rotate( const Quaternion& rotation ){ - if ( !nothingSelected() ) { - //ASSERT_MESSAGE(!m_pivotChanged, "pivot is invalid"); + bool nothingSelected() const + { + return (Mode() == eComponent && m_count_component.empty()) + || (Mode() == ePrimitive && m_count_primitive.empty()); + } - m_rotation = rotation; - if ( Mode() == eComponent ) { - Scene_Rotate_Component_Selected( GlobalSceneGraph(), m_rotation, vector4_to_vector3( m_pivot2world.t() ) ); +public: + enum EModifier { + eManipulator, + eToggle, + eReplace, + eCycle, + }; + + RadiantSelectionSystem() : + m_undo_begun(false), + m_mode(ePrimitive), + m_componentmode(eDefault), + m_count_primitive(SelectionChangedCaller(*this)), + m_count_component(SelectionChangedCaller(*this)), + m_translate_manipulator(*this, 2, 64), + m_rotate_manipulator(*this, 8, 64), + m_scale_manipulator(*this, 0, 64), + m_pivotChanged(false), + m_pivot_moving(false) + { + SetManipulatorMode(eTranslate); + pivotChanged(); + addSelectionChangeCallback(PivotChangedSelectionCaller(*this)); + AddGridChangeCallback(PivotChangedCaller(*this)); + } + + void pivotChanged() const + { + m_pivotChanged = true; + SceneChangeNotify(); + } + + typedef ConstMemberCaller PivotChangedCaller; + + void pivotChangedSelection(const Selectable &selectable) + { + pivotChanged(); + } + + typedef MemberCaller PivotChangedSelectionCaller; + + void SetMode(EMode mode) + { + if (m_mode != mode) { + m_mode = mode; + pivotChanged(); + } + } + + EMode Mode() const + { + return m_mode; + } + + void SetComponentMode(EComponentMode mode) + { + m_componentmode = mode; + } + + EComponentMode ComponentMode() const + { + return m_componentmode; + } + + void SetManipulatorMode(EManipulatorMode mode) + { + m_manipulator_mode = mode; + switch (m_manipulator_mode) { + case eTranslate: + m_manipulator = &m_translate_manipulator; + break; + case eRotate: + m_manipulator = &m_rotate_manipulator; + break; + case eScale: + m_manipulator = &m_scale_manipulator; + break; + case eDrag: + m_manipulator = &m_drag_manipulator; + break; + case eClip: + m_manipulator = &m_clip_manipulator; + break; + } + pivotChanged(); + } + + EManipulatorMode ManipulatorMode() const + { + return m_manipulator_mode; + } + + SelectionChangeCallback getObserver(EMode mode) + { + if (mode == ePrimitive) { + return makeCallback(m_count_primitive); + } else { + return makeCallback(m_count_component); + } + } + + std::size_t countSelected() const + { + return m_count_primitive.size(); + } + + std::size_t countSelectedComponents() const + { + return m_count_component.size(); + } + + void onSelectedChanged(scene::Instance &instance, const Selectable &selectable) + { + if (selectable.isSelected()) { + m_selection.append(instance); + } else { + m_selection.erase(instance); + } + + ASSERT_MESSAGE(m_selection.size() == m_count_primitive.size(), "selection-tracking error"); + } + + void onComponentSelection(scene::Instance &instance, const Selectable &selectable) + { + if (selectable.isSelected()) { + m_component_selection.append(instance); + } else { + m_component_selection.erase(instance); + } + + ASSERT_MESSAGE(m_component_selection.size() == m_count_component.size(), "selection-tracking error"); + } + + scene::Instance &ultimateSelected() const + { + ASSERT_MESSAGE(m_selection.size() > 0, "no instance selected"); + return m_selection.back(); + } + + scene::Instance &penultimateSelected() const + { + ASSERT_MESSAGE(m_selection.size() > 1, "only one instance selected"); + return *(*(--(--m_selection.end()))); + } + + void setSelectedAll(bool selected) + { + GlobalSceneGraph().traverse(select_all(selected)); + + m_manipulator->setSelected(selected); + } + + void setSelectedAllComponents(bool selected) + { + Scene_SelectAll_Component(selected, SelectionSystem::eVertex); + Scene_SelectAll_Component(selected, SelectionSystem::eEdge); + Scene_SelectAll_Component(selected, SelectionSystem::eFace); + + m_manipulator->setSelected(selected); + } + + void foreachSelected(const Visitor &visitor) const + { + selection_t::const_iterator i = m_selection.begin(); + while (i != m_selection.end()) { + visitor.visit(*(*(i++))); + } + } + + void foreachSelectedComponent(const Visitor &visitor) const + { + selection_t::const_iterator i = m_component_selection.begin(); + while (i != m_component_selection.end()) { + visitor.visit(*(*(i++))); + } + } + + void addSelectionChangeCallback(const SelectionChangeHandler &handler) + { + m_selectionChanged_callbacks.connectLast(handler); + } + + void selectionChanged(const Selectable &selectable) + { + m_selectionChanged_callbacks(selectable); + } + + typedef MemberCaller SelectionChangedCaller; + + + void startMove() + { + m_pivot2world_start = GetPivot2World(); + } + + bool SelectManipulator(const View &view, const float device_point[2], const float device_epsilon[2]) + { + if (!nothingSelected() || (ManipulatorMode() == eDrag && Mode() == eComponent)) { +#if defined ( DEBUG_SELECTION ) + g_render_clipped.destroy(); +#endif + + m_manipulator->setSelected(false); - matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() ); - } - else - { - Scene_Rotate_Selected( GlobalSceneGraph(), m_rotation, vector4_to_vector3( m_pivot2world.t() ) ); + if (!nothingSelected() || (ManipulatorMode() == eDrag && Mode() == eComponent)) { + View scissored(view); + ConstructSelectionTest(scissored, SelectionBoxForPoint(device_point, device_epsilon)); + m_manipulator->testSelect(scissored, GetPivot2World()); + } - matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() ); - } + startMove(); - SceneChangeNotify(); - } -} -void outputRotation( TextOutputStream& ostream ){ - ostream << " -eulerXYZ " << m_rotation.x() << " " << m_rotation.y() << " " << m_rotation.z(); -} -void scale( const Vector3& scaling ){ - if ( !nothingSelected() ) { - m_scale = scaling; + m_pivot_moving = m_manipulator->isSelected(); - if ( Mode() == eComponent ) { - Scene_Scale_Component_Selected( GlobalSceneGraph(), m_scale, vector4_to_vector3( m_pivot2world.t() ) ); - } - else - { - Scene_Scale_Selected( GlobalSceneGraph(), m_scale, vector4_to_vector3( m_pivot2world.t() ) ); - } + if (m_pivot_moving) { + Pivot2World pivot; + pivot.update(GetPivot2World(), view.GetModelview(), view.GetProjection(), view.GetViewport()); - SceneChangeNotify(); - } -} -void outputScale( TextOutputStream& ostream ){ - ostream << " -scale " << m_scale.x() << " " << m_scale.y() << " " << m_scale.z(); -} + m_manip2pivot_start = matrix4_multiplied_by_matrix4(matrix4_full_inverse(m_pivot2world_start), + pivot.m_worldSpace); -void rotateSelected( const Quaternion& rotation ){ - startMove(); - rotate( rotation ); - freezeTransforms(); -} -void translateSelected( const Vector3& translation ){ - startMove(); - translate( translation ); - freezeTransforms(); -} -void scaleSelected( const Vector3& scaling ){ - startMove(); - scale( scaling ); - freezeTransforms(); -} + Matrix4 device2manip; + ConstructDevice2Manip(device2manip, m_pivot2world_start, view.GetModelview(), view.GetProjection(), + view.GetViewport()); + m_manipulator->GetManipulatable()->Construct(device2manip, device_point[0], device_point[1]); -void MoveSelected( const View& view, const float device_point[2] ){ - if ( m_manipulator->isSelected() ) { - if ( !m_undo_begun ) { - m_undo_begun = true; - GlobalUndoSystem().start(); - } + m_undo_begun = false; + } - Matrix4 device2manip; - ConstructDevice2Manip( device2manip, m_pivot2world_start, view.GetModelview(), view.GetProjection(), view.GetViewport() ); - m_manipulator->GetManipulatable()->Transform( m_manip2pivot_start, device2manip, device_point[0], device_point[1] ); - } -} + SceneChangeNotify(); + } -/// \todo Support view-dependent nudge. -void NudgeManipulator( const Vector3& nudge, const Vector3& view ){ - if ( ManipulatorMode() == eTranslate || ManipulatorMode() == eDrag ) { - translateSelected( nudge ); - } -} + return m_pivot_moving; + } -void endMove(); -void freezeTransforms(); + void deselectAll() + { + if (Mode() == eComponent) { + setSelectedAllComponents(false); + } else { + setSelectedAll(false); + } + } -void renderSolid( Renderer& renderer, const VolumeTest& volume ) const; -void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { - renderSolid( renderer, volume ); -} + void SelectPoint(const View &view, const float device_point[2], const float device_epsilon[2], + RadiantSelectionSystem::EModifier modifier, bool face) + { + ASSERT_MESSAGE(fabs(device_point[0]) <= 1.0f && fabs(device_point[1]) <= 1.0f, "point-selection error"); + if (modifier == eReplace) { + if (face) { + setSelectedAllComponents(false); + } else { + deselectAll(); + } + } -const Matrix4& GetPivot2World() const { - ConstructPivot(); - return m_pivot2world; -} +#if defined ( DEBUG_SELECTION ) + g_render_clipped.destroy(); +#endif -static void constructStatic(){ - m_state = GlobalShaderCache().capture( "$POINT" ); - #if defined( DEBUG_SELECTION ) - g_state_clipped = GlobalShaderCache().capture( "$DEBUG_CLIPPED" ); - #endif - TranslateManipulator::m_state_wire = GlobalShaderCache().capture( "$WIRE_OVERLAY" ); - TranslateManipulator::m_state_fill = GlobalShaderCache().capture( "$FLATSHADE_OVERLAY" ); - RotateManipulator::m_state_outer = GlobalShaderCache().capture( "$WIRE_OVERLAY" ); -} + { + View scissored(view); + ConstructSelectionTest(scissored, SelectionBoxForPoint(device_point, device_epsilon)); + + SelectionVolume volume(scissored); + SelectionPool selector; + if (face) { + Scene_TestSelect_Component(selector, volume, scissored, eFace); + } else { + Scene_TestSelect(selector, volume, scissored, Mode(), ComponentMode()); + } + + if (!selector.failed()) { + switch (modifier) { + case RadiantSelectionSystem::eToggle: { + SelectableSortedSet::iterator best = selector.begin(); + // toggle selection of the object with least depth + if ((*best).second->isSelected()) { + (*best).second->setSelected(false); + } else { + (*best).second->setSelected(true); + } + } + break; + // if cycle mode not enabled, enable it + case RadiantSelectionSystem::eReplace: { + // select closest + (*selector.begin()).second->setSelected(true); + } + break; + // select the next object in the list from the one already selected + case RadiantSelectionSystem::eCycle: { + SelectionPool::iterator i = selector.begin(); + while (i != selector.end()) { + if ((*i).second->isSelected()) { + (*i).second->setSelected(false); + ++i; + if (i != selector.end()) { + i->second->setSelected(true); + } else { + selector.begin()->second->setSelected(true); + } + break; + } + ++i; + } + } + break; + default: + break; + } + } + } + } + + void SelectArea(const View &view, const float device_point[2], const float device_delta[2], + RadiantSelectionSystem::EModifier modifier, bool face) + { + if (modifier == eReplace) { + if (face) { + setSelectedAllComponents(false); + } else { + deselectAll(); + } + } -static void destroyStatic(){ - #if defined( DEBUG_SELECTION ) - GlobalShaderCache().release( "$DEBUG_CLIPPED" ); - #endif - GlobalShaderCache().release( "$WIRE_OVERLAY" ); - GlobalShaderCache().release( "$FLATSHADE_OVERLAY" ); - GlobalShaderCache().release( "$WIRE_OVERLAY" ); - GlobalShaderCache().release( "$POINT" ); -} -}; +#if defined ( DEBUG_SELECTION ) + g_render_clipped.destroy(); +#endif -Shader* RadiantSelectionSystem::m_state = 0; + { + View scissored(view); + ConstructSelectionTest(scissored, SelectionBoxForArea(device_point, device_delta)); + + SelectionVolume volume(scissored); + SelectionPool pool; + if (face) { + Scene_TestSelect_Component(pool, volume, scissored, eFace); + } else { + Scene_TestSelect(pool, volume, scissored, Mode(), ComponentMode()); + } + + for (SelectionPool::iterator i = pool.begin(); i != pool.end(); ++i) { + (*i).second->setSelected(!(modifier == RadiantSelectionSystem::eToggle && (*i).second->isSelected())); + } + } + } + + + void translate(const Vector3 &translation) + { + if (!nothingSelected()) { + //ASSERT_MESSAGE(!m_pivotChanged, "pivot is invalid"); + + m_translation = translation; + + m_pivot2world = m_pivot2world_start; + matrix4_translate_by_vec3(m_pivot2world, translation); + + if (Mode() == eComponent) { + Scene_Translate_Component_Selected(GlobalSceneGraph(), m_translation); + } else { + Scene_Translate_Selected(GlobalSceneGraph(), m_translation); + } + + SceneChangeNotify(); + } + } + + void outputTranslation(TextOutputStream &ostream) + { + ostream << " -xyz " << m_translation.x() << " " << m_translation.y() << " " << m_translation.z(); + } + + void rotate(const Quaternion &rotation) + { + if (!nothingSelected()) { + //ASSERT_MESSAGE(!m_pivotChanged, "pivot is invalid"); + + m_rotation = rotation; + + if (Mode() == eComponent) { + Scene_Rotate_Component_Selected(GlobalSceneGraph(), m_rotation, vector4_to_vector3(m_pivot2world.t())); + + matrix4_assign_rotation_for_pivot(m_pivot2world, m_component_selection.back()); + } else { + Scene_Rotate_Selected(GlobalSceneGraph(), m_rotation, vector4_to_vector3(m_pivot2world.t())); + + matrix4_assign_rotation_for_pivot(m_pivot2world, m_selection.back()); + } + + SceneChangeNotify(); + } + } + + void outputRotation(TextOutputStream &ostream) + { + ostream << " -eulerXYZ " << m_rotation.x() << " " << m_rotation.y() << " " << m_rotation.z(); + } + + void scale(const Vector3 &scaling) + { + if (!nothingSelected()) { + m_scale = scaling; + + if (Mode() == eComponent) { + Scene_Scale_Component_Selected(GlobalSceneGraph(), m_scale, vector4_to_vector3(m_pivot2world.t())); + } else { + Scene_Scale_Selected(GlobalSceneGraph(), m_scale, vector4_to_vector3(m_pivot2world.t())); + } + + SceneChangeNotify(); + } + } + + void outputScale(TextOutputStream &ostream) + { + ostream << " -scale " << m_scale.x() << " " << m_scale.y() << " " << m_scale.z(); + } + + void rotateSelected(const Quaternion &rotation) + { + startMove(); + rotate(rotation); + freezeTransforms(); + } + + void translateSelected(const Vector3 &translation) + { + startMove(); + translate(translation); + freezeTransforms(); + } + + void scaleSelected(const Vector3 &scaling) + { + startMove(); + scale(scaling); + freezeTransforms(); + } + + void MoveSelected(const View &view, const float device_point[2]) + { + if (m_manipulator->isSelected()) { + if (!m_undo_begun) { + m_undo_begun = true; + GlobalUndoSystem().start(); + } + + Matrix4 device2manip; + ConstructDevice2Manip(device2manip, m_pivot2world_start, view.GetModelview(), view.GetProjection(), + view.GetViewport()); + m_manipulator->GetManipulatable()->Transform(m_manip2pivot_start, device2manip, device_point[0], + device_point[1]); + } + } +/// \todo Support view-dependent nudge. + void NudgeManipulator(const Vector3 &nudge, const Vector3 &view) + { + if (ManipulatorMode() == eTranslate || ManipulatorMode() == eDrag) { + translateSelected(nudge); + } + } -namespace -{ -RadiantSelectionSystem* g_RadiantSelectionSystem; + void endMove(); -inline RadiantSelectionSystem& getSelectionSystem(){ - return *g_RadiantSelectionSystem; -} -} + void freezeTransforms(); + void renderSolid(Renderer &renderer, const VolumeTest &volume) const; + void renderWireframe(Renderer &renderer, const VolumeTest &volume) const + { + renderSolid(renderer, volume); + } -class testselect_entity_visible : public scene::Graph::Walker -{ -Selector& m_selector; -SelectionTest& m_test; -public: -testselect_entity_visible( Selector& selector, SelectionTest& test ) - : m_selector( selector ), m_test( test ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && Node_isEntity( path.top() ) ) { - m_selector.pushSelectable( *selectable ); - } + const Matrix4 &GetPivot2World() const + { + ConstructPivot(); + return m_pivot2world; + } - SelectionTestable* selectionTestable = Instance_getSelectionTestable( instance ); - if ( selectionTestable ) { - selectionTestable->testSelect( m_selector, m_test ); - } + static void constructStatic() + { + m_state = GlobalShaderCache().capture("$POINT"); +#if defined( DEBUG_SELECTION ) + g_state_clipped = GlobalShaderCache().capture("$DEBUG_CLIPPED"); +#endif + TranslateManipulator::m_state_wire = GlobalShaderCache().capture("$WIRE_OVERLAY"); + TranslateManipulator::m_state_fill = GlobalShaderCache().capture("$FLATSHADE_OVERLAY"); + RotateManipulator::m_state_outer = GlobalShaderCache().capture("$WIRE_OVERLAY"); + } - return true; -} -void post( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && Node_isEntity( path.top() ) ) { - m_selector.popSelectable(); - } -} + static void destroyStatic() + { +#if defined( DEBUG_SELECTION ) + GlobalShaderCache().release("$DEBUG_CLIPPED"); +#endif + GlobalShaderCache().release("$WIRE_OVERLAY"); + GlobalShaderCache().release("$FLATSHADE_OVERLAY"); + GlobalShaderCache().release("$WIRE_OVERLAY"); + GlobalShaderCache().release("$POINT"); + } }; -class testselect_primitive_visible : public scene::Graph::Walker -{ -Selector& m_selector; -SelectionTest& m_test; -public: -testselect_primitive_visible( Selector& selector, SelectionTest& test ) - : m_selector( selector ), m_test( test ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 ) { - m_selector.pushSelectable( *selectable ); - } +Shader *RadiantSelectionSystem::m_state = 0; - SelectionTestable* selectionTestable = Instance_getSelectionTestable( instance ); - if ( selectionTestable ) { - selectionTestable->testSelect( m_selector, m_test ); - } - return true; -} -void post( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 ) { - m_selector.popSelectable(); - } +namespace { + RadiantSelectionSystem *g_RadiantSelectionSystem; + + inline RadiantSelectionSystem &getSelectionSystem() + { + return *g_RadiantSelectionSystem; + } } -}; -class testselect_component_visible : public scene::Graph::Walker -{ -Selector& m_selector; -SelectionTest& m_test; -SelectionSystem::EComponentMode m_mode; + +class testselect_entity_visible : public scene::Graph::Walker { + Selector &m_selector; + SelectionTest &m_test; public: -testselect_component_visible( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ) - : m_selector( selector ), m_test( test ), m_mode( mode ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - ComponentSelectionTestable* componentSelectionTestable = Instance_getComponentSelectionTestable( instance ); - if ( componentSelectionTestable ) { - componentSelectionTestable->testSelectComponents( m_selector, m_test, m_mode ); - } + testselect_entity_visible(Selector &selector, SelectionTest &test) + : m_selector(selector), m_test(test) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && Node_isEntity(path.top())) { + m_selector.pushSelectable(*selectable); + } + + SelectionTestable *selectionTestable = Instance_getSelectionTestable(instance); + if (selectionTestable) { + selectionTestable->testSelect(m_selector, m_test); + } + + return true; + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && Node_isEntity(path.top())) { + m_selector.popSelectable(); + } + } +}; + +class testselect_primitive_visible : public scene::Graph::Walker { + Selector &m_selector; + SelectionTest &m_test; +public: + testselect_primitive_visible(Selector &selector, SelectionTest &test) + : m_selector(selector), m_test(test) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0) { + m_selector.pushSelectable(*selectable); + } + + SelectionTestable *selectionTestable = Instance_getSelectionTestable(instance); + if (selectionTestable) { + selectionTestable->testSelect(m_selector, m_test); + } + + return true; + } + + void post(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0) { + m_selector.popSelectable(); + } + } +}; + +class testselect_component_visible : public scene::Graph::Walker { + Selector &m_selector; + SelectionTest &m_test; + SelectionSystem::EComponentMode m_mode; +public: + testselect_component_visible(Selector &selector, SelectionTest &test, SelectionSystem::EComponentMode mode) + : m_selector(selector), m_test(test), m_mode(mode) + { + } - return true; -} + bool pre(const scene::Path &path, scene::Instance &instance) const + { + ComponentSelectionTestable *componentSelectionTestable = Instance_getComponentSelectionTestable(instance); + if (componentSelectionTestable) { + componentSelectionTestable->testSelectComponents(m_selector, m_test, m_mode); + } + + return true; + } }; -class testselect_component_visible_selected : public scene::Graph::Walker -{ -Selector& m_selector; -SelectionTest& m_test; -SelectionSystem::EComponentMode m_mode; +class testselect_component_visible_selected : public scene::Graph::Walker { + Selector &m_selector; + SelectionTest &m_test; + SelectionSystem::EComponentMode m_mode; public: -testselect_component_visible_selected( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ) - : m_selector( selector ), m_test( test ), m_mode( mode ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 && selectable->isSelected() ) { - ComponentSelectionTestable* componentSelectionTestable = Instance_getComponentSelectionTestable( instance ); - if ( componentSelectionTestable ) { - componentSelectionTestable->testSelectComponents( m_selector, m_test, m_mode ); - } - } + testselect_component_visible_selected(Selector &selector, SelectionTest &test, SelectionSystem::EComponentMode mode) + : m_selector(selector), m_test(test), m_mode(mode) + { + } - return true; -} + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 && selectable->isSelected()) { + ComponentSelectionTestable *componentSelectionTestable = Instance_getComponentSelectionTestable(instance); + if (componentSelectionTestable) { + componentSelectionTestable->testSelectComponents(m_selector, m_test, m_mode); + } + } + + return true; + } }; -void Scene_TestSelect_Primitive( Selector& selector, SelectionTest& test, const VolumeTest& volume ){ - Scene_forEachVisible( GlobalSceneGraph(), volume, testselect_primitive_visible( selector, test ) ); +void Scene_TestSelect_Primitive(Selector &selector, SelectionTest &test, const VolumeTest &volume) +{ + Scene_forEachVisible(GlobalSceneGraph(), volume, testselect_primitive_visible(selector, test)); } -void Scene_TestSelect_Component_Selected( Selector& selector, SelectionTest& test, const VolumeTest& volume, SelectionSystem::EComponentMode componentMode ){ - Scene_forEachVisible( GlobalSceneGraph(), volume, testselect_component_visible_selected( selector, test, componentMode ) ); +void Scene_TestSelect_Component_Selected(Selector &selector, SelectionTest &test, const VolumeTest &volume, + SelectionSystem::EComponentMode componentMode) +{ + Scene_forEachVisible(GlobalSceneGraph(), volume, + testselect_component_visible_selected(selector, test, componentMode)); } -void Scene_TestSelect_Component( Selector& selector, SelectionTest& test, const VolumeTest& volume, SelectionSystem::EComponentMode componentMode ){ - Scene_forEachVisible( GlobalSceneGraph(), volume, testselect_component_visible( selector, test, componentMode ) ); +void Scene_TestSelect_Component(Selector &selector, SelectionTest &test, const VolumeTest &volume, + SelectionSystem::EComponentMode componentMode) +{ + Scene_forEachVisible(GlobalSceneGraph(), volume, testselect_component_visible(selector, test, componentMode)); } -void RadiantSelectionSystem::Scene_TestSelect( Selector& selector, SelectionTest& test, const View& view, SelectionSystem::EMode mode, SelectionSystem::EComponentMode componentMode ){ - switch ( mode ) - { - case eEntity: - { - Scene_forEachVisible( GlobalSceneGraph(), view, testselect_entity_visible( selector, test ) ); - } - break; - case ePrimitive: - Scene_TestSelect_Primitive( selector, test, view ); - break; - case eComponent: - Scene_TestSelect_Component_Selected( selector, test, view, componentMode ); - break; - } +void RadiantSelectionSystem::Scene_TestSelect(Selector &selector, SelectionTest &test, const View &view, + SelectionSystem::EMode mode, + SelectionSystem::EComponentMode componentMode) +{ + switch (mode) { + case eEntity: { + Scene_forEachVisible(GlobalSceneGraph(), view, testselect_entity_visible(selector, test)); + } + break; + case ePrimitive: + Scene_TestSelect_Primitive(selector, test, view); + break; + case eComponent: + Scene_TestSelect_Component_Selected(selector, test, view, componentMode); + break; + } } -class FreezeTransforms : public scene::Graph::Walker -{ +class FreezeTransforms : public scene::Graph::Walker { public: -bool pre( const scene::Path& path, scene::Instance& instance ) const { - TransformNode* transformNode = Node_getTransformNode( path.top() ); - if ( transformNode != 0 ) { - Transformable* transform = Instance_getTransformable( instance ); - if ( transform != 0 ) { - transform->freezeTransform(); - } - } - return true; -} + bool pre(const scene::Path &path, scene::Instance &instance) const + { + TransformNode *transformNode = Node_getTransformNode(path.top()); + if (transformNode != 0) { + Transformable *transform = Instance_getTransformable(instance); + if (transform != 0) { + transform->freezeTransform(); + } + } + return true; + } }; -void RadiantSelectionSystem::freezeTransforms(){ - GlobalSceneGraph().traverse( FreezeTransforms() ); +void RadiantSelectionSystem::freezeTransforms() +{ + GlobalSceneGraph().traverse(FreezeTransforms()); } -void RadiantSelectionSystem::endMove(){ - freezeTransforms(); +void RadiantSelectionSystem::endMove() +{ + freezeTransforms(); - if ( Mode() == ePrimitive ) { - if ( ManipulatorMode() == eDrag ) { - Scene_SelectAll_Component( false, SelectionSystem::eFace ); - } - } + if (Mode() == ePrimitive) { + if (ManipulatorMode() == eDrag) { + Scene_SelectAll_Component(false, SelectionSystem::eFace); + } + } - m_pivot_moving = false; - pivotChanged(); + m_pivot_moving = false; + pivotChanged(); - SceneChangeNotify(); + SceneChangeNotify(); - if ( m_undo_begun ) { - StringOutputStream command; + if (m_undo_begun) { + StringOutputStream command; - if ( ManipulatorMode() == eTranslate ) { - command << "translateTool"; - outputTranslation( command ); - } - else if ( ManipulatorMode() == eRotate ) { - command << "rotateTool"; - outputRotation( command ); - } - else if ( ManipulatorMode() == eScale ) { - command << "scaleTool"; - outputScale( command ); - } - else if ( ManipulatorMode() == eDrag ) { - command << "dragTool"; - } + if (ManipulatorMode() == eTranslate) { + command << "translateTool"; + outputTranslation(command); + } else if (ManipulatorMode() == eRotate) { + command << "rotateTool"; + outputRotation(command); + } else if (ManipulatorMode() == eScale) { + command << "scaleTool"; + outputScale(command); + } else if (ManipulatorMode() == eDrag) { + command << "dragTool"; + } - GlobalUndoSystem().finish( command.c_str() ); - } + GlobalUndoSystem().finish(command.c_str()); + } } -inline AABB Instance_getPivotBounds( scene::Instance& instance ){ - Entity* entity = Node_getEntity( instance.path().top() ); - if ( entity != 0 - && ( entity->getEntityClass().fixedsize - || !node_is_group( instance.path().top() ) ) ) { - Editable* editable = Node_getEditable( instance.path().top() ); - if ( editable != 0 ) { - return AABB( vector4_to_vector3( matrix4_multiplied_by_matrix4( instance.localToWorld(), editable->getLocalPivot() ).t() ), Vector3( 0, 0, 0 ) ); - } - else - { - return AABB( vector4_to_vector3( instance.localToWorld().t() ), Vector3( 0, 0, 0 ) ); - } - } +inline AABB Instance_getPivotBounds(scene::Instance &instance) +{ + Entity *entity = Node_getEntity(instance.path().top()); + if (entity != 0 + && (entity->getEntityClass().fixedsize + || !node_is_group(instance.path().top()))) { + Editable *editable = Node_getEditable(instance.path().top()); + if (editable != 0) { + return AABB(vector4_to_vector3( + matrix4_multiplied_by_matrix4(instance.localToWorld(), editable->getLocalPivot()).t()), + Vector3(0, 0, 0)); + } else { + return AABB(vector4_to_vector3(instance.localToWorld().t()), Vector3(0, 0, 0)); + } + } - return instance.worldAABB(); + return instance.worldAABB(); } -class bounds_selected : public scene::Graph::Walker -{ -AABB& m_bounds; +class bounds_selected : public scene::Graph::Walker { + AABB &m_bounds; public: -bounds_selected( AABB& bounds ) - : m_bounds( bounds ){ - m_bounds = AABB(); -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() ) { - aabb_extend_by_aabb_safe( m_bounds, Instance_getPivotBounds( instance ) ); - } - return true; -} -}; - -class bounds_selected_component : public scene::Graph::Walker -{ -AABB& m_bounds; + bounds_selected(AABB &bounds) + : m_bounds(bounds) + { + m_bounds = AABB(); + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected()) { + aabb_extend_by_aabb_safe(m_bounds, Instance_getPivotBounds(instance)); + } + return true; + } +}; + +class bounds_selected_component : public scene::Graph::Walker { + AABB &m_bounds; public: -bounds_selected_component( AABB& bounds ) - : m_bounds( bounds ){ - m_bounds = AABB(); -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - Selectable* selectable = Instance_getSelectable( instance ); - if ( selectable != 0 - && selectable->isSelected() ) { - ComponentEditable* componentEditable = Instance_getComponentEditable( instance ); - if ( componentEditable ) { - aabb_extend_by_aabb_safe( m_bounds, aabb_for_oriented_aabb_safe( componentEditable->getSelectedComponentsBounds(), instance.localToWorld() ) ); - } - } - return true; -} + bounds_selected_component(AABB &bounds) + : m_bounds(bounds) + { + m_bounds = AABB(); + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + Selectable *selectable = Instance_getSelectable(instance); + if (selectable != 0 + && selectable->isSelected()) { + ComponentEditable *componentEditable = Instance_getComponentEditable(instance); + if (componentEditable) { + aabb_extend_by_aabb_safe(m_bounds, + aabb_for_oriented_aabb_safe(componentEditable->getSelectedComponentsBounds(), + instance.localToWorld())); + } + } + return true; + } }; -void Scene_BoundsSelected( scene::Graph& graph, AABB& bounds ){ - graph.traverse( bounds_selected( bounds ) ); +void Scene_BoundsSelected(scene::Graph &graph, AABB &bounds) +{ + graph.traverse(bounds_selected(bounds)); } -void Scene_BoundsSelectedComponent( scene::Graph& graph, AABB& bounds ){ - graph.traverse( bounds_selected_component( bounds ) ); +void Scene_BoundsSelectedComponent(scene::Graph &graph, AABB &bounds) +{ + graph.traverse(bounds_selected_component(bounds)); } #if 0 -inline void pivot_for_node( Matrix4& pivot, scene::Node& node, scene::Instance& instance ){ + inline void pivot_for_node( Matrix4& pivot, scene::Node& node, scene::Instance& instance ){ ComponentEditable* componentEditable = Instance_getComponentEditable( instance ); if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent && componentEditable != 0 ) { @@ -3314,132 +3638,136 @@ inline void pivot_for_node( Matrix4& pivot, scene::Node& node, scene::Instance& } #endif -void RadiantSelectionSystem::ConstructPivot() const { - if ( !m_pivotChanged || m_pivot_moving ) { - return; - } - m_pivotChanged = false; - - Vector3 m_object_pivot; - - if ( !nothingSelected() ) { - { - AABB bounds; - if ( Mode() == eComponent ) { - Scene_BoundsSelectedComponent( GlobalSceneGraph(), bounds ); - } - else - { - Scene_BoundsSelected( GlobalSceneGraph(), bounds ); - } - m_object_pivot = bounds.origin; - } - - vector3_snap( m_object_pivot, GetSnapGridSize() ); - m_pivot2world = matrix4_translation_for_vec3( m_object_pivot ); - - switch ( m_manipulator_mode ) - { - case eTranslate: - break; - case eRotate: - if ( Mode() == eComponent ) { - matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() ); - } - else - { - matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() ); - } - break; - case eScale: - if ( Mode() == eComponent ) { - matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() ); - } - else - { - matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() ); - } - break; - default: - break; - } - } -} - -void RadiantSelectionSystem::renderSolid( Renderer& renderer, const VolumeTest& volume ) const { - //if(view->TestPoint(m_object_pivot)) - if ( !nothingSelected() ) { - renderer.Highlight( Renderer::ePrimitive, false ); - renderer.Highlight( Renderer::eFace, false ); - - renderer.SetState( m_state, Renderer::eWireframeOnly ); - renderer.SetState( m_state, Renderer::eFullMaterials ); - - m_manipulator->render( renderer, volume, GetPivot2World() ); - } +void RadiantSelectionSystem::ConstructPivot() const +{ + if (!m_pivotChanged || m_pivot_moving) { + return; + } + m_pivotChanged = false; + + Vector3 m_object_pivot; + + if (!nothingSelected()) { + { + AABB bounds; + if (Mode() == eComponent) { + Scene_BoundsSelectedComponent(GlobalSceneGraph(), bounds); + } else { + Scene_BoundsSelected(GlobalSceneGraph(), bounds); + } + m_object_pivot = bounds.origin; + } + + vector3_snap(m_object_pivot, GetSnapGridSize()); + m_pivot2world = matrix4_translation_for_vec3(m_object_pivot); + + switch (m_manipulator_mode) { + case eTranslate: + break; + case eRotate: + if (Mode() == eComponent) { + matrix4_assign_rotation_for_pivot(m_pivot2world, m_component_selection.back()); + } else { + matrix4_assign_rotation_for_pivot(m_pivot2world, m_selection.back()); + } + break; + case eScale: + if (Mode() == eComponent) { + matrix4_assign_rotation_for_pivot(m_pivot2world, m_component_selection.back()); + } else { + matrix4_assign_rotation_for_pivot(m_pivot2world, m_selection.back()); + } + break; + default: + break; + } + } +} + +void RadiantSelectionSystem::renderSolid(Renderer &renderer, const VolumeTest &volume) const +{ + //if(view->TestPoint(m_object_pivot)) + if (!nothingSelected()) { + renderer.Highlight(Renderer::ePrimitive, false); + renderer.Highlight(Renderer::eFace, false); + + renderer.SetState(m_state, Renderer::eWireframeOnly); + renderer.SetState(m_state, Renderer::eFullMaterials); + + m_manipulator->render(renderer, volume, GetPivot2World()); + } #if defined( DEBUG_SELECTION ) - renderer.SetState( g_state_clipped, Renderer::eWireframeOnly ); - renderer.SetState( g_state_clipped, Renderer::eFullMaterials ); - renderer.addRenderable( g_render_clipped, g_render_clipped.m_world ); + renderer.SetState(g_state_clipped, Renderer::eWireframeOnly); + renderer.SetState(g_state_clipped, Renderer::eFullMaterials); + renderer.addRenderable(g_render_clipped, g_render_clipped.m_world); #endif } -void SelectionSystem_OnBoundsChanged(){ - getSelectionSystem().pivotChanged(); +void SelectionSystem_OnBoundsChanged() +{ + getSelectionSystem().pivotChanged(); } SignalHandlerId SelectionSystem_boundsChanged; -void SelectionSystem_Construct(){ - RadiantSelectionSystem::constructStatic(); +void SelectionSystem_Construct() +{ + RadiantSelectionSystem::constructStatic(); - g_RadiantSelectionSystem = new RadiantSelectionSystem; + g_RadiantSelectionSystem = new RadiantSelectionSystem; - SelectionSystem_boundsChanged = GlobalSceneGraph().addBoundsChangedCallback( FreeCaller() ); + SelectionSystem_boundsChanged = GlobalSceneGraph().addBoundsChangedCallback( + FreeCaller()); - GlobalShaderCache().attachRenderable( getSelectionSystem() ); + GlobalShaderCache().attachRenderable(getSelectionSystem()); } -void SelectionSystem_Destroy(){ - GlobalShaderCache().detachRenderable( getSelectionSystem() ); +void SelectionSystem_Destroy() +{ + GlobalShaderCache().detachRenderable(getSelectionSystem()); - GlobalSceneGraph().removeBoundsChangedCallback( SelectionSystem_boundsChanged ); + GlobalSceneGraph().removeBoundsChangedCallback(SelectionSystem_boundsChanged); - delete g_RadiantSelectionSystem; + delete g_RadiantSelectionSystem; - RadiantSelectionSystem::destroyStatic(); + RadiantSelectionSystem::destroyStatic(); } - - -inline float screen_normalised( float pos, std::size_t size ){ - return ( ( 2.0f * pos ) / size ) - 1.0f; +inline float screen_normalised(float pos, std::size_t size) +{ + return ((2.0f * pos) / size) - 1.0f; } typedef Vector2 DeviceVector; -inline DeviceVector window_to_normalised_device( WindowVector window, std::size_t width, std::size_t height ){ - return DeviceVector( screen_normalised( window.x(), width ), screen_normalised( height - 1 - window.y(), height ) ); +inline DeviceVector window_to_normalised_device(WindowVector window, std::size_t width, std::size_t height) +{ + return DeviceVector(screen_normalised(window.x(), width), screen_normalised(height - 1 - window.y(), height)); } -inline float device_constrained( float pos ){ - return std::min( 1.0f, std::max( -1.0f, pos ) ); +inline float device_constrained(float pos) +{ + return std::min(1.0f, std::max(-1.0f, pos)); } -inline DeviceVector device_constrained( DeviceVector device ){ - return DeviceVector( device_constrained( device.x() ), device_constrained( device.y() ) ); +inline DeviceVector device_constrained(DeviceVector device) +{ + return DeviceVector(device_constrained(device.x()), device_constrained(device.y())); } -inline float window_constrained( float pos, std::size_t origin, std::size_t size ){ - return std::min( static_cast( origin + size ), std::max( static_cast( origin ), pos ) ); +inline float window_constrained(float pos, std::size_t origin, std::size_t size) +{ + return std::min(static_cast( origin + size ), std::max(static_cast( origin ), pos)); } -inline WindowVector window_constrained( WindowVector window, std::size_t x, std::size_t y, std::size_t width, std::size_t height ){ - return WindowVector( window_constrained( window.x(), x, width ), window_constrained( window.y(), y, height ) ); +inline WindowVector +window_constrained(WindowVector window, std::size_t x, std::size_t y, std::size_t width, std::size_t height) +{ + return WindowVector(window_constrained(window.x(), x, width), window_constrained(window.y(), y, height)); } typedef Callback MouseEventCallback; @@ -3454,7 +3782,7 @@ const ModifierFlags c_modifier_toggle = c_modifierShift; const ModifierFlags c_modifier_replace = c_modifierShift | c_modifierAlt; const ModifierFlags c_modifier_face = c_modifierControl; #else -const ButtonIdentifier c_button_select = c_buttonLeft; + const ButtonIdentifier c_button_select = c_buttonLeft; const ModifierFlags c_modifier_manipulator = c_modifierNone; const ModifierFlags c_modifier_toggle = c_modifierControl; const ModifierFlags c_modifier_replace = c_modifierNone; @@ -3466,264 +3794,301 @@ const ModifierFlags c_modifier_replace_face = c_modifier_replace | c_modifier_fa const ButtonIdentifier c_button_texture = c_buttonMiddle; const ModifierFlags c_modifier_apply_texture1 = c_modifierControl | c_modifierShift; const ModifierFlags c_modifier_apply_texture2 = c_modifierControl; -const ModifierFlags c_modifier_apply_texture3 = c_modifierShift; +const ModifierFlags c_modifier_apply_texture3 = c_modifierShift; const ModifierFlags c_modifier_copy_texture = c_modifierNone; -class Selector_ -{ -RadiantSelectionSystem::EModifier modifier_for_state( ModifierFlags state ){ - if ( state == c_modifier_toggle || state == c_modifier_toggle_face ) { - return RadiantSelectionSystem::eToggle; - } - if ( state == c_modifier_replace || state == c_modifier_replace_face ) { - return RadiantSelectionSystem::eReplace; - } - return RadiantSelectionSystem::eManipulator; -} - -rect_t getDeviceArea() const { - DeviceVector delta( m_current - m_start ); - if ( selecting() && fabs( delta.x() ) > m_epsilon.x() && fabs( delta.y() ) > m_epsilon.y() ) { - return SelectionBoxForArea( &m_start[0], &delta[0] ); - } - else - { - rect_t default_area = { { 0, 0, }, { 0, 0, }, }; - return default_area; - } -} +class Selector_ { + RadiantSelectionSystem::EModifier modifier_for_state(ModifierFlags state) + { + if (state == c_modifier_toggle || state == c_modifier_toggle_face) { + return RadiantSelectionSystem::eToggle; + } + if (state == c_modifier_replace || state == c_modifier_replace_face) { + return RadiantSelectionSystem::eReplace; + } + return RadiantSelectionSystem::eManipulator; + } + + rect_t getDeviceArea() const + { + DeviceVector delta(m_current - m_start); + if (selecting() && fabs(delta.x()) > m_epsilon.x() && fabs(delta.y()) > m_epsilon.y()) { + return SelectionBoxForArea(&m_start[0], &delta[0]); + } else { + rect_t default_area = {{0, 0,}, + {0, 0,},}; + return default_area; + } + } public: -DeviceVector m_start; -DeviceVector m_current; -DeviceVector m_epsilon; -std::size_t m_unmoved_replaces; -ModifierFlags m_state; -const View* m_view; -RectangleCallback m_window_update; - -Selector_() : m_start( 0.0f, 0.0f ), m_current( 0.0f, 0.0f ), m_unmoved_replaces( 0 ), m_state( c_modifierNone ){ -} - -void draw_area(){ - m_window_update( getDeviceArea() ); -} - -void testSelect( DeviceVector position ){ - RadiantSelectionSystem::EModifier modifier = modifier_for_state( m_state ); - if ( modifier != RadiantSelectionSystem::eManipulator ) { - DeviceVector delta( position - m_start ); - if ( fabs( delta.x() ) > m_epsilon.x() && fabs( delta.y() ) > m_epsilon.y() ) { - DeviceVector delta( position - m_start ); - getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone ); - } - else - { - if ( modifier == RadiantSelectionSystem::eReplace && m_unmoved_replaces++ > 0 ) { - modifier = RadiantSelectionSystem::eCycle; - } - getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone ); - } - } - - m_start = m_current = DeviceVector( 0.0f, 0.0f ); - draw_area(); -} - -bool selecting() const { - return m_state != c_modifier_manipulator; -} - -void setState( ModifierFlags state ){ - bool was_selecting = selecting(); - m_state = state; - if ( was_selecting ^ selecting() ) { - draw_area(); - } -} - -ModifierFlags getState() const { - return m_state; -} - -void modifierEnable( ModifierFlags type ){ - setState( bitfield_enable( getState(), type ) ); -} -void modifierDisable( ModifierFlags type ){ - setState( bitfield_disable( getState(), type ) ); -} - -void mouseDown( DeviceVector position ){ - m_start = m_current = device_constrained( position ); -} - -void mouseMoved( DeviceVector position ){ - m_current = device_constrained( position ); - draw_area(); -} -typedef MemberCaller MouseMovedCaller; - -void mouseUp( DeviceVector position ){ - testSelect( device_constrained( position ) ); - - g_mouseMovedCallback.clear(); - g_mouseUpCallback.clear(); -} -typedef MemberCaller MouseUpCaller; -}; - - -class Manipulator_ -{ + DeviceVector m_start; + DeviceVector m_current; + DeviceVector m_epsilon; + std::size_t m_unmoved_replaces; + ModifierFlags m_state; + const View *m_view; + RectangleCallback m_window_update; + + Selector_() : m_start(0.0f, 0.0f), m_current(0.0f, 0.0f), m_unmoved_replaces(0), m_state(c_modifierNone) + { + } + + void draw_area() + { + m_window_update(getDeviceArea()); + } + + void testSelect(DeviceVector position) + { + RadiantSelectionSystem::EModifier modifier = modifier_for_state(m_state); + if (modifier != RadiantSelectionSystem::eManipulator) { + DeviceVector delta(position - m_start); + if (fabs(delta.x()) > m_epsilon.x() && fabs(delta.y()) > m_epsilon.y()) { + DeviceVector delta(position - m_start); + getSelectionSystem().SelectArea(*m_view, &m_start[0], &delta[0], modifier, + (m_state & c_modifier_face) != c_modifierNone); + } else { + if (modifier == RadiantSelectionSystem::eReplace && m_unmoved_replaces++ > 0) { + modifier = RadiantSelectionSystem::eCycle; + } + getSelectionSystem().SelectPoint(*m_view, &position[0], &m_epsilon[0], modifier, + (m_state & c_modifier_face) != c_modifierNone); + } + } + + m_start = m_current = DeviceVector(0.0f, 0.0f); + draw_area(); + } + + bool selecting() const + { + return m_state != c_modifier_manipulator; + } + + void setState(ModifierFlags state) + { + bool was_selecting = selecting(); + m_state = state; + if (was_selecting ^ selecting()) { + draw_area(); + } + } + + ModifierFlags getState() const + { + return m_state; + } + + void modifierEnable(ModifierFlags type) + { + setState(bitfield_enable(getState(), type)); + } + + void modifierDisable(ModifierFlags type) + { + setState(bitfield_disable(getState(), type)); + } + + void mouseDown(DeviceVector position) + { + m_start = m_current = device_constrained(position); + } + + void mouseMoved(DeviceVector position) + { + m_current = device_constrained(position); + draw_area(); + } + + typedef MemberCaller MouseMovedCaller; + + void mouseUp(DeviceVector position) + { + testSelect(device_constrained(position)); + + g_mouseMovedCallback.clear(); + g_mouseUpCallback.clear(); + } + + typedef MemberCaller MouseUpCaller; +}; + + +class Manipulator_ { public: -DeviceVector m_epsilon; -const View* m_view; + DeviceVector m_epsilon; + const View *m_view; -bool mouseDown( DeviceVector position ){ - return getSelectionSystem().SelectManipulator( *m_view, &position[0], &m_epsilon[0] ); -} + bool mouseDown(DeviceVector position) + { + return getSelectionSystem().SelectManipulator(*m_view, &position[0], &m_epsilon[0]); + } -void mouseMoved( DeviceVector position ){ - getSelectionSystem().MoveSelected( *m_view, &position[0] ); -} -typedef MemberCaller MouseMovedCaller; + void mouseMoved(DeviceVector position) + { + getSelectionSystem().MoveSelected(*m_view, &position[0]); + } -void mouseUp( DeviceVector position ){ - getSelectionSystem().endMove(); - g_mouseMovedCallback.clear(); - g_mouseUpCallback.clear(); -} -typedef MemberCaller MouseUpCaller; -}; + typedef MemberCaller MouseMovedCaller; -void Scene_copyClosestTexture( SelectionTest& test ); -void Scene_applyClosestTexture( SelectionTest& test ); + void mouseUp(DeviceVector position) + { + getSelectionSystem().endMove(); + g_mouseMovedCallback.clear(); + g_mouseUpCallback.clear(); + } -class RadiantWindowObserver : public SelectionSystemWindowObserver -{ -enum -{ - SELECT_EPSILON = 8, + typedef MemberCaller MouseUpCaller; }; -int m_width; -int m_height; - -bool m_mouse_down; - -public: -Selector_ m_selector; -Manipulator_ m_manipulator; - -RadiantWindowObserver() : m_mouse_down( false ){ -} -void release(){ - delete this; -} -void setView( const View& view ){ - m_selector.m_view = &view; - m_manipulator.m_view = &view; -} -void setRectangleDrawCallback( const RectangleCallback& callback ){ - m_selector.m_window_update = callback; -} -void onSizeChanged( int width, int height ){ - m_width = width; - m_height = height; - DeviceVector epsilon( SELECT_EPSILON / static_cast( m_width ), SELECT_EPSILON / static_cast( m_height ) ); - m_selector.m_epsilon = m_manipulator.m_epsilon = epsilon; -} -void onMouseDown( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ){ - if ( button == c_button_select ) { - m_mouse_down = true; - - DeviceVector devicePosition( window_to_normalised_device( position, m_width, m_height ) ); - if ( modifiers == c_modifier_manipulator && m_manipulator.mouseDown( devicePosition ) ) { - g_mouseMovedCallback.insert( MouseEventCallback( Manipulator_::MouseMovedCaller( m_manipulator ) ) ); - g_mouseUpCallback.insert( MouseEventCallback( Manipulator_::MouseUpCaller( m_manipulator ) ) ); - } - else - { - m_selector.mouseDown( devicePosition ); - g_mouseMovedCallback.insert( MouseEventCallback( Selector_::MouseMovedCaller( m_selector ) ) ); - g_mouseUpCallback.insert( MouseEventCallback( Selector_::MouseUpCaller( m_selector ) ) ); - } - } - else if ( button == c_button_texture ) { - DeviceVector devicePosition( device_constrained( window_to_normalised_device( position, m_width, m_height ) ) ); - - View scissored( *m_selector.m_view ); - ConstructSelectionTest( scissored, SelectionBoxForPoint( &devicePosition[0], &m_selector.m_epsilon[0] ) ); - SelectionVolume volume( scissored ); - - if ( modifiers == c_modifier_apply_texture1 || modifiers == c_modifier_apply_texture2 || modifiers == c_modifier_apply_texture3 ) { - Scene_applyClosestTexture( volume ); - } - else if ( modifiers == c_modifier_copy_texture ) { - Scene_copyClosestTexture( volume ); - } - } -} -void onMouseMotion( const WindowVector& position, ModifierFlags modifiers ){ - m_selector.m_unmoved_replaces = 0; +void Scene_copyClosestTexture(SelectionTest &test); - if ( m_mouse_down && !g_mouseMovedCallback.empty() ) { - g_mouseMovedCallback.get() ( window_to_normalised_device( position, m_width, m_height ) ); - } -} -void onMouseUp( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ){ - if ( button == c_button_select && !g_mouseUpCallback.empty() ) { - m_mouse_down = false; +void Scene_applyClosestTexture(SelectionTest &test); - g_mouseUpCallback.get() ( window_to_normalised_device( position, m_width, m_height ) ); - } -} -void onModifierDown( ModifierFlags type ){ - m_selector.modifierEnable( type ); -} -void onModifierUp( ModifierFlags type ){ - m_selector.modifierDisable( type ); -} -}; +class RadiantWindowObserver : public SelectionSystemWindowObserver { + enum { + SELECT_EPSILON = 8, + }; + int m_width; + int m_height; + bool m_mouse_down; -SelectionSystemWindowObserver* NewWindowObserver(){ - return new RadiantWindowObserver; +public: + Selector_ m_selector; + Manipulator_ m_manipulator; + + RadiantWindowObserver() : m_mouse_down(false) + { + } + + void release() + { + delete this; + } + + void setView(const View &view) + { + m_selector.m_view = &view; + m_manipulator.m_view = &view; + } + + void setRectangleDrawCallback(const RectangleCallback &callback) + { + m_selector.m_window_update = callback; + } + + void onSizeChanged(int width, int height) + { + m_width = width; + m_height = height; + DeviceVector epsilon(SELECT_EPSILON / static_cast( m_width ), + SELECT_EPSILON / static_cast( m_height )); + m_selector.m_epsilon = m_manipulator.m_epsilon = epsilon; + } + + void onMouseDown(const WindowVector &position, ButtonIdentifier button, ModifierFlags modifiers) + { + if (button == c_button_select) { + m_mouse_down = true; + + DeviceVector devicePosition(window_to_normalised_device(position, m_width, m_height)); + if (modifiers == c_modifier_manipulator && m_manipulator.mouseDown(devicePosition)) { + g_mouseMovedCallback.insert(MouseEventCallback(Manipulator_::MouseMovedCaller(m_manipulator))); + g_mouseUpCallback.insert(MouseEventCallback(Manipulator_::MouseUpCaller(m_manipulator))); + } else { + m_selector.mouseDown(devicePosition); + g_mouseMovedCallback.insert(MouseEventCallback(Selector_::MouseMovedCaller(m_selector))); + g_mouseUpCallback.insert(MouseEventCallback(Selector_::MouseUpCaller(m_selector))); + } + } else if (button == c_button_texture) { + DeviceVector devicePosition(device_constrained(window_to_normalised_device(position, m_width, m_height))); + + View scissored(*m_selector.m_view); + ConstructSelectionTest(scissored, SelectionBoxForPoint(&devicePosition[0], &m_selector.m_epsilon[0])); + SelectionVolume volume(scissored); + + if (modifiers == c_modifier_apply_texture1 || modifiers == c_modifier_apply_texture2 || + modifiers == c_modifier_apply_texture3) { + Scene_applyClosestTexture(volume); + } else if (modifiers == c_modifier_copy_texture) { + Scene_copyClosestTexture(volume); + } + } + } + + void onMouseMotion(const WindowVector &position, ModifierFlags modifiers) + { + m_selector.m_unmoved_replaces = 0; + + if (m_mouse_down && !g_mouseMovedCallback.empty()) { + g_mouseMovedCallback.get()(window_to_normalised_device(position, m_width, m_height)); + } + } + + void onMouseUp(const WindowVector &position, ButtonIdentifier button, ModifierFlags modifiers) + { + if (button == c_button_select && !g_mouseUpCallback.empty()) { + m_mouse_down = false; + + g_mouseUpCallback.get()(window_to_normalised_device(position, m_width, m_height)); + } + } + + void onModifierDown(ModifierFlags type) + { + m_selector.modifierEnable(type); + } + + void onModifierUp(ModifierFlags type) + { + m_selector.modifierDisable(type); + } +}; + + +SelectionSystemWindowObserver *NewWindowObserver() +{ + return new RadiantWindowObserver; } - #include "modulesystem/singletonmodule.h" #include "modulesystem/moduleregistry.h" class SelectionDependencies : - public GlobalSceneGraphModuleRef, - public GlobalShaderCacheModuleRef, - public GlobalOpenGLModuleRef -{ + public GlobalSceneGraphModuleRef, + public GlobalShaderCacheModuleRef, + public GlobalOpenGLModuleRef { }; -class SelectionAPI : public TypeSystemRef -{ -SelectionSystem* m_selection; +class SelectionAPI : public TypeSystemRef { + SelectionSystem *m_selection; public: -typedef SelectionSystem Type; -STRING_CONSTANT( Name, "*" ); + typedef SelectionSystem Type; -SelectionAPI(){ - SelectionSystem_Construct(); + STRING_CONSTANT(Name, "*"); - m_selection = &getSelectionSystem(); -} -~SelectionAPI(){ - SelectionSystem_Destroy(); -} -SelectionSystem* getTable(){ - return m_selection; -} + SelectionAPI() + { + SelectionSystem_Construct(); + + m_selection = &getSelectionSystem(); + } + + ~SelectionAPI() + { + SelectionSystem_Destroy(); + } + + SelectionSystem *getTable() + { + return m_selection; + } }; typedef SingletonModule SelectionModule; typedef Static StaticSelectionModule; -StaticRegisterModule staticRegisterSelection( StaticSelectionModule::instance() ); +StaticRegisterModule staticRegisterSelection(StaticSelectionModule::instance()); diff --git a/radiant/selection.h b/radiant/selection.h index 99846fed..b15ff93c 100644 --- a/radiant/selection.h +++ b/radiant/selection.h @@ -25,31 +25,31 @@ #include "windowobserver.h" #include "generic/callback.h" -struct rect_t -{ - float min[2]; - float max[2]; +struct rect_t { + float min[2]; + float max[2]; }; typedef Callback RectangleCallback; class View; -class SelectionSystemWindowObserver : public WindowObserver -{ +class SelectionSystemWindowObserver : public WindowObserver { public: -virtual ~SelectionSystemWindowObserver() = default; -virtual void setView( const View& view ) = 0; -virtual void setRectangleDrawCallback( const RectangleCallback& callback ) = 0; + virtual ~SelectionSystemWindowObserver() = default; + + virtual void setView(const View &view) = 0; + + virtual void setRectangleDrawCallback(const RectangleCallback &callback) = 0; }; -SelectionSystemWindowObserver* NewWindowObserver(); +SelectionSystemWindowObserver *NewWindowObserver(); class AABB; -namespace scene -{ -class Graph; +namespace scene { + class Graph; } -void Scene_BoundsSelected( scene::Graph& graph, AABB& bounds ); + +void Scene_BoundsSelected(scene::Graph &graph, AABB &bounds); #endif diff --git a/radiant/server.cpp b/radiant/server.cpp index 2a264e6d..718a0a29 100644 --- a/radiant/server.cpp +++ b/radiant/server.cpp @@ -31,61 +31,71 @@ #include "modulesystem.h" -class RadiantModuleServer : public ModuleServer -{ -typedef std::pair ModuleType; -typedef std::pair ModuleKey; -typedef std::map Modules_; -Modules_ m_modules; -bool m_error; +class RadiantModuleServer : public ModuleServer { + typedef std::pair ModuleType; + typedef std::pair ModuleKey; + typedef std::map Modules_; + Modules_ m_modules; + bool m_error; public: -RadiantModuleServer() : m_error( false ){ -} - -void setError( bool error ){ - m_error = error; -} -bool getError() const { - return m_error; -} - -TextOutputStream& getOutputStream(){ - return globalOutputStream(); -} -TextOutputStream& getErrorStream(){ - return globalErrorStream(); -} -DebugMessageHandler& getDebugMessageHandler(){ - return globalDebugMessageHandler(); -} - -void registerModule( const char* type, int version, const char* name, Module& module ){ - if ( !m_modules.insert( Modules_::value_type( ModuleKey( ModuleType( type, version ), name ), &module ) ).second ) { - globalErrorStream() << "module already registered: type=" << makeQuoted( type ) << " name=" << makeQuoted( name ) << "\n"; - } - else - { - globalOutputStream() << "Module Registered: type=" << makeQuoted( type ) << " version=" << makeQuoted( version ) << " name=" << makeQuoted( name ) << "\n"; - } -} - -Module* findModule( const char* type, int version, const char* name ) const { - Modules_::const_iterator i = m_modules.find( ModuleKey( ModuleType( type, version ), name ) ); - if ( i != m_modules.end() ) { - return ( *i ).second; - } - return 0; -} - -void foreachModule( const char* type, int version, const Visitor& visitor ){ - for ( Modules_::const_iterator i = m_modules.begin(); i != m_modules.end(); ++i ) - { - if ( string_equal( ( *i ).first.first.first.c_str(), type ) ) { - visitor.visit( ( *i ).first.second.c_str(), *( *i ).second ); - } - } -} + RadiantModuleServer() : m_error(false) + { + } + + void setError(bool error) + { + m_error = error; + } + + bool getError() const + { + return m_error; + } + + TextOutputStream &getOutputStream() + { + return globalOutputStream(); + } + + TextOutputStream &getErrorStream() + { + return globalErrorStream(); + } + + DebugMessageHandler &getDebugMessageHandler() + { + return globalDebugMessageHandler(); + } + + void registerModule(const char *type, int version, const char *name, Module &module) + { + if (!m_modules.insert(Modules_::value_type(ModuleKey(ModuleType(type, version), name), &module)).second) { + globalErrorStream() << "module already registered: type=" << makeQuoted(type) << " name=" + << makeQuoted(name) << "\n"; + } else { + globalOutputStream() << "Module Registered: type=" << makeQuoted(type) << " version=" << makeQuoted(version) + << " name=" << makeQuoted(name) << "\n"; + } + } + + Module *findModule(const char *type, int version, const char *name) const + { + Modules_::const_iterator i = m_modules.find(ModuleKey(ModuleType(type, version), name)); + if (i != m_modules.end()) { + return (*i).second; + } + return 0; + } + + void foreachModule(const char *type, int version, const Visitor &visitor) + { + for (Modules_::const_iterator i = m_modules.begin(); i != m_modules.end(); ++i) { + if (string_equal((*i).first.first.first.c_str(), type)) { + visitor.visit((*i).first.second.c_str(), *(*i).second); + } + } + } }; @@ -95,18 +105,18 @@ void foreachModule( const char* type, int version, const Visitor& visitor ){ const int FORMAT_BUFSIZE = 2048; const char* FormatGetLastError(){ - static char buf[FORMAT_BUFSIZE]; - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language - buf, - FORMAT_BUFSIZE, - NULL - ); - return buf; + static char buf[FORMAT_BUFSIZE]; + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language + buf, + FORMAT_BUFSIZE, + NULL + ); + return buf; } class DynamicLibrary @@ -116,27 +126,27 @@ public: typedef int ( __stdcall * FunctionPointer )(); DynamicLibrary( const char* filename ){ - m_library = LoadLibrary( filename ); - if ( m_library == 0 ) { - globalErrorStream() << "LoadLibrary failed: '" << filename << "'\n"; - globalErrorStream() << "GetLastError: " << FormatGetLastError(); - } + m_library = LoadLibrary( filename ); + if ( m_library == 0 ) { + globalErrorStream() << "LoadLibrary failed: '" << filename << "'\n"; + globalErrorStream() << "GetLastError: " << FormatGetLastError(); + } } ~DynamicLibrary(){ - if ( !failed() ) { - FreeLibrary( m_library ); - } + if ( !failed() ) { + FreeLibrary( m_library ); + } } bool failed(){ - return m_library == 0; + return m_library == 0; } FunctionPointer findSymbol( const char* symbol ){ - FunctionPointer address = (FunctionPointer) GetProcAddress( m_library, symbol ); - if ( address == 0 ) { - globalErrorStream() << "GetProcAddress failed: '" << symbol << "'\n"; - globalErrorStream() << "GetLastError: " << FormatGetLastError(); - } - return address; + FunctionPointer address = (FunctionPointer) GetProcAddress( m_library, symbol ); + if ( address == 0 ) { + globalErrorStream() << "GetProcAddress failed: '" << symbol << "'\n"; + globalErrorStream() << "GetLastError: " << FormatGetLastError(); + } + return address; } }; @@ -145,109 +155,128 @@ FunctionPointer findSymbol( const char* symbol ){ #include class DynamicLibrary { - void *m_library; + void *m_library; public: -typedef int ( *FunctionPointer )(); - -DynamicLibrary( const char* filename ){ - m_library = dlopen( filename, RTLD_NOW ); -} -~DynamicLibrary(){ - if ( !failed() ) { - dlclose( m_library ); - } -} -bool failed(){ - return m_library == 0; -} -FunctionPointer findSymbol( const char* symbol ){ - FunctionPointer p = (FunctionPointer)dlsym( m_library, symbol ); - if ( p == 0 ) { - const char* error = reinterpret_cast( dlerror() ); - if ( error != 0 ) { - globalErrorStream() << error; - } - } - return p; -} + typedef int ( *FunctionPointer )(); + + DynamicLibrary(const char *filename) + { + m_library = dlopen(filename, RTLD_NOW); + } + + ~DynamicLibrary() + { + if (!failed()) { + dlclose(m_library); + } + } + + bool failed() + { + return m_library == 0; + } + + FunctionPointer findSymbol(const char *symbol) + { + FunctionPointer p = (FunctionPointer) dlsym(m_library, symbol); + if (p == 0) { + const char *error = reinterpret_cast( dlerror()); + if (error != 0) { + globalErrorStream() << error; + } + } + return p; + } }; #else #error "unsupported platform" #endif -class DynamicLibraryModule -{ -typedef void ( RADIANT_DLLIMPORT * RegisterModulesFunc )( ModuleServer& server ); -DynamicLibrary m_library; -RegisterModulesFunc m_registerModule; +class DynamicLibraryModule { + typedef void ( RADIANT_DLLIMPORT *RegisterModulesFunc )(ModuleServer &server); + + DynamicLibrary m_library; + RegisterModulesFunc m_registerModule; public: -DynamicLibraryModule( const char* filename ) - : m_library( filename ), m_registerModule( 0 ){ - if ( !m_library.failed() ) { - m_registerModule = reinterpret_cast( m_library.findSymbol( "Radiant_RegisterModules" ) ); + DynamicLibraryModule(const char *filename) + : m_library(filename), m_registerModule(0) + { + if (!m_library.failed()) { + m_registerModule = reinterpret_cast( m_library.findSymbol("Radiant_RegisterModules")); #if 0 - if ( !m_registerModule ) { - m_registerModule = reinterpret_cast( m_library.findSymbol( "Radiant_RegisterModules@4" ) ); - } + if ( !m_registerModule ) { + m_registerModule = reinterpret_cast( m_library.findSymbol( "Radiant_RegisterModules@4" ) ); + } #endif - } -} -bool failed(){ - return m_registerModule == 0; -} -void registerModules( ModuleServer& server ){ - m_registerModule( server ); -} + } + } + + bool failed() + { + return m_registerModule == 0; + } + + void registerModules(ModuleServer &server) + { + m_registerModule(server); + } }; -class Libraries -{ -typedef std::vector libraries_t; -libraries_t m_libraries; +class Libraries { + typedef std::vector libraries_t; + libraries_t m_libraries; public: -~Libraries(){ - release(); -} -void registerLibrary( const char* filename, ModuleServer& server ){ - DynamicLibraryModule* library = new DynamicLibraryModule( filename ); - - if ( library->failed() ) { - delete library; - } - else - { - m_libraries.push_back( library ); - library->registerModules( server ); - } -} -void release(){ - for ( libraries_t::iterator i = m_libraries.begin(); i != m_libraries.end(); ++i ) - { - delete *i; - } -} -void clear(){ - m_libraries.clear(); -} + ~Libraries() + { + release(); + } + + void registerLibrary(const char *filename, ModuleServer &server) + { + DynamicLibraryModule *library = new DynamicLibraryModule(filename); + + if (library->failed()) { + delete library; + } else { + m_libraries.push_back(library); + library->registerModules(server); + } + } + + void release() + { + for (libraries_t::iterator i = m_libraries.begin(); i != m_libraries.end(); ++i) { + delete *i; + } + } + + void clear() + { + m_libraries.clear(); + } }; Libraries g_libraries; RadiantModuleServer g_server; -ModuleServer& GlobalModuleServer_get(){ - return g_server; +ModuleServer &GlobalModuleServer_get() +{ + return g_server; } -void GlobalModuleServer_loadModule( const char* filename ){ - g_libraries.registerLibrary( filename, g_server ); +void GlobalModuleServer_loadModule(const char *filename) +{ + g_libraries.registerLibrary(filename, g_server); } -void GlobalModuleServer_Initialise(){ +void GlobalModuleServer_Initialise() +{ } -void GlobalModuleServer_Shutdown(){ +void GlobalModuleServer_Shutdown() +{ } diff --git a/radiant/server.h b/radiant/server.h index 2e29a804..c54b9d2b 100644 --- a/radiant/server.h +++ b/radiant/server.h @@ -23,9 +23,13 @@ #define INCLUDED_SERVER_H class ModuleServer; -ModuleServer& GlobalModuleServer_get(); -void GlobalModuleServer_loadModule( const char* filename ); + +ModuleServer &GlobalModuleServer_get(); + +void GlobalModuleServer_loadModule(const char *filename); + void GlobalModuleServer_Initialise(); + void GlobalModuleServer_Shutdown(); #endif diff --git a/radiant/shaders.cpp b/radiant/shaders.cpp index d6748c07..aec784ad 100644 --- a/radiant/shaders.cpp +++ b/radiant/shaders.cpp @@ -27,45 +27,45 @@ #include "gtkdlgs.h" -void ViewShader( const char *pFile, const char *pName ){ - char* pBuff = 0; - //int nSize = - vfsLoadFile( pFile, reinterpret_cast( &pBuff ) ); - if ( pBuff == 0 ) { - globalErrorStream() << "Failed to load shader file " << pFile << "\n"; - return; - } - // look for the shader declaration - StringOutputStream strFind( string_length( pName ) ); - strFind << LowerCase( pName ); - StringOutputStream strLook( string_length( pBuff ) ); - strFind << LowerCase( pBuff ); - // offset used when jumping over commented out definitions - std::size_t nOffset = 0; - while ( true ) - { - const char* substr = strstr( strFind.c_str() + nOffset, strFind.c_str() ); - if ( substr == 0 ) { - break; - } - std::size_t nStart = substr - strLook.c_str(); - // we have found something, maybe it's a commented out shader name? - char *strCheck = new char[string_length( strLook.c_str() ) + 1]; - strcpy( strCheck, strLook.c_str() ); - strCheck[nStart] = 0; - char *pCheck = strrchr( strCheck, '\n' ); - // if there's a commentary sign in-between we'll continue - if ( pCheck && strstr( pCheck, "//" ) ) { - delete[] strCheck; - nOffset = nStart + 1; - continue; - } - delete[] strCheck; - nOffset = nStart; - break; - } - // now close the file - vfsFreeFile( pBuff ); +void ViewShader(const char *pFile, const char *pName) +{ + char *pBuff = 0; + //int nSize = + vfsLoadFile(pFile, reinterpret_cast( &pBuff )); + if (pBuff == 0) { + globalErrorStream() << "Failed to load shader file " << pFile << "\n"; + return; + } + // look for the shader declaration + StringOutputStream strFind(string_length(pName)); + strFind << LowerCase(pName); + StringOutputStream strLook(string_length(pBuff)); + strFind << LowerCase(pBuff); + // offset used when jumping over commented out definitions + std::size_t nOffset = 0; + while (true) { + const char *substr = strstr(strFind.c_str() + nOffset, strFind.c_str()); + if (substr == 0) { + break; + } + std::size_t nStart = substr - strLook.c_str(); + // we have found something, maybe it's a commented out shader name? + char *strCheck = new char[string_length(strLook.c_str()) + 1]; + strcpy(strCheck, strLook.c_str()); + strCheck[nStart] = 0; + char *pCheck = strrchr(strCheck, '\n'); + // if there's a commentary sign in-between we'll continue + if (pCheck && strstr(pCheck, "//")) { + delete[] strCheck; + nOffset = nStart + 1; + continue; + } + delete[] strCheck; + nOffset = nStart; + break; + } + // now close the file + vfsFreeFile(pBuff); - DoTextEditor( pFile, static_cast( nOffset ) ); + DoTextEditor(pFile, static_cast( nOffset )); } diff --git a/radiant/shaders.h b/radiant/shaders.h index 6cf0ec85..7c6bd2b9 100644 --- a/radiant/shaders.h +++ b/radiant/shaders.h @@ -22,6 +22,6 @@ #if !defined( INCLUDED_SHADERS_H ) #define INCLUDED_SHADERS_H -void ViewShader( const char* file, const char* shader ); +void ViewShader(const char *file, const char *shader); #endif diff --git a/radiant/sockets.cpp b/radiant/sockets.cpp index d2a27d7e..cf5d2dd7 100644 --- a/radiant/sockets.cpp +++ b/radiant/sockets.cpp @@ -4,7 +4,9 @@ #if GDEF_OS_WINDOWS #include #elif GDEF_OS_POSIX + #include + const int SOCKET_ERROR = -1; #else #error "unsupported platform" @@ -14,32 +16,32 @@ const int SOCKET_ERROR = -1; #include #endif -int Net_Wait( socket_t *sock, long sec, long usec ){ +int Net_Wait(socket_t *sock, long sec, long usec) +{ // used for select() #if GDEF_OS_WINDOWS - TIMEVAL tout = { sec, usec }; + TIMEVAL tout = { sec, usec }; #endif #if GDEF_OS_POSIX - timeval tout; - tout.tv_sec = sec; - tout.tv_usec = usec; + timeval tout; + tout.tv_sec = sec; + tout.tv_usec = usec; #endif - // select() will identify if the socket needs an update - // if the socket is identified that means there's either a message or the connection has been closed/reset/terminated - fd_set readfds; - FD_ZERO( &readfds ); - FD_SET( ( (unsigned int)sock->socket ), &readfds ); - // from select man page: - // n is the highest-numbered descriptor in any of the three sets, plus 1 - // (no use on windows) - switch ( select( sock->socket + 1, &readfds, 0, 0, &tout ) ) - { - case SOCKET_ERROR: - return -1; - case 0: - return 0; - default: - return 1; - } + // select() will identify if the socket needs an update + // if the socket is identified that means there's either a message or the connection has been closed/reset/terminated + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(((unsigned int) sock->socket), &readfds); + // from select man page: + // n is the highest-numbered descriptor in any of the three sets, plus 1 + // (no use on windows) + switch (select(sock->socket + 1, &readfds, 0, 0, &tout)) { + case SOCKET_ERROR: + return -1; + case 0: + return 0; + default: + return 1; + } } diff --git a/radiant/sockets.h b/radiant/sockets.h index 434a3699..2ab62647 100644 --- a/radiant/sockets.h +++ b/radiant/sockets.h @@ -9,6 +9,6 @@ // -1: error // 0: timeout // 1: ready -int Net_Wait( socket_t *sock, long sec, long usec ); +int Net_Wait(socket_t *sock, long sec, long usec); #endif diff --git a/radiant/stacktrace.cpp b/radiant/stacktrace.cpp index 5e638574..e2d383f5 100644 --- a/radiant/stacktrace.cpp +++ b/radiant/stacktrace.cpp @@ -27,29 +27,33 @@ #include "environment.h" #if GDEF_OS_LINUX -#include - -void write_stack_trace( TextOutputStream& outputStream ){ - const unsigned int MAX_SYMBOLS = 256; - void* symbols[MAX_SYMBOLS]; - - // get return addresses - int symbol_count = backtrace( symbols, MAX_SYMBOLS ); - if ( !symbol_count ) { - return; - } - - // resolve and print names - char** symbol_names = backtrace_symbols( symbols, symbol_count ); - if ( symbol_names ) { - for ( int i = 0; ( i < symbol_count ); ++i ) - outputStream << symbol_names[i] << "\n"; +#include - // not a memleak, see www.gnu.org/software/libc/manual (Debugging Support, Backtraces) - free( symbol_names ); - } +void write_stack_trace(TextOutputStream &outputStream) +{ + const unsigned int MAX_SYMBOLS = 256; + void *symbols[MAX_SYMBOLS]; + + // get return addresses + int symbol_count = backtrace(symbols, MAX_SYMBOLS); + + if (!symbol_count) { + return; + } + + // resolve and print names + char **symbol_names = backtrace_symbols(symbols, symbol_count); + if (symbol_names) { + for (int i = 0; (i < symbol_count); ++i) { + outputStream << symbol_names[i] << "\n"; + } + + // not a memleak, see www.gnu.org/software/libc/manual (Debugging Support, Backtraces) + free(symbol_names); + } } + #elif GDEF_COMPILER_MSVC #include "windows.h" @@ -67,10 +71,10 @@ Address( void* value ) : m_value( value ){ /// \brief Writes an address \p p to \p ostream in hexadecimal form. template inline TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const Address& p ){ - const std::size_t bufferSize = ( sizeof( void* ) * 2 ) + 1; - char buf[bufferSize]; - ostream.write( buf, snprintf( buf, bufferSize, "%0p", p.m_value ) ); - return ostream; + const std::size_t bufferSize = ( sizeof( void* ) * 2 ) + 1; + char buf[bufferSize]; + ostream.write( buf, snprintf( buf, bufferSize, "%0p", p.m_value ) ); + return ostream; } class Offset @@ -84,218 +88,218 @@ Offset( void* value ) : m_value( value ){ /// \brief Writes an address \p p to \p ostream in hexadecimal form. template inline TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const Offset& p ){ - const std::size_t bufferSize = ( sizeof( void* ) * 2 ) + 1; - char buf[bufferSize]; - ostream.write( buf, snprintf( buf, bufferSize, "%X", p.m_value ) ); - return ostream; + const std::size_t bufferSize = ( sizeof( void* ) * 2 ) + 1; + char buf[bufferSize]; + ostream.write( buf, snprintf( buf, bufferSize, "%X", p.m_value ) ); + return ostream; } /// \brief Writes a WCHAR string \p s to \p ostream. template inline TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const WCHAR* s ){ - const std::size_t bufferSize = 1024; - char buf[bufferSize]; - ostream.write( buf, snprintf( buf, bufferSize, "%ls", s ) ); - return ostream; + const std::size_t bufferSize = 1024; + char buf[bufferSize]; + ostream.write( buf, snprintf( buf, bufferSize, "%ls", s ) ); + return ostream; } struct EnumerateSymbolsContext { - STACKFRAME64& sf; - TextOutputStream& outputStream; - std::size_t count; - EnumerateSymbolsContext( STACKFRAME64& sf, TextOutputStream& outputStream ) : sf( sf ), outputStream( outputStream ), count( 0 ){ - } + STACKFRAME64& sf; + TextOutputStream& outputStream; + std::size_t count; + EnumerateSymbolsContext( STACKFRAME64& sf, TextOutputStream& outputStream ) : sf( sf ), outputStream( outputStream ), count( 0 ){ + } }; void write_symbol( PSYMBOL_INFO pSym, STACKFRAME64& sf, TextOutputStream& outputStream, std::size_t& count ){ #if 0 - if ( pSym->Flags & SYMFLAG_PARAMETER ) { - - DWORD basicType; - if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, pSym->TypeIndex, - TI_GET_BASETYPE, &basicType ) ) { - int bleh = 0; - } - else - { - DWORD typeId; - if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, pSym->TypeIndex, - TI_GET_TYPEID, &typeId ) ) { - if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, pSym->TypeIndex, - TI_GET_BASETYPE, &basicType ) ) { - int bleh = 0; - } - else - { - const char* FormatGetLastError(); - const char* error = FormatGetLastError(); - int bleh = 0; - - WCHAR* name; - if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, typeId, - TI_GET_SYMNAME, &name ) ) { - outputStream << name << " "; - LocalFree( name ); - int bleh = 0; - } - else - { - const char* FormatGetLastError(); - const char* error = FormatGetLastError(); - int bleh = 0; - } - } - } - else - { - const char* FormatGetLastError(); - const char* error = FormatGetLastError(); - int bleh = 0; - } - } - if ( count != 0 ) { - outputStream << ", "; - } - outputStream << pSym->Name; - ++count; - } + if ( pSym->Flags & SYMFLAG_PARAMETER ) { + + DWORD basicType; + if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, pSym->TypeIndex, + TI_GET_BASETYPE, &basicType ) ) { + int bleh = 0; + } + else + { + DWORD typeId; + if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, pSym->TypeIndex, + TI_GET_TYPEID, &typeId ) ) { + if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, pSym->TypeIndex, + TI_GET_BASETYPE, &basicType ) ) { + int bleh = 0; + } + else + { + const char* FormatGetLastError(); + const char* error = FormatGetLastError(); + int bleh = 0; + + WCHAR* name; + if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, typeId, + TI_GET_SYMNAME, &name ) ) { + outputStream << name << " "; + LocalFree( name ); + int bleh = 0; + } + else + { + const char* FormatGetLastError(); + const char* error = FormatGetLastError(); + int bleh = 0; + } + } + } + else + { + const char* FormatGetLastError(); + const char* error = FormatGetLastError(); + int bleh = 0; + } + } + if ( count != 0 ) { + outputStream << ", "; + } + outputStream << pSym->Name; + ++count; + } #endif } BOOL CALLBACK EnumerateSymbolsCallback( - PSYMBOL_INFO pSymInfo, - ULONG SymbolSize, - PVOID UserContext ){ - write_symbol( pSymInfo, ( (EnumerateSymbolsContext*)UserContext )->sf, ( (EnumerateSymbolsContext*)UserContext )->outputStream, ( (EnumerateSymbolsContext*)UserContext )->count ); + PSYMBOL_INFO pSymInfo, + ULONG SymbolSize, + PVOID UserContext ){ + write_symbol( pSymInfo, ( (EnumerateSymbolsContext*)UserContext )->sf, ( (EnumerateSymbolsContext*)UserContext )->outputStream, ( (EnumerateSymbolsContext*)UserContext )->count ); - return TRUE; + return TRUE; } void write_stack_trace( PCONTEXT pContext, TextOutputStream& outputStream ){ - HANDLE m_hProcess = GetCurrentProcess(); - DWORD dwMachineType = 0; + HANDLE m_hProcess = GetCurrentProcess(); + DWORD dwMachineType = 0; - CONTEXT context = *pContext; + CONTEXT context = *pContext; - // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag - if ( !SymInitialize( m_hProcess, (PSTR)environment_get_app_path(), TRUE ) ) { - return; - } + // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag + if ( !SymInitialize( m_hProcess, (PSTR)environment_get_app_path(), TRUE ) ) { + return; + } - STACKFRAME64 sf; - memset( &sf, 0, sizeof( sf ) ); - sf.AddrPC.Mode = AddrModeFlat; - sf.AddrStack.Mode = AddrModeFlat; - sf.AddrFrame.Mode = AddrModeFlat; + STACKFRAME64 sf; + memset( &sf, 0, sizeof( sf ) ); + sf.AddrPC.Mode = AddrModeFlat; + sf.AddrStack.Mode = AddrModeFlat; + sf.AddrFrame.Mode = AddrModeFlat; #ifdef _M_IX86 - // Initialize the STACKFRAME structure for the first call. This is only - // necessary for Intel CPUs, and isn't mentioned in the documentation. - sf.AddrPC.Offset = context.Eip; - sf.AddrStack.Offset = context.Esp; - sf.AddrFrame.Offset = context.Ebp; + // Initialize the STACKFRAME structure for the first call. This is only + // necessary for Intel CPUs, and isn't mentioned in the documentation. + sf.AddrPC.Offset = context.Eip; + sf.AddrStack.Offset = context.Esp; + sf.AddrFrame.Offset = context.Ebp; - dwMachineType = IMAGE_FILE_MACHINE_I386; + dwMachineType = IMAGE_FILE_MACHINE_I386; #elif _M_X64 - sf.AddrPC.Offset = context.Rip; - sf.AddrStack.Offset = context.Rsp; + sf.AddrPC.Offset = context.Rip; + sf.AddrStack.Offset = context.Rsp; - // MSDN: x64: The frame pointer is RBP or RDI. This value is not always used. - // very funny, we'll try Rdi for now - sf.AddrFrame.Offset = context.Rdi; + // MSDN: x64: The frame pointer is RBP or RDI. This value is not always used. + // very funny, we'll try Rdi for now + sf.AddrFrame.Offset = context.Rdi; - dwMachineType = IMAGE_FILE_MACHINE_AMD64; + dwMachineType = IMAGE_FILE_MACHINE_AMD64; #endif - const unsigned int max_sym_name = 1024; // should be enough - - while ( 1 ) - { - // Get the next stack frame - if ( !StackWalk64( dwMachineType, - m_hProcess, - GetCurrentThread(), - &sf, - &context, - 0, - SymFunctionTableAccess64, - SymGetModuleBase64, - 0 ) ) { - break; - } - - if ( 0 == sf.AddrFrame.Offset ) { // Basic sanity check to make sure - break; // the frame is OK. Bail if not. - - } - // Get the name of the function for this stack frame entry - BYTE symbolBuffer[ sizeof( SYMBOL_INFO ) + max_sym_name ]; - PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer; - pSymbol->SizeOfStruct = sizeof( SYMBOL_INFO ); - pSymbol->MaxNameLen = max_sym_name; - - DWORD64 symDisplacement = 0; // Displacement of the input address, - // relative to the start of the symbol - - IMAGEHLP_MODULE64 module = { sizeof( IMAGEHLP_MODULE64 ) }; - if ( SymGetModuleInfo64( m_hProcess, sf.AddrPC.Offset, &module ) ) { - outputStream << module.ModuleName << "!"; - - if ( SymFromAddr( m_hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol ) ) { - char undecoratedName[max_sym_name]; - UnDecorateSymbolName( pSymbol->Name, undecoratedName, max_sym_name, UNDNAME_COMPLETE ); - - outputStream << undecoratedName; - - outputStream << "("; - // Use SymSetContext to get just the locals/params for this frame - IMAGEHLP_STACK_FRAME imagehlpStackFrame; - imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; - SymSetContext( m_hProcess, &imagehlpStackFrame, 0 ); - - // Enumerate the locals/parameters - EnumerateSymbolsContext context( sf, outputStream ); - SymEnumSymbols( m_hProcess, 0, 0, EnumerateSymbolsCallback, &context ); - outputStream << ")"; - - outputStream << " + " << Offset( reinterpret_cast( symDisplacement ) ); - - // Get the source line for this stack frame entry - IMAGEHLP_LINE64 lineInfo = { sizeof( IMAGEHLP_LINE64 ) }; - DWORD dwLineDisplacement; - if ( SymGetLineFromAddr64( m_hProcess, sf.AddrPC.Offset, - &dwLineDisplacement, &lineInfo ) ) { - outputStream << " " << lineInfo.FileName << " line " << Unsigned( lineInfo.LineNumber ); - } - } - else - { - outputStream << Address( reinterpret_cast( sf.AddrPC.Offset ) ); - } - } - - outputStream << "\n"; - } - - SymCleanup( m_hProcess ); - - return; + const unsigned int max_sym_name = 1024; // should be enough + + while ( 1 ) + { + // Get the next stack frame + if ( !StackWalk64( dwMachineType, + m_hProcess, + GetCurrentThread(), + &sf, + &context, + 0, + SymFunctionTableAccess64, + SymGetModuleBase64, + 0 ) ) { + break; + } + + if ( 0 == sf.AddrFrame.Offset ) { // Basic sanity check to make sure + break; // the frame is OK. Bail if not. + + } + // Get the name of the function for this stack frame entry + BYTE symbolBuffer[ sizeof( SYMBOL_INFO ) + max_sym_name ]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer; + pSymbol->SizeOfStruct = sizeof( SYMBOL_INFO ); + pSymbol->MaxNameLen = max_sym_name; + + DWORD64 symDisplacement = 0; // Displacement of the input address, + // relative to the start of the symbol + + IMAGEHLP_MODULE64 module = { sizeof( IMAGEHLP_MODULE64 ) }; + if ( SymGetModuleInfo64( m_hProcess, sf.AddrPC.Offset, &module ) ) { + outputStream << module.ModuleName << "!"; + + if ( SymFromAddr( m_hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol ) ) { + char undecoratedName[max_sym_name]; + UnDecorateSymbolName( pSymbol->Name, undecoratedName, max_sym_name, UNDNAME_COMPLETE ); + + outputStream << undecoratedName; + + outputStream << "("; + // Use SymSetContext to get just the locals/params for this frame + IMAGEHLP_STACK_FRAME imagehlpStackFrame; + imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; + SymSetContext( m_hProcess, &imagehlpStackFrame, 0 ); + + // Enumerate the locals/parameters + EnumerateSymbolsContext context( sf, outputStream ); + SymEnumSymbols( m_hProcess, 0, 0, EnumerateSymbolsCallback, &context ); + outputStream << ")"; + + outputStream << " + " << Offset( reinterpret_cast( symDisplacement ) ); + + // Get the source line for this stack frame entry + IMAGEHLP_LINE64 lineInfo = { sizeof( IMAGEHLP_LINE64 ) }; + DWORD dwLineDisplacement; + if ( SymGetLineFromAddr64( m_hProcess, sf.AddrPC.Offset, + &dwLineDisplacement, &lineInfo ) ) { + outputStream << " " << lineInfo.FileName << " line " << Unsigned( lineInfo.LineNumber ); + } + } + else + { + outputStream << Address( reinterpret_cast( sf.AddrPC.Offset ) ); + } + } + + outputStream << "\n"; + } + + SymCleanup( m_hProcess ); + + return; } void write_stack_trace( TextOutputStream& outputStream ){ - __try { RaiseException( 0,0,0,0 ); } __except( write_stack_trace( ( GetExceptionInformation() )->ContextRecord, outputStream ), EXCEPTION_CONTINUE_EXECUTION ) { - } + __try { RaiseException( 0,0,0,0 ); } __except( write_stack_trace( ( GetExceptionInformation() )->ContextRecord, outputStream ), EXCEPTION_CONTINUE_EXECUTION ) { + } } #elif GDEF_OS_WINDOWS void write_stack_trace( TextOutputStream& outputStream ){ - outputStream << "\nStacktrace is disabled on this compiler\n"; + outputStream << "\nStacktrace is disabled on this compiler\n"; } #else void write_stack_trace( TextOutputStream& outputStream ){ - outputStream << "\nStacktrace is disabled on this platform\n"; + outputStream << "\nStacktrace is disabled on this platform\n"; } #endif diff --git a/radiant/stacktrace.h b/radiant/stacktrace.h index ddbe3a71..8475cebe 100644 --- a/radiant/stacktrace.h +++ b/radiant/stacktrace.h @@ -23,6 +23,7 @@ #define INCLUDED_STACKTRACE_H class TextOutputStream; -void write_stack_trace( TextOutputStream& outputStream ); + +void write_stack_trace(TextOutputStream &outputStream); #endif diff --git a/radiant/surfacedialog.cpp b/radiant/surfacedialog.cpp index f4471578..b9926714 100644 --- a/radiant/surfacedialog.cpp +++ b/radiant/surfacedialog.cpp @@ -98,259 +98,293 @@ ui::Widget g_textoolWin; //End Textool globals void queueDraw(){ - gtk_widget_queue_draw( g_textoolWin ); + gtk_widget_queue_draw( g_textoolWin ); } } #endif -inline void spin_button_set_step( ui::SpinButton spin, gfloat step ){ +inline void spin_button_set_step(ui::SpinButton spin, gfloat step) +{ #if 1 - gtk_adjustment_set_step_increment(gtk_spin_button_get_adjustment( spin ), step); + gtk_adjustment_set_step_increment(gtk_spin_button_get_adjustment(spin), step); #else - GValue gvalue = GValue_default(); - g_value_init( &gvalue, G_TYPE_DOUBLE ); - g_value_set_double( &gvalue, step ); - g_object_set( G_OBJECT( gtk_spin_button_get_adjustment( spin ) ), "step-increment", &gvalue, NULL ); + GValue gvalue = GValue_default(); + g_value_init( &gvalue, G_TYPE_DOUBLE ); + g_value_set_double( &gvalue, step ); + g_object_set( G_OBJECT( gtk_spin_button_get_adjustment( spin ) ), "step-increment", &gvalue, NULL ); #endif } -class Increment -{ -float& m_f; +class Increment { + float &m_f; public: -ui::SpinButton m_spin; -ui::Entry m_entry; -Increment( float& f ) : m_f( f ), m_spin( ui::null ), m_entry( ui::null ){ -} -void cancel(){ - entry_set_float( m_entry, m_f ); -} -typedef MemberCaller CancelCaller; -void apply(){ - m_f = static_cast( entry_get_float( m_entry ) ); - spin_button_set_step( m_spin, m_f ); -} -typedef MemberCaller ApplyCaller; + ui::SpinButton m_spin; + ui::Entry m_entry; + + Increment(float &f) : m_f(f), m_spin(ui::null), m_entry(ui::null) + { + } + + void cancel() + { + entry_set_float(m_entry, m_f); + } + + typedef MemberCaller CancelCaller; + + void apply() + { + m_f = static_cast( entry_get_float(m_entry)); + spin_button_set_step(m_spin, m_f); + } + + typedef MemberCaller ApplyCaller; }; void SurfaceInspector_GridChange(); -class SurfaceInspector : public Dialog -{ -ui::Window BuildDialog(); - -NonModalEntry m_textureEntry; -NonModalSpinner m_hshiftSpinner; -NonModalEntry m_hshiftEntry; -NonModalSpinner m_vshiftSpinner; -NonModalEntry m_vshiftEntry; -NonModalSpinner m_hscaleSpinner; -NonModalEntry m_hscaleEntry; -NonModalSpinner m_vscaleSpinner; -NonModalEntry m_vscaleEntry; -NonModalSpinner m_rotateSpinner; -NonModalEntry m_rotateEntry; - -IdleDraw m_idleDraw; - -GtkCheckButton* m_surfaceFlags[32]; -GtkCheckButton* m_contentFlags[32]; - -NonModalEntry m_valueEntry; -ui::Entry m_valueEntryWidget{ui::null}; +class SurfaceInspector : public Dialog { + ui::Window BuildDialog(); + + NonModalEntry m_textureEntry; + NonModalSpinner m_hshiftSpinner; + NonModalEntry m_hshiftEntry; + NonModalSpinner m_vshiftSpinner; + NonModalEntry m_vshiftEntry; + NonModalSpinner m_hscaleSpinner; + NonModalEntry m_hscaleEntry; + NonModalSpinner m_vscaleSpinner; + NonModalEntry m_vscaleEntry; + NonModalSpinner m_rotateSpinner; + NonModalEntry m_rotateEntry; + + IdleDraw m_idleDraw; + + GtkCheckButton *m_surfaceFlags[32]; + GtkCheckButton *m_contentFlags[32]; + + NonModalEntry m_valueEntry; + ui::Entry m_valueEntryWidget{ui::null}; public: -WindowPositionTracker m_positionTracker; + WindowPositionTracker m_positionTracker; // Dialog Data -float m_fitHorizontal; -float m_fitVertical; - -Increment m_hshiftIncrement; -Increment m_vshiftIncrement; -Increment m_hscaleIncrement; -Increment m_vscaleIncrement; -Increment m_rotateIncrement; -ui::Entry m_texture{ui::null}; - -SurfaceInspector() : - m_textureEntry( ApplyShaderCaller( *this ), UpdateCaller( *this ) ), - m_hshiftSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), - m_hshiftEntry( Increment::ApplyCaller( m_hshiftIncrement ), Increment::CancelCaller( m_hshiftIncrement ) ), - m_vshiftSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), - m_vshiftEntry( Increment::ApplyCaller( m_vshiftIncrement ), Increment::CancelCaller( m_vshiftIncrement ) ), - m_hscaleSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), - m_hscaleEntry( Increment::ApplyCaller( m_hscaleIncrement ), Increment::CancelCaller( m_hscaleIncrement ) ), - m_vscaleSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), - m_vscaleEntry( Increment::ApplyCaller( m_vscaleIncrement ), Increment::CancelCaller( m_vscaleIncrement ) ), - m_rotateSpinner( ApplyTexdefCaller( *this ), UpdateCaller( *this ) ), - m_rotateEntry( Increment::ApplyCaller( m_rotateIncrement ), Increment::CancelCaller( m_rotateIncrement ) ), - m_idleDraw( UpdateCaller( *this ) ), - m_valueEntry( ApplyFlagsCaller( *this ), UpdateCaller( *this ) ), - m_hshiftIncrement( g_si_globals.shift[0] ), - m_vshiftIncrement( g_si_globals.shift[1] ), - m_hscaleIncrement( g_si_globals.scale[0] ), - m_vscaleIncrement( g_si_globals.scale[1] ), - m_rotateIncrement( g_si_globals.rotate ){ - m_fitVertical = 1; - m_fitHorizontal = 1; - m_positionTracker.setPosition( c_default_window_pos ); -} - -void constructWindow( ui::Window main_window ){ - m_parent = main_window; - Create(); - AddGridChangeCallback( FreeCaller() ); -} -void destroyWindow(){ - Destroy(); -} -bool visible() { - return GetWidget().visible(); -} -void queueDraw(){ - if ( visible() ) { - m_idleDraw.queueDraw(); - } -} - -void Update(); -typedef MemberCaller UpdateCaller; -void ApplyShader(); -typedef MemberCaller ApplyShaderCaller; -void ApplyTexdef(); -typedef MemberCaller ApplyTexdefCaller; -void ApplyFlags(); -typedef MemberCaller ApplyFlagsCaller; + float m_fitHorizontal; + float m_fitVertical; + + Increment m_hshiftIncrement; + Increment m_vshiftIncrement; + Increment m_hscaleIncrement; + Increment m_vscaleIncrement; + Increment m_rotateIncrement; + ui::Entry m_texture{ui::null}; + + SurfaceInspector() : + m_textureEntry(ApplyShaderCaller(*this), UpdateCaller(*this)), + m_hshiftSpinner(ApplyTexdefCaller(*this), UpdateCaller(*this)), + m_hshiftEntry(Increment::ApplyCaller(m_hshiftIncrement), Increment::CancelCaller(m_hshiftIncrement)), + m_vshiftSpinner(ApplyTexdefCaller(*this), UpdateCaller(*this)), + m_vshiftEntry(Increment::ApplyCaller(m_vshiftIncrement), Increment::CancelCaller(m_vshiftIncrement)), + m_hscaleSpinner(ApplyTexdefCaller(*this), UpdateCaller(*this)), + m_hscaleEntry(Increment::ApplyCaller(m_hscaleIncrement), Increment::CancelCaller(m_hscaleIncrement)), + m_vscaleSpinner(ApplyTexdefCaller(*this), UpdateCaller(*this)), + m_vscaleEntry(Increment::ApplyCaller(m_vscaleIncrement), Increment::CancelCaller(m_vscaleIncrement)), + m_rotateSpinner(ApplyTexdefCaller(*this), UpdateCaller(*this)), + m_rotateEntry(Increment::ApplyCaller(m_rotateIncrement), Increment::CancelCaller(m_rotateIncrement)), + m_idleDraw(UpdateCaller(*this)), + m_valueEntry(ApplyFlagsCaller(*this), UpdateCaller(*this)), + m_hshiftIncrement(g_si_globals.shift[0]), + m_vshiftIncrement(g_si_globals.shift[1]), + m_hscaleIncrement(g_si_globals.scale[0]), + m_vscaleIncrement(g_si_globals.scale[1]), + m_rotateIncrement(g_si_globals.rotate) + { + m_fitVertical = 1; + m_fitHorizontal = 1; + m_positionTracker.setPosition(c_default_window_pos); + } + + void constructWindow(ui::Window main_window) + { + m_parent = main_window; + Create(); + AddGridChangeCallback(FreeCaller()); + } + + void destroyWindow() + { + Destroy(); + } + + bool visible() + { + return GetWidget().visible(); + } + + void queueDraw() + { + if (visible()) { + m_idleDraw.queueDraw(); + } + } + + void Update(); + + typedef MemberCaller UpdateCaller; + + void ApplyShader(); + + typedef MemberCaller ApplyShaderCaller; + + void ApplyTexdef(); + + typedef MemberCaller ApplyTexdefCaller; + + void ApplyFlags(); + + typedef MemberCaller ApplyFlagsCaller; }; -namespace -{ -SurfaceInspector* g_SurfaceInspector; +namespace { + SurfaceInspector *g_SurfaceInspector; -inline SurfaceInspector& getSurfaceInspector(){ - ASSERT_NOTNULL( g_SurfaceInspector ); - return *g_SurfaceInspector; -} + inline SurfaceInspector &getSurfaceInspector() + { + ASSERT_NOTNULL(g_SurfaceInspector); + return *g_SurfaceInspector; + } } -void SurfaceInspector_constructWindow( ui::Window main_window ){ - getSurfaceInspector().constructWindow( main_window ); -} -void SurfaceInspector_destroyWindow(){ - getSurfaceInspector().destroyWindow(); +void SurfaceInspector_constructWindow(ui::Window main_window) +{ + getSurfaceInspector().constructWindow(main_window); } -void SurfaceInspector_queueDraw(){ - getSurfaceInspector().queueDraw(); +void SurfaceInspector_destroyWindow() +{ + getSurfaceInspector().destroyWindow(); } -namespace +void SurfaceInspector_queueDraw() { -CopiedString g_selectedShader; -TextureProjection g_selectedTexdef; -ContentsFlagsValue g_selectedFlags; -size_t g_selectedShaderSize[2]; + getSurfaceInspector().queueDraw(); } -void SurfaceInspector_SetSelectedShader( const char* shader ){ - g_selectedShader = shader; - SurfaceInspector_queueDraw(); +namespace { + CopiedString g_selectedShader; + TextureProjection g_selectedTexdef; + ContentsFlagsValue g_selectedFlags; + size_t g_selectedShaderSize[2]; } -void SurfaceInspector_SetSelectedTexdef( const TextureProjection& projection ){ - g_selectedTexdef = projection; - SurfaceInspector_queueDraw(); +void SurfaceInspector_SetSelectedShader(const char *shader) +{ + g_selectedShader = shader; + SurfaceInspector_queueDraw(); } -void SurfaceInspector_SetSelectedFlags( const ContentsFlagsValue& flags ){ - g_selectedFlags = flags; - SurfaceInspector_queueDraw(); +void SurfaceInspector_SetSelectedTexdef(const TextureProjection &projection) +{ + g_selectedTexdef = projection; + SurfaceInspector_queueDraw(); +} + +void SurfaceInspector_SetSelectedFlags(const ContentsFlagsValue &flags) +{ + g_selectedFlags = flags; + SurfaceInspector_queueDraw(); } static bool s_texture_selection_dirty = false; -void SurfaceInspector_updateSelection(){ - s_texture_selection_dirty = true; - SurfaceInspector_queueDraw(); +void SurfaceInspector_updateSelection() +{ + s_texture_selection_dirty = true; + SurfaceInspector_queueDraw(); #if TEXTOOL_ENABLED - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - TexTool::queueDraw(); - //globalOutputStream() << "textool texture changed..\n"; - } + if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { + TexTool::queueDraw(); + //globalOutputStream() << "textool texture changed..\n"; + } #endif } -void SurfaceInspector_SelectionChanged( const Selectable& selectable ){ - SurfaceInspector_updateSelection(); +void SurfaceInspector_SelectionChanged(const Selectable &selectable) +{ + SurfaceInspector_updateSelection(); } -void SurfaceInspector_SetCurrent_FromSelected(){ - if ( s_texture_selection_dirty == true ) { - s_texture_selection_dirty = false; - if ( !g_SelectedFaceInstances.empty() ) { - TextureProjection projection; +void SurfaceInspector_SetCurrent_FromSelected() +{ + if (s_texture_selection_dirty == true) { + s_texture_selection_dirty = false; + if (!g_SelectedFaceInstances.empty()) { + TextureProjection projection; //This *may* be the point before it fucks up... Let's see! //Yep, there was a call to removeScale in there... - Scene_BrushGetTexdef_Component_Selected( GlobalSceneGraph(), projection ); - - SurfaceInspector_SetSelectedTexdef( projection ); - - Scene_BrushGetShaderSize_Component_Selected( GlobalSceneGraph(), g_selectedShaderSize[0], g_selectedShaderSize[1] ); - g_selectedTexdef.m_brushprimit_texdef.coords[0][2] = float_mod( g_selectedTexdef.m_brushprimit_texdef.coords[0][2], (float)g_selectedShaderSize[0] ); - g_selectedTexdef.m_brushprimit_texdef.coords[1][2] = float_mod( g_selectedTexdef.m_brushprimit_texdef.coords[1][2], (float)g_selectedShaderSize[1] ); - - CopiedString name; - Scene_BrushGetShader_Component_Selected( GlobalSceneGraph(), name ); - if ( string_not_empty( name.c_str() ) ) { - SurfaceInspector_SetSelectedShader( name.c_str() ); - } - - ContentsFlagsValue flags; - Scene_BrushGetFlags_Component_Selected( GlobalSceneGraph(), flags ); - SurfaceInspector_SetSelectedFlags( flags ); - } - else - { - TextureProjection projection; - Scene_BrushGetTexdef_Selected( GlobalSceneGraph(), projection ); - SurfaceInspector_SetSelectedTexdef( projection ); - - CopiedString name; - Scene_BrushGetShader_Selected( GlobalSceneGraph(), name ); - if ( string_empty( name.c_str() ) ) { - Scene_PatchGetShader_Selected( GlobalSceneGraph(), name ); - } - if ( string_not_empty( name.c_str() ) ) { - SurfaceInspector_SetSelectedShader( name.c_str() ); - } - - ContentsFlagsValue flags( 0, 0, 0, false ); - Scene_BrushGetFlags_Selected( GlobalSceneGraph(), flags ); - SurfaceInspector_SetSelectedFlags( flags ); - } - } + Scene_BrushGetTexdef_Component_Selected(GlobalSceneGraph(), projection); + + SurfaceInspector_SetSelectedTexdef(projection); + + Scene_BrushGetShaderSize_Component_Selected(GlobalSceneGraph(), g_selectedShaderSize[0], + g_selectedShaderSize[1]); + g_selectedTexdef.m_brushprimit_texdef.coords[0][2] = float_mod( + g_selectedTexdef.m_brushprimit_texdef.coords[0][2], (float) g_selectedShaderSize[0]); + g_selectedTexdef.m_brushprimit_texdef.coords[1][2] = float_mod( + g_selectedTexdef.m_brushprimit_texdef.coords[1][2], (float) g_selectedShaderSize[1]); + + CopiedString name; + Scene_BrushGetShader_Component_Selected(GlobalSceneGraph(), name); + if (string_not_empty(name.c_str())) { + SurfaceInspector_SetSelectedShader(name.c_str()); + } + + ContentsFlagsValue flags; + Scene_BrushGetFlags_Component_Selected(GlobalSceneGraph(), flags); + SurfaceInspector_SetSelectedFlags(flags); + } else { + TextureProjection projection; + Scene_BrushGetTexdef_Selected(GlobalSceneGraph(), projection); + SurfaceInspector_SetSelectedTexdef(projection); + + CopiedString name; + Scene_BrushGetShader_Selected(GlobalSceneGraph(), name); + if (string_empty(name.c_str())) { + Scene_PatchGetShader_Selected(GlobalSceneGraph(), name); + } + if (string_not_empty(name.c_str())) { + SurfaceInspector_SetSelectedShader(name.c_str()); + } + + ContentsFlagsValue flags(0, 0, 0, false); + Scene_BrushGetFlags_Selected(GlobalSceneGraph(), flags); + SurfaceInspector_SetSelectedFlags(flags); + } + } } -const char* SurfaceInspector_GetSelectedShader(){ - SurfaceInspector_SetCurrent_FromSelected(); - return g_selectedShader.c_str(); +const char *SurfaceInspector_GetSelectedShader() +{ + SurfaceInspector_SetCurrent_FromSelected(); + return g_selectedShader.c_str(); } -const TextureProjection& SurfaceInspector_GetSelectedTexdef(){ - SurfaceInspector_SetCurrent_FromSelected(); - return g_selectedTexdef; +const TextureProjection &SurfaceInspector_GetSelectedTexdef() +{ + SurfaceInspector_SetCurrent_FromSelected(); + return g_selectedTexdef; } -const ContentsFlagsValue& SurfaceInspector_GetSelectedFlags(){ - SurfaceInspector_SetCurrent_FromSelected(); - return g_selectedFlags; +const ContentsFlagsValue &SurfaceInspector_GetSelectedFlags() +{ + SurfaceInspector_SetCurrent_FromSelected(); + return g_selectedFlags; } - /* =================================================== @@ -372,16 +406,18 @@ si_globals_t g_si_globals; // NOTE: the default scale depends if you are using BP mode or regular. // For regular it's 0.5f (128 pixels cover 64 world units), for BP it's simply 1.0f // see fenris #2810 -void DoSnapTToGrid( float hscale, float vscale ){ - g_si_globals.shift[0] = static_cast( float_to_integer( static_cast( GetGridSize() ) / hscale ) ); - g_si_globals.shift[1] = static_cast( float_to_integer( static_cast( GetGridSize() ) / vscale ) ); - getSurfaceInspector().queueDraw(); +void DoSnapTToGrid(float hscale, float vscale) +{ + g_si_globals.shift[0] = static_cast( float_to_integer(static_cast( GetGridSize()) / hscale)); + g_si_globals.shift[1] = static_cast( float_to_integer(static_cast( GetGridSize()) / vscale)); + getSurfaceInspector().queueDraw(); } -void SurfaceInspector_GridChange(){ - if ( g_si_globals.m_bSnapTToGrid ) { - DoSnapTToGrid( Texdef_getDefaultTextureScale(), Texdef_getDefaultTextureScale() ); - } +void SurfaceInspector_GridChange() +{ + if (g_si_globals.m_bSnapTToGrid) { + DoSnapTToGrid(Texdef_getDefaultTextureScale(), Texdef_getDefaultTextureScale()); + } } // make the shift increments match the grid settings @@ -390,609 +426,618 @@ void SurfaceInspector_GridChange(){ // we move the textures in pixels, not world units. (i.e. increment values are in pixel) // depending on the texture scale it doesn't take the same amount of pixels to move of GetGridSize() // increment * scale = gridsize -static void OnBtnMatchGrid( ui::Widget widget, gpointer data ){ - float hscale, vscale; - hscale = static_cast( gtk_spin_button_get_value( getSurfaceInspector().m_hscaleIncrement.m_spin ) ); - vscale = static_cast( gtk_spin_button_get_value( getSurfaceInspector().m_vscaleIncrement.m_spin ) ); +static void OnBtnMatchGrid(ui::Widget widget, gpointer data) +{ + float hscale, vscale; + hscale = static_cast( gtk_spin_button_get_value(getSurfaceInspector().m_hscaleIncrement.m_spin)); + vscale = static_cast( gtk_spin_button_get_value(getSurfaceInspector().m_vscaleIncrement.m_spin)); - if ( hscale == 0.0f || vscale == 0.0f ) { - globalOutputStream() << "ERROR: unexpected scale == 0.0f\n"; - return; - } + if (hscale == 0.0f || vscale == 0.0f) { + globalOutputStream() << "ERROR: unexpected scale == 0.0f\n"; + return; + } - DoSnapTToGrid( hscale, vscale ); + DoSnapTToGrid(hscale, vscale); } // DoSurface will always try to show the surface inspector // or update it because something new has been selected // Shamus: It does get called when the SI is hidden, but not when you select something new. ;-) -void DoSurface( void ){ - if ( !getSurfaceInspector().GetWidget() ) { - getSurfaceInspector().Create(); +void DoSurface(void) +{ + if (!getSurfaceInspector().GetWidget()) { + getSurfaceInspector().Create(); - } - getSurfaceInspector().Update(); - getSurfaceInspector().importData(); - getSurfaceInspector().ShowDlg(); + } + getSurfaceInspector().Update(); + getSurfaceInspector().importData(); + getSurfaceInspector().ShowDlg(); } -void SurfaceInspector_toggleShown(){ - if ( getSurfaceInspector().visible() ) { - getSurfaceInspector().HideDlg(); - } - else - { - DoSurface(); - } +void SurfaceInspector_toggleShown() +{ + if (getSurfaceInspector().visible()) { + getSurfaceInspector().HideDlg(); + } else { + DoSurface(); + } } -void SurfaceInspector_FitTexture(){ - UndoableCommand undo( "textureAutoFit" ); - Select_FitTexture( getSurfaceInspector().m_fitHorizontal, getSurfaceInspector().m_fitVertical ); +void SurfaceInspector_FitTexture() +{ + UndoableCommand undo("textureAutoFit"); + Select_FitTexture(getSurfaceInspector().m_fitHorizontal, getSurfaceInspector().m_fitVertical); } -static void OnBtnPatchdetails( ui::Widget widget, gpointer data ){ - Patch_CapTexture(); +static void OnBtnPatchdetails(ui::Widget widget, gpointer data) +{ + Patch_CapTexture(); } -static void OnBtnPatchnatural( ui::Widget widget, gpointer data ){ - Patch_NaturalTexture(); +static void OnBtnPatchnatural(ui::Widget widget, gpointer data) +{ + Patch_NaturalTexture(); } -static void OnBtnPatchreset( ui::Widget widget, gpointer data ){ - Patch_ResetTexture(); +static void OnBtnPatchreset(ui::Widget widget, gpointer data) +{ + Patch_ResetTexture(); } -static void OnBtnPatchFit( ui::Widget widget, gpointer data ){ - Patch_FitTexture(); +static void OnBtnPatchFit(ui::Widget widget, gpointer data) +{ + Patch_FitTexture(); } -static void OnBtnAxial( ui::Widget widget, gpointer data ){ +static void OnBtnAxial(ui::Widget widget, gpointer data) +{ //globalOutputStream() << "--> [OnBtnAxial]...\n"; - UndoableCommand undo( "textureDefault" ); - TextureProjection projection; + UndoableCommand undo("textureDefault"); + TextureProjection projection; //globalOutputStream() << " TexDef_Construct_Default()...\n"; - TexDef_Construct_Default( projection ); + TexDef_Construct_Default(projection); //globalOutputStream() << " Select_SetTexdef()...\n"; #if TEXTOOL_ENABLED - //Shamus: - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { - // Scale up texture width/height if in BP mode... + //Shamus: + if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { + // Scale up texture width/height if in BP mode... //NOTE: This may not be correct any more! :-P - if ( !g_SelectedFaceInstances.empty() ) { - Face & face = g_SelectedFaceInstances.last().getFace(); - float x = face.getShader().m_state->getTexture().width; - float y = face.getShader().m_state->getTexture().height; - projection.m_brushprimit_texdef.coords[0][0] /= x; - projection.m_brushprimit_texdef.coords[0][1] /= y; - projection.m_brushprimit_texdef.coords[1][0] /= x; - projection.m_brushprimit_texdef.coords[1][1] /= y; - } - } + if ( !g_SelectedFaceInstances.empty() ) { + Face & face = g_SelectedFaceInstances.last().getFace(); + float x = face.getShader().m_state->getTexture().width; + float y = face.getShader().m_state->getTexture().height; + projection.m_brushprimit_texdef.coords[0][0] /= x; + projection.m_brushprimit_texdef.coords[0][1] /= y; + projection.m_brushprimit_texdef.coords[1][0] /= x; + projection.m_brushprimit_texdef.coords[1][1] /= y; + } + } #endif - Select_SetTexdef( projection ); + Select_SetTexdef(projection); } -static void OnBtnFaceFit( ui::Widget widget, gpointer data ){ - getSurfaceInspector().exportData(); - SurfaceInspector_FitTexture(); +static void OnBtnFaceFit(ui::Widget widget, gpointer data) +{ + getSurfaceInspector().exportData(); + SurfaceInspector_FitTexture(); } -typedef const char* FlagName; +typedef const char *FlagName; const FlagName surfaceflagNamesDefault[32] = { - "surf1", - "surf2", - "surf3", - "surf4", - "surf5", - "surf6", - "surf7", - "surf8", - "surf9", - "surf10", - "surf11", - "surf12", - "surf13", - "surf14", - "surf15", - "surf16", - "surf17", - "surf18", - "surf19", - "surf20", - "surf21", - "surf22", - "surf23", - "surf24", - "surf25", - "surf26", - "surf27", - "surf28", - "surf29", - "surf30", - "surf31", - "surf32" + "surf1", + "surf2", + "surf3", + "surf4", + "surf5", + "surf6", + "surf7", + "surf8", + "surf9", + "surf10", + "surf11", + "surf12", + "surf13", + "surf14", + "surf15", + "surf16", + "surf17", + "surf18", + "surf19", + "surf20", + "surf21", + "surf22", + "surf23", + "surf24", + "surf25", + "surf26", + "surf27", + "surf28", + "surf29", + "surf30", + "surf31", + "surf32" }; const FlagName contentflagNamesDefault[32] = { - "cont1", - "cont2", - "cont3", - "cont4", - "cont5", - "cont6", - "cont7", - "cont8", - "cont9", - "cont10", - "cont11", - "cont12", - "cont13", - "cont14", - "cont15", - "cont16", - "cont17", - "cont18", - "cont19", - "cont20", - "cont21", - "cont22", - "cont23", - "cont24", - "cont25", - "cont26", - "cont27", - "cont28", - "cont29", - "cont30", - "cont31", - "cont32" + "cont1", + "cont2", + "cont3", + "cont4", + "cont5", + "cont6", + "cont7", + "cont8", + "cont9", + "cont10", + "cont11", + "cont12", + "cont13", + "cont14", + "cont15", + "cont16", + "cont17", + "cont18", + "cont19", + "cont20", + "cont21", + "cont22", + "cont23", + "cont24", + "cont25", + "cont26", + "cont27", + "cont28", + "cont29", + "cont30", + "cont31", + "cont32" }; -const char* getSurfaceFlagName( std::size_t bit ){ - const char* value = g_pGameDescription->getKeyValue( surfaceflagNamesDefault[bit] ); - if ( string_empty( value ) ) { - return surfaceflagNamesDefault[bit]; - } - return value; +const char *getSurfaceFlagName(std::size_t bit) +{ + const char *value = g_pGameDescription->getKeyValue(surfaceflagNamesDefault[bit]); + if (string_empty(value)) { + return surfaceflagNamesDefault[bit]; + } + return value; } -const char* getContentFlagName( std::size_t bit ){ - const char* value = g_pGameDescription->getKeyValue( contentflagNamesDefault[bit] ); - if ( string_empty( value ) ) { - return contentflagNamesDefault[bit]; - } - return value; +const char *getContentFlagName(std::size_t bit) +{ + const char *value = g_pGameDescription->getKeyValue(contentflagNamesDefault[bit]); + if (string_empty(value)) { + return contentflagNamesDefault[bit]; + } + return value; } // ============================================================================= // SurfaceInspector class -guint togglebutton_connect_toggled( ui::ToggleButton button, const Callback& callback ){ - return g_signal_connect_swapped( G_OBJECT( button ), "toggled", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() ); -} - -ui::Window SurfaceInspector::BuildDialog(){ - ui::Window window = ui::Window(create_floating_window( "Surface Inspector", m_parent )); - - m_positionTracker.connect( window ); - - global_accel_connect_window( window ); - - window_connect_focus_in_clear_focus_widget( window ); - - - { - // replaced by only the vbox: - auto vbox = ui::VBox( FALSE, 5 ); - vbox.show(); - window.add(vbox); - gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); - - { - auto hbox2 = ui::HBox( FALSE, 5 ); - hbox2.show(); - vbox.pack_start( hbox2, FALSE, FALSE, 0 ); - - { - ui::Widget label = ui::Label( "Texture" ); - label.show(); - hbox2.pack_start( label, FALSE, TRUE, 0 ); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); - hbox2.pack_start( entry, TRUE, TRUE, 0 ); - m_texture = entry; - m_textureEntry.connect( entry ); - GlobalTextureEntryCompletion::instance().connect( entry ); - } - } - - - { - auto table = ui::Table(6, 4, FALSE); - table.show(); - vbox.pack_start( table, FALSE, FALSE, 0 ); - gtk_table_set_row_spacings(table, 5); - gtk_table_set_col_spacings(table, 5); - { - ui::Widget label = ui::Label( "Horizontal shift" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - } - { - auto spin = ui::SpinButton( ui::Adjustment( 0, -8192, 8192, 2, 8, 0 ), 0, 2 ); - m_hshiftIncrement.m_spin = spin; - m_hshiftSpinner.connect( spin ); - spin.show(); - table.attach(spin, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); +guint togglebutton_connect_toggled(ui::ToggleButton button, const Callback &callback) +{ + return g_signal_connect_swapped(G_OBJECT(button), "toggled", G_CALLBACK(callback.getThunk()), + callback.getEnvironment()); +} + +ui::Window SurfaceInspector::BuildDialog() +{ + ui::Window window = ui::Window(create_floating_window("Surface Inspector", m_parent)); + + m_positionTracker.connect(window); + + global_accel_connect_window(window); + + window_connect_focus_in_clear_focus_widget(window); + + + { + // replaced by only the vbox: + auto vbox = ui::VBox(FALSE, 5); + vbox.show(); + window.add(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + + { + auto hbox2 = ui::HBox(FALSE, 5); + hbox2.show(); + vbox.pack_start(hbox2, FALSE, FALSE, 0); + + { + ui::Widget label = ui::Label("Texture"); + label.show(); + hbox2.pack_start(label, FALSE, TRUE, 0); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); + hbox2.pack_start(entry, TRUE, TRUE, 0); + m_texture = entry; + m_textureEntry.connect(entry); + GlobalTextureEntryCompletion::instance().connect(entry); + } + } + + + { + auto table = ui::Table(6, 4, FALSE); + table.show(); + vbox.pack_start(table, FALSE, FALSE, 0); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + { + ui::Widget label = ui::Label("Horizontal shift"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); + } + { + auto spin = ui::SpinButton(ui::Adjustment(0, -8192, 8192, 2, 8, 0), 0, 2); + m_hshiftIncrement.m_spin = spin; + m_hshiftSpinner.connect(spin); + spin.show(); + table.attach(spin, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); spin.dimensions(60, -1); - } - { - ui::Widget label = ui::Label( "Step" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {2, 3, 0, 1}, {GTK_FILL, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); - table.attach(entry, {3, 4, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); + } + { + ui::Widget label = ui::Label("Step"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {2, 3, 0, 1}, {GTK_FILL, 0}); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); + table.attach(entry, {3, 4, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); entry.dimensions(50, -1); - m_hshiftIncrement.m_entry = entry; - m_hshiftEntry.connect( entry ); - } - { - ui::Widget label = ui::Label( "Vertical shift" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); - } - { - auto spin = ui::SpinButton( ui::Adjustment( 0, -8192, 8192, 2, 8, 0 ), 0, 2 ); - m_vshiftIncrement.m_spin = spin; - m_vshiftSpinner.connect( spin ); - spin.show(); - table.attach(spin, {1, 2, 1, 2}, {GTK_FILL, 0}); + m_hshiftIncrement.m_entry = entry; + m_hshiftEntry.connect(entry); + } + { + ui::Widget label = ui::Label("Vertical shift"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); + } + { + auto spin = ui::SpinButton(ui::Adjustment(0, -8192, 8192, 2, 8, 0), 0, 2); + m_vshiftIncrement.m_spin = spin; + m_vshiftSpinner.connect(spin); + spin.show(); + table.attach(spin, {1, 2, 1, 2}, {GTK_FILL, 0}); spin.dimensions(60, -1); - } - { - ui::Widget label = ui::Label( "Step" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {2, 3, 1, 2}, {GTK_FILL, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); - table.attach(entry, {3, 4, 1, 2}, {GTK_FILL, 0}); + } + { + ui::Widget label = ui::Label("Step"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {2, 3, 1, 2}, {GTK_FILL, 0}); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); + table.attach(entry, {3, 4, 1, 2}, {GTK_FILL, 0}); entry.dimensions(50, -1); - m_vshiftIncrement.m_entry = entry; - m_vshiftEntry.connect( entry ); - } - { - ui::Widget label = ui::Label( "Horizontal stretch" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {0, 1, 2, 3}, {GTK_FILL, 0}); - } - { - auto spin = ui::SpinButton( ui::Adjustment( 0, -8192, 8192, 2, 8, 0 ), 0, 5 ); - m_hscaleIncrement.m_spin = spin; - m_hscaleSpinner.connect( spin ); - spin.show(); - table.attach(spin, {1, 2, 2, 3}, {GTK_FILL, 0}); + m_vshiftIncrement.m_entry = entry; + m_vshiftEntry.connect(entry); + } + { + ui::Widget label = ui::Label("Horizontal stretch"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {0, 1, 2, 3}, {GTK_FILL, 0}); + } + { + auto spin = ui::SpinButton(ui::Adjustment(0, -8192, 8192, 2, 8, 0), 0, 5); + m_hscaleIncrement.m_spin = spin; + m_hscaleSpinner.connect(spin); + spin.show(); + table.attach(spin, {1, 2, 2, 3}, {GTK_FILL, 0}); spin.dimensions(60, -1); - } - { - ui::Widget label = ui::Label( "Step" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {2, 3, 2, 3}, {GTK_FILL, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); - table.attach(entry, {3, 4, 2, 3}, {GTK_FILL, 0}); + } + { + ui::Widget label = ui::Label("Step"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {2, 3, 2, 3}, {GTK_FILL, 0}); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); + table.attach(entry, {3, 4, 2, 3}, {GTK_FILL, 0}); entry.dimensions(50, -1); - m_hscaleIncrement.m_entry = entry; - m_hscaleEntry.connect( entry ); - } - { - ui::Widget label = ui::Label( "Vertical stretch" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {0, 1, 3, 4}, {GTK_FILL, 0}); - } - { - auto spin = ui::SpinButton( ui::Adjustment( 0, -8192, 8192, 2, 8, 0 ), 0, 5 ); - m_vscaleIncrement.m_spin = spin; - m_vscaleSpinner.connect( spin ); - spin.show(); - table.attach(spin, {1, 2, 3, 4}, {GTK_FILL, 0}); + m_hscaleIncrement.m_entry = entry; + m_hscaleEntry.connect(entry); + } + { + ui::Widget label = ui::Label("Vertical stretch"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {0, 1, 3, 4}, {GTK_FILL, 0}); + } + { + auto spin = ui::SpinButton(ui::Adjustment(0, -8192, 8192, 2, 8, 0), 0, 5); + m_vscaleIncrement.m_spin = spin; + m_vscaleSpinner.connect(spin); + spin.show(); + table.attach(spin, {1, 2, 3, 4}, {GTK_FILL, 0}); spin.dimensions(60, -1); - } - { - ui::Widget label = ui::Label( "Step" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {2, 3, 3, 4}, {GTK_FILL, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); - table.attach(entry, {3, 4, 3, 4}, {GTK_FILL, 0}); + } + { + ui::Widget label = ui::Label("Step"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {2, 3, 3, 4}, {GTK_FILL, 0}); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); + table.attach(entry, {3, 4, 3, 4}, {GTK_FILL, 0}); entry.dimensions(50, -1); - m_vscaleIncrement.m_entry = entry; - m_vscaleEntry.connect( entry ); - } - { - ui::Widget label = ui::Label( "Rotate" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {0, 1, 4, 5}, {GTK_FILL, 0}); - } - { - auto spin = ui::SpinButton( ui::Adjustment( 0, -8192, 8192, 2, 8, 0 ), 0, 2 ); - m_rotateIncrement.m_spin = spin; - m_rotateSpinner.connect( spin ); - spin.show(); - table.attach(spin, {1, 2, 4, 5}, {GTK_FILL, 0}); + m_vscaleIncrement.m_entry = entry; + m_vscaleEntry.connect(entry); + } + { + ui::Widget label = ui::Label("Rotate"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {0, 1, 4, 5}, {GTK_FILL, 0}); + } + { + auto spin = ui::SpinButton(ui::Adjustment(0, -8192, 8192, 2, 8, 0), 0, 2); + m_rotateIncrement.m_spin = spin; + m_rotateSpinner.connect(spin); + spin.show(); + table.attach(spin, {1, 2, 4, 5}, {GTK_FILL, 0}); spin.dimensions(60, -1); - gtk_spin_button_set_wrap( spin, TRUE ); - } - { - ui::Widget label = ui::Label( "Step" ); - label.show(); - gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); - table.attach(label, {2, 3, 4, 5}, {GTK_FILL, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); - table.attach(entry, {3, 4, 4, 5}, {GTK_FILL, 0}); + gtk_spin_button_set_wrap(spin, TRUE); + } + { + ui::Widget label = ui::Label("Step"); + label.show(); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + table.attach(label, {2, 3, 4, 5}, {GTK_FILL, 0}); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); + table.attach(entry, {3, 4, 4, 5}, {GTK_FILL, 0}); entry.dimensions(50, -1); - m_rotateIncrement.m_entry = entry; - m_rotateEntry.connect( entry ); - } - { - // match grid button - ui::Widget button = ui::Button( "Match Grid" ); - button.show(); - table.attach(button, {2, 4, 5, 6}, {GTK_EXPAND | GTK_FILL, 0}); - button.connect( "clicked", G_CALLBACK( OnBtnMatchGrid ), 0 ); - } - } - - { - auto frame = ui::Frame( "Texturing" ); - frame.show(); - vbox.pack_start( frame, FALSE, FALSE, 0 ); - { - auto table = ui::Table(4, 4, FALSE); - table.show(); - frame.add(table); - gtk_table_set_row_spacings(table, 5); - gtk_table_set_col_spacings(table, 5); - gtk_container_set_border_width( GTK_CONTAINER( table ), 5 ); - { - ui::Widget label = ui::Label( "Brush" ); - label.show(); - table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - } - { - ui::Widget label = ui::Label( "Patch" ); - label.show(); - table.attach(label, {0, 1, 2, 3}, {GTK_FILL, 0}); - } - { - ui::Widget label = ui::Label( "Width" ); - label.show(); - table.attach(label, {2, 3, 0, 1}, {GTK_FILL, 0}); - } - { - ui::Widget label = ui::Label( "Height" ); - label.show(); - table.attach(label, {3, 4, 0, 1}, {GTK_FILL, 0}); - } - { - ui::Widget button = ui::Button( "Axial" ); - button.show(); - table.attach(button, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - button.connect( "clicked", - G_CALLBACK( OnBtnAxial ), 0 ); + m_rotateIncrement.m_entry = entry; + m_rotateEntry.connect(entry); + } + { + // match grid button + ui::Widget button = ui::Button("Match Grid"); + button.show(); + table.attach(button, {2, 4, 5, 6}, {GTK_EXPAND | GTK_FILL, 0}); + button.connect("clicked", G_CALLBACK(OnBtnMatchGrid), 0); + } + } + + { + auto frame = ui::Frame("Texturing"); + frame.show(); + vbox.pack_start(frame, FALSE, FALSE, 0); + { + auto table = ui::Table(4, 4, FALSE); + table.show(); + frame.add(table); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + { + ui::Widget label = ui::Label("Brush"); + label.show(); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); + } + { + ui::Widget label = ui::Label("Patch"); + label.show(); + table.attach(label, {0, 1, 2, 3}, {GTK_FILL, 0}); + } + { + ui::Widget label = ui::Label("Width"); + label.show(); + table.attach(label, {2, 3, 0, 1}, {GTK_FILL, 0}); + } + { + ui::Widget label = ui::Label("Height"); + label.show(); + table.attach(label, {3, 4, 0, 1}, {GTK_FILL, 0}); + } + { + ui::Widget button = ui::Button("Axial"); + button.show(); + table.attach(button, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); + button.connect("clicked", + G_CALLBACK(OnBtnAxial), 0); button.dimensions(60, -1); - } - { - ui::Widget button = ui::Button( "Fit" ); - button.show(); - table.attach(button, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - button.connect( "clicked", - G_CALLBACK( OnBtnFaceFit ), 0 ); + } + { + ui::Widget button = ui::Button("Fit"); + button.show(); + table.attach(button, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); + button.connect("clicked", + G_CALLBACK(OnBtnFaceFit), 0); button.dimensions(60, -1); - } - { - ui::Widget button = ui::Button( "CAP" ); - button.show(); - table.attach(button, {0, 1, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); - button.connect( "clicked", - G_CALLBACK( OnBtnPatchdetails ), 0 ); + } + { + ui::Widget button = ui::Button("CAP"); + button.show(); + table.attach(button, {0, 1, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); + button.connect("clicked", + G_CALLBACK(OnBtnPatchdetails), 0); button.dimensions(60, -1); - } - { - ui::Widget button = ui::Button( "Set..." ); - button.show(); - table.attach(button, {1, 2, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); - button.connect( "clicked", - G_CALLBACK( OnBtnPatchreset ), 0 ); + } + { + ui::Widget button = ui::Button("Set..."); + button.show(); + table.attach(button, {1, 2, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); + button.connect("clicked", + G_CALLBACK(OnBtnPatchreset), 0); button.dimensions(60, -1); - } - { - ui::Widget button = ui::Button( "Natural" ); - button.show(); - table.attach(button, {2, 3, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); - button.connect( "clicked", - G_CALLBACK( OnBtnPatchnatural ), 0 ); + } + { + ui::Widget button = ui::Button("Natural"); + button.show(); + table.attach(button, {2, 3, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); + button.connect("clicked", + G_CALLBACK(OnBtnPatchnatural), 0); button.dimensions(60, -1); - } - { - ui::Widget button = ui::Button( "Fit" ); - button.show(); - table.attach(button, {3, 4, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); - button.connect( "clicked", - G_CALLBACK( OnBtnPatchFit ), 0 ); + } + { + ui::Widget button = ui::Button("Fit"); + button.show(); + table.attach(button, {3, 4, 3, 4}, {GTK_EXPAND | GTK_FILL, 0}); + button.connect("clicked", + G_CALLBACK(OnBtnPatchFit), 0); button.dimensions(60, -1); - } - { - auto spin = ui::SpinButton( ui::Adjustment( 1, 0, 1 << 16, 1, 10, 0 ), 0, 6 ); - spin.show(); - table.attach(spin, {2, 3, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); + } + { + auto spin = ui::SpinButton(ui::Adjustment(1, 0, 1 << 16, 1, 10, 0), 0, 6); + spin.show(); + table.attach(spin, {2, 3, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); spin.dimensions(60, -1); - AddDialogData( spin, m_fitHorizontal ); - } - { - auto spin = ui::SpinButton( ui::Adjustment( 1, 0, 1 << 16, 1, 10, 0 ), 0, 6 ); - spin.show(); - table.attach(spin, {3, 4, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); + AddDialogData(spin, m_fitHorizontal); + } + { + auto spin = ui::SpinButton(ui::Adjustment(1, 0, 1 << 16, 1, 10, 0), 0, 6); + spin.show(); + table.attach(spin, {3, 4, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); spin.dimensions(60, -1); - AddDialogData( spin, m_fitVertical ); - } - } - } - if ( !string_empty( g_pGameDescription->getKeyValue( "si_flags" ) ) ) { - { - auto frame = ui::Frame( "Surface Flags" ); - frame.show(); - vbox.pack_start( frame, TRUE, TRUE, 0 ); - { - auto vbox3 = ui::VBox( FALSE, 4 ); - //gtk_container_set_border_width(GTK_CONTAINER(vbox3), 4); - vbox3.show(); - frame.add(vbox3); - { - auto table = ui::Table( 8, 4, FALSE ); - table.show(); - vbox3.pack_start( table, TRUE, TRUE, 0 ); - gtk_table_set_row_spacings( table, 0 ); - gtk_table_set_col_spacings( table, 0 ); - - GtkCheckButton** p = m_surfaceFlags; - - for (unsigned int c = 0; c != 4; ++c) - { - for (unsigned int r = 0; r != 8; ++r) - { - auto check = ui::CheckButton( getSurfaceFlagName( c * 8 + r ) ); - check.show(); - table.attach(check, {c, c + 1, r, r + 1}, {GTK_EXPAND | GTK_FILL, 0}); - *p++ = check; - guint handler_id = togglebutton_connect_toggled( check, ApplyFlagsCaller( *this ) ); - g_object_set_data( G_OBJECT( check ), "handler", gint_to_pointer( handler_id ) ); - } - } - } - } - } - { - auto frame = ui::Frame( "Content Flags" ); - frame.show(); - vbox.pack_start( frame, TRUE, TRUE, 0 ); - { - auto vbox3 = ui::VBox( FALSE, 4 ); - //gtk_container_set_border_width(GTK_CONTAINER(vbox3), 4); - vbox3.show(); - frame.add(vbox3); - { - - auto table = ui::Table( 8, 4, FALSE ); - table.show(); - vbox3.pack_start( table, TRUE, TRUE, 0 ); - gtk_table_set_row_spacings( table, 0 ); - gtk_table_set_col_spacings( table, 0 ); - - GtkCheckButton** p = m_contentFlags; - - for (unsigned int c = 0; c != 4; ++c) - { - for (unsigned int r = 0; r != 8; ++r) - { - auto check = ui::CheckButton( getContentFlagName( c * 8 + r ) ); - check.show(); - table.attach(check, {c, c + 1, r, r + 1}, {GTK_EXPAND | GTK_FILL, 0}); - *p++ = check; - guint handler_id = togglebutton_connect_toggled( check, ApplyFlagsCaller( *this ) ); - g_object_set_data( G_OBJECT( check ), "handler", gint_to_pointer( handler_id ) ); - } - } - - // not allowed to modify detail flag using Surface Inspector - gtk_widget_set_sensitive( ui::CheckButton::from(m_contentFlags[BRUSH_DETAIL_FLAG]), FALSE ); - } - } - } - { - auto frame = ui::Frame( "Value" ); - frame.show(); - vbox.pack_start( frame, TRUE, TRUE, 0 ); - { - auto vbox3 = ui::VBox( FALSE, 4 ); - gtk_container_set_border_width( GTK_CONTAINER( vbox3 ), 4 ); - vbox3.show(); - frame.add(vbox3); - - { - auto entry = ui::Entry(ui::New); - entry.show(); - vbox3.pack_start( entry, TRUE, TRUE, 0 ); - m_valueEntryWidget = entry; - m_valueEntry.connect( entry ); - } - } - } - } + AddDialogData(spin, m_fitVertical); + } + } + } + if (!string_empty(g_pGameDescription->getKeyValue("si_flags"))) { + { + auto frame = ui::Frame("Surface Flags"); + frame.show(); + vbox.pack_start(frame, TRUE, TRUE, 0); + { + auto vbox3 = ui::VBox(FALSE, 4); + //gtk_container_set_border_width(GTK_CONTAINER(vbox3), 4); + vbox3.show(); + frame.add(vbox3); + { + auto table = ui::Table(8, 4, FALSE); + table.show(); + vbox3.pack_start(table, TRUE, TRUE, 0); + gtk_table_set_row_spacings(table, 0); + gtk_table_set_col_spacings(table, 0); + + GtkCheckButton **p = m_surfaceFlags; + + for (unsigned int c = 0; c != 4; ++c) { + for (unsigned int r = 0; r != 8; ++r) { + auto check = ui::CheckButton(getSurfaceFlagName(c * 8 + r)); + check.show(); + table.attach(check, {c, c + 1, r, r + 1}, {GTK_EXPAND | GTK_FILL, 0}); + *p++ = check; + guint handler_id = togglebutton_connect_toggled(check, ApplyFlagsCaller(*this)); + g_object_set_data(G_OBJECT(check), "handler", gint_to_pointer(handler_id)); + } + } + } + } + } + { + auto frame = ui::Frame("Content Flags"); + frame.show(); + vbox.pack_start(frame, TRUE, TRUE, 0); + { + auto vbox3 = ui::VBox(FALSE, 4); + //gtk_container_set_border_width(GTK_CONTAINER(vbox3), 4); + vbox3.show(); + frame.add(vbox3); + { + + auto table = ui::Table(8, 4, FALSE); + table.show(); + vbox3.pack_start(table, TRUE, TRUE, 0); + gtk_table_set_row_spacings(table, 0); + gtk_table_set_col_spacings(table, 0); + + GtkCheckButton **p = m_contentFlags; + + for (unsigned int c = 0; c != 4; ++c) { + for (unsigned int r = 0; r != 8; ++r) { + auto check = ui::CheckButton(getContentFlagName(c * 8 + r)); + check.show(); + table.attach(check, {c, c + 1, r, r + 1}, {GTK_EXPAND | GTK_FILL, 0}); + *p++ = check; + guint handler_id = togglebutton_connect_toggled(check, ApplyFlagsCaller(*this)); + g_object_set_data(G_OBJECT(check), "handler", gint_to_pointer(handler_id)); + } + } + + // not allowed to modify detail flag using Surface Inspector + gtk_widget_set_sensitive(ui::CheckButton::from(m_contentFlags[BRUSH_DETAIL_FLAG]), FALSE); + } + } + } + { + auto frame = ui::Frame("Value"); + frame.show(); + vbox.pack_start(frame, TRUE, TRUE, 0); + { + auto vbox3 = ui::VBox(FALSE, 4); + gtk_container_set_border_width(GTK_CONTAINER(vbox3), 4); + vbox3.show(); + frame.add(vbox3); + + { + auto entry = ui::Entry(ui::New); + entry.show(); + vbox3.pack_start(entry, TRUE, TRUE, 0); + m_valueEntryWidget = entry; + m_valueEntry.connect(entry); + } + } + } + } #if TEXTOOL_ENABLED - if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { + if ( g_bp_globals.m_texdefTypeId == TEXDEFTYPEID_BRUSHPRIMITIVES ) { // Shamus: Textool goodies... - ui::Widget frame = ui::Frame( "Textool" ); - frame.show(); - vbox.pack_start( frame , FALSE, FALSE, 0 ); - { - //Prolly should make this a member or global var, so the SI can draw on it... - TexTool::g_textoolWin = glwidget_new( FALSE ); - // --> Dunno, but this stuff may be necessary... (Looks like it!) - g_object_ref( TexTool::g_textoolWin ); - gtk_widget_set_events( TexTool::g_textoolWin, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ); - gtk_widget_set_can_focus( TexTool::g_textoolWin, true ); - // <-- end stuff... - TexTool::g_textoolWin.show(); - TexTool::g_textoolWin.dimensions( -1, 240 ); //Yeah! - frame.add(TexTool::g_textoolWin); - - TexTool::g_textoolWin.connect( "size_allocate", G_CALLBACK( TexTool::size_allocate ), NULL ); - TexTool::g_textoolWin.connect( "expose_event", G_CALLBACK( TexTool::expose ), NULL ); - TexTool::g_textoolWin.connect( "button_press_event", G_CALLBACK( TexTool::button_press ), NULL ); - TexTool::g_textoolWin.connect( "button_release_event", G_CALLBACK( TexTool::button_release ), NULL ); - TexTool::g_textoolWin.connect( "motion_notify_event", G_CALLBACK( TexTool::motion ), NULL ); - } - { - ui::Widget hbox = ui::HBox( FALSE, 5 ); - hbox.show(); - vbox.pack_start( hbox , FALSE, FALSE, 0 ); - // Checkboxes go here... (Flip X/Y) - ui::Widget flipX = ui::CheckButton( "Flip X axis" ); - ui::Widget flipY = ui::CheckButton( "Flip Y axis" ); - flipX.show(); - flipY.show(); - hbox.pack_start( flipX, FALSE, FALSE, 0 ); - hbox.pack_start( flipY, FALSE, FALSE, 0 ); + ui::Widget frame = ui::Frame( "Textool" ); + frame.show(); + vbox.pack_start( frame , FALSE, FALSE, 0 ); + { + //Prolly should make this a member or global var, so the SI can draw on it... + TexTool::g_textoolWin = glwidget_new( FALSE ); + // --> Dunno, but this stuff may be necessary... (Looks like it!) + g_object_ref( TexTool::g_textoolWin ); + gtk_widget_set_events( TexTool::g_textoolWin, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ); + gtk_widget_set_can_focus( TexTool::g_textoolWin, true ); + // <-- end stuff... + TexTool::g_textoolWin.show(); + TexTool::g_textoolWin.dimensions( -1, 240 ); //Yeah! + frame.add(TexTool::g_textoolWin); + + TexTool::g_textoolWin.connect( "size_allocate", G_CALLBACK( TexTool::size_allocate ), NULL ); + TexTool::g_textoolWin.connect( "expose_event", G_CALLBACK( TexTool::expose ), NULL ); + TexTool::g_textoolWin.connect( "button_press_event", G_CALLBACK( TexTool::button_press ), NULL ); + TexTool::g_textoolWin.connect( "button_release_event", G_CALLBACK( TexTool::button_release ), NULL ); + TexTool::g_textoolWin.connect( "motion_notify_event", G_CALLBACK( TexTool::motion ), NULL ); + } + { + ui::Widget hbox = ui::HBox( FALSE, 5 ); + hbox.show(); + vbox.pack_start( hbox , FALSE, FALSE, 0 ); + // Checkboxes go here... (Flip X/Y) + ui::Widget flipX = ui::CheckButton( "Flip X axis" ); + ui::Widget flipY = ui::CheckButton( "Flip Y axis" ); + flipX.show(); + flipY.show(); + hbox.pack_start( flipX, FALSE, FALSE, 0 ); + hbox.pack_start( flipY, FALSE, FALSE, 0 ); //Instead of this, we probably need to create a vbox to put into the frame, then the //window, then the hbox. !!! FIX !!! @@ -1002,14 +1047,14 @@ ui::Window SurfaceInspector::BuildDialog(){ // g_object_set_data(G_OBJECT(flipX), "handler", gint_to_pointer(flipX.connect("toggled", G_CALLBACK(TexTool::flipX), 0))); // g_object_set_data(G_OBJECT(flipY), "handler", gint_to_pointer(flipY.connect("toggled", G_CALLBACK(TexTool::flipY), 0))); //Instead, just do: - flipX.connect( "toggled", G_CALLBACK( TexTool::flipX ), NULL ); - flipY.connect( "toggled", G_CALLBACK( TexTool::flipY ), NULL ); - } - } + flipX.connect( "toggled", G_CALLBACK( TexTool::flipX ), NULL ); + flipY.connect( "toggled", G_CALLBACK( TexTool::flipY ), NULL ); + } + } #endif - } + } - return window; + return window; } /* @@ -1022,30 +1067,31 @@ ui::Window SurfaceInspector::BuildDialog(){ =============== */ -void spin_button_set_value_no_signal( ui::SpinButton spin, gdouble value ){ - guint handler_id = gpointer_to_int( g_object_get_data( G_OBJECT( spin ), "handler" ) ); - g_signal_handler_block( G_OBJECT( gtk_spin_button_get_adjustment( spin ) ), handler_id ); - gtk_spin_button_set_value( spin, value ); - g_signal_handler_unblock( G_OBJECT( gtk_spin_button_get_adjustment( spin ) ), handler_id ); +void spin_button_set_value_no_signal(ui::SpinButton spin, gdouble value) +{ + guint handler_id = gpointer_to_int(g_object_get_data(G_OBJECT(spin), "handler")); + g_signal_handler_block(G_OBJECT(gtk_spin_button_get_adjustment(spin)), handler_id); + gtk_spin_button_set_value(spin, value); + g_signal_handler_unblock(G_OBJECT(gtk_spin_button_get_adjustment(spin)), handler_id); } -void spin_button_set_step_increment( ui::SpinButton spin, gdouble value ){ - auto adjust = gtk_spin_button_get_adjustment( spin ); - gtk_adjustment_set_step_increment(adjust, value); +void spin_button_set_step_increment(ui::SpinButton spin, gdouble value) +{ + auto adjust = gtk_spin_button_get_adjustment(spin); + gtk_adjustment_set_step_increment(adjust, value); } -void SurfaceInspector::Update(){ - const char * name = SurfaceInspector_GetSelectedShader(); +void SurfaceInspector::Update() +{ + const char *name = SurfaceInspector_GetSelectedShader(); - if ( shader_is_texture( name ) ) { - m_texture.text(shader_get_textureName(name)); - } - else - { - m_texture.text(""); - } + if (shader_is_texture(name)) { + m_texture.text(shader_get_textureName(name)); + } else { + m_texture.text(""); + } - texdef_t shiftScaleRotate; + texdef_t shiftScaleRotate; //Shamus: This is where we get into trouble--the BP code tries to convert to a "faked" //shift, rotate & scale values from the brush face, which seems to screw up for some reason. //!!! FIX !!! @@ -1055,57 +1101,57 @@ void SurfaceInspector::Update(){ << g_selectedBrushPrimitTexdef.coords[1][0] << ", " << g_selectedBrushPrimitTexdef.coords[1][1] << ")(" << g_selectedBrushPrimitTexdef.coords[0][2] << ", " << g_selectedBrushPrimitTexdef.coords[1][2] << ") SurfaceInspector::Update\n";//*/ //Ok, it's screwed up *before* we get here... - ShiftScaleRotate_fromFace( shiftScaleRotate, SurfaceInspector_GetSelectedTexdef() ); - - // normalize again to hide the ridiculously high scale values that get created when using texlock - shiftScaleRotate.shift[0] = float_mod( shiftScaleRotate.shift[0], (float)g_selectedShaderSize[0] ); - shiftScaleRotate.shift[1] = float_mod( shiftScaleRotate.shift[1], (float)g_selectedShaderSize[1] ); - - { - spin_button_set_value_no_signal( m_hshiftIncrement.m_spin, shiftScaleRotate.shift[0] ); - spin_button_set_step_increment( m_hshiftIncrement.m_spin, g_si_globals.shift[0] ); - entry_set_float( m_hshiftIncrement.m_entry, g_si_globals.shift[0] ); - } - - { - spin_button_set_value_no_signal( m_vshiftIncrement.m_spin, shiftScaleRotate.shift[1] ); - spin_button_set_step_increment( m_vshiftIncrement.m_spin, g_si_globals.shift[1] ); - entry_set_float( m_vshiftIncrement.m_entry, g_si_globals.shift[1] ); - } - - { - spin_button_set_value_no_signal( m_hscaleIncrement.m_spin, shiftScaleRotate.scale[0] ); - spin_button_set_step_increment( m_hscaleIncrement.m_spin, g_si_globals.scale[0] ); - entry_set_float( m_hscaleIncrement.m_entry, g_si_globals.scale[0] ); - } - - { - spin_button_set_value_no_signal( m_vscaleIncrement.m_spin, shiftScaleRotate.scale[1] ); - spin_button_set_step_increment( m_vscaleIncrement.m_spin, g_si_globals.scale[1] ); - entry_set_float( m_vscaleIncrement.m_entry, g_si_globals.scale[1] ); - } - - { - spin_button_set_value_no_signal( m_rotateIncrement.m_spin, shiftScaleRotate.rotate ); - spin_button_set_step_increment( m_rotateIncrement.m_spin, g_si_globals.rotate ); - entry_set_float( m_rotateIncrement.m_entry, g_si_globals.rotate ); - } - - if ( !string_empty( g_pGameDescription->getKeyValue( "si_flags" ) ) ) { - ContentsFlagsValue flags( SurfaceInspector_GetSelectedFlags() ); - - entry_set_int( m_valueEntryWidget, flags.m_value ); - - for ( GtkCheckButton** p = m_surfaceFlags; p != m_surfaceFlags + 32; ++p ) - { - toggle_button_set_active_no_signal( ui::CheckButton::from( *p ), flags.m_surfaceFlags & ( 1 << ( p - m_surfaceFlags ) ) ); - } - - for ( GtkCheckButton** p = m_contentFlags; p != m_contentFlags + 32; ++p ) - { - toggle_button_set_active_no_signal( ui::CheckButton::from( *p ), flags.m_contentFlags & ( 1 << ( p - m_contentFlags ) ) ); - } - } + ShiftScaleRotate_fromFace(shiftScaleRotate, SurfaceInspector_GetSelectedTexdef()); + + // normalize again to hide the ridiculously high scale values that get created when using texlock + shiftScaleRotate.shift[0] = float_mod(shiftScaleRotate.shift[0], (float) g_selectedShaderSize[0]); + shiftScaleRotate.shift[1] = float_mod(shiftScaleRotate.shift[1], (float) g_selectedShaderSize[1]); + + { + spin_button_set_value_no_signal(m_hshiftIncrement.m_spin, shiftScaleRotate.shift[0]); + spin_button_set_step_increment(m_hshiftIncrement.m_spin, g_si_globals.shift[0]); + entry_set_float(m_hshiftIncrement.m_entry, g_si_globals.shift[0]); + } + + { + spin_button_set_value_no_signal(m_vshiftIncrement.m_spin, shiftScaleRotate.shift[1]); + spin_button_set_step_increment(m_vshiftIncrement.m_spin, g_si_globals.shift[1]); + entry_set_float(m_vshiftIncrement.m_entry, g_si_globals.shift[1]); + } + + { + spin_button_set_value_no_signal(m_hscaleIncrement.m_spin, shiftScaleRotate.scale[0]); + spin_button_set_step_increment(m_hscaleIncrement.m_spin, g_si_globals.scale[0]); + entry_set_float(m_hscaleIncrement.m_entry, g_si_globals.scale[0]); + } + + { + spin_button_set_value_no_signal(m_vscaleIncrement.m_spin, shiftScaleRotate.scale[1]); + spin_button_set_step_increment(m_vscaleIncrement.m_spin, g_si_globals.scale[1]); + entry_set_float(m_vscaleIncrement.m_entry, g_si_globals.scale[1]); + } + + { + spin_button_set_value_no_signal(m_rotateIncrement.m_spin, shiftScaleRotate.rotate); + spin_button_set_step_increment(m_rotateIncrement.m_spin, g_si_globals.rotate); + entry_set_float(m_rotateIncrement.m_entry, g_si_globals.rotate); + } + + if (!string_empty(g_pGameDescription->getKeyValue("si_flags"))) { + ContentsFlagsValue flags(SurfaceInspector_GetSelectedFlags()); + + entry_set_int(m_valueEntryWidget, flags.m_value); + + for (GtkCheckButton **p = m_surfaceFlags; p != m_surfaceFlags + 32; ++p) { + toggle_button_set_active_no_signal(ui::CheckButton::from(*p), + flags.m_surfaceFlags & (1 << (p - m_surfaceFlags))); + } + + for (GtkCheckButton **p = m_contentFlags; p != m_contentFlags + 32; ++p) { + toggle_button_set_active_no_signal(ui::CheckButton::from(*p), + flags.m_contentFlags & (1 << (p - m_contentFlags))); + } + } } /* @@ -1116,321 +1162,366 @@ void SurfaceInspector::Update(){ in brush primitive mode, grab the fake shift scale rot and compute a new texture matrix =============== */ -void SurfaceInspector::ApplyShader(){ - StringOutputStream name( 256 ); - name << GlobalTexturePrefix_get() << gtk_entry_get_text( m_texture ); - - // TTimo: detect and refuse invalid texture names (at least the ones with spaces) - if ( !texdef_name_valid( name.c_str() ) ) { - globalErrorStream() << "invalid texture name '" << name.c_str() << "'\n"; - SurfaceInspector_queueDraw(); - return; - } +void SurfaceInspector::ApplyShader() +{ + StringOutputStream name(256); + name << GlobalTexturePrefix_get() << gtk_entry_get_text(m_texture); + + // TTimo: detect and refuse invalid texture names (at least the ones with spaces) + if (!texdef_name_valid(name.c_str())) { + globalErrorStream() << "invalid texture name '" << name.c_str() << "'\n"; + SurfaceInspector_queueDraw(); + return; + } - UndoableCommand undo( "textureNameSetSelected" ); - Select_SetShader( name.c_str() ); + UndoableCommand undo("textureNameSetSelected"); + Select_SetShader(name.c_str()); } -void SurfaceInspector::ApplyTexdef(){ - texdef_t shiftScaleRotate; +void SurfaceInspector::ApplyTexdef() +{ + texdef_t shiftScaleRotate; - shiftScaleRotate.shift[0] = static_cast( gtk_spin_button_get_value( m_hshiftIncrement.m_spin ) ); - shiftScaleRotate.shift[1] = static_cast( gtk_spin_button_get_value( m_vshiftIncrement.m_spin ) ); - shiftScaleRotate.scale[0] = static_cast( gtk_spin_button_get_value( m_hscaleIncrement.m_spin ) ); - shiftScaleRotate.scale[1] = static_cast( gtk_spin_button_get_value( m_vscaleIncrement.m_spin ) ); - shiftScaleRotate.rotate = static_cast( gtk_spin_button_get_value( m_rotateIncrement.m_spin ) ); + shiftScaleRotate.shift[0] = static_cast( gtk_spin_button_get_value(m_hshiftIncrement.m_spin)); + shiftScaleRotate.shift[1] = static_cast( gtk_spin_button_get_value(m_vshiftIncrement.m_spin)); + shiftScaleRotate.scale[0] = static_cast( gtk_spin_button_get_value(m_hscaleIncrement.m_spin)); + shiftScaleRotate.scale[1] = static_cast( gtk_spin_button_get_value(m_vscaleIncrement.m_spin)); + shiftScaleRotate.rotate = static_cast( gtk_spin_button_get_value(m_rotateIncrement.m_spin)); - TextureProjection projection; + TextureProjection projection; //Shamus: This is the other place that screws up, it seems, since it doesn't seem to do the //conversion from the face (I think) and so bogus values end up in the thing... !!! FIX !!! //This is actually OK. :-P - ShiftScaleRotate_toFace( shiftScaleRotate, projection ); + ShiftScaleRotate_toFace(shiftScaleRotate, projection); - UndoableCommand undo( "textureProjectionSetSelected" ); - Select_SetTexdef( projection ); + UndoableCommand undo("textureProjectionSetSelected"); + Select_SetTexdef(projection); } -void SurfaceInspector::ApplyFlags(){ - unsigned int surfaceflags = 0; - for ( GtkCheckButton** p = m_surfaceFlags; p != m_surfaceFlags + 32; ++p ) - { - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( *p ) ) ) { - surfaceflags |= ( 1 << ( p - m_surfaceFlags ) ); - } - } +void SurfaceInspector::ApplyFlags() +{ + unsigned int surfaceflags = 0; + for (GtkCheckButton **p = m_surfaceFlags; p != m_surfaceFlags + 32; ++p) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(*p))) { + surfaceflags |= (1 << (p - m_surfaceFlags)); + } + } - unsigned int contentflags = 0; - for ( GtkCheckButton** p = m_contentFlags; p != m_contentFlags + 32; ++p ) - { - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( *p ) ) ) { - contentflags |= ( 1 << ( p - m_contentFlags ) ); - } - } + unsigned int contentflags = 0; + for (GtkCheckButton **p = m_contentFlags; p != m_contentFlags + 32; ++p) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(*p))) { + contentflags |= (1 << (p - m_contentFlags)); + } + } - int value = entry_get_int( m_valueEntryWidget ); + int value = entry_get_int(m_valueEntryWidget); - UndoableCommand undo( "flagsSetSelected" ); - Select_SetFlags( ContentsFlagsValue( surfaceflags, contentflags, value, true ) ); + UndoableCommand undo("flagsSetSelected"); + Select_SetFlags(ContentsFlagsValue(surfaceflags, contentflags, value, true)); } -void Face_getTexture( Face& face, CopiedString& shader, TextureProjection& projection, ContentsFlagsValue& flags ){ - shader = face.GetShader(); - face.GetTexdef( projection ); - flags = face.getShader().m_flags; +void Face_getTexture(Face &face, CopiedString &shader, TextureProjection &projection, ContentsFlagsValue &flags) +{ + shader = face.GetShader(); + face.GetTexdef(projection); + flags = face.getShader().m_flags; } -typedef Function FaceGetTexture; -void Face_setTexture( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ - face.SetShader( shader ); - face.SetTexdef( projection ); - face.SetFlags( flags ); +typedef Function FaceGetTexture; + +void +Face_setTexture(Face &face, const char *shader, const TextureProjection &projection, const ContentsFlagsValue &flags) +{ + face.SetShader(shader); + face.SetTexdef(projection); + face.SetFlags(flags); } -typedef Function FaceSetTexture; + +typedef Function FaceSetTexture; -void Patch_getTexture( Patch& patch, CopiedString& shader, TextureProjection& projection, ContentsFlagsValue& flags ){ - shader = patch.GetShader(); - projection = TextureProjection( texdef_t(), brushprimit_texdef_t(), Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ) ); - flags = ContentsFlagsValue( 0, 0, 0, false ); +void Patch_getTexture(Patch &patch, CopiedString &shader, TextureProjection &projection, ContentsFlagsValue &flags) +{ + shader = patch.GetShader(); + projection = TextureProjection(texdef_t(), brushprimit_texdef_t(), Vector3(0, 0, 0), Vector3(0, 0, 0)); + flags = ContentsFlagsValue(0, 0, 0, false); } -typedef Function PatchGetTexture; -void Patch_setTexture( Patch& patch, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ - patch.SetShader( shader ); +typedef Function PatchGetTexture; + +void +Patch_setTexture(Patch &patch, const char *shader, const TextureProjection &projection, const ContentsFlagsValue &flags) +{ + patch.SetShader(shader); } -typedef Function PatchSetTexture; +typedef Function PatchSetTexture; -typedef Callback GetTextureCallback; -typedef Callback SetTextureCallback; -struct Texturable -{ - GetTextureCallback getTexture; - SetTextureCallback setTexture; +typedef Callback GetTextureCallback; +typedef Callback SetTextureCallback; + +struct Texturable { + GetTextureCallback getTexture; + SetTextureCallback setTexture; }; -void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable ){ - SelectionIntersection intersection; - face.testSelect( test, intersection ); - if ( intersection.valid() - && SelectionIntersection_closer( intersection, bestIntersection ) ) { - bestIntersection = intersection; - texturable.setTexture = makeCallback( FaceSetTexture(), face ); - texturable.getTexture = makeCallback( FaceGetTexture(), face ); - } +void Face_getClosest(Face &face, SelectionTest &test, SelectionIntersection &bestIntersection, Texturable &texturable) +{ + SelectionIntersection intersection; + face.testSelect(test, intersection); + if (intersection.valid() + && SelectionIntersection_closer(intersection, bestIntersection)) { + bestIntersection = intersection; + texturable.setTexture = makeCallback(FaceSetTexture(), face); + texturable.getTexture = makeCallback(FaceGetTexture(), face); + } } -class OccludeSelector : public Selector -{ -SelectionIntersection& m_bestIntersection; -bool& m_occluded; +class OccludeSelector : public Selector { + SelectionIntersection &m_bestIntersection; + bool &m_occluded; public: -OccludeSelector( SelectionIntersection& bestIntersection, bool& occluded ) : m_bestIntersection( bestIntersection ), m_occluded( occluded ){ - m_occluded = false; -} -void pushSelectable( Selectable& selectable ){ -} -void popSelectable(){ -} -void addIntersection( const SelectionIntersection& intersection ){ - if ( SelectionIntersection_closer( intersection, m_bestIntersection ) ) { - m_bestIntersection = intersection; - m_occluded = true; - } -} + OccludeSelector(SelectionIntersection &bestIntersection, bool &occluded) : m_bestIntersection(bestIntersection), + m_occluded(occluded) + { + m_occluded = false; + } + + void pushSelectable(Selectable &selectable) + { + } + + void popSelectable() + { + } + + void addIntersection(const SelectionIntersection &intersection) + { + if (SelectionIntersection_closer(intersection, m_bestIntersection)) { + m_bestIntersection = intersection; + m_occluded = true; + } + } }; -class BrushGetClosestFaceVisibleWalker : public scene::Graph::Walker -{ -SelectionTest& m_test; -Texturable& m_texturable; -mutable SelectionIntersection m_bestIntersection; +class BrushGetClosestFaceVisibleWalker : public scene::Graph::Walker { + SelectionTest &m_test; + Texturable &m_texturable; + mutable SelectionIntersection m_bestIntersection; public: -BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable ) : m_test( test ), m_texturable( texturable ){ -} -bool pre( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { - BrushInstance* brush = Instance_getBrush( instance ); - if ( brush != 0 ) { - m_test.BeginMesh( brush->localToWorld() ); - - for ( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i ) - { - Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable ); - } - } - else - { - SelectionTestable* selectionTestable = Instance_getSelectionTestable( instance ); - if ( selectionTestable ) { - bool occluded; - OccludeSelector selector( m_bestIntersection, occluded ); - selectionTestable->testSelect( selector, m_test ); - if ( occluded ) { - Patch* patch = Node_getPatch( path.top() ); - if ( patch != 0 ) { - m_texturable.setTexture = makeCallback( PatchSetTexture(), *patch ); - m_texturable.getTexture = makeCallback( PatchGetTexture(), *patch ); - } - else - { - m_texturable = Texturable(); - } - } - } - } - } - return true; -} + BrushGetClosestFaceVisibleWalker(SelectionTest &test, Texturable &texturable) : m_test(test), + m_texturable(texturable) + { + } + + bool pre(const scene::Path &path, scene::Instance &instance) const + { + if (path.top().get().visible()) { + BrushInstance *brush = Instance_getBrush(instance); + if (brush != 0) { + m_test.BeginMesh(brush->localToWorld()); + + for (Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i) { + Face_getClosest(*(*i), m_test, m_bestIntersection, m_texturable); + } + } else { + SelectionTestable *selectionTestable = Instance_getSelectionTestable(instance); + if (selectionTestable) { + bool occluded; + OccludeSelector selector(m_bestIntersection, occluded); + selectionTestable->testSelect(selector, m_test); + if (occluded) { + Patch *patch = Node_getPatch(path.top()); + if (patch != 0) { + m_texturable.setTexture = makeCallback(PatchSetTexture(), *patch); + m_texturable.getTexture = makeCallback(PatchGetTexture(), *patch); + } else { + m_texturable = Texturable(); + } + } + } + } + } + return true; + } }; -Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test ){ - Texturable texturable; - graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable ) ); - return texturable; +Texturable Scene_getClosestTexturable(scene::Graph &graph, SelectionTest &test) +{ + Texturable texturable; + graph.traverse(BrushGetClosestFaceVisibleWalker(test, texturable)); + return texturable; } -bool Scene_getClosestTexture( scene::Graph& graph, SelectionTest& test, CopiedString& shader, TextureProjection& projection, ContentsFlagsValue& flags ){ - Texturable texturable = Scene_getClosestTexturable( graph, test ); - if ( texturable.getTexture != GetTextureCallback() ) { - texturable.getTexture( shader, projection, flags ); - return true; - } - return false; +bool +Scene_getClosestTexture(scene::Graph &graph, SelectionTest &test, CopiedString &shader, TextureProjection &projection, + ContentsFlagsValue &flags) +{ + Texturable texturable = Scene_getClosestTexturable(graph, test); + if (texturable.getTexture != GetTextureCallback()) { + texturable.getTexture(shader, projection, flags); + return true; + } + return false; } -void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ - Texturable texturable = Scene_getClosestTexturable( graph, test ); - if ( texturable.setTexture != SetTextureCallback() ) { - texturable.setTexture( shader, projection, flags ); - } +void Scene_setClosestTexture(scene::Graph &graph, SelectionTest &test, const char *shader, + const TextureProjection &projection, const ContentsFlagsValue &flags) +{ + Texturable texturable = Scene_getClosestTexturable(graph, test); + if (texturable.setTexture != SetTextureCallback()) { + texturable.setTexture(shader, projection, flags); + } } -class FaceTexture -{ +class FaceTexture { public: -TextureProjection m_projection; -ContentsFlagsValue m_flags; + TextureProjection m_projection; + ContentsFlagsValue m_flags; }; FaceTexture g_faceTextureClipboard; -void FaceTextureClipboard_setDefault(){ - g_faceTextureClipboard.m_flags = ContentsFlagsValue( 0, 0, 0, false ); - TexDef_Construct_Default( g_faceTextureClipboard.m_projection ); +void FaceTextureClipboard_setDefault() +{ + g_faceTextureClipboard.m_flags = ContentsFlagsValue(0, 0, 0, false); + TexDef_Construct_Default(g_faceTextureClipboard.m_projection); } -void TextureClipboard_textureSelected( const char* shader ){ - FaceTextureClipboard_setDefault(); +void TextureClipboard_textureSelected(const char *shader) +{ + FaceTextureClipboard_setDefault(); } class TextureBrowser; -extern TextureBrowser g_TextureBrowser; -void TextureBrowser_SetSelectedShader( TextureBrowser& textureBrowser, const char* shader ); -const char* TextureBrowser_GetSelectedShader( TextureBrowser& textureBrowser ); -void Scene_copyClosestTexture( SelectionTest& test ){ - CopiedString shader; - if ( Scene_getClosestTexture( GlobalSceneGraph(), test, shader, g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags ) ) { - TextureBrowser_SetSelectedShader( g_TextureBrowser, shader.c_str() ); - } -} +extern TextureBrowser g_TextureBrowser; -void Scene_applyClosestTexture( SelectionTest& test ){ - UndoableCommand command( "facePaintTexture" ); +void TextureBrowser_SetSelectedShader(TextureBrowser &textureBrowser, const char *shader); - Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags ); +const char *TextureBrowser_GetSelectedShader(TextureBrowser &textureBrowser); - SceneChangeNotify(); +void Scene_copyClosestTexture(SelectionTest &test) +{ + CopiedString shader; + if (Scene_getClosestTexture(GlobalSceneGraph(), test, shader, g_faceTextureClipboard.m_projection, + g_faceTextureClipboard.m_flags)) { + TextureBrowser_SetSelectedShader(g_TextureBrowser, shader.c_str()); + } } +void Scene_applyClosestTexture(SelectionTest &test) +{ + UndoableCommand command("facePaintTexture"); + Scene_setClosestTexture(GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader(g_TextureBrowser), + g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags); + SceneChangeNotify(); +} -void SelectedFaces_copyTexture(){ - if ( !g_SelectedFaceInstances.empty() ) { - Face& face = g_SelectedFaceInstances.last().getFace(); - face.GetTexdef( g_faceTextureClipboard.m_projection ); - g_faceTextureClipboard.m_flags = face.getShader().m_flags; +void SelectedFaces_copyTexture() +{ + if (!g_SelectedFaceInstances.empty()) { + Face &face = g_SelectedFaceInstances.last().getFace(); + face.GetTexdef(g_faceTextureClipboard.m_projection); + g_faceTextureClipboard.m_flags = face.getShader().m_flags; - TextureBrowser_SetSelectedShader( g_TextureBrowser, face.getShader().getShader() ); - } + TextureBrowser_SetSelectedShader(g_TextureBrowser, face.getShader().getShader()); + } } -void FaceInstance_pasteTexture( FaceInstance& faceInstance ){ - faceInstance.getFace().SetTexdef( g_faceTextureClipboard.m_projection ); - faceInstance.getFace().SetShader( TextureBrowser_GetSelectedShader( g_TextureBrowser ) ); - faceInstance.getFace().SetFlags( g_faceTextureClipboard.m_flags ); - SceneChangeNotify(); +void FaceInstance_pasteTexture(FaceInstance &faceInstance) +{ + faceInstance.getFace().SetTexdef(g_faceTextureClipboard.m_projection); + faceInstance.getFace().SetShader(TextureBrowser_GetSelectedShader(g_TextureBrowser)); + faceInstance.getFace().SetFlags(g_faceTextureClipboard.m_flags); + SceneChangeNotify(); } -bool SelectedFaces_empty(){ - return g_SelectedFaceInstances.empty(); +bool SelectedFaces_empty() +{ + return g_SelectedFaceInstances.empty(); } -void SelectedFaces_pasteTexture(){ - UndoableCommand command( "facePasteTexture" ); - g_SelectedFaceInstances.foreach( FaceInstance_pasteTexture ); +void SelectedFaces_pasteTexture() +{ + UndoableCommand command("facePasteTexture"); + g_SelectedFaceInstances.foreach(FaceInstance_pasteTexture); } - -void SurfaceInspector_constructPreferences( PreferencesPage& page ){ - page.appendCheckBox( "", "Surface Inspector Increments Match Grid", g_si_globals.m_bSnapTToGrid ); +void SurfaceInspector_constructPreferences(PreferencesPage &page) +{ + page.appendCheckBox("", "Surface Inspector Increments Match Grid", g_si_globals.m_bSnapTToGrid); } -void SurfaceInspector_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Surface Inspector", "Surface Inspector Preferences" ) ); - SurfaceInspector_constructPreferences( page ); + +void SurfaceInspector_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Surface Inspector", "Surface Inspector Preferences")); + SurfaceInspector_constructPreferences(page); } -void SurfaceInspector_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage( makeCallbackF(SurfaceInspector_constructPage) ); + +void SurfaceInspector_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(SurfaceInspector_constructPage)); } -void SurfaceInspector_registerCommands(){ - GlobalCommands_insert( "FitTexture", makeCallbackF(SurfaceInspector_FitTexture), Accelerator( 'B', (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "SurfaceInspector", makeCallbackF(SurfaceInspector_toggleShown), Accelerator( 'S' ) ); +void SurfaceInspector_registerCommands() +{ + GlobalCommands_insert("FitTexture", makeCallbackF(SurfaceInspector_FitTexture), + Accelerator('B', (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("SurfaceInspector", makeCallbackF(SurfaceInspector_toggleShown), Accelerator('S')); - GlobalCommands_insert( "FaceCopyTexture", makeCallbackF(SelectedFaces_copyTexture) ); - GlobalCommands_insert( "FacePasteTexture", makeCallbackF(SelectedFaces_pasteTexture) ); + GlobalCommands_insert("FaceCopyTexture", makeCallbackF(SelectedFaces_copyTexture)); + GlobalCommands_insert("FacePasteTexture", makeCallbackF(SelectedFaces_pasteTexture)); } #include "preferencesystem.h" -void SurfaceInspector_Construct(){ - g_SurfaceInspector = new SurfaceInspector; +void SurfaceInspector_Construct() +{ + g_SurfaceInspector = new SurfaceInspector; - SurfaceInspector_registerCommands(); + SurfaceInspector_registerCommands(); - FaceTextureClipboard_setDefault(); + FaceTextureClipboard_setDefault(); - GlobalPreferenceSystem().registerPreference( "SurfaceWnd", make_property( getSurfaceInspector().m_positionTracker) ); - GlobalPreferenceSystem().registerPreference( "SI_SurfaceTexdef_Scale1", make_property_string( g_si_globals.scale[0] ) ); - GlobalPreferenceSystem().registerPreference( "SI_SurfaceTexdef_Scale2", make_property_string( g_si_globals.scale[1] ) ); - GlobalPreferenceSystem().registerPreference( "SI_SurfaceTexdef_Shift1", make_property_string( g_si_globals.shift[0] ) ); - GlobalPreferenceSystem().registerPreference( "SI_SurfaceTexdef_Shift2", make_property_string( g_si_globals.shift[1] ) ); - GlobalPreferenceSystem().registerPreference( "SI_SurfaceTexdef_Rotate", make_property_string( g_si_globals.rotate ) ); - GlobalPreferenceSystem().registerPreference( "SnapTToGrid", make_property_string( g_si_globals.m_bSnapTToGrid ) ); + GlobalPreferenceSystem().registerPreference("SurfaceWnd", make_property( + getSurfaceInspector().m_positionTracker)); + GlobalPreferenceSystem().registerPreference("SI_SurfaceTexdef_Scale1", make_property_string(g_si_globals.scale[0])); + GlobalPreferenceSystem().registerPreference("SI_SurfaceTexdef_Scale2", make_property_string(g_si_globals.scale[1])); + GlobalPreferenceSystem().registerPreference("SI_SurfaceTexdef_Shift1", make_property_string(g_si_globals.shift[0])); + GlobalPreferenceSystem().registerPreference("SI_SurfaceTexdef_Shift2", make_property_string(g_si_globals.shift[1])); + GlobalPreferenceSystem().registerPreference("SI_SurfaceTexdef_Rotate", make_property_string(g_si_globals.rotate)); + GlobalPreferenceSystem().registerPreference("SnapTToGrid", make_property_string(g_si_globals.m_bSnapTToGrid)); - typedef FreeCaller SurfaceInspectorSelectionChangedCaller; - GlobalSelectionSystem().addSelectionChangeCallback( SurfaceInspectorSelectionChangedCaller() ); - typedef FreeCaller SurfaceInspectorUpdateSelectionCaller; - Brush_addTextureChangedCallback( SurfaceInspectorUpdateSelectionCaller() ); - Patch_addTextureChangedCallback( SurfaceInspectorUpdateSelectionCaller() ); + typedef FreeCaller SurfaceInspectorSelectionChangedCaller; + GlobalSelectionSystem().addSelectionChangeCallback(SurfaceInspectorSelectionChangedCaller()); + typedef FreeCaller SurfaceInspectorUpdateSelectionCaller; + Brush_addTextureChangedCallback(SurfaceInspectorUpdateSelectionCaller()); + Patch_addTextureChangedCallback(SurfaceInspectorUpdateSelectionCaller()); - SurfaceInspector_registerPreferencesPage(); -} -void SurfaceInspector_Destroy(){ - delete g_SurfaceInspector; + SurfaceInspector_registerPreferencesPage(); } +void SurfaceInspector_Destroy() +{ + delete g_SurfaceInspector; +} #if TEXTOOL_ENABLED @@ -1444,9 +1535,9 @@ namespace TexTool { // namespace hides these symbols from other object-files // But... You can see down below that it *is* initialized! WTF? struct Extent { - float minX, minY, maxX, maxY; - float width( void ) { return fabs( maxX - minX ); } - float height( void ) { return fabs( maxY - minY ); } + float minX, minY, maxX, maxY; + float width( void ) { return fabs( maxX - minX ); } + float height( void ) { return fabs( maxY - minY ); } }; //This seems to control the texture scale... (Yep! ;-) @@ -1489,51 +1580,51 @@ void DrawCircularArc( Vector2 ctr, float startAngle, float endAngle, float radiu void CopyPointsFromSelectedFace( void ){ - // Make sure that there's a face and winding to get! + // Make sure that there's a face and winding to get! - if ( g_SelectedFaceInstances.empty() ) { - numPts = 0; - return; - } + if ( g_SelectedFaceInstances.empty() ) { + numPts = 0; + return; + } - Face & face = g_SelectedFaceInstances.last().getFace(); - textureNum = face.getShader().m_state->getTexture().texture_number; - textureSize.x() = face.getShader().m_state->getTexture().width; - textureSize.y() = face.getShader().m_state->getTexture().height; + Face & face = g_SelectedFaceInstances.last().getFace(); + textureNum = face.getShader().m_state->getTexture().texture_number; + textureSize.x() = face.getShader().m_state->getTexture().width; + textureSize.y() = face.getShader().m_state->getTexture().height; //globalOutputStream() << "--> Texture #" << textureNum << ": " << textureSize.x() << " x " << textureSize.y() << "...\n"; - currentBP = SurfaceInspector_GetSelectedTexdef().m_brushprimit_texdef; + currentBP = SurfaceInspector_GetSelectedTexdef().m_brushprimit_texdef; - face.EmitTextureCoordinates(); - Winding & w = face.getWinding(); - int count = 0; + face.EmitTextureCoordinates(); + Winding & w = face.getWinding(); + int count = 0; - for ( Winding::const_iterator i = w.begin(); i != w.end(); i++ ) - { - //globalOutputStream() << (*i).texcoord.x() << " " << (*i).texcoord.y() << ", "; - pts[count].x() = ( *i ).texcoord.x(); - pts[count].y() = ( *i ).texcoord.y(); - count++; - } + for ( Winding::const_iterator i = w.begin(); i != w.end(); i++ ) + { + //globalOutputStream() << (*i).texcoord.x() << " " << (*i).texcoord.y() << ", "; + pts[count].x() = ( *i ).texcoord.x(); + pts[count].y() = ( *i ).texcoord.y(); + count++; + } - numPts = count; + numPts = count; - //globalOutputStream() << " ..copied points\n"; + //globalOutputStream() << " ..copied points\n"; } brushprimit_texdef_t bp; //This approach is probably wrongheaded and just not right anyway. So, !!! FIX !!! [DONE] void CommitChanges( void ){ - texdef_t t; // Throwaway, since this is BP only + texdef_t t; // Throwaway, since this is BP only - bp.coords[0][0] = tm.coords[0][0] * origBP.coords[0][0] + tm.coords[0][1] * origBP.coords[1][0]; - bp.coords[0][1] = tm.coords[0][0] * origBP.coords[0][1] + tm.coords[0][1] * origBP.coords[1][1]; - bp.coords[0][2] = tm.coords[0][0] * origBP.coords[0][2] + tm.coords[0][1] * origBP.coords[1][2] + tm.coords[0][2]; + bp.coords[0][0] = tm.coords[0][0] * origBP.coords[0][0] + tm.coords[0][1] * origBP.coords[1][0]; + bp.coords[0][1] = tm.coords[0][0] * origBP.coords[0][1] + tm.coords[0][1] * origBP.coords[1][1]; + bp.coords[0][2] = tm.coords[0][0] * origBP.coords[0][2] + tm.coords[0][1] * origBP.coords[1][2] + tm.coords[0][2]; //Ok, this works for translation... // bp.coords[0][2] = tm.coords[0][0] * origBP.coords[0][2] + tm.coords[0][1] * origBP.coords[1][2] + tm.coords[0][2] * textureSize.x(); - bp.coords[1][0] = tm.coords[1][0] * origBP.coords[0][0] + tm.coords[1][1] * origBP.coords[1][0]; - bp.coords[1][1] = tm.coords[1][0] * origBP.coords[0][1] + tm.coords[1][1] * origBP.coords[1][1]; - bp.coords[1][2] = tm.coords[1][0] * origBP.coords[0][2] + tm.coords[1][1] * origBP.coords[1][2] + tm.coords[1][2]; + bp.coords[1][0] = tm.coords[1][0] * origBP.coords[0][0] + tm.coords[1][1] * origBP.coords[1][0]; + bp.coords[1][1] = tm.coords[1][0] * origBP.coords[0][1] + tm.coords[1][1] * origBP.coords[1][1]; + bp.coords[1][2] = tm.coords[1][0] * origBP.coords[0][2] + tm.coords[1][1] * origBP.coords[1][2] + tm.coords[1][2]; // bp.coords[1][2] = tm.coords[1][0] * origBP.coords[0][2] + tm.coords[1][1] * origBP.coords[1][2] + tm.coords[1][2] * textureSize.y(); //This doesn't work: g_brush_texture_changed(); @@ -1541,7 +1632,7 @@ void CommitChanges( void ){ //Note: We should only set an undo *after* the button has been released... !!! FIX !!! //Definitely *should* have an undo, though! // UndoableCommand undo("textureProjectionSetSelected"); - Select_SetTexdef( TextureProjection( t, bp, Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ) ) ); + Select_SetTexdef( TextureProjection( t, bp, Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ) ) ); //This is working, but for some reason the translate is causing the rest of the SI //widgets to yield bad readings... !!! FIX !!! //I.e., click on textool window, translate face wireframe, then controls go crazy. Dunno why. @@ -1553,12 +1644,12 @@ void CommitChanges( void ){ } void UpdateControlPoints( void ){ - CommitChanges(); + CommitChanges(); - // Init texture transform matrix + // Init texture transform matrix - tm.coords[0][0] = 1.0f; tm.coords[0][1] = 0.0f; tm.coords[0][2] = 0.0f; - tm.coords[1][0] = 0.0f; tm.coords[1][1] = 1.0f; tm.coords[1][2] = 0.0f; + tm.coords[0][0] = 1.0f; tm.coords[0][1] = 0.0f; tm.coords[0][2] = 0.0f; + tm.coords[1][0] = 0.0f; tm.coords[1][1] = 1.0f; tm.coords[1][2] = 0.0f; } @@ -1593,18 +1684,18 @@ const float gridRadius = gridWidth * 0.5f; typedef const float WidgetColor[3]; const WidgetColor widgetColor[10] = { - { 1.0000f, 0.2000f, 0.0000f }, // Red - { 0.9137f, 0.9765f, 0.4980f }, // Yellow - { 0.0000f, 0.6000f, 0.3216f }, // Green - { 0.6157f, 0.7726f, 0.8196f }, // Cyan - { 0.4980f, 0.5000f, 0.4716f }, // Grey - - // Highlight colors - { 1.0000f, 0.6000f, 0.4000f }, // Light Red - { 1.0000f, 1.0000f, 0.8980f }, // Light Yellow - { 0.4000f, 1.0000f, 0.7216f }, // Light Green - { 1.0000f, 1.0000f, 1.0000f }, // Light Cyan - { 0.8980f, 0.9000f, 0.8716f } // Light Grey + { 1.0000f, 0.2000f, 0.0000f }, // Red + { 0.9137f, 0.9765f, 0.4980f }, // Yellow + { 0.0000f, 0.6000f, 0.3216f }, // Green + { 0.6157f, 0.7726f, 0.8196f }, // Cyan + { 0.4980f, 0.5000f, 0.4716f }, // Grey + + // Highlight colors + { 1.0000f, 0.6000f, 0.4000f }, // Light Red + { 1.0000f, 1.0000f, 0.8980f }, // Light Yellow + { 0.4000f, 1.0000f, 0.7216f }, // Light Green + { 1.0000f, 1.0000f, 1.0000f }, // Light Cyan + { 0.8980f, 0.9000f, 0.8716f } // Light Grey }; #define COLOR_RED 0 @@ -1620,188 +1711,188 @@ const WidgetColor widgetColor[10] = { void DrawControlWidgets( void ){ //Note that the grid should go *behind* the face outline... !!! FIX !!! - // Grid - float xStart = center.x() - ( gridWidth / 2.0f ); - float yStart = center.y() - ( gridWidth / 2.0f ); - float xScale = ( extents.height() / extents.width() ) * ( textureSize.y() / textureSize.x() ); + // Grid + float xStart = center.x() - ( gridWidth / 2.0f ); + float yStart = center.y() - ( gridWidth / 2.0f ); + float xScale = ( extents.height() / extents.width() ) * ( textureSize.y() / textureSize.x() ); - glPushMatrix(); + glPushMatrix(); //Small problem with this approach: Changing the center point in the TX code doesn't seem to //change anything here--prolly because we load a new identity matrix. A couple of ways to fix //this would be to get rid of that code, or change the center to a new point by taking into //account the transforms that we toss with the new identity matrix. Dunno which is better. - glLoadIdentity(); - glScalef( xScale, 1.0, 1.0 ); // Will that square it up? Yup. - glRotatef( static_cast( radians_to_degrees( atan2( -currentBP.coords[0][1], currentBP.coords[0][0] ) ) ), 0.0, 0.0, -1.0 ); - glTranslatef( -center.x(), -center.y(), 0.0 ); - - // Circle - glColor3fv( translatingX && translatingY ? widgetColor[COLOR_LT_YELLOW] : widgetColor[COLOR_YELLOW] ); - glBegin( GL_LINE_LOOP ); - DrawCircularArc( center, 0, 2.0f * PI, gridRadius * 0.16 ); - - glEnd(); - - // Axes - glBegin( GL_LINES ); - glColor3fv( translatingY && !translatingX ? widgetColor[COLOR_LT_GREEN] : widgetColor[COLOR_GREEN] ); - glVertex2f( center.x(), center.y() + ( gridRadius * 0.16 ) ); - glVertex2f( center.x(), center.y() + ( gridRadius * 1.00 ) ); - glColor3fv( translatingX && !translatingY ? widgetColor[COLOR_LT_RED] : widgetColor[COLOR_RED] ); - glVertex2f( center.x() + ( gridRadius * 0.16 ), center.y() ); - glVertex2f( center.x() + ( gridRadius * 1.00 ), center.y() ); - glEnd(); - - // Arrowheads - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - glBegin( GL_TRIANGLES ); - glColor3fv( translatingY && !translatingX ? widgetColor[COLOR_LT_GREEN] : widgetColor[COLOR_GREEN] ); - glVertex2f( center.x(), center.y() + ( gridRadius * 1.10 ) ); - glVertex2f( center.x() + ( gridRadius * 0.06 ), center.y() + ( gridRadius * 0.94 ) ); - glVertex2f( center.x() - ( gridRadius * 0.06 ), center.y() + ( gridRadius * 0.94 ) ); - glColor3fv( translatingX && !translatingY ? widgetColor[COLOR_LT_RED] : widgetColor[COLOR_RED] ); - glVertex2f( center.x() + ( gridRadius * 1.10 ), center.y() ); - glVertex2f( center.x() + ( gridRadius * 0.94 ), center.y() + ( gridRadius * 0.06 ) ); - glVertex2f( center.x() + ( gridRadius * 0.94 ), center.y() - ( gridRadius * 0.06 ) ); - glEnd(); - - // Arc - glBegin( GL_LINE_STRIP ); - glColor3fv( rotating ? widgetColor[COLOR_LT_CYAN] : widgetColor[COLOR_CYAN] ); - DrawCircularArc( center, 0.03f * PI, 0.47f * PI, gridRadius * 0.90 ); - glEnd(); - - // Boxes - glColor3fv( scalingY && !scalingX ? widgetColor[COLOR_LT_GREEN] : widgetColor[COLOR_GREEN] ); - glBegin( GL_LINES ); - glVertex2f( center.x() + ( gridRadius * 0.20 ), center.y() + ( gridRadius * 1.50 ) ); - glVertex2f( center.x() - ( gridRadius * 0.20 ), center.y() + ( gridRadius * 1.50 ) ); - glEnd(); - glBegin( GL_LINE_LOOP ); - glVertex2f( center.x() + ( gridRadius * 0.10 ), center.y() + ( gridRadius * 1.40 ) ); - glVertex2f( center.x() - ( gridRadius * 0.10 ), center.y() + ( gridRadius * 1.40 ) ); - glVertex2f( center.x() - ( gridRadius * 0.10 ), center.y() + ( gridRadius * 1.20 ) ); - glVertex2f( center.x() + ( gridRadius * 0.10 ), center.y() + ( gridRadius * 1.20 ) ); - glEnd(); - - glColor3fv( scalingX && !scalingY ? widgetColor[COLOR_LT_RED] : widgetColor[COLOR_RED] ); - glBegin( GL_LINES ); - glVertex2f( center.x() + ( gridRadius * 1.50 ), center.y() + ( gridRadius * 0.20 ) ); - glVertex2f( center.x() + ( gridRadius * 1.50 ), center.y() - ( gridRadius * 0.20 ) ); - glEnd(); - glBegin( GL_LINE_LOOP ); - glVertex2f( center.x() + ( gridRadius * 1.40 ), center.y() + ( gridRadius * 0.10 ) ); - glVertex2f( center.x() + ( gridRadius * 1.40 ), center.y() - ( gridRadius * 0.10 ) ); - glVertex2f( center.x() + ( gridRadius * 1.20 ), center.y() - ( gridRadius * 0.10 ) ); - glVertex2f( center.x() + ( gridRadius * 1.20 ), center.y() + ( gridRadius * 0.10 ) ); - glEnd(); - - glColor3fv( scalingX && scalingY ? widgetColor[COLOR_LT_CYAN] : widgetColor[COLOR_CYAN] ); - glBegin( GL_LINE_STRIP ); - glVertex2f( center.x() + ( gridRadius * 1.50 ), center.y() + ( gridRadius * 1.10 ) ); - glVertex2f( center.x() + ( gridRadius * 1.50 ), center.y() + ( gridRadius * 1.50 ) ); - glVertex2f( center.x() + ( gridRadius * 1.10 ), center.y() + ( gridRadius * 1.50 ) ); - glEnd(); - glBegin( GL_LINE_LOOP ); - glVertex2f( center.x() + ( gridRadius * 1.40 ), center.y() + ( gridRadius * 1.40 ) ); - glVertex2f( center.x() + ( gridRadius * 1.40 ), center.y() + ( gridRadius * 1.20 ) ); - glVertex2f( center.x() + ( gridRadius * 1.20 ), center.y() + ( gridRadius * 1.20 ) ); - glVertex2f( center.x() + ( gridRadius * 1.20 ), center.y() + ( gridRadius * 1.40 ) ); - glEnd(); - - glPopMatrix(); + glLoadIdentity(); + glScalef( xScale, 1.0, 1.0 ); // Will that square it up? Yup. + glRotatef( static_cast( radians_to_degrees( atan2( -currentBP.coords[0][1], currentBP.coords[0][0] ) ) ), 0.0, 0.0, -1.0 ); + glTranslatef( -center.x(), -center.y(), 0.0 ); + + // Circle + glColor3fv( translatingX && translatingY ? widgetColor[COLOR_LT_YELLOW] : widgetColor[COLOR_YELLOW] ); + glBegin( GL_LINE_LOOP ); + DrawCircularArc( center, 0, 2.0f * PI, gridRadius * 0.16 ); + + glEnd(); + + // Axes + glBegin( GL_LINES ); + glColor3fv( translatingY && !translatingX ? widgetColor[COLOR_LT_GREEN] : widgetColor[COLOR_GREEN] ); + glVertex2f( center.x(), center.y() + ( gridRadius * 0.16 ) ); + glVertex2f( center.x(), center.y() + ( gridRadius * 1.00 ) ); + glColor3fv( translatingX && !translatingY ? widgetColor[COLOR_LT_RED] : widgetColor[COLOR_RED] ); + glVertex2f( center.x() + ( gridRadius * 0.16 ), center.y() ); + glVertex2f( center.x() + ( gridRadius * 1.00 ), center.y() ); + glEnd(); + + // Arrowheads + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + glBegin( GL_TRIANGLES ); + glColor3fv( translatingY && !translatingX ? widgetColor[COLOR_LT_GREEN] : widgetColor[COLOR_GREEN] ); + glVertex2f( center.x(), center.y() + ( gridRadius * 1.10 ) ); + glVertex2f( center.x() + ( gridRadius * 0.06 ), center.y() + ( gridRadius * 0.94 ) ); + glVertex2f( center.x() - ( gridRadius * 0.06 ), center.y() + ( gridRadius * 0.94 ) ); + glColor3fv( translatingX && !translatingY ? widgetColor[COLOR_LT_RED] : widgetColor[COLOR_RED] ); + glVertex2f( center.x() + ( gridRadius * 1.10 ), center.y() ); + glVertex2f( center.x() + ( gridRadius * 0.94 ), center.y() + ( gridRadius * 0.06 ) ); + glVertex2f( center.x() + ( gridRadius * 0.94 ), center.y() - ( gridRadius * 0.06 ) ); + glEnd(); + + // Arc + glBegin( GL_LINE_STRIP ); + glColor3fv( rotating ? widgetColor[COLOR_LT_CYAN] : widgetColor[COLOR_CYAN] ); + DrawCircularArc( center, 0.03f * PI, 0.47f * PI, gridRadius * 0.90 ); + glEnd(); + + // Boxes + glColor3fv( scalingY && !scalingX ? widgetColor[COLOR_LT_GREEN] : widgetColor[COLOR_GREEN] ); + glBegin( GL_LINES ); + glVertex2f( center.x() + ( gridRadius * 0.20 ), center.y() + ( gridRadius * 1.50 ) ); + glVertex2f( center.x() - ( gridRadius * 0.20 ), center.y() + ( gridRadius * 1.50 ) ); + glEnd(); + glBegin( GL_LINE_LOOP ); + glVertex2f( center.x() + ( gridRadius * 0.10 ), center.y() + ( gridRadius * 1.40 ) ); + glVertex2f( center.x() - ( gridRadius * 0.10 ), center.y() + ( gridRadius * 1.40 ) ); + glVertex2f( center.x() - ( gridRadius * 0.10 ), center.y() + ( gridRadius * 1.20 ) ); + glVertex2f( center.x() + ( gridRadius * 0.10 ), center.y() + ( gridRadius * 1.20 ) ); + glEnd(); + + glColor3fv( scalingX && !scalingY ? widgetColor[COLOR_LT_RED] : widgetColor[COLOR_RED] ); + glBegin( GL_LINES ); + glVertex2f( center.x() + ( gridRadius * 1.50 ), center.y() + ( gridRadius * 0.20 ) ); + glVertex2f( center.x() + ( gridRadius * 1.50 ), center.y() - ( gridRadius * 0.20 ) ); + glEnd(); + glBegin( GL_LINE_LOOP ); + glVertex2f( center.x() + ( gridRadius * 1.40 ), center.y() + ( gridRadius * 0.10 ) ); + glVertex2f( center.x() + ( gridRadius * 1.40 ), center.y() - ( gridRadius * 0.10 ) ); + glVertex2f( center.x() + ( gridRadius * 1.20 ), center.y() - ( gridRadius * 0.10 ) ); + glVertex2f( center.x() + ( gridRadius * 1.20 ), center.y() + ( gridRadius * 0.10 ) ); + glEnd(); + + glColor3fv( scalingX && scalingY ? widgetColor[COLOR_LT_CYAN] : widgetColor[COLOR_CYAN] ); + glBegin( GL_LINE_STRIP ); + glVertex2f( center.x() + ( gridRadius * 1.50 ), center.y() + ( gridRadius * 1.10 ) ); + glVertex2f( center.x() + ( gridRadius * 1.50 ), center.y() + ( gridRadius * 1.50 ) ); + glVertex2f( center.x() + ( gridRadius * 1.10 ), center.y() + ( gridRadius * 1.50 ) ); + glEnd(); + glBegin( GL_LINE_LOOP ); + glVertex2f( center.x() + ( gridRadius * 1.40 ), center.y() + ( gridRadius * 1.40 ) ); + glVertex2f( center.x() + ( gridRadius * 1.40 ), center.y() + ( gridRadius * 1.20 ) ); + glVertex2f( center.x() + ( gridRadius * 1.20 ), center.y() + ( gridRadius * 1.20 ) ); + glVertex2f( center.x() + ( gridRadius * 1.20 ), center.y() + ( gridRadius * 1.40 ) ); + glEnd(); + + glPopMatrix(); } void DrawControlPoints( void ){ - glColor3f( 1, 1, 1 ); - glBegin( GL_LINE_LOOP ); + glColor3f( 1, 1, 1 ); + glBegin( GL_LINE_LOOP ); - for ( int i = 0; i < numPts; i++ ) - glVertex2f( pts[i].x(), pts[i].y() ); + for ( int i = 0; i < numPts; i++ ) + glVertex2f( pts[i].x(), pts[i].y() ); - glEnd(); + glEnd(); } // Note: Setup and all that jazz must be done by the caller! void DrawCircularArc( Vector2 ctr, float startAngle, float endAngle, float radius ){ - float stepSize = ( 2.0f * PI ) / 200.0f; + float stepSize = ( 2.0f * PI ) / 200.0f; - for ( float angle = startAngle; angle <= endAngle; angle += stepSize ) - glVertex2f( ctr.x() + radius * cos( angle ), ctr.y() + radius * sin( angle ) ); + for ( float angle = startAngle; angle <= endAngle; angle += stepSize ) + glVertex2f( ctr.x() + radius * cos( angle ), ctr.y() + radius * sin( angle ) ); } void focus(){ - if ( numPts == 0 ) { - return; - } - - // Find selected texture's extents... - - extents.minX = extents.maxX = pts[0].x(), - extents.minY = extents.maxY = pts[0].y(); - - for ( int i = 1; i < numPts; i++ ) - { - if ( pts[i].x() < extents.minX ) { - extents.minX = pts[i].x(); - } - if ( pts[i].x() > extents.maxX ) { - extents.maxX = pts[i].x(); - } - if ( pts[i].y() < extents.minY ) { - extents.minY = pts[i].y(); - } - if ( pts[i].y() > extents.maxY ) { - extents.maxY = pts[i].y(); - } - } - - // Do some viewport fitting stuff... + if ( numPts == 0 ) { + return; + } + + // Find selected texture's extents... + + extents.minX = extents.maxX = pts[0].x(), + extents.minY = extents.maxY = pts[0].y(); + + for ( int i = 1; i < numPts; i++ ) + { + if ( pts[i].x() < extents.minX ) { + extents.minX = pts[i].x(); + } + if ( pts[i].x() > extents.maxX ) { + extents.maxX = pts[i].x(); + } + if ( pts[i].y() < extents.minY ) { + extents.minY = pts[i].y(); + } + if ( pts[i].y() > extents.maxY ) { + extents.maxY = pts[i].y(); + } + } + + // Do some viewport fitting stuff... //globalOutputStream() << "--> Center: " << center.x() << ", " << center.y() << "\n"; //globalOutputStream() << "--> Extents (stage 1): " << extents.minX << ", " // << extents.maxX << ", " << extents.minY << ", " << extents.maxY << "\n"; - // TTimo: Apply a ratio to get the area we'll draw. - center.x() = 0.5f * ( extents.minX + extents.maxX ), - center.y() = 0.5f * ( extents.minY + extents.maxY ); - extents.minX = center.x() + VP_PADDING * ( extents.minX - center.x() ), - extents.minY = center.y() + VP_PADDING * ( extents.minY - center.y() ), - extents.maxX = center.x() + VP_PADDING * ( extents.maxX - center.x() ), - extents.maxY = center.y() + VP_PADDING * ( extents.maxY - center.y() ); + // TTimo: Apply a ratio to get the area we'll draw. + center.x() = 0.5f * ( extents.minX + extents.maxX ), + center.y() = 0.5f * ( extents.minY + extents.maxY ); + extents.minX = center.x() + VP_PADDING * ( extents.minX - center.x() ), + extents.minY = center.y() + VP_PADDING * ( extents.minY - center.y() ), + extents.maxX = center.x() + VP_PADDING * ( extents.maxX - center.x() ), + extents.maxY = center.y() + VP_PADDING * ( extents.maxY - center.y() ); //globalOutputStream() << "--> Extents (stage 2): " << extents.minX << ", " // << extents.maxX << ", " << extents.minY << ", " << extents.maxY << "\n"; - // TTimo: We want a texture with the same X / Y ratio. - // TTimo: Compute XY space / window size ratio. - float SSize = extents.width(), TSize = extents.height(); - float ratioX = textureSize.x() * extents.width() / windowSize.x(), - ratioY = textureSize.y() * extents.height() / windowSize.y(); + // TTimo: We want a texture with the same X / Y ratio. + // TTimo: Compute XY space / window size ratio. + float SSize = extents.width(), TSize = extents.height(); + float ratioX = textureSize.x() * extents.width() / windowSize.x(), + ratioY = textureSize.y() * extents.height() / windowSize.y(); //globalOutputStream() << "--> Texture size: " << textureSize.x() << ", " << textureSize.y() << "\n"; //globalOutputStream() << "--> Window size: " << windowSize.x() << ", " << windowSize.y() << "\n"; - if ( ratioX > ratioY ) { - TSize = ( windowSize.y() * ratioX ) / textureSize.y(); + if ( ratioX > ratioY ) { + TSize = ( windowSize.y() * ratioX ) / textureSize.y(); // TSize = extents.width() * (windowSize.y() / windowSize.x()) * (textureSize.x() / textureSize.y()); - } - else - { - SSize = ( windowSize.x() * ratioY ) / textureSize.x(); + } + else + { + SSize = ( windowSize.x() * ratioY ) / textureSize.x(); // SSize = extents.height() * (windowSize.x() / windowSize.y()) * (textureSize.y() / textureSize.x()); - } + } - extents.minX = center.x() - 0.5f * SSize, extents.maxX = center.x() + 0.5f * SSize, - extents.minY = center.y() - 0.5f * TSize, extents.maxY = center.y() + 0.5f * TSize; + extents.minX = center.x() - 0.5f * SSize, extents.maxX = center.x() + 0.5f * SSize, + extents.minY = center.y() - 0.5f * TSize, extents.maxY = center.y() + 0.5f * TSize; //globalOutputStream() << "--> Extents (stage 3): " << extents.minX << ", " // << extents.maxX << ", " << extents.minY << ", " << extents.maxY << "\n"; } gboolean size_allocate( ui::Widget win, GtkAllocation * a, gpointer ){ - windowSize.x() = a->width; - windowSize.y() = a->height; - queueDraw(); - return false; + windowSize.x() = a->width; + windowSize.y() = a->height; + queueDraw(); + return false; } gboolean expose( ui::Widget win, GdkEventExpose * e, gpointer ){ @@ -1812,77 +1903,77 @@ gboolean expose( ui::Widget win, GdkEventExpose * e, gpointer ){ //This needs to go elsewhere... // InitTextool(); - if ( glwidget_make_current( win ) == FALSE ) { - globalOutputStream() << " FAILED to make current! Oh, the agony! :-(\n"; - return true; - } + if ( glwidget_make_current( win ) == FALSE ) { + globalOutputStream() << " FAILED to make current! Oh, the agony! :-(\n"; + return true; + } - CopyPointsFromSelectedFace(); + CopyPointsFromSelectedFace(); - if ( !lButtonDown ) { - focus(); - } + if ( !lButtonDown ) { + focus(); + } - // Probably should init button/anchor states here as well... + // Probably should init button/anchor states here as well... // rotationAngle = 0.0f; - glClearColor( 0, 0, 0, 0 ); - glViewport( 0, 0, e->area.width, e->area.height ); - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); + glClearColor( 0, 0, 0, 0 ); + glViewport( 0, 0, e->area.width, e->area.height ); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); //??? - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - glDisable( GL_DEPTH_TEST ); - glDisable( GL_BLEND ); - - glOrtho( extents.minX, extents.maxX, extents.maxY, extents.minY, -1, 1 ); - - glColor3f( 1, 1, 1 ); - // draw the texture background - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - glBindTexture( GL_TEXTURE_2D, textureNum ); - - glEnable( GL_TEXTURE_2D ); - glBegin( GL_QUADS ); - glTexCoord2f( extents.minX, extents.minY ); - glVertex2f( extents.minX, extents.minY ); - glTexCoord2f( extents.maxX, extents.minY ); - glVertex2f( extents.maxX, extents.minY ); - glTexCoord2f( extents.maxX, extents.maxY ); - glVertex2f( extents.maxX, extents.maxY ); - glTexCoord2f( extents.minX, extents.maxY ); - glVertex2f( extents.minX, extents.maxY ); - glEnd(); - glDisable( GL_TEXTURE_2D ); - - // draw the texture-space grid - glColor3fv( widgetColor[COLOR_GREY] ); - glBegin( GL_LINES ); - - const int gridSubdivisions = 8; - const float gridExtents = 4.0f; - - for ( int i = 0; i < gridSubdivisions + 1; ++i ) - { - float y = i * ( gridExtents / float(gridSubdivisions) ); - float x = i * ( gridExtents / float(gridSubdivisions) ); - glVertex2f( 0, y ); - glVertex2f( gridExtents, y ); - glVertex2f( x, 0 ); - glVertex2f( x, gridExtents ); - } - - glEnd(); - - DrawControlPoints(); - DrawControlWidgets(); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glDisable( GL_DEPTH_TEST ); + glDisable( GL_BLEND ); + + glOrtho( extents.minX, extents.maxX, extents.maxY, extents.minY, -1, 1 ); + + glColor3f( 1, 1, 1 ); + // draw the texture background + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + glBindTexture( GL_TEXTURE_2D, textureNum ); + + glEnable( GL_TEXTURE_2D ); + glBegin( GL_QUADS ); + glTexCoord2f( extents.minX, extents.minY ); + glVertex2f( extents.minX, extents.minY ); + glTexCoord2f( extents.maxX, extents.minY ); + glVertex2f( extents.maxX, extents.minY ); + glTexCoord2f( extents.maxX, extents.maxY ); + glVertex2f( extents.maxX, extents.maxY ); + glTexCoord2f( extents.minX, extents.maxY ); + glVertex2f( extents.minX, extents.maxY ); + glEnd(); + glDisable( GL_TEXTURE_2D ); + + // draw the texture-space grid + glColor3fv( widgetColor[COLOR_GREY] ); + glBegin( GL_LINES ); + + const int gridSubdivisions = 8; + const float gridExtents = 4.0f; + + for ( int i = 0; i < gridSubdivisions + 1; ++i ) + { + float y = i * ( gridExtents / float(gridSubdivisions) ); + float x = i * ( gridExtents / float(gridSubdivisions) ); + glVertex2f( 0, y ); + glVertex2f( gridExtents, y ); + glVertex2f( x, 0 ); + glVertex2f( x, gridExtents ); + } + + glEnd(); + + DrawControlPoints(); + DrawControlWidgets(); //??? - // reset the current texture + // reset the current texture // glBindTexture(GL_TEXTURE_2D, 0); // glFinish(); - glwidget_swap_buffers( win ); + glwidget_swap_buffers( win ); - return false; + return false; } /*int FindSelectedPoint(int x, int y) @@ -1906,29 +1997,29 @@ Vector2 oldTrans; gboolean button_press( ui::Widget win, GdkEventButton * e, gpointer ){ // globalOutputStream() << "--> Textool button press...\n"; - if ( e->button == 1 ) { - lButtonDown = true; - GlobalUndoSystem().start(); + if ( e->button == 1 ) { + lButtonDown = true; + GlobalUndoSystem().start(); - origBP = currentBP; + origBP = currentBP; - //globalOutputStream() << "--> Original BP: [" << origBP.coords[0][0] << "][" << origBP.coords[0][1] << "][" << origBP.coords[0][2] << "]\n"; - //globalOutputStream() << " [" << origBP.coords[1][0] << "][" << origBP.coords[1][1] << "][" << origBP.coords[1][2] << "]\n"; - //float angle = atan2(origBP.coords[0][1], origBP.coords[0][0]) * 180.0f / 3.141592653589f; - origAngle = ( origBP.coords[0][1] > 0 ? PI : -PI ); // Could also be -PI... !!! FIX !!! [DONE] + //globalOutputStream() << "--> Original BP: [" << origBP.coords[0][0] << "][" << origBP.coords[0][1] << "][" << origBP.coords[0][2] << "]\n"; + //globalOutputStream() << " [" << origBP.coords[1][0] << "][" << origBP.coords[1][1] << "][" << origBP.coords[1][2] << "]\n"; + //float angle = atan2(origBP.coords[0][1], origBP.coords[0][0]) * 180.0f / 3.141592653589f; + origAngle = ( origBP.coords[0][1] > 0 ? PI : -PI ); // Could also be -PI... !!! FIX !!! [DONE] - if ( origBP.coords[0][0] != 0.0f ) { - origAngle = atan( origBP.coords[0][1] / origBP.coords[0][0] ); - } + if ( origBP.coords[0][0] != 0.0f ) { + origAngle = atan( origBP.coords[0][1] / origBP.coords[0][0] ); + } - origScaleX = origBP.coords[0][0] / cos( origAngle ); - origScaleY = origBP.coords[1][1] / cos( origAngle ); - rotationAngle = origAngle; - oldCenter[0] = oldCenter[1] = 0; + origScaleX = origBP.coords[0][0] / cos( origAngle ); + origScaleY = origBP.coords[1][1] / cos( origAngle ); + rotationAngle = origAngle; + oldCenter[0] = oldCenter[1] = 0; - //globalOutputStream() << "--> BP stats: ang=" << origAngle * RAD_TO_DEG << ", scale=" << origScaleX << "/" << origScaleY << "\n"; - //Should also set the Flip X/Y checkboxes here as well... !!! FIX !!! - //Also: should reverse texture left/right up/down instead of flipping the points... + //globalOutputStream() << "--> BP stats: ang=" << origAngle * RAD_TO_DEG << ", scale=" << origScaleX << "/" << origScaleY << "\n"; + //Should also set the Flip X/Y checkboxes here as well... !!! FIX !!! + //Also: should reverse texture left/right up/down instead of flipping the points... //disnowok //float nx = windowSize.x() * (e->x - extents.minX) / (extents.maxX - extents.minX); @@ -1936,25 +2027,25 @@ gboolean button_press( ui::Widget win, GdkEventButton * e, gpointer ){ //disdoes... //But I want it to scroll the texture window, not the points... !!! FIX !!! //Actually, should scroll the texture window only when mouse is down on no widgets... - float nx = e->x / windowSize.x() * extents.width() + extents.minX; - float ny = e->y / windowSize.y() * extents.height() + extents.minY; - trans.x() = -tm.coords[0][0] * nx - tm.coords[0][1] * ny; - trans.y() = -tm.coords[1][0] * nx - tm.coords[1][1] * ny; - - dragPoint.x() = e->x, dragPoint.y() = e->y; - trans2.x() = nx, trans2.y() = ny; - oldRotationAngle = rotationAngle; + float nx = e->x / windowSize.x() * extents.width() + extents.minX; + float ny = e->y / windowSize.y() * extents.height() + extents.minY; + trans.x() = -tm.coords[0][0] * nx - tm.coords[0][1] * ny; + trans.y() = -tm.coords[1][0] * nx - tm.coords[1][1] * ny; + + dragPoint.x() = e->x, dragPoint.y() = e->y; + trans2.x() = nx, trans2.y() = ny; + oldRotationAngle = rotationAngle; // oldTrans.x() = tm.coords[0][2] - nx * textureSize.x(); // oldTrans.y() = tm.coords[1][2] - ny * textureSize.y(); - oldTrans.x() = tm.coords[0][2]; - oldTrans.y() = tm.coords[1][2]; - oldCenter.x() = center.x(); - oldCenter.y() = center.y(); + oldTrans.x() = tm.coords[0][2]; + oldTrans.y() = tm.coords[1][2]; + oldCenter.x() = center.x(); + oldCenter.y() = center.y(); - queueDraw(); + queueDraw(); - return true; - } + return true; + } /* else if (e->button == 3) { rButtonDown = true; @@ -1962,13 +2053,13 @@ gboolean button_press( ui::Widget win, GdkEventButton * e, gpointer ){ //globalOutputStream() << "(" << (haveAnchor ? "anchor" : "released") << ")\n"; - return false; + return false; } gboolean button_release( ui::Widget win, GdkEventButton * e, gpointer ){ // globalOutputStream() << "--> Textool button release...\n"; - if ( e->button == 1 ) { + if ( e->button == 1 ) { /* float ptx = e->x / windowSize.x() * extents.width() + extents.minX; float pty = e->y / windowSize.y() * extents.height() + extents.minY; @@ -1977,35 +2068,35 @@ gboolean button_release( ui::Widget win, GdkEventButton * e, gpointer ){ if (translatingX || translatingY) center.x() = ptx, center.y() = pty;//*/ - lButtonDown = false; - - if ( translatingX || translatingY ) { - GlobalUndoSystem().finish( "translateTexture" ); - } - else if ( rotating ) { - GlobalUndoSystem().finish( "rotateTexture" ); - } - else if ( scalingX || scalingY ) { - GlobalUndoSystem().finish( "scaleTexture" ); - } - else if ( resizingX || resizingY ) { - GlobalUndoSystem().finish( "resizeTexture" ); - } - else - { - GlobalUndoSystem().finish( "textoolUnknown" ); - } - - rotating = translatingX = translatingY = scalingX = scalingY - = resizingX = resizingY = false; - - queueDraw(); - } - else if ( e->button == 3 ) { - rButtonDown = false; - } - - return true; + lButtonDown = false; + + if ( translatingX || translatingY ) { + GlobalUndoSystem().finish( "translateTexture" ); + } + else if ( rotating ) { + GlobalUndoSystem().finish( "rotateTexture" ); + } + else if ( scalingX || scalingY ) { + GlobalUndoSystem().finish( "scaleTexture" ); + } + else if ( resizingX || resizingY ) { + GlobalUndoSystem().finish( "resizeTexture" ); + } + else + { + GlobalUndoSystem().finish( "textoolUnknown" ); + } + + rotating = translatingX = translatingY = scalingX = scalingY + = resizingX = resizingY = false; + + queueDraw(); + } + else if ( e->button == 3 ) { + rButtonDown = false; + } + + return true; } /* @@ -2030,58 +2121,58 @@ gboolean button_release( ui::Widget win, GdkEventButton * e, gpointer ){ gboolean motion( ui::Widget win, GdkEventMotion * e, gpointer ){ // globalOutputStream() << "--> Textool motion...\n"; - if ( lButtonDown ) { - if ( translatingX || translatingY ) { - float ptx = e->x / windowSize.x() * extents.width() + extents.minX; - float pty = e->y / windowSize.y() * extents.height() + extents.minY; + if ( lButtonDown ) { + if ( translatingX || translatingY ) { + float ptx = e->x / windowSize.x() * extents.width() + extents.minX; + float pty = e->y / windowSize.y() * extents.height() + extents.minY; //Need to fix this to take the rotation angle into account, so that it moves along //the rotated X/Y axis... - if ( translatingX ) { + if ( translatingX ) { // tm.coords[0][2] = (trans.x() + ptx) * textureSize.x(); //This works, but only when the angle is zero. !!! FIX !!! [DONE] // tm.coords[0][2] = oldCenter.x() + (ptx * textureSize.x()); - tm.coords[0][2] = oldTrans.x() + ( ptx - trans2.x() ) * textureSize.x(); + tm.coords[0][2] = oldTrans.x() + ( ptx - trans2.x() ) * textureSize.x(); // center.x() = oldCenter.x() + (ptx - trans2.x()); - } + } - if ( translatingY ) { + if ( translatingY ) { // tm.coords[1][2] = (trans.y() + pty) * textureSize.y(); // tm.coords[1][2] = oldCenter.y() + (pty * textureSize.y()); - tm.coords[1][2] = oldTrans.y() + ( pty - trans2.y() ) * textureSize.y(); + tm.coords[1][2] = oldTrans.y() + ( pty - trans2.y() ) * textureSize.y(); // center.y() = oldCenter.y() + (pty - trans2.y()); - } + } //Need to update center.x/y() so that the widget translates as well. Also, oldCenter //is badly named... Should be oldTrans or something like that... !!! FIX !!! //Changing center.x/y() here doesn't seem to change anything... :-/ - UpdateControlPoints(); - } - else if ( rotating ) { - // Shamus: New rotate code - int cx = (int)( windowSize.x() * ( center.x() - extents.minX ) / extents.width() ); - int cy = (int)( windowSize.y() * ( center.y() - extents.minY ) / extents.height() ); - Vector3 v1( dragPoint.x() - cx, dragPoint.y() - cy, 0 ), v2( e->x - cx, e->y - cy, 0 ); - - vector3_normalise( v1 ); - vector3_normalise( v2 ); - float c = vector3_dot( v1, v2 ); - Vector3 cross = vector3_cross( v1, v2 ); - float s = vector3_length( cross ); - - if ( cross[2] > 0 ) { - s = -s; - } + UpdateControlPoints(); + } + else if ( rotating ) { + // Shamus: New rotate code + int cx = (int)( windowSize.x() * ( center.x() - extents.minX ) / extents.width() ); + int cy = (int)( windowSize.y() * ( center.y() - extents.minY ) / extents.height() ); + Vector3 v1( dragPoint.x() - cx, dragPoint.y() - cy, 0 ), v2( e->x - cx, e->y - cy, 0 ); + + vector3_normalise( v1 ); + vector3_normalise( v2 ); + float c = vector3_dot( v1, v2 ); + Vector3 cross = vector3_cross( v1, v2 ); + float s = vector3_length( cross ); + + if ( cross[2] > 0 ) { + s = -s; + } // Problem with this: arcsin/cos seems to only return -90 to 90 and 0 to 180... // Can't derive angle from that! //rotationAngle = asin(s);// * 180.0f / 3.141592653589f; - rotationAngle = acos( c ); + rotationAngle = acos( c ); //rotationAngle2 = asin(s); - if ( cross[2] < 0 ) { - rotationAngle = -rotationAngle; - } + if ( cross[2] < 0 ) { + rotationAngle = -rotationAngle; + } //NO! DOESN'T WORK! rotationAngle -= 45.0f * DEG_TO_RAD; //Let's try this: @@ -2104,10 +2195,10 @@ gboolean motion( ui::Widget win, GdkEventMotion * e, gpointer ){ // See brush_primit.cpp line 244 (Texdef_EmitTextureCoordinates()) for where texcoords come from... - tm.coords[0][0] = c; - tm.coords[0][1] = s; - tm.coords[1][0] = -s; - tm.coords[1][1] = c; + tm.coords[0][0] = c; + tm.coords[0][1] = s; + tm.coords[1][0] = -s; + tm.coords[1][1] = c; //It doesn't work anymore... Dunno why... //tm.coords[0][2] = -trans.x(); // This works!!! Yeah!!! //tm.coords[1][2] = -trans.y(); @@ -2131,91 +2222,91 @@ gboolean motion( ui::Widget win, GdkEventMotion * e, gpointer ){ /*tm.coords[0][2] = -c * center.x() * textureSize.x() - s * center.y() * textureSize.y(); tm.coords[1][2] = s * center.x() * textureSize.x() - c * center.y() * textureSize.y();//*/ //Yes!!! - tm.coords[0][2] = ( -c * center.x() * textureSize.x() - s * center.y() * textureSize.y() ) + center.x() * textureSize.x(); - tm.coords[1][2] = ( s * center.x() * textureSize.x() - c * center.y() * textureSize.y() ) + center.y() * textureSize.y(); //*/ + tm.coords[0][2] = ( -c * center.x() * textureSize.x() - s * center.y() * textureSize.y() ) + center.x() * textureSize.x(); + tm.coords[1][2] = ( s * center.x() * textureSize.x() - c * center.y() * textureSize.y() ) + center.y() * textureSize.y(); //*/ //This doesn't work... //And this is the wrong place for this anyway (I'm pretty sure). /*tm.coords[0][2] += oldCenter.x(); tm.coords[1][2] += oldCenter.y();//*/ - UpdateControlPoints(); // will cause a redraw - } - - return true; - } - else // Check for widget mouseovers - { - Vector2 tran; - float nx = e->x / windowSize.x() * extents.width() + extents.minX; - float ny = e->y / windowSize.y() * extents.height() + extents.minY; - // Translate nx/y to the "center" point... - nx -= center.x(); - ny -= center.y(); - ny = -ny; // Flip Y-axis so that increasing numbers move up - - tran.x() = tm.coords[0][0] * nx + tm.coords[0][1] * ny; - tran.y() = tm.coords[1][0] * nx + tm.coords[1][1] * ny; + UpdateControlPoints(); // will cause a redraw + } + + return true; + } + else // Check for widget mouseovers + { + Vector2 tran; + float nx = e->x / windowSize.x() * extents.width() + extents.minX; + float ny = e->y / windowSize.y() * extents.height() + extents.minY; + // Translate nx/y to the "center" point... + nx -= center.x(); + ny -= center.y(); + ny = -ny; // Flip Y-axis so that increasing numbers move up + + tran.x() = tm.coords[0][0] * nx + tm.coords[0][1] * ny; + tran.y() = tm.coords[1][0] * nx + tm.coords[1][1] * ny; //This doesn't seem to generate a valid distance from the center--for some reason it //calculates a fixed number every time //Look at nx/y above: they're getting fixed there! !!! FIX !!! [DONE] - float dist = sqrt( ( nx * nx ) + ( ny * ny ) ); - // Normalize to the 2.0 = height standard (for now) + float dist = sqrt( ( nx * nx ) + ( ny * ny ) ); + // Normalize to the 2.0 = height standard (for now) //globalOutputStream() << "--> Distance before: " << dist; - dist = dist * 2.0f / extents.height(); + dist = dist * 2.0f / extents.height(); //globalOutputStream() << ". After: " << dist; - tran.x() = tran.x() * 2.0f / extents.height(); - tran.y() = tran.y() * 2.0f / extents.height(); + tran.x() = tran.x() * 2.0f / extents.height(); + tran.y() = tran.y() * 2.0f / extents.height(); //globalOutputStream() << ". Trans: " << tran.x() << ", " << tran.y() << "\n"; //Let's try this instead... //Interesting! It seems that e->x/y are rotated //(no, they're not--the TM above is what's doing it...) - nx = ( ( e->x / windowSize.y() ) * 2.0f ) - ( windowSize.x() / windowSize.y() ); - ny = ( ( e->y / windowSize.y() ) * 2.0f ) - ( windowSize.y() / windowSize.y() ); - ny = -ny; + nx = ( ( e->x / windowSize.y() ) * 2.0f ) - ( windowSize.x() / windowSize.y() ); + ny = ( ( e->y / windowSize.y() ) * 2.0f ) - ( windowSize.y() / windowSize.y() ); + ny = -ny; //Cool! It works! Now just need to do rotation... - rotating = translatingX = translatingY = scalingX = scalingY - = resizingX = resizingY = false; - - if ( dist < ( gridRadius * 0.16f ) ) { - translatingX = translatingY = true; - } - else if ( dist > ( gridRadius * 0.16f ) && dist < ( gridRadius * 1.10f ) - && fabs( ny ) < ( gridRadius * 0.05f ) && nx > 0 ) { - translatingX = true; - } - else if ( dist > ( gridRadius * 0.16f ) && dist < ( gridRadius * 1.10f ) - && fabs( nx ) < ( gridRadius * 0.05f ) && ny > 0 ) { - translatingY = true; - } - // Should tighten up the angle on this, or put this test after the axis tests... - else if ( tran.x() > 0 && tran.y() > 0 - && ( dist > ( gridRadius * 0.82f ) && dist < ( gridRadius * 0.98f ) ) ) { - rotating = true; - } - - queueDraw(); - - return true; - } + rotating = translatingX = translatingY = scalingX = scalingY + = resizingX = resizingY = false; + + if ( dist < ( gridRadius * 0.16f ) ) { + translatingX = translatingY = true; + } + else if ( dist > ( gridRadius * 0.16f ) && dist < ( gridRadius * 1.10f ) + && fabs( ny ) < ( gridRadius * 0.05f ) && nx > 0 ) { + translatingX = true; + } + else if ( dist > ( gridRadius * 0.16f ) && dist < ( gridRadius * 1.10f ) + && fabs( nx ) < ( gridRadius * 0.05f ) && ny > 0 ) { + translatingY = true; + } + // Should tighten up the angle on this, or put this test after the axis tests... + else if ( tran.x() > 0 && tran.y() > 0 + && ( dist > ( gridRadius * 0.82f ) && dist < ( gridRadius * 0.98f ) ) ) { + rotating = true; + } + + queueDraw(); + + return true; + } - return false; + return false; } //It seems the fake tex coords conversion is screwing this stuff up... !!! FIX !!! //This is still wrong... Prolly need to do something with the oldScaleX/Y stuff... void flipX( ui::ToggleButton, gpointer ){ // globalOutputStream() << "--> Flip X...\n"; - //Shamus: + //Shamus: // SurfaceInspector_GetSelectedBPTexdef(); // Refresh g_selectedBrushPrimitTexdef... // tm.coords[0][0] = -tm.coords[0][0]; // tm.coords[1][0] = -tm.coords[1][0]; // tm.coords[0][0] = -tm.coords[0][0]; // This should be correct now...Nope. // tm.coords[1][1] = -tm.coords[1][1]; - tm.coords[0][0] = -tm.coords[0][0]; // This should be correct now... - tm.coords[1][0] = -tm.coords[1][0]; + tm.coords[0][0] = -tm.coords[0][0]; // This should be correct now... + tm.coords[1][0] = -tm.coords[1][0]; // tm.coords[2][0] = -tm.coords[2][0];//wil wok? no. - UpdateControlPoints(); + UpdateControlPoints(); } void flipY( ui::ToggleButton, gpointer ){ @@ -2224,10 +2315,10 @@ void flipY( ui::ToggleButton, gpointer ){ // tm.coords[1][1] = -tm.coords[1][1]; // tm.coords[0][1] = -tm.coords[0][1]; // This should be correct now...Nope. // tm.coords[1][0] = -tm.coords[1][0]; - tm.coords[0][1] = -tm.coords[0][1]; // This should be correct now... - tm.coords[1][1] = -tm.coords[1][1]; + tm.coords[0][1] = -tm.coords[0][1]; // This should be correct now... + tm.coords[1][1] = -tm.coords[1][1]; // tm.coords[2][1] = -tm.coords[2][1];//wil wok? no. - UpdateControlPoints(); + UpdateControlPoints(); } } // end namespace TexTool diff --git a/radiant/surfacedialog.h b/radiant/surfacedialog.h index 2c1d945d..739a1bf5 100644 --- a/radiant/surfacedialog.h +++ b/radiant/surfacedialog.h @@ -26,34 +26,40 @@ void SurfaceInspector_Construct(); + void SurfaceInspector_Destroy(); -void SurfaceInspector_constructWindow( ui::Window widget ); +void SurfaceInspector_constructWindow(ui::Window widget); + void SurfaceInspector_destroyWindow(); bool SelectedFaces_empty(); + void SelectedFaces_copyTexture(); + void SelectedFaces_pasteTexture(); + void FaceTextureClipboard_setDefault(); // the increment we are using for the surface inspector (this is saved in the prefs) -struct si_globals_t -{ - float shift[2]; - float scale[2]; - float rotate; - - bool m_bSnapTToGrid; - - si_globals_t() : m_bSnapTToGrid( false ){ - shift[0] = 8.0f; - shift[1] = 8.0f; - scale[0] = 0.5f; - scale[1] = 0.5f; - rotate = 45.0f; - } +struct si_globals_t { + float shift[2]; + float scale[2]; + float rotate; + + bool m_bSnapTToGrid; + + si_globals_t() : m_bSnapTToGrid(false) + { + shift[0] = 8.0f; + shift[1] = 8.0f; + scale[0] = 0.5f; + scale[1] = 0.5f; + rotate = 45.0f; + } }; + extern si_globals_t g_si_globals; #endif diff --git a/radiant/texmanip.cpp b/radiant/texmanip.cpp index 03196c3c..5f66bb2d 100644 --- a/radiant/texmanip.cpp +++ b/radiant/texmanip.cpp @@ -37,64 +37,58 @@ static byte *row1 = NULL, *row2 = NULL; static int rowsize = 0; -void R_ResampleTextureLerpLine( const byte *in, byte *out, int inwidth, int outwidth, int bytesperpixel ){ - int j, xi, oldx = 0, f, fstep, endx, lerp; -#define LERPBYTE( i ) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] ) +void R_ResampleTextureLerpLine(const byte *in, byte *out, int inwidth, int outwidth, int bytesperpixel) +{ + int j, xi, oldx = 0, f, fstep, endx, lerp; +#define LERPBYTE(i) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] ) - fstep = (int) ( inwidth * 65536.0f / outwidth ); - endx = ( inwidth - 1 ); - if ( bytesperpixel == 4 ) { - for ( j = 0,f = 0; j < outwidth; j++, f += fstep ) - { - xi = f >> 16; - if ( xi != oldx ) { - in += ( xi - oldx ) * 4; - oldx = xi; - } + fstep = (int) (inwidth * 65536.0f / outwidth); + endx = (inwidth - 1); + if (bytesperpixel == 4) { + for (j = 0, f = 0; j < outwidth; j++, f += fstep) { + xi = f >> 16; + if (xi != oldx) { + in += (xi - oldx) * 4; + oldx = xi; + } - if ( xi < endx ) { - lerp = f & 0xFFFF; - *out++ = (byte) ( ( ( ( in[4] - in[0] ) * lerp ) >> 16 ) + in[0] ); - *out++ = (byte) ( ( ( ( in[5] - in[1] ) * lerp ) >> 16 ) + in[1] ); - *out++ = (byte) ( ( ( ( in[6] - in[2] ) * lerp ) >> 16 ) + in[2] ); - *out++ = (byte) ( ( ( ( in[7] - in[3] ) * lerp ) >> 16 ) + in[3] ); - } - else // last pixel of the line has no pixel to lerp to - { - *out++ = in[0]; - *out++ = in[1]; - *out++ = in[2]; - *out++ = in[3]; - } - } - } - else if ( bytesperpixel == 3 ) { - for ( j = 0, f = 0; j < outwidth; j++, f += fstep ) - { - xi = f >> 16; - if ( xi != oldx ) { - in += ( xi - oldx ) * 3; - oldx = xi; - } + if (xi < endx) { + lerp = f & 0xFFFF; + *out++ = (byte) ((((in[4] - in[0]) * lerp) >> 16) + in[0]); + *out++ = (byte) ((((in[5] - in[1]) * lerp) >> 16) + in[1]); + *out++ = (byte) ((((in[6] - in[2]) * lerp) >> 16) + in[2]); + *out++ = (byte) ((((in[7] - in[3]) * lerp) >> 16) + in[3]); + } else // last pixel of the line has no pixel to lerp to + { + *out++ = in[0]; + *out++ = in[1]; + *out++ = in[2]; + *out++ = in[3]; + } + } + } else if (bytesperpixel == 3) { + for (j = 0, f = 0; j < outwidth; j++, f += fstep) { + xi = f >> 16; + if (xi != oldx) { + in += (xi - oldx) * 3; + oldx = xi; + } - if ( xi < endx ) { - lerp = f & 0xFFFF; - *out++ = (byte) ( ( ( ( in[3] - in[0] ) * lerp ) >> 16 ) + in[0] ); - *out++ = (byte) ( ( ( ( in[4] - in[1] ) * lerp ) >> 16 ) + in[1] ); - *out++ = (byte) ( ( ( ( in[5] - in[2] ) * lerp ) >> 16 ) + in[2] ); - } - else // last pixel of the line has no pixel to lerp to - { - *out++ = in[0]; - *out++ = in[1]; - *out++ = in[2]; - } - } - } - else - { - globalOutputStream() << "R_ResampleTextureLerpLine: unsupported bytesperpixel " << bytesperpixel << "\n"; - } + if (xi < endx) { + lerp = f & 0xFFFF; + *out++ = (byte) ((((in[3] - in[0]) * lerp) >> 16) + in[0]); + *out++ = (byte) ((((in[4] - in[1]) * lerp) >> 16) + in[1]); + *out++ = (byte) ((((in[5] - in[2]) * lerp) >> 16) + in[2]); + } else // last pixel of the line has no pixel to lerp to + { + *out++ = in[0]; + *out++ = in[1]; + *out++ = in[2]; + } + } + } else { + globalOutputStream() << "R_ResampleTextureLerpLine: unsupported bytesperpixel " << bytesperpixel << "\n"; + } } /* @@ -102,272 +96,248 @@ void R_ResampleTextureLerpLine( const byte *in, byte *out, int inwidth, int outw R_ResampleTexture ================ */ -void R_ResampleTexture( const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight, int bytesperpixel ){ - if ( rowsize < outwidth * bytesperpixel ) { - if ( row1 ) { - free( row1 ); - } - if ( row2 ) { - free( row2 ); - } +void R_ResampleTexture(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight, + int bytesperpixel) +{ + if (rowsize < outwidth * bytesperpixel) { + if (row1) { + free(row1); + } + if (row2) { + free(row2); + } - rowsize = outwidth * bytesperpixel; - row1 = (byte *)malloc( rowsize ); - row2 = (byte *)malloc( rowsize ); - } + rowsize = outwidth * bytesperpixel; + row1 = (byte *) malloc(rowsize); + row2 = (byte *) malloc(rowsize); + } - if ( bytesperpixel == 4 ) { - int i, j, yi, oldy, f, fstep, lerp, endy = ( inheight - 1 ), inwidth4 = inwidth * 4, outwidth4 = outwidth * 4; - byte *inrow, *out; - out = (byte *)outdata; - fstep = (int) ( inheight * 65536.0f / outheight ); -#define LERPBYTE( i ) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] ) + if (bytesperpixel == 4) { + int i, j, yi, oldy, f, fstep, lerp, endy = (inheight - 1), inwidth4 = inwidth * 4, outwidth4 = outwidth * 4; + byte *inrow, *out; + out = (byte *) outdata; + fstep = (int) (inheight * 65536.0f / outheight); +#define LERPBYTE(i) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] ) - inrow = (byte *)indata; - oldy = 0; - R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel ); - R_ResampleTextureLerpLine( inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel ); + inrow = (byte *) indata; + oldy = 0; + R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel); + R_ResampleTextureLerpLine(inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel); - for ( i = 0, f = 0; i < outheight; i++,f += fstep ) - { - yi = f >> 16; - if ( yi < endy ) { - lerp = f & 0xFFFF; - if ( yi != oldy ) { - inrow = (byte *)indata + inwidth4 * yi; - if ( yi == oldy + 1 ) { - memcpy( row1, row2, outwidth4 ); - } - else{ - R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel ); - } + for (i = 0, f = 0; i < outheight; i++, f += fstep) { + yi = f >> 16; + if (yi < endy) { + lerp = f & 0xFFFF; + if (yi != oldy) { + inrow = (byte *) indata + inwidth4 * yi; + if (yi == oldy + 1) { + memcpy(row1, row2, outwidth4); + } else { + R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel); + } - R_ResampleTextureLerpLine( inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel ); - oldy = yi; - } - j = outwidth - 4; - while ( j >= 0 ) - { - LERPBYTE( 0 ); - LERPBYTE( 1 ); - LERPBYTE( 2 ); - LERPBYTE( 3 ); - LERPBYTE( 4 ); - LERPBYTE( 5 ); - LERPBYTE( 6 ); - LERPBYTE( 7 ); - LERPBYTE( 8 ); - LERPBYTE( 9 ); - LERPBYTE( 10 ); - LERPBYTE( 11 ); - LERPBYTE( 12 ); - LERPBYTE( 13 ); - LERPBYTE( 14 ); - LERPBYTE( 15 ); - out += 16; - row1 += 16; - row2 += 16; - j -= 4; - } - if ( j & 2 ) { - LERPBYTE( 0 ); - LERPBYTE( 1 ); - LERPBYTE( 2 ); - LERPBYTE( 3 ); - LERPBYTE( 4 ); - LERPBYTE( 5 ); - LERPBYTE( 6 ); - LERPBYTE( 7 ); - out += 8; - row1 += 8; - row2 += 8; - } - if ( j & 1 ) { - LERPBYTE( 0 ); - LERPBYTE( 1 ); - LERPBYTE( 2 ); - LERPBYTE( 3 ); - out += 4; - row1 += 4; - row2 += 4; - } - row1 -= outwidth4; - row2 -= outwidth4; - } - else - { - if ( yi != oldy ) { - inrow = (byte *)indata + inwidth4 * yi; - if ( yi == oldy + 1 ) { - memcpy( row1, row2, outwidth4 ); - } - else{ - R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel ); - } + R_ResampleTextureLerpLine(inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel); + oldy = yi; + } + j = outwidth - 4; + while (j >= 0) { + LERPBYTE(0); + LERPBYTE(1); + LERPBYTE(2); + LERPBYTE(3); + LERPBYTE(4); + LERPBYTE(5); + LERPBYTE(6); + LERPBYTE(7); + LERPBYTE(8); + LERPBYTE(9); + LERPBYTE(10); + LERPBYTE(11); + LERPBYTE(12); + LERPBYTE(13); + LERPBYTE(14); + LERPBYTE(15); + out += 16; + row1 += 16; + row2 += 16; + j -= 4; + } + if (j & 2) { + LERPBYTE(0); + LERPBYTE(1); + LERPBYTE(2); + LERPBYTE(3); + LERPBYTE(4); + LERPBYTE(5); + LERPBYTE(6); + LERPBYTE(7); + out += 8; + row1 += 8; + row2 += 8; + } + if (j & 1) { + LERPBYTE(0); + LERPBYTE(1); + LERPBYTE(2); + LERPBYTE(3); + out += 4; + row1 += 4; + row2 += 4; + } + row1 -= outwidth4; + row2 -= outwidth4; + } else { + if (yi != oldy) { + inrow = (byte *) indata + inwidth4 * yi; + if (yi == oldy + 1) { + memcpy(row1, row2, outwidth4); + } else { + R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel); + } - oldy = yi; - } - memcpy( out, row1, outwidth4 ); - } - } - } - else if ( bytesperpixel == 3 ) { - int i, j, yi, oldy, f, fstep, lerp, endy = ( inheight - 1 ), inwidth3 = inwidth * 3, outwidth3 = outwidth * 3; - byte *inrow, *out; - out = (byte *)outdata; - fstep = (int) ( inheight * 65536.0f / outheight ); -#define LERPBYTE( i ) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] ) + oldy = yi; + } + memcpy(out, row1, outwidth4); + } + } + } else if (bytesperpixel == 3) { + int i, j, yi, oldy, f, fstep, lerp, endy = (inheight - 1), inwidth3 = inwidth * 3, outwidth3 = outwidth * 3; + byte *inrow, *out; + out = (byte *) outdata; + fstep = (int) (inheight * 65536.0f / outheight); +#define LERPBYTE(i) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] ) - inrow = (byte *)indata; - oldy = 0; - R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel ); - R_ResampleTextureLerpLine( inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel ); - for ( i = 0, f = 0; i < outheight; i++,f += fstep ) - { - yi = f >> 16; - if ( yi < endy ) { - lerp = f & 0xFFFF; - if ( yi != oldy ) { - inrow = (byte *)indata + inwidth3 * yi; - if ( yi == oldy + 1 ) { - memcpy( row1, row2, outwidth3 ); - } - else{ - R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel ); - } + inrow = (byte *) indata; + oldy = 0; + R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel); + R_ResampleTextureLerpLine(inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel); + for (i = 0, f = 0; i < outheight; i++, f += fstep) { + yi = f >> 16; + if (yi < endy) { + lerp = f & 0xFFFF; + if (yi != oldy) { + inrow = (byte *) indata + inwidth3 * yi; + if (yi == oldy + 1) { + memcpy(row1, row2, outwidth3); + } else { + R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel); + } - R_ResampleTextureLerpLine( inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel ); - oldy = yi; - } - j = outwidth - 4; - while ( j >= 0 ) - { - LERPBYTE( 0 ); - LERPBYTE( 1 ); - LERPBYTE( 2 ); - LERPBYTE( 3 ); - LERPBYTE( 4 ); - LERPBYTE( 5 ); - LERPBYTE( 6 ); - LERPBYTE( 7 ); - LERPBYTE( 8 ); - LERPBYTE( 9 ); - LERPBYTE( 10 ); - LERPBYTE( 11 ); - out += 12; - row1 += 12; - row2 += 12; - j -= 4; - } - if ( j & 2 ) { - LERPBYTE( 0 ); - LERPBYTE( 1 ); - LERPBYTE( 2 ); - LERPBYTE( 3 ); - LERPBYTE( 4 ); - LERPBYTE( 5 ); - out += 6; - row1 += 6; - row2 += 6; - } - if ( j & 1 ) { - LERPBYTE( 0 ); - LERPBYTE( 1 ); - LERPBYTE( 2 ); - out += 3; - row1 += 3; - row2 += 3; - } - row1 -= outwidth3; - row2 -= outwidth3; - } - else - { - if ( yi != oldy ) { - inrow = (byte *)indata + inwidth3 * yi; - if ( yi == oldy + 1 ) { - memcpy( row1, row2, outwidth3 ); - } - else{ - R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel ); - } + R_ResampleTextureLerpLine(inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel); + oldy = yi; + } + j = outwidth - 4; + while (j >= 0) { + LERPBYTE(0); + LERPBYTE(1); + LERPBYTE(2); + LERPBYTE(3); + LERPBYTE(4); + LERPBYTE(5); + LERPBYTE(6); + LERPBYTE(7); + LERPBYTE(8); + LERPBYTE(9); + LERPBYTE(10); + LERPBYTE(11); + out += 12; + row1 += 12; + row2 += 12; + j -= 4; + } + if (j & 2) { + LERPBYTE(0); + LERPBYTE(1); + LERPBYTE(2); + LERPBYTE(3); + LERPBYTE(4); + LERPBYTE(5); + out += 6; + row1 += 6; + row2 += 6; + } + if (j & 1) { + LERPBYTE(0); + LERPBYTE(1); + LERPBYTE(2); + out += 3; + row1 += 3; + row2 += 3; + } + row1 -= outwidth3; + row2 -= outwidth3; + } else { + if (yi != oldy) { + inrow = (byte *) indata + inwidth3 * yi; + if (yi == oldy + 1) { + memcpy(row1, row2, outwidth3); + } else { + R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel); + } - oldy = yi; - } - memcpy( out, row1, outwidth3 ); - } - } - } - else - { - globalOutputStream() << "R_ResampleTexture: unsupported bytesperpixel " << bytesperpixel << "\n"; - } + oldy = yi; + } + memcpy(out, row1, outwidth3); + } + } + } else { + globalOutputStream() << "R_ResampleTexture: unsupported bytesperpixel " << bytesperpixel << "\n"; + } } // in can be the same as out -void GL_MipReduce( byte *in, byte *out, int width, int height, int destwidth, int destheight ){ - int x, y, width2, height2, nextrow; - if ( width > destwidth ) { - if ( height > destheight ) { - // reduce both - width2 = width >> 1; - height2 = height >> 1; - nextrow = width << 2; - for ( y = 0; y < height2; y++ ) - { - for ( x = 0; x < width2; x++ ) - { - out[0] = (byte) ( ( in[0] + in[4] + in[nextrow ] + in[nextrow + 4] ) >> 2 ); - out[1] = (byte) ( ( in[1] + in[5] + in[nextrow + 1] + in[nextrow + 5] ) >> 2 ); - out[2] = (byte) ( ( in[2] + in[6] + in[nextrow + 2] + in[nextrow + 6] ) >> 2 ); - out[3] = (byte) ( ( in[3] + in[7] + in[nextrow + 3] + in[nextrow + 7] ) >> 2 ); - out += 4; - in += 8; - } - in += nextrow; // skip a line - } - } - else - { - // reduce width - width2 = width >> 1; - for ( y = 0; y < height; y++ ) - { - for ( x = 0; x < width2; x++ ) - { - out[0] = (byte) ( ( in[0] + in[4] ) >> 1 ); - out[1] = (byte) ( ( in[1] + in[5] ) >> 1 ); - out[2] = (byte) ( ( in[2] + in[6] ) >> 1 ); - out[3] = (byte) ( ( in[3] + in[7] ) >> 1 ); - out += 4; - in += 8; - } - } - } - } - else - { - if ( height > destheight ) { - // reduce height - height2 = height >> 1; - nextrow = width << 2; - for ( y = 0; y < height2; y++ ) - { - for ( x = 0; x < width; x++ ) - { - out[0] = (byte) ( ( in[0] + in[nextrow ] ) >> 1 ); - out[1] = (byte) ( ( in[1] + in[nextrow + 1] ) >> 1 ); - out[2] = (byte) ( ( in[2] + in[nextrow + 2] ) >> 1 ); - out[3] = (byte) ( ( in[3] + in[nextrow + 3] ) >> 1 ); - out += 4; - in += 4; - } - in += nextrow; // skip a line - } - } - else - { - globalOutputStream() << "GL_MipReduce: desired size already achieved\n"; - } - } +void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight) +{ + int x, y, width2, height2, nextrow; + if (width > destwidth) { + if (height > destheight) { + // reduce both + width2 = width >> 1; + height2 = height >> 1; + nextrow = width << 2; + for (y = 0; y < height2; y++) { + for (x = 0; x < width2; x++) { + out[0] = (byte) ((in[0] + in[4] + in[nextrow] + in[nextrow + 4]) >> 2); + out[1] = (byte) ((in[1] + in[5] + in[nextrow + 1] + in[nextrow + 5]) >> 2); + out[2] = (byte) ((in[2] + in[6] + in[nextrow + 2] + in[nextrow + 6]) >> 2); + out[3] = (byte) ((in[3] + in[7] + in[nextrow + 3] + in[nextrow + 7]) >> 2); + out += 4; + in += 8; + } + in += nextrow; // skip a line + } + } else { + // reduce width + width2 = width >> 1; + for (y = 0; y < height; y++) { + for (x = 0; x < width2; x++) { + out[0] = (byte) ((in[0] + in[4]) >> 1); + out[1] = (byte) ((in[1] + in[5]) >> 1); + out[2] = (byte) ((in[2] + in[6]) >> 1); + out[3] = (byte) ((in[3] + in[7]) >> 1); + out += 4; + in += 8; + } + } + } + } else { + if (height > destheight) { + // reduce height + height2 = height >> 1; + nextrow = width << 2; + for (y = 0; y < height2; y++) { + for (x = 0; x < width; x++) { + out[0] = (byte) ((in[0] + in[nextrow]) >> 1); + out[1] = (byte) ((in[1] + in[nextrow + 1]) >> 1); + out[2] = (byte) ((in[2] + in[nextrow + 2]) >> 1); + out[3] = (byte) ((in[3] + in[nextrow + 3]) >> 1); + out += 4; + in += 4; + } + in += nextrow; // skip a line + } + } else { + globalOutputStream() << "GL_MipReduce: desired size already achieved\n"; + } + } } diff --git a/radiant/texmanip.h b/radiant/texmanip.h index 34434141..cd01ab0a 100644 --- a/radiant/texmanip.h +++ b/radiant/texmanip.h @@ -34,7 +34,9 @@ typedef unsigned char byte; -void R_ResampleTexture( const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight, int bytesperpixel ); -void GL_MipReduce( byte *in, byte *out, int width, int height, int destwidth, int destheight ); +void R_ResampleTexture(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight, + int bytesperpixel); + +void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight); #endif diff --git a/radiant/textures.cpp b/radiant/textures.cpp index 02f706b9..a0e0b12b 100644 --- a/radiant/textures.cpp +++ b/radiant/textures.cpp @@ -40,228 +40,221 @@ #include "preferences.h" +enum ETexturesMode { + eTextures_NEAREST = 0, + eTextures_NEAREST_MIPMAP_NEAREST = 1, + eTextures_NEAREST_MIPMAP_LINEAR = 2, + eTextures_LINEAR = 3, + eTextures_LINEAR_MIPMAP_NEAREST = 4, + eTextures_LINEAR_MIPMAP_LINEAR = 5, + eTextures_MAX_ANISOTROPY = 6, +}; -enum ETexturesMode -{ - eTextures_NEAREST = 0, - eTextures_NEAREST_MIPMAP_NEAREST = 1, - eTextures_NEAREST_MIPMAP_LINEAR = 2, - eTextures_LINEAR = 3, - eTextures_LINEAR_MIPMAP_NEAREST = 4, - eTextures_LINEAR_MIPMAP_LINEAR = 5, - eTextures_MAX_ANISOTROPY = 6, +enum TextureCompressionFormat { + TEXTURECOMPRESSION_NONE = 0, + TEXTURECOMPRESSION_RGBA = 1, + TEXTURECOMPRESSION_RGBA_S3TC_DXT1 = 2, + TEXTURECOMPRESSION_RGBA_S3TC_DXT3 = 3, + TEXTURECOMPRESSION_RGBA_S3TC_DXT5 = 4, }; -enum TextureCompressionFormat -{ - TEXTURECOMPRESSION_NONE = 0, - TEXTURECOMPRESSION_RGBA = 1, - TEXTURECOMPRESSION_RGBA_S3TC_DXT1 = 2, - TEXTURECOMPRESSION_RGBA_S3TC_DXT3 = 3, - TEXTURECOMPRESSION_RGBA_S3TC_DXT5 = 4, +struct texture_globals_t { + // RIANT + // texture compression format + TextureCompressionFormat m_nTextureCompressionFormat; + + float fGamma; + + bool bTextureCompressionSupported; // is texture compression supported by hardware? + GLint texture_components; + + // temporary values that should be initialised only once at run-time + bool m_bOpenGLCompressionSupported; + bool m_bS3CompressionSupported; + + texture_globals_t(GLint components) : + m_nTextureCompressionFormat(TEXTURECOMPRESSION_NONE), + fGamma(1.0f), + bTextureCompressionSupported(false), + texture_components(components), + m_bOpenGLCompressionSupported(false), + m_bS3CompressionSupported(false) + { + } }; -struct texture_globals_t +texture_globals_t g_texture_globals(GL_RGBA); + +void SetTexParameters(ETexturesMode mode) { - // RIANT - // texture compression format - TextureCompressionFormat m_nTextureCompressionFormat; - - float fGamma; - - bool bTextureCompressionSupported; // is texture compression supported by hardware? - GLint texture_components; - - // temporary values that should be initialised only once at run-time - bool m_bOpenGLCompressionSupported; - bool m_bS3CompressionSupported; - - texture_globals_t( GLint components ) : - m_nTextureCompressionFormat( TEXTURECOMPRESSION_NONE ), - fGamma( 1.0f ), - bTextureCompressionSupported( false ), - texture_components( components ), - m_bOpenGLCompressionSupported( false ), - m_bS3CompressionSupported( false ){ - } -}; + float maxAniso = QGL_maxTextureAnisotropy(); + if (maxAniso > 1) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f); + } else if (mode == eTextures_MAX_ANISOTROPY) { + mode = eTextures_LINEAR_MIPMAP_LINEAR; + } -texture_globals_t g_texture_globals( GL_RGBA ); - -void SetTexParameters( ETexturesMode mode ){ - float maxAniso = QGL_maxTextureAnisotropy(); - if ( maxAniso > 1 ) { - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f ); - } - else - if ( mode == eTextures_MAX_ANISOTROPY ) { - mode = eTextures_LINEAR_MIPMAP_LINEAR; - } - - switch ( mode ) - { - case eTextures_NEAREST: - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - break; - case eTextures_NEAREST_MIPMAP_NEAREST: - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - break; - case eTextures_NEAREST_MIPMAP_LINEAR: - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - break; - case eTextures_LINEAR: - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - break; - case eTextures_LINEAR_MIPMAP_NEAREST: - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - break; - case eTextures_LINEAR_MIPMAP_LINEAR: - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - break; - case eTextures_MAX_ANISOTROPY: - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso ); - break; - default: - globalOutputStream() << "invalid texture mode\n"; - } + switch (mode) { + case eTextures_NEAREST: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + case eTextures_NEAREST_MIPMAP_NEAREST: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + case eTextures_NEAREST_MIPMAP_LINEAR: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + case eTextures_LINEAR: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + case eTextures_LINEAR_MIPMAP_NEAREST: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + case eTextures_LINEAR_MIPMAP_LINEAR: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + case eTextures_MAX_ANISOTROPY: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso); + break; + default: + globalOutputStream() << "invalid texture mode\n"; + } } ETexturesMode g_texture_mode = eTextures_LINEAR_MIPMAP_LINEAR; - - byte g_gammatable[256]; -void ResampleGamma( float fGamma ){ - int i,inf; - if ( fGamma == 1.0 ) { - for ( i = 0; i < 256; i++ ) - g_gammatable[i] = i; - } - else - { - for ( i = 0; i < 256; i++ ) - { - inf = (int)( 255 * pow( static_cast( ( i + 0.5 ) / 255.5 ), static_cast( fGamma ) ) + 0.5 ); - if ( inf < 0 ) { - inf = 0; - } - if ( inf > 255 ) { - inf = 255; - } - g_gammatable[i] = inf; - } - } + +void ResampleGamma(float fGamma) +{ + int i, inf; + if (fGamma == 1.0) { + for (i = 0; i < 256; i++) { + g_gammatable[i] = i; + } + } else { + for (i = 0; i < 256; i++) { + inf = (int) (255 * pow(static_cast((i + 0.5) / 255.5 ), static_cast( fGamma )) + 0.5); + if (inf < 0) { + inf = 0; + } + if (inf > 255) { + inf = 255; + } + g_gammatable[i] = inf; + } + } } -inline const int& min_int( const int& left, const int& right ){ - return std::min( left, right ); +inline const int &min_int(const int &left, const int &right) +{ + return std::min(left, right); } int max_tex_size = 0; const int max_texture_quality = 3; -LatchedValue g_Textures_textureQuality( 3, "Texture Quality" ); +LatchedValue g_Textures_textureQuality(3, "Texture Quality"); /// \brief This function does the actual processing of raw RGBA data into a GL texture. /// It will also resample to power-of-two dimensions, generate the mipmaps and adjust gamma. -void LoadTextureRGBA( qtexture_t* q, unsigned char* pPixels, int nWidth, int nHeight ){ - static float fGamma = -1; - float total[3]; - byte *outpixels = 0; - int nCount = nWidth * nHeight; - - if ( fGamma != g_texture_globals.fGamma ) { - fGamma = g_texture_globals.fGamma; - ResampleGamma( fGamma ); - } - - q->width = nWidth; - q->height = nHeight; - - total[0] = total[1] = total[2] = 0.0f; - - // resample texture gamma according to user settings - for ( int i = 0; i < ( nCount * 4 ); i += 4 ) - { - for ( int j = 0; j < 3; j++ ) - { - total[j] += ( pPixels + i )[j]; - byte b = ( pPixels + i )[j]; - ( pPixels + i )[j] = g_gammatable[b]; - } - } - - q->color[0] = total[0] / ( nCount * 255 ); - q->color[1] = total[1] / ( nCount * 255 ); - q->color[2] = total[2] / ( nCount * 255 ); - - glGenTextures( 1, &q->texture_number ); - - glBindTexture( GL_TEXTURE_2D, q->texture_number ); - - SetTexParameters( g_texture_mode ); - - int gl_width = 1; - while ( gl_width < nWidth ) - gl_width <<= 1; - - int gl_height = 1; - while ( gl_height < nHeight ) - gl_height <<= 1; - - bool resampled = false; - if ( !( gl_width == nWidth && gl_height == nHeight ) ) { - resampled = true; - outpixels = (byte *)malloc( gl_width * gl_height * 4 ); - R_ResampleTexture( pPixels, nWidth, nHeight, outpixels, gl_width, gl_height, 4 ); - } - else - { - outpixels = pPixels; - } - - int quality_reduction = max_texture_quality - g_Textures_textureQuality.m_value; - int target_width = min_int( gl_width >> quality_reduction, max_tex_size ); - int target_height = min_int( gl_height >> quality_reduction, max_tex_size ); - - while ( gl_width > target_width || gl_height > target_height ) - { - GL_MipReduce( outpixels, outpixels, gl_width, gl_height, target_width, target_height ); - - if ( gl_width > target_width ) { - gl_width >>= 1; - } - if ( gl_height > target_height ) { - gl_height >>= 1; - } - } - - int mip = 0; - glTexImage2D( GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, outpixels ); - while ( gl_width > 1 || gl_height > 1 ) - { - GL_MipReduce( outpixels, outpixels, gl_width, gl_height, 1, 1 ); - - if ( gl_width > 1 ) { - gl_width >>= 1; - } - if ( gl_height > 1 ) { - gl_height >>= 1; - } - - glTexImage2D( GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, outpixels ); - } - - glBindTexture( GL_TEXTURE_2D, 0 ); - if ( resampled ) { - free( outpixels ); - } +void LoadTextureRGBA(qtexture_t *q, unsigned char *pPixels, int nWidth, int nHeight) +{ + static float fGamma = -1; + float total[3]; + byte *outpixels = 0; + int nCount = nWidth * nHeight; + + if (fGamma != g_texture_globals.fGamma) { + fGamma = g_texture_globals.fGamma; + ResampleGamma(fGamma); + } + + q->width = nWidth; + q->height = nHeight; + + total[0] = total[1] = total[2] = 0.0f; + + // resample texture gamma according to user settings + for (int i = 0; i < (nCount * 4); i += 4) { + for (int j = 0; j < 3; j++) { + total[j] += (pPixels + i)[j]; + byte b = (pPixels + i)[j]; + (pPixels + i)[j] = g_gammatable[b]; + } + } + + q->color[0] = total[0] / (nCount * 255); + q->color[1] = total[1] / (nCount * 255); + q->color[2] = total[2] / (nCount * 255); + + glGenTextures(1, &q->texture_number); + + glBindTexture(GL_TEXTURE_2D, q->texture_number); + + SetTexParameters(g_texture_mode); + + int gl_width = 1; + while (gl_width < nWidth) { + gl_width <<= 1; + } + + int gl_height = 1; + while (gl_height < nHeight) { + gl_height <<= 1; + } + + bool resampled = false; + if (!(gl_width == nWidth && gl_height == nHeight)) { + resampled = true; + outpixels = (byte *) malloc(gl_width * gl_height * 4); + R_ResampleTexture(pPixels, nWidth, nHeight, outpixels, gl_width, gl_height, 4); + } else { + outpixels = pPixels; + } + + int quality_reduction = max_texture_quality - g_Textures_textureQuality.m_value; + int target_width = min_int(gl_width >> quality_reduction, max_tex_size); + int target_height = min_int(gl_height >> quality_reduction, max_tex_size); + + while (gl_width > target_width || gl_height > target_height) { + GL_MipReduce(outpixels, outpixels, gl_width, gl_height, target_width, target_height); + + if (gl_width > target_width) { + gl_width >>= 1; + } + if (gl_height > target_height) { + gl_height >>= 1; + } + } + + int mip = 0; + glTexImage2D(GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, outpixels); + while (gl_width > 1 || gl_height > 1) { + GL_MipReduce(outpixels, outpixels, gl_width, gl_height, 1, 1); + + if (gl_width > 1) { + gl_width >>= 1; + } + if (gl_height > 1) { + gl_height >>= 1; + } + + glTexImage2D(GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, outpixels); + } + + glBindTexture(GL_TEXTURE_2D, 0); + if (resampled) { + free(outpixels); + } } #if 0 @@ -271,48 +264,48 @@ void LoadTextureRGBA( qtexture_t* q, unsigned char* pPixels, int nWidth, int nHe ============== */ void Texture_InitPalette( byte *pal ){ - int r,g,b; - int i; - int inf; - byte gammatable[256]; - float gamma; - - gamma = g_texture_globals.fGamma; - - if ( gamma == 1.0 ) { - for ( i = 0 ; i < 256 ; i++ ) - gammatable[i] = i; - } - else - { - for ( i = 0 ; i < 256 ; i++ ) - { - inf = (int)( 255 * pow( ( i + 0.5 ) / 255.5, gamma ) + 0.5 ); - if ( inf < 0 ) { - inf = 0; - } - if ( inf > 255 ) { - inf = 255; - } - gammatable[i] = inf; - } - } - - for ( i = 0 ; i < 256 ; i++ ) - { - r = gammatable[pal[0]]; - g = gammatable[pal[1]]; - b = gammatable[pal[2]]; - pal += 3; - - //v = (r<<24) + (g<<16) + (b<<8) + 255; - //v = BigLong (v); - - //tex_palette[i] = v; - tex_palette[i * 3 + 0] = r; - tex_palette[i * 3 + 1] = g; - tex_palette[i * 3 + 2] = b; - } + int r,g,b; + int i; + int inf; + byte gammatable[256]; + float gamma; + + gamma = g_texture_globals.fGamma; + + if ( gamma == 1.0 ) { + for ( i = 0 ; i < 256 ; i++ ) + gammatable[i] = i; + } + else + { + for ( i = 0 ; i < 256 ; i++ ) + { + inf = (int)( 255 * pow( ( i + 0.5 ) / 255.5, gamma ) + 0.5 ); + if ( inf < 0 ) { + inf = 0; + } + if ( inf > 255 ) { + inf = 255; + } + gammatable[i] = inf; + } + } + + for ( i = 0 ; i < 256 ; i++ ) + { + r = gammatable[pal[0]]; + g = gammatable[pal[1]]; + b = gammatable[pal[2]]; + pal += 3; + + //v = (r<<24) + (g<<16) + (b<<8) + 255; + //v = BigLong (v); + + //tex_palette[i] = v; + tex_palette[i * 3 + 0] = r; + tex_palette[i * 3 + 1] = g; + tex_palette[i * 3 + 2] = b; + } } #endif @@ -321,9 +314,9 @@ class TestHashtable { public: TestHashtable(){ - HashTable strings; - strings["Monkey"] = "bleh"; - strings["MonkeY"] = "blah"; + HashTable strings; + strings["Monkey"] = "bleh"; + strings["MonkeY"] = "blah"; } }; @@ -333,300 +326,329 @@ const TestHashtable g_testhashtable; typedef std::pair TextureKey; -void qtexture_realise( qtexture_t& texture, const TextureKey& key ){ - texture.texture_number = 0; - if ( !string_empty( key.second.c_str() ) ) { - Image* image = key.first.loadImage( key.second.c_str() ); - if ( image != 0 ) { - LoadTextureRGBA( &texture, image->getRGBAPixels(), image->getWidth(), image->getHeight() ); - texture.surfaceFlags = image->getSurfaceFlags(); - texture.contentFlags = image->getContentFlags(); - texture.value = image->getValue(); - image->release(); - globalOutputStream() << "Loaded Texture: \"" << key.second.c_str() << "\"\n"; - GlobalOpenGL_debugAssertNoErrors(); - } - else - { - globalErrorStream() << "Texture load failed: \"" << key.second.c_str() << "\"\n"; - } - } +void qtexture_realise(qtexture_t &texture, const TextureKey &key) +{ + texture.texture_number = 0; + if (!string_empty(key.second.c_str())) { + Image *image = key.first.loadImage(key.second.c_str()); + if (image != 0) { + LoadTextureRGBA(&texture, image->getRGBAPixels(), image->getWidth(), image->getHeight()); + texture.surfaceFlags = image->getSurfaceFlags(); + texture.contentFlags = image->getContentFlags(); + texture.value = image->getValue(); + image->release(); + globalOutputStream() << "Loaded Texture: \"" << key.second.c_str() << "\"\n"; + GlobalOpenGL_debugAssertNoErrors(); + } else { + globalErrorStream() << "Texture load failed: \"" << key.second.c_str() << "\"\n"; + } + } } -void qtexture_unrealise( qtexture_t& texture ){ - if ( GlobalOpenGL().contextValid && texture.texture_number != 0 ) { - glDeleteTextures( 1, &texture.texture_number ); - GlobalOpenGL_debugAssertNoErrors(); - } +void qtexture_unrealise(qtexture_t &texture) +{ + if (GlobalOpenGL().contextValid && texture.texture_number != 0) { + glDeleteTextures(1, &texture.texture_number); + GlobalOpenGL_debugAssertNoErrors(); + } } -class TextureKeyEqualNoCase -{ +class TextureKeyEqualNoCase { public: -bool operator()( const TextureKey& key, const TextureKey& other ) const { - return key.first == other.first && string_equal_nocase( key.second.c_str(), other.second.c_str() ); -} + bool operator()(const TextureKey &key, const TextureKey &other) const + { + return key.first == other.first && string_equal_nocase(key.second.c_str(), other.second.c_str()); + } }; -class TextureKeyHashNoCase -{ +class TextureKeyHashNoCase { public: -typedef hash_t hash_type; -hash_t operator()( const TextureKey& key ) const { - return hash_combine( string_hash_nocase( key.second.c_str() ), pod_hash( key.first ) ); -} + typedef hash_t hash_type; + + hash_t operator()(const TextureKey &key) const + { + return hash_combine(string_hash_nocase(key.second.c_str()), pod_hash(key.first)); + } }; #define DEBUG_TEXTURES 0 -class TexturesMap : public TexturesCache -{ -class TextureConstructor -{ -TexturesMap* m_cache; -public: -explicit TextureConstructor( TexturesMap* cache ) - : m_cache( cache ){ -} -qtexture_t* construct( const TextureKey& key ){ - qtexture_t* texture = new qtexture_t( key.first, key.second.c_str() ); - if ( m_cache->realised() ) { - qtexture_realise( *texture, key ); - } - return texture; -} -void destroy( qtexture_t* texture ){ - if ( m_cache->realised() ) { - qtexture_unrealise( *texture ); - } - delete texture; -} -}; +class TexturesMap : public TexturesCache { + class TextureConstructor { + TexturesMap *m_cache; + public: + explicit TextureConstructor(TexturesMap *cache) + : m_cache(cache) + { + } -typedef HashedCache qtextures_t; -qtextures_t m_qtextures; -TexturesCacheObserver* m_observer; -std::size_t m_unrealised; + qtexture_t *construct(const TextureKey &key) + { + qtexture_t *texture = new qtexture_t(key.first, key.second.c_str()); + if (m_cache->realised()) { + qtexture_realise(*texture, key); + } + return texture; + } + + void destroy(qtexture_t *texture) + { + if (m_cache->realised()) { + qtexture_unrealise(*texture); + } + delete texture; + } + }; + + typedef HashedCache qtextures_t; + qtextures_t m_qtextures; + TexturesCacheObserver *m_observer; + std::size_t m_unrealised; public: -virtual ~TexturesMap() = default; -TexturesMap() : m_qtextures( TextureConstructor( this ) ), m_observer( 0 ), m_unrealised( 1 ){ -} -typedef qtextures_t::iterator iterator; + virtual ~TexturesMap() = default; -iterator begin(){ - return m_qtextures.begin(); -} -iterator end(){ - return m_qtextures.end(); -} + TexturesMap() : m_qtextures(TextureConstructor(this)), m_observer(0), m_unrealised(1) + { + } -LoadImageCallback defaultLoader() const { - return LoadImageCallback( 0, QERApp_LoadImage ); -} -Image* loadImage( const char* name ){ - return defaultLoader().loadImage( name ); -} -qtexture_t* capture( const char* name ){ - return capture( defaultLoader(), name ); -} -qtexture_t* capture( const LoadImageCallback& loader, const char* name ){ + typedef qtextures_t::iterator iterator; + + iterator begin() + { + return m_qtextures.begin(); + } + + iterator end() + { + return m_qtextures.end(); + } + + LoadImageCallback defaultLoader() const + { + return LoadImageCallback(0, QERApp_LoadImage); + } + + Image *loadImage(const char *name) + { + return defaultLoader().loadImage(name); + } + + qtexture_t *capture(const char *name) + { + return capture(defaultLoader(), name); + } + + qtexture_t *capture(const LoadImageCallback &loader, const char *name) + { #if DEBUG_TEXTURES - globalOutputStream() << "textures capture: " << makeQuoted( name ) << '\n'; + globalOutputStream() << "textures capture: " << makeQuoted( name ) << '\n'; #endif - return m_qtextures.capture( TextureKey( loader, name ) ).get(); -} -void release( qtexture_t* texture ){ + return m_qtextures.capture(TextureKey(loader, name)).get(); + } + + void release(qtexture_t *texture) + { #if DEBUG_TEXTURES - globalOutputStream() << "textures release: " << makeQuoted( texture->name ) << '\n'; + globalOutputStream() << "textures release: " << makeQuoted( texture->name ) << '\n'; #endif - m_qtextures.release( TextureKey( texture->load, texture->name ) ); -} -void attach( TexturesCacheObserver& observer ){ - ASSERT_MESSAGE( m_observer == 0, "TexturesMap::attach: cannot attach observer" ); - m_observer = &observer; -} -void detach( TexturesCacheObserver& observer ){ - ASSERT_MESSAGE( m_observer == &observer, "TexturesMap::detach: cannot detach observer" ); - m_observer = 0; -} -void realise(){ - if ( --m_unrealised == 0 ) { - g_texture_globals.bTextureCompressionSupported = false; - - if ( GlobalOpenGL().ARB_texture_compression() ) { - g_texture_globals.bTextureCompressionSupported = true; - g_texture_globals.m_bOpenGLCompressionSupported = true; - } - - if ( GlobalOpenGL().EXT_texture_compression_s3tc() ) { - g_texture_globals.bTextureCompressionSupported = true; - g_texture_globals.m_bS3CompressionSupported = true; - } - - switch ( g_texture_globals.texture_components ) - { - case GL_RGBA: - break; - case GL_COMPRESSED_RGBA_ARB: - if ( !g_texture_globals.m_bOpenGLCompressionSupported ) { - globalOutputStream() << "OpenGL extension GL_ARB_texture_compression not supported by current graphics drivers\n"; - g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; - g_texture_globals.texture_components = GL_RGBA; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - if ( !g_texture_globals.m_bS3CompressionSupported ) { - globalOutputStream() << "OpenGL extension GL_EXT_texture_compression_s3tc not supported by current graphics drivers\n"; - if ( g_texture_globals.m_bOpenGLCompressionSupported ) { - g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_RGBA; - g_texture_globals.texture_components = GL_COMPRESSED_RGBA_ARB; - } - else - { - g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; - g_texture_globals.texture_components = GL_RGBA; - } - } - break; - default: - globalOutputStream() << "Unknown texture compression selected, reverting\n"; - g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; - g_texture_globals.texture_components = GL_RGBA; - break; - } - - - glGetIntegerv( GL_MAX_TEXTURE_SIZE, &max_tex_size ); - if ( max_tex_size == 0 ) { - max_tex_size = 1024; - } - - for ( qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i ) - { - if ( !( *i ).value.empty() ) { - qtexture_realise( *( *i ).value, ( *i ).key ); - } - } - if ( m_observer != 0 ) { - m_observer->realise(); - } - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - if ( m_observer != 0 ) { - m_observer->unrealise(); - } - for ( qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i ) - { - if ( !( *i ).value.empty() ) { - qtexture_unrealise( *( *i ).value ); - } - } - } -} -bool realised(){ - return m_unrealised == 0; -} + m_qtextures.release(TextureKey(texture->load, texture->name)); + } + + void attach(TexturesCacheObserver &observer) + { + ASSERT_MESSAGE(m_observer == 0, "TexturesMap::attach: cannot attach observer"); + m_observer = &observer; + } + + void detach(TexturesCacheObserver &observer) + { + ASSERT_MESSAGE(m_observer == &observer, "TexturesMap::detach: cannot detach observer"); + m_observer = 0; + } + + void realise() + { + if (--m_unrealised == 0) { + g_texture_globals.bTextureCompressionSupported = false; + + if (GlobalOpenGL().ARB_texture_compression()) { + g_texture_globals.bTextureCompressionSupported = true; + g_texture_globals.m_bOpenGLCompressionSupported = true; + } + + if (GlobalOpenGL().EXT_texture_compression_s3tc()) { + g_texture_globals.bTextureCompressionSupported = true; + g_texture_globals.m_bS3CompressionSupported = true; + } + + switch (g_texture_globals.texture_components) { + case GL_RGBA: + break; + case GL_COMPRESSED_RGBA_ARB: + if (!g_texture_globals.m_bOpenGLCompressionSupported) { + globalOutputStream() + << "OpenGL extension GL_ARB_texture_compression not supported by current graphics drivers\n"; + g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; + g_texture_globals.texture_components = GL_RGBA; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + if (!g_texture_globals.m_bS3CompressionSupported) { + globalOutputStream() + << "OpenGL extension GL_EXT_texture_compression_s3tc not supported by current graphics drivers\n"; + if (g_texture_globals.m_bOpenGLCompressionSupported) { + g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_RGBA; + g_texture_globals.texture_components = GL_COMPRESSED_RGBA_ARB; + } else { + g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; + g_texture_globals.texture_components = GL_RGBA; + } + } + break; + default: + globalOutputStream() << "Unknown texture compression selected, reverting\n"; + g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; + g_texture_globals.texture_components = GL_RGBA; + break; + } + + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); + if (max_tex_size == 0) { + max_tex_size = 1024; + } + + for (qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i) { + if (!(*i).value.empty()) { + qtexture_realise(*(*i).value, (*i).key); + } + } + if (m_observer != 0) { + m_observer->realise(); + } + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + if (m_observer != 0) { + m_observer->unrealise(); + } + for (qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i) { + if (!(*i).value.empty()) { + qtexture_unrealise(*(*i).value); + } + } + } + } + + bool realised() + { + return m_unrealised == 0; + } }; -TexturesMap* g_texturesmap; +TexturesMap *g_texturesmap; -TexturesCache& GetTexturesCache(){ - return *g_texturesmap; +TexturesCache &GetTexturesCache() +{ + return *g_texturesmap; } -void Textures_Realise(){ - g_texturesmap->realise(); +void Textures_Realise() +{ + g_texturesmap->realise(); } -void Textures_Unrealise(){ - g_texturesmap->unrealise(); +void Textures_Unrealise() +{ + g_texturesmap->unrealise(); } Callback g_texturesModeChangedNotify; -void Textures_setModeChangedNotify( const Callback& notify ){ - g_texturesModeChangedNotify = notify; +void Textures_setModeChangedNotify(const Callback ¬ify) +{ + g_texturesModeChangedNotify = notify; } -void Textures_ModeChanged(){ - if ( g_texturesmap->realised() ) { - SetTexParameters( g_texture_mode ); +void Textures_ModeChanged() +{ + if (g_texturesmap->realised()) { + SetTexParameters(g_texture_mode); - for ( TexturesMap::iterator i = g_texturesmap->begin(); i != g_texturesmap->end(); ++i ) - { - glBindTexture( GL_TEXTURE_2D, ( *i ).value->texture_number ); - SetTexParameters( g_texture_mode ); - } + for (TexturesMap::iterator i = g_texturesmap->begin(); i != g_texturesmap->end(); ++i) { + glBindTexture(GL_TEXTURE_2D, (*i).value->texture_number); + SetTexParameters(g_texture_mode); + } - glBindTexture( GL_TEXTURE_2D, 0 ); - } - g_texturesModeChangedNotify(); + glBindTexture(GL_TEXTURE_2D, 0); + } + g_texturesModeChangedNotify(); } -void Textures_SetMode( ETexturesMode mode ){ - if ( g_texture_mode != mode ) { - g_texture_mode = mode; +void Textures_SetMode(ETexturesMode mode) +{ + if (g_texture_mode != mode) { + g_texture_mode = mode; - Textures_ModeChanged(); - } + Textures_ModeChanged(); + } } -void Textures_setTextureComponents( GLint texture_components ){ - if ( g_texture_globals.texture_components != texture_components ) { - Textures_Unrealise(); - g_texture_globals.texture_components = texture_components; - Textures_Realise(); - } +void Textures_setTextureComponents(GLint texture_components) +{ + if (g_texture_globals.texture_components != texture_components) { + Textures_Unrealise(); + g_texture_globals.texture_components = texture_components; + Textures_Realise(); + } } -void Textures_UpdateTextureCompressionFormat(){ - GLint texture_components = GL_RGBA; - - switch ( g_texture_globals.m_nTextureCompressionFormat ) - { - case ( TEXTURECOMPRESSION_NONE ): - { - texture_components = GL_RGBA; - break; - } - case ( TEXTURECOMPRESSION_RGBA ): - { - texture_components = GL_COMPRESSED_RGBA_ARB; - break; - } - case ( TEXTURECOMPRESSION_RGBA_S3TC_DXT1 ): - { - texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - break; - } - case ( TEXTURECOMPRESSION_RGBA_S3TC_DXT3 ): - { - texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - break; - } - case ( TEXTURECOMPRESSION_RGBA_S3TC_DXT5 ): - { - texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - break; - } - } - - Textures_setTextureComponents( texture_components ); +void Textures_UpdateTextureCompressionFormat() +{ + GLint texture_components = GL_RGBA; + + switch (g_texture_globals.m_nTextureCompressionFormat) { + case (TEXTURECOMPRESSION_NONE): { + texture_components = GL_RGBA; + break; + } + case (TEXTURECOMPRESSION_RGBA): { + texture_components = GL_COMPRESSED_RGBA_ARB; + break; + } + case (TEXTURECOMPRESSION_RGBA_S3TC_DXT1): { + texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + break; + } + case (TEXTURECOMPRESSION_RGBA_S3TC_DXT3): { + texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + break; + } + case (TEXTURECOMPRESSION_RGBA_S3TC_DXT5): { + texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + } + } + + Textures_setTextureComponents(texture_components); } struct TextureCompression { - static void Export(const TextureCompressionFormat &self, const Callback &returnz) { + static void Export(const TextureCompressionFormat &self, const Callback &returnz) + { returnz(self); } - static void Import(TextureCompressionFormat &self, int value) { + static void Import(TextureCompressionFormat &self, int value) + { if (!g_texture_globals.m_bOpenGLCompressionSupported && g_texture_globals.m_bS3CompressionSupported && value >= 1) { @@ -654,21 +676,24 @@ struct TextureCompression { }; struct TextureGamma { - static void Export(const float &self, const Callback &returnz) { - returnz(self); - } - - static void Import(float &self, float value) { - if (value != self) { - Textures_Unrealise(); - self = value; - Textures_Realise(); - } - } + static void Export(const float &self, const Callback &returnz) + { + returnz(self); + } + + static void Import(float &self, float value) + { + if (value != self) { + Textures_Unrealise(); + self = value; + Textures_Realise(); + } + } }; struct TextureMode { - static void Export(const ETexturesMode &self, const Callback &returnz) { + static void Export(const ETexturesMode &self, const Callback &returnz) + { switch (self) { case eTextures_NEAREST: returnz(0); @@ -696,7 +721,8 @@ struct TextureMode { } } - static void Import(ETexturesMode &self, int value) { + static void Import(ETexturesMode &self, int value) + { switch (value) { case 0: Textures_SetMode(eTextures_NEAREST); @@ -722,86 +748,100 @@ struct TextureMode { } }; -void Textures_constructPreferences( PreferencesPage& page ){ - { - const char* percentages[] = { "12.5%", "25%", "50%", "100%", }; - page.appendRadio( - "Texture Quality", - STRING_ARRAY_RANGE( percentages ), - make_property( g_Textures_textureQuality ) - ); - } - page.appendSpinner( - "Texture Gamma", - 1.0, - 0.0, - 1.0, - make_property(g_texture_globals.fGamma) - ); - { - const char* texture_mode[] = { "Nearest", "Nearest Mipmap", "Linear", "Bilinear", "Bilinear Mipmap", "Trilinear", "Anisotropy" }; - page.appendCombo( - "Texture Render Mode", - STRING_ARRAY_RANGE( texture_mode ), - make_property(g_texture_mode) - ); - } - { - const char* compression_none[] = { "None" }; - const char* compression_opengl[] = { "None", "OpenGL ARB" }; - const char* compression_s3tc[] = { "None", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5" }; - const char* compression_opengl_s3tc[] = { "None", "OpenGL ARB", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5" }; - StringArrayRange compression( - ( g_texture_globals.m_bOpenGLCompressionSupported ) - ? ( g_texture_globals.m_bS3CompressionSupported ) - ? STRING_ARRAY_RANGE( compression_opengl_s3tc ) - : STRING_ARRAY_RANGE( compression_opengl ) - : ( g_texture_globals.m_bS3CompressionSupported ) - ? STRING_ARRAY_RANGE( compression_s3tc ) - : STRING_ARRAY_RANGE( compression_none ) - ); - page.appendCombo( - "Hardware Texture Compression", - compression, - make_property(g_texture_globals.m_nTextureCompressionFormat) - ); - } +void Textures_constructPreferences(PreferencesPage &page) +{ + { + const char *percentages[] = {"12.5%", "25%", "50%", "100%",}; + page.appendRadio( + "Texture Quality", + STRING_ARRAY_RANGE(percentages), + make_property(g_Textures_textureQuality) + ); + } + page.appendSpinner( + "Texture Gamma", + 1.0, + 0.0, + 1.0, + make_property(g_texture_globals.fGamma) + ); + { + const char *texture_mode[] = {"Nearest", "Nearest Mipmap", "Linear", "Bilinear", "Bilinear Mipmap", "Trilinear", + "Anisotropy"}; + page.appendCombo( + "Texture Render Mode", + STRING_ARRAY_RANGE(texture_mode), + make_property(g_texture_mode) + ); + } + { + const char *compression_none[] = {"None"}; + const char *compression_opengl[] = {"None", "OpenGL ARB"}; + const char *compression_s3tc[] = {"None", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5"}; + const char *compression_opengl_s3tc[] = {"None", "OpenGL ARB", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5"}; + StringArrayRange compression( + (g_texture_globals.m_bOpenGLCompressionSupported) + ? (g_texture_globals.m_bS3CompressionSupported) + ? STRING_ARRAY_RANGE(compression_opengl_s3tc) + : STRING_ARRAY_RANGE(compression_opengl) + : (g_texture_globals.m_bS3CompressionSupported) + ? STRING_ARRAY_RANGE(compression_s3tc) + : STRING_ARRAY_RANGE(compression_none) + ); + page.appendCombo( + "Hardware Texture Compression", + compression, + make_property(g_texture_globals.m_nTextureCompressionFormat) + ); + } } -void Textures_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Textures", "Texture Settings" ) ); - Textures_constructPreferences( page ); + +void Textures_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Textures", "Texture Settings")); + Textures_constructPreferences(page); } -void Textures_registerPreferencesPage(){ - PreferencesDialog_addDisplayPage( makeCallbackF(Textures_constructPage) ); + +void Textures_registerPreferencesPage() +{ + PreferencesDialog_addDisplayPage(makeCallbackF(Textures_constructPage)); } struct TextureCompressionPreference { - static void Export(const Callback &returnz) { - returnz(g_texture_globals.m_nTextureCompressionFormat); - } - - static void Import(int value) { - g_texture_globals.m_nTextureCompressionFormat = static_cast( value ); - Textures_UpdateTextureCompressionFormat(); - } + static void Export(const Callback &returnz) + { + returnz(g_texture_globals.m_nTextureCompressionFormat); + } + + static void Import(int value) + { + g_texture_globals.m_nTextureCompressionFormat = static_cast( value ); + Textures_UpdateTextureCompressionFormat(); + } }; -void Textures_Construct(){ - g_texturesmap = new TexturesMap; +void Textures_Construct() +{ + g_texturesmap = new TexturesMap; - GlobalPreferenceSystem().registerPreference( "TextureCompressionFormat", make_property_string() ); - GlobalPreferenceSystem().registerPreference( "TextureFiltering", make_property_string( reinterpret_cast( g_texture_mode ) ) ); - GlobalPreferenceSystem().registerPreference( "TextureQuality", make_property_string( g_Textures_textureQuality.m_latched ) ); - GlobalPreferenceSystem().registerPreference( "SI_Gamma", make_property_string( g_texture_globals.fGamma ) ); + GlobalPreferenceSystem().registerPreference("TextureCompressionFormat", + make_property_string()); + GlobalPreferenceSystem().registerPreference("TextureFiltering", + make_property_string(reinterpret_cast( g_texture_mode ))); + GlobalPreferenceSystem().registerPreference("TextureQuality", + make_property_string(g_Textures_textureQuality.m_latched)); + GlobalPreferenceSystem().registerPreference("SI_Gamma", make_property_string(g_texture_globals.fGamma)); - g_Textures_textureQuality.useLatched(); + g_Textures_textureQuality.useLatched(); - Textures_registerPreferencesPage(); + Textures_registerPreferencesPage(); - Textures_ModeChanged(); + Textures_ModeChanged(); } -void Textures_Destroy(){ - delete g_texturesmap; + +void Textures_Destroy() +{ + delete g_texturesmap; } @@ -810,44 +850,52 @@ void Textures_Destroy(){ #include "modulesystem/moduleregistry.h" class TexturesDependencies : - public GlobalRadiantModuleRef, - public GlobalOpenGLModuleRef, - public GlobalPreferenceSystemModuleRef -{ -ImageModulesRef m_image_modules; + public GlobalRadiantModuleRef, + public GlobalOpenGLModuleRef, + public GlobalPreferenceSystemModuleRef { + ImageModulesRef m_image_modules; public: -TexturesDependencies() : - m_image_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "texturetypes" ) ){ -} -ImageModules& getImageModules(){ - return m_image_modules.get(); -} + TexturesDependencies() : + m_image_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("texturetypes")) + { + } + + ImageModules &getImageModules() + { + return m_image_modules.get(); + } }; -class TexturesAPI -{ -TexturesCache* m_textures; +class TexturesAPI { + TexturesCache *m_textures; public: -typedef TexturesCache Type; -STRING_CONSTANT( Name, "*" ); + typedef TexturesCache Type; -TexturesAPI(){ - Textures_Construct(); + STRING_CONSTANT(Name, "*"); - m_textures = &GetTexturesCache(); -} -~TexturesAPI(){ - Textures_Destroy(); -} -TexturesCache* getTable(){ - return m_textures; -} + TexturesAPI() + { + Textures_Construct(); + + m_textures = &GetTexturesCache(); + } + + ~TexturesAPI() + { + Textures_Destroy(); + } + + TexturesCache *getTable() + { + return m_textures; + } }; typedef SingletonModule TexturesModule; typedef Static StaticTexturesModule; -StaticRegisterModule staticRegisterTextures( StaticTexturesModule::instance() ); +StaticRegisterModule staticRegisterTextures(StaticTexturesModule::instance()); -ImageModules& Textures_getImageModules(){ - return StaticTexturesModule::instance().getDependencies().getImageModules(); +ImageModules &Textures_getImageModules() +{ + return StaticTexturesModule::instance().getDependencies().getImageModules(); } diff --git a/radiant/textures.h b/radiant/textures.h index 3176ce6d..35f22f38 100644 --- a/radiant/textures.h +++ b/radiant/textures.h @@ -25,9 +25,11 @@ #include "generic/callback.h" void Textures_Realise(); + void Textures_Unrealise(); + void Textures_sharedContextDestroyed(); -void Textures_setModeChangedNotify( const Callback& notify ); +void Textures_setModeChangedNotify(const Callback ¬ify); #endif diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index cc31400e..e6afb71d 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -89,353 +89,388 @@ #define NOTEX_BASENAME "notex" #define SHADERNOTEX_BASENAME "shadernotex" -bool TextureBrowser_showWads(){ - return !string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ); +bool TextureBrowser_showWads() +{ + return !string_empty(g_pGameDescription->getKeyValue("show_wads")); } -void TextureBrowser_queueDraw( TextureBrowser& textureBrowser ); +void TextureBrowser_queueDraw(TextureBrowser &textureBrowser); -bool string_equal_start( const char* string, StringRange start ){ - return string_equal_n( string, start.first, start.last - start.first ); +bool string_equal_start(const char *string, StringRange start) +{ + return string_equal_n(string, start.first, start.last - start.first); } typedef std::set TextureGroups; -void TextureGroups_addWad( TextureGroups& groups, const char* archive ){ - if ( extension_equal( path_get_extension( archive ), "wad" ) ) { +void TextureGroups_addWad(TextureGroups &groups, const char *archive) +{ + if (extension_equal(path_get_extension(archive), "wad")) { #if 1 - groups.insert( archive ); + groups.insert(archive); #else - CopiedString archiveBaseName( path_get_filename_start( archive ), path_get_filename_base_end( archive ) ); + CopiedString archiveBaseName( path_get_filename_start( archive ), path_get_filename_base_end( archive ) ); groups.insert( archiveBaseName ); #endif - } + } } -typedef ReferenceCaller TextureGroupsAddWadCaller; -namespace -{ -bool g_TextureBrowser_shaderlistOnly = false; -bool g_TextureBrowser_fixedSize = true; -bool g_TextureBrowser_filterMissing = false; -bool g_TextureBrowser_filterFallback = true; -bool g_TextureBrowser_enableAlpha = true; +typedef ReferenceCaller TextureGroupsAddWadCaller; + +namespace { + bool g_TextureBrowser_shaderlistOnly = false; + bool g_TextureBrowser_fixedSize = true; + bool g_TextureBrowser_filterMissing = false; + bool g_TextureBrowser_filterFallback = true; + bool g_TextureBrowser_enableAlpha = true; } CopiedString g_notex; CopiedString g_shadernotex; -bool isMissing(const char* name); -bool isNotex(const char* name); - -bool isMissing(const char* name){ - if ( string_equal( g_notex.c_str(), name ) ) { - return true; - } - if ( string_equal( g_shadernotex.c_str(), name ) ) { - return true; - } - return false; -} - -bool isNotex(const char* name){ - if ( string_equal_suffix( name, "/" NOTEX_BASENAME ) ) { - return true; - } - if ( string_equal_suffix( name, "/" SHADERNOTEX_BASENAME ) ) { - return true; - } - return false; -} - -void TextureGroups_addShader( TextureGroups& groups, const char* shaderName ){ - const char* texture = path_make_relative( shaderName, "textures/" ); - - // hide notex / shadernotex images - if ( g_TextureBrowser_filterFallback ) { - if ( isNotex( shaderName ) ) { - return; - } - if ( isNotex( texture ) ) { - return; - } - } - - if ( texture != shaderName ) { - const char* last = path_remove_directory( texture ); - if ( !string_empty( last ) ) { - groups.insert( CopiedString( StringRange( texture, --last ) ) ); - } - } -} -typedef ReferenceCaller TextureGroupsAddShaderCaller; - -void TextureGroups_addDirectory( TextureGroups& groups, const char* directory ){ - groups.insert( directory ); -} -typedef ReferenceCaller TextureGroupsAddDirectoryCaller; - -class DeferredAdjustment -{ -gdouble m_value; -guint m_handler; -typedef void ( *ValueChangedFunction )( void* data, gdouble value ); -ValueChangedFunction m_function; -void* m_data; - -static gboolean deferred_value_changed( gpointer data ){ - reinterpret_cast( data )->m_function( - reinterpret_cast( data )->m_data, - reinterpret_cast( data )->m_value - ); - reinterpret_cast( data )->m_handler = 0; - reinterpret_cast( data )->m_value = 0; - return FALSE; -} -public: -DeferredAdjustment( ValueChangedFunction function, void* data ) : m_value( 0 ), m_handler( 0 ), m_function( function ), m_data( data ){ + +bool isMissing(const char *name); + +bool isNotex(const char *name); + +bool isMissing(const char *name) +{ + if (string_equal(g_notex.c_str(), name)) { + return true; + } + if (string_equal(g_shadernotex.c_str(), name)) { + return true; + } + return false; } -void flush(){ - if ( m_handler != 0 ) { - g_source_remove( m_handler ); - deferred_value_changed( this ); - } + +bool isNotex(const char *name) +{ + if (string_equal_suffix(name, "/" NOTEX_BASENAME)) { + return true; + } + if (string_equal_suffix(name, "/" SHADERNOTEX_BASENAME)) { + return true; + } + return false; } -void value_changed( gdouble value ){ - m_value = value; - if ( m_handler == 0 ) { - m_handler = g_idle_add( deferred_value_changed, this ); - } + +void TextureGroups_addShader(TextureGroups &groups, const char *shaderName) +{ + const char *texture = path_make_relative(shaderName, "textures/"); + + // hide notex / shadernotex images + if (g_TextureBrowser_filterFallback) { + if (isNotex(shaderName)) { + return; + } + if (isNotex(texture)) { + return; + } + } + + if (texture != shaderName) { + const char *last = path_remove_directory(texture); + if (!string_empty(last)) { + groups.insert(CopiedString(StringRange(texture, --last))); + } + } } -static void adjustment_value_changed(ui::Adjustment adjustment, DeferredAdjustment* self ){ - self->value_changed( gtk_adjustment_get_value(adjustment) ); + +typedef ReferenceCaller TextureGroupsAddShaderCaller; + +void TextureGroups_addDirectory(TextureGroups &groups, const char *directory) +{ + groups.insert(directory); } -}; +typedef ReferenceCaller TextureGroupsAddDirectoryCaller; + +class DeferredAdjustment { + gdouble m_value; + guint m_handler; + + typedef void ( *ValueChangedFunction )(void *data, gdouble value); + + ValueChangedFunction m_function; + void *m_data; + + static gboolean deferred_value_changed(gpointer data) + { + reinterpret_cast( data )->m_function( + reinterpret_cast( data )->m_data, + reinterpret_cast( data )->m_value + ); + reinterpret_cast( data )->m_handler = 0; + reinterpret_cast( data )->m_value = 0; + return FALSE; + } + +public: + DeferredAdjustment(ValueChangedFunction function, void *data) : m_value(0), m_handler(0), m_function(function), + m_data(data) + { + } + + void flush() + { + if (m_handler != 0) { + g_source_remove(m_handler); + deferred_value_changed(this); + } + } + + void value_changed(gdouble value) + { + m_value = value; + if (m_handler == 0) { + m_handler = g_idle_add(deferred_value_changed, this); + } + } + + static void adjustment_value_changed(ui::Adjustment adjustment, DeferredAdjustment *self) + { + self->value_changed(gtk_adjustment_get_value(adjustment)); + } +}; class TextureBrowser; typedef ReferenceCaller TextureBrowserQueueDrawCaller; -void TextureBrowser_scrollChanged( void* data, gdouble value ); +void TextureBrowser_scrollChanged(void *data, gdouble value); -enum StartupShaders -{ - STARTUPSHADERS_NONE = 0, - STARTUPSHADERS_COMMON, +enum StartupShaders { + STARTUPSHADERS_NONE = 0, + STARTUPSHADERS_COMMON, }; -void TextureBrowser_hideUnusedExport( const Callback & importer ); +void TextureBrowser_hideUnusedExport(const Callback &importer); + typedef FreeCaller &), TextureBrowser_hideUnusedExport> TextureBrowserHideUnusedExport; -void TextureBrowser_showShadersExport( const Callback & importer ); -typedef FreeCaller &), TextureBrowser_showShadersExport> TextureBrowserShowShadersExport; +void TextureBrowser_showShadersExport(const Callback &importer); + +typedef FreeCaller &), TextureBrowser_showShadersExport> TextureBrowserShowShadersExport; + +void TextureBrowser_showShaderlistOnly(const Callback &importer); + +typedef FreeCaller &), TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport; -void TextureBrowser_showShaderlistOnly( const Callback & importer ); -typedef FreeCaller &), TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport; +void TextureBrowser_fixedSize(const Callback &importer); -void TextureBrowser_fixedSize( const Callback & importer ); typedef FreeCaller &), TextureBrowser_fixedSize> TextureBrowserFixedSizeExport; -void TextureBrowser_filterMissing( const Callback & importer ); +void TextureBrowser_filterMissing(const Callback &importer); + typedef FreeCaller &), TextureBrowser_filterMissing> TextureBrowserFilterMissingExport; -void TextureBrowser_filterFallback( const Callback & importer ); -typedef FreeCaller &), TextureBrowser_filterFallback> TextureBrowserFilterFallbackExport; +void TextureBrowser_filterFallback(const Callback &importer); + +typedef FreeCaller &), TextureBrowser_filterFallback> TextureBrowserFilterFallbackExport; + +void TextureBrowser_enableAlpha(const Callback &importer); -void TextureBrowser_enableAlpha( const Callback & importer ); typedef FreeCaller &), TextureBrowser_enableAlpha> TextureBrowserEnableAlphaExport; -class TextureBrowser -{ +class TextureBrowser { public: -int width, height; -int originy; -int m_nTotalHeight; - -CopiedString shader; - -ui::Window m_parent{ui::null}; -ui::GLArea m_gl_widget{ui::null}; -ui::Widget m_texture_scroll{ui::null}; -ui::TreeView m_treeViewTree{ui::New}; -ui::TreeView m_treeViewTags{ui::null}; -ui::Frame m_tag_frame{ui::null}; -ui::ListStore m_assigned_store{ui::null}; -ui::ListStore m_available_store{ui::null}; -ui::TreeView m_assigned_tree{ui::null}; -ui::TreeView m_available_tree{ui::null}; -ui::Widget m_scr_win_tree{ui::null}; -ui::Widget m_scr_win_tags{ui::null}; -ui::Widget m_tag_notebook{ui::null}; -ui::Button m_search_button{ui::null}; -ui::Widget m_shader_info_item{ui::null}; - -std::set m_all_tags; -ui::ListStore m_all_tags_list{ui::null}; -std::vector m_copied_tags; -std::set m_found_shaders; - -ToggleItem m_hideunused_item; -ToggleItem m_hidenotex_item; -ToggleItem m_showshaders_item; -ToggleItem m_showshaderlistonly_item; -ToggleItem m_fixedsize_item; -ToggleItem m_filternotex_item; -ToggleItem m_enablealpha_item; - -guint m_sizeHandler; -guint m_exposeHandler; - -bool m_heightChanged; -bool m_originInvalid; - -DeferredAdjustment m_scrollAdjustment; -FreezePointer m_freezePointer; - -Vector3 color_textureback; + int width, height; + int originy; + int m_nTotalHeight; + + CopiedString shader; + + ui::Window m_parent{ui::null}; + ui::GLArea m_gl_widget{ui::null}; + ui::Widget m_texture_scroll{ui::null}; + ui::TreeView m_treeViewTree{ui::New}; + ui::TreeView m_treeViewTags{ui::null}; + ui::Frame m_tag_frame{ui::null}; + ui::ListStore m_assigned_store{ui::null}; + ui::ListStore m_available_store{ui::null}; + ui::TreeView m_assigned_tree{ui::null}; + ui::TreeView m_available_tree{ui::null}; + ui::Widget m_scr_win_tree{ui::null}; + ui::Widget m_scr_win_tags{ui::null}; + ui::Widget m_tag_notebook{ui::null}; + ui::Button m_search_button{ui::null}; + ui::Widget m_shader_info_item{ui::null}; + + std::set m_all_tags; + ui::ListStore m_all_tags_list{ui::null}; + std::vector m_copied_tags; + std::set m_found_shaders; + + ToggleItem m_hideunused_item; + ToggleItem m_hidenotex_item; + ToggleItem m_showshaders_item; + ToggleItem m_showshaderlistonly_item; + ToggleItem m_fixedsize_item; + ToggleItem m_filternotex_item; + ToggleItem m_enablealpha_item; + + guint m_sizeHandler; + guint m_exposeHandler; + + bool m_heightChanged; + bool m_originInvalid; + + DeferredAdjustment m_scrollAdjustment; + FreezePointer m_freezePointer; + + Vector3 color_textureback; // the increment step we use against the wheel mouse -std::size_t m_mouseWheelScrollIncrement; -std::size_t m_textureScale; + std::size_t m_mouseWheelScrollIncrement; + std::size_t m_textureScale; // make the texture increments match the grid changes -bool m_showShaders; -bool m_showTextureScrollbar; -StartupShaders m_startupShaders; + bool m_showShaders; + bool m_showTextureScrollbar; + StartupShaders m_startupShaders; // if true, the texture window will only display in-use shaders // if false, all the shaders in memory are displayed -bool m_hideUnused; -bool m_rmbSelected; -bool m_searchedTags; -bool m_tags; + bool m_hideUnused; + bool m_rmbSelected; + bool m_searchedTags; + bool m_tags; // The uniform size (in pixels) that textures are resized to when m_resizeTextures is true. -int m_uniformTextureSize; + int m_uniformTextureSize; + // Return the display width of a texture in the texture browser -int getTextureWidth( qtexture_t* tex ){ - int width; - if ( !g_TextureBrowser_fixedSize ) { - // Don't use uniform size - width = (int)( tex->width * ( (float)m_textureScale / 100 ) ); - } - else if - ( tex->width >= tex->height ) { - // Texture is square, or wider than it is tall - width = m_uniformTextureSize; - } - else { - // Otherwise, preserve the texture's aspect ratio - width = (int)( m_uniformTextureSize * ( (float)tex->width / tex->height ) ); - } - return width; -} + int getTextureWidth(qtexture_t *tex) + { + int width; + if (!g_TextureBrowser_fixedSize) { + // Don't use uniform size + width = (int) (tex->width * ((float) m_textureScale / 100)); + } else if + (tex->width >= tex->height) { + // Texture is square, or wider than it is tall + width = m_uniformTextureSize; + } else { + // Otherwise, preserve the texture's aspect ratio + width = (int) (m_uniformTextureSize * ((float) tex->width / tex->height)); + } + return width; + } + // Return the display height of a texture in the texture browser -int getTextureHeight( qtexture_t* tex ){ - int height; - if ( !g_TextureBrowser_fixedSize ) { - // Don't use uniform size - height = (int)( tex->height * ( (float)m_textureScale / 100 ) ); - } - else if ( tex->height >= tex->width ) { - // Texture is square, or taller than it is wide - height = m_uniformTextureSize; - } - else { - // Otherwise, preserve the texture's aspect ratio - height = (int)( m_uniformTextureSize * ( (float)tex->height / tex->width ) ); - } - return height; -} - -TextureBrowser() : - m_texture_scroll( ui::null ), - m_hideunused_item( TextureBrowserHideUnusedExport() ), - m_hidenotex_item( TextureBrowserFilterFallbackExport() ), - m_showshaders_item( TextureBrowserShowShadersExport() ), - m_showshaderlistonly_item( TextureBrowserShowShaderlistOnlyExport() ), - m_fixedsize_item( TextureBrowserFixedSizeExport() ), - m_filternotex_item( TextureBrowserFilterMissingExport() ), - m_enablealpha_item( TextureBrowserEnableAlphaExport() ), - m_heightChanged( true ), - m_originInvalid( true ), - m_scrollAdjustment( TextureBrowser_scrollChanged, this ), - color_textureback( 0.25f, 0.25f, 0.25f ), - m_mouseWheelScrollIncrement( 64 ), - m_textureScale( 50 ), - m_showShaders( true ), - m_showTextureScrollbar( true ), - m_startupShaders( STARTUPSHADERS_NONE ), - m_hideUnused( false ), - m_rmbSelected( false ), - m_searchedTags( false ), - m_tags( false ), - m_uniformTextureSize( 96 ){ -} + int getTextureHeight(qtexture_t *tex) + { + int height; + if (!g_TextureBrowser_fixedSize) { + // Don't use uniform size + height = (int) (tex->height * ((float) m_textureScale / 100)); + } else if (tex->height >= tex->width) { + // Texture is square, or taller than it is wide + height = m_uniformTextureSize; + } else { + // Otherwise, preserve the texture's aspect ratio + height = (int) (m_uniformTextureSize * ((float) tex->height / tex->width)); + } + return height; + } + + TextureBrowser() : + m_texture_scroll(ui::null), + m_hideunused_item(TextureBrowserHideUnusedExport()), + m_hidenotex_item(TextureBrowserFilterFallbackExport()), + m_showshaders_item(TextureBrowserShowShadersExport()), + m_showshaderlistonly_item(TextureBrowserShowShaderlistOnlyExport()), + m_fixedsize_item(TextureBrowserFixedSizeExport()), + m_filternotex_item(TextureBrowserFilterMissingExport()), + m_enablealpha_item(TextureBrowserEnableAlphaExport()), + m_heightChanged(true), + m_originInvalid(true), + m_scrollAdjustment(TextureBrowser_scrollChanged, this), + color_textureback(0.25f, 0.25f, 0.25f), + m_mouseWheelScrollIncrement(64), + m_textureScale(50), + m_showShaders(true), + m_showTextureScrollbar(true), + m_startupShaders(STARTUPSHADERS_NONE), + m_hideUnused(false), + m_rmbSelected(false), + m_searchedTags(false), + m_tags(false), + m_uniformTextureSize(96) + { + } }; -void ( *TextureBrowser_textureSelected )( const char* shader ); +void ( *TextureBrowser_textureSelected )(const char *shader); -void TextureBrowser_updateScroll( TextureBrowser& textureBrowser ); +void TextureBrowser_updateScroll(TextureBrowser &textureBrowser); -const char* TextureBrowser_getComonShadersName(){ - const char* value = g_pGameDescription->getKeyValue( "common_shaders_name" ); - if ( !string_empty( value ) ) { - return value; - } - return "Common"; +const char *TextureBrowser_getComonShadersName() +{ + const char *value = g_pGameDescription->getKeyValue("common_shaders_name"); + if (!string_empty(value)) { + return value; + } + return "Common"; } -const char* TextureBrowser_getComonShadersDir(){ - const char* value = g_pGameDescription->getKeyValue( "common_shaders_dir" ); - if ( !string_empty( value ) ) { - return value; - } - return "common/"; +const char *TextureBrowser_getComonShadersDir() +{ + const char *value = g_pGameDescription->getKeyValue("common_shaders_dir"); + if (!string_empty(value)) { + return value; + } + return "common/"; } -inline int TextureBrowser_fontHeight( TextureBrowser& textureBrowser ){ - return GlobalOpenGL().m_font->getPixelHeight(); +inline int TextureBrowser_fontHeight(TextureBrowser &textureBrowser) +{ + return GlobalOpenGL().m_font->getPixelHeight(); } -const char* TextureBrowser_GetSelectedShader( TextureBrowser& textureBrowser ){ - return textureBrowser.shader.c_str(); +const char *TextureBrowser_GetSelectedShader(TextureBrowser &textureBrowser) +{ + return textureBrowser.shader.c_str(); } -void TextureBrowser_SetStatus( TextureBrowser& textureBrowser, const char* name ){ - IShader* shader = QERApp_Shader_ForName( name ); - qtexture_t* q = shader->getTexture(); - StringOutputStream strTex( 256 ); - strTex << name << " W: " << Unsigned( q->width ) << " H: " << Unsigned( q->height ); - shader->DecRef(); - g_pParentWnd->SetStatusText( g_pParentWnd->m_texture_status, strTex.c_str() ); +void TextureBrowser_SetStatus(TextureBrowser &textureBrowser, const char *name) +{ + IShader *shader = QERApp_Shader_ForName(name); + qtexture_t *q = shader->getTexture(); + StringOutputStream strTex(256); + strTex << name << " W: " << Unsigned(q->width) << " H: " << Unsigned(q->height); + shader->DecRef(); + g_pParentWnd->SetStatusText(g_pParentWnd->m_texture_status, strTex.c_str()); } -void TextureBrowser_Focus( TextureBrowser& textureBrowser, const char* name ); +void TextureBrowser_Focus(TextureBrowser &textureBrowser, const char *name); -void TextureBrowser_SetSelectedShader( TextureBrowser& textureBrowser, const char* shader ){ - textureBrowser.shader = shader; - TextureBrowser_SetStatus( textureBrowser, shader ); - TextureBrowser_Focus( textureBrowser, shader ); +void TextureBrowser_SetSelectedShader(TextureBrowser &textureBrowser, const char *shader) +{ + textureBrowser.shader = shader; + TextureBrowser_SetStatus(textureBrowser, shader); + TextureBrowser_Focus(textureBrowser, shader); - if ( FindTextureDialog_isOpen() ) { - FindTextureDialog_selectTexture( shader ); - } + if (FindTextureDialog_isOpen()) { + FindTextureDialog_selectTexture(shader); + } - // disable the menu item "shader info" if no shader was selected - IShader* ishader = QERApp_Shader_ForName( shader ); - CopiedString filename = ishader->getShaderFileName(); + // disable the menu item "shader info" if no shader was selected + IShader *ishader = QERApp_Shader_ForName(shader); + CopiedString filename = ishader->getShaderFileName(); - if ( filename.empty() ) { - if ( textureBrowser.m_shader_info_item != NULL ) { - gtk_widget_set_sensitive( textureBrowser.m_shader_info_item, FALSE ); - } - } - else { - gtk_widget_set_sensitive( textureBrowser.m_shader_info_item, TRUE ); - } + if (filename.empty()) { + if (textureBrowser.m_shader_info_item != NULL) { + gtk_widget_set_sensitive(textureBrowser.m_shader_info_item, FALSE); + } + } else { + gtk_widget_set_sensitive(textureBrowser.m_shader_info_item, TRUE); + } - ishader->DecRef(); + ishader->DecRef(); } @@ -452,237 +487,254 @@ CopiedString g_TextureBrowser_currentDirectory; ============================================================================ */ -class TextureLayout -{ +class TextureLayout { public: // texture layout functions // TTimo: now based on shaders -int current_x, current_y, current_row; + int current_x, current_y, current_row; }; -void Texture_StartPos( TextureLayout& layout ){ - layout.current_x = 8; - layout.current_y = -8; - layout.current_row = 0; +void Texture_StartPos(TextureLayout &layout) +{ + layout.current_x = 8; + layout.current_y = -8; + layout.current_row = 0; } -void Texture_NextPos( TextureBrowser& textureBrowser, TextureLayout& layout, qtexture_t* current_texture, int *x, int *y ){ - qtexture_t* q = current_texture; +void Texture_NextPos(TextureBrowser &textureBrowser, TextureLayout &layout, qtexture_t *current_texture, int *x, int *y) +{ + qtexture_t *q = current_texture; - int nWidth = textureBrowser.getTextureWidth( q ); - int nHeight = textureBrowser.getTextureHeight( q ); - if ( layout.current_x + nWidth > textureBrowser.width - 8 && layout.current_row ) { // go to the next row unless the texture is the first on the row - layout.current_x = 8; - layout.current_y -= layout.current_row + TextureBrowser_fontHeight( textureBrowser ) + 4; - layout.current_row = 0; - } + int nWidth = textureBrowser.getTextureWidth(q); + int nHeight = textureBrowser.getTextureHeight(q); + if (layout.current_x + nWidth > textureBrowser.width - 8 && + layout.current_row) { // go to the next row unless the texture is the first on the row + layout.current_x = 8; + layout.current_y -= layout.current_row + TextureBrowser_fontHeight(textureBrowser) + 4; + layout.current_row = 0; + } - *x = layout.current_x; - *y = layout.current_y; + *x = layout.current_x; + *y = layout.current_y; - // Is our texture larger than the row? If so, grow the - // row height to match it + // Is our texture larger than the row? If so, grow the + // row height to match it - if ( layout.current_row < nHeight ) { - layout.current_row = nHeight; - } + if (layout.current_row < nHeight) { + layout.current_row = nHeight; + } - // never go less than 96, or the names get all crunched up - layout.current_x += nWidth < 96 ? 96 : nWidth; - layout.current_x += 8; + // never go less than 96, or the names get all crunched up + layout.current_x += nWidth < 96 ? 96 : nWidth; + layout.current_x += 8; } -bool TextureSearch_IsShown( const char* name ){ - std::set::iterator iter; +bool TextureSearch_IsShown(const char *name) +{ + std::set::iterator iter; - iter = GlobalTextureBrowser().m_found_shaders.find( name ); + iter = GlobalTextureBrowser().m_found_shaders.find(name); - if ( iter == GlobalTextureBrowser().m_found_shaders.end() ) { - return false; - } - else { - return true; - } + if (iter == GlobalTextureBrowser().m_found_shaders.end()) { + return false; + } else { + return true; + } } // if texture_showinuse jump over non in-use textures -bool Texture_IsShown( IShader* shader, bool show_shaders, bool hideUnused ){ - // filter missing shaders - // ugly: filter on built-in fallback name after substitution - if ( g_TextureBrowser_filterMissing ) { - if ( isMissing( shader->getTexture()->name ) ) { - return false; - } - } - // filter the fallback (notex/shadernotex) for missing shaders or editor image - if ( g_TextureBrowser_filterFallback ) { - if ( isNotex( shader->getName() ) ) { - return false; - } - if ( isNotex( shader->getTexture()->name ) ) { - return false; - } - } - - if ( g_TextureBrowser_currentDirectory == "Untagged" ) { - std::set::iterator iter; - - iter = GlobalTextureBrowser().m_found_shaders.find( shader->getName() ); - - if ( iter == GlobalTextureBrowser().m_found_shaders.end() ) { - return false; - } - else { - return true; - } - } - - if ( !shader_equal_prefix( shader->getName(), "textures/" ) ) { - return false; - } - - if ( !show_shaders && !shader->IsDefault() ) { - return false; - } - - if ( hideUnused && !shader->IsInUse() ) { - return false; - } - - if ( GlobalTextureBrowser().m_searchedTags ) { - if ( !TextureSearch_IsShown( shader->getName() ) ) { - return false; - } - else { - return true; - } - } - else { - if ( !shader_equal_prefix( shader_get_textureName( shader->getName() ), g_TextureBrowser_currentDirectory.c_str() ) ) { - return false; - } - } - - return true; -} - -void TextureBrowser_heightChanged( TextureBrowser& textureBrowser ){ - textureBrowser.m_heightChanged = true; - - TextureBrowser_updateScroll( textureBrowser ); - TextureBrowser_queueDraw( textureBrowser ); -} - -void TextureBrowser_evaluateHeight( TextureBrowser& textureBrowser ){ - if ( textureBrowser.m_heightChanged ) { - textureBrowser.m_heightChanged = false; - - textureBrowser.m_nTotalHeight = 0; - - TextureLayout layout; - Texture_StartPos( layout ); - for ( QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement() ) - { - IShader* shader = QERApp_ActiveShaders_IteratorCurrent(); - - if ( !Texture_IsShown( shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused ) ) { - continue; - } - - int x, y; - Texture_NextPos( textureBrowser, layout, shader->getTexture(), &x, &y ); - textureBrowser.m_nTotalHeight = std::max( textureBrowser.m_nTotalHeight, abs( layout.current_y ) + TextureBrowser_fontHeight( textureBrowser ) + textureBrowser.getTextureHeight( shader->getTexture() ) + 4 ); - } - } -} - -int TextureBrowser_TotalHeight( TextureBrowser& textureBrowser ){ - TextureBrowser_evaluateHeight( textureBrowser ); - return textureBrowser.m_nTotalHeight; -} - -inline const int& min_int( const int& left, const int& right ){ - return std::min( left, right ); -} - -void TextureBrowser_clampOriginY( TextureBrowser& textureBrowser ){ - if ( textureBrowser.originy > 0 ) { - textureBrowser.originy = 0; - } - int lower = min_int( textureBrowser.height - TextureBrowser_TotalHeight( textureBrowser ), 0 ); - if ( textureBrowser.originy < lower ) { - textureBrowser.originy = lower; - } +bool Texture_IsShown(IShader *shader, bool show_shaders, bool hideUnused) +{ + // filter missing shaders + // ugly: filter on built-in fallback name after substitution + if (g_TextureBrowser_filterMissing) { + if (isMissing(shader->getTexture()->name)) { + return false; + } + } + // filter the fallback (notex/shadernotex) for missing shaders or editor image + if (g_TextureBrowser_filterFallback) { + if (isNotex(shader->getName())) { + return false; + } + if (isNotex(shader->getTexture()->name)) { + return false; + } + } + + if (g_TextureBrowser_currentDirectory == "Untagged") { + std::set::iterator iter; + + iter = GlobalTextureBrowser().m_found_shaders.find(shader->getName()); + + if (iter == GlobalTextureBrowser().m_found_shaders.end()) { + return false; + } else { + return true; + } + } + + if (!shader_equal_prefix(shader->getName(), "textures/")) { + return false; + } + + if (!show_shaders && !shader->IsDefault()) { + return false; + } + + if (hideUnused && !shader->IsInUse()) { + return false; + } + + if (GlobalTextureBrowser().m_searchedTags) { + if (!TextureSearch_IsShown(shader->getName())) { + return false; + } else { + return true; + } + } else { + if (!shader_equal_prefix(shader_get_textureName(shader->getName()), + g_TextureBrowser_currentDirectory.c_str())) { + return false; + } + } + + return true; +} + +void TextureBrowser_heightChanged(TextureBrowser &textureBrowser) +{ + textureBrowser.m_heightChanged = true; + + TextureBrowser_updateScroll(textureBrowser); + TextureBrowser_queueDraw(textureBrowser); +} + +void TextureBrowser_evaluateHeight(TextureBrowser &textureBrowser) +{ + if (textureBrowser.m_heightChanged) { + textureBrowser.m_heightChanged = false; + + textureBrowser.m_nTotalHeight = 0; + + TextureLayout layout; + Texture_StartPos(layout); + for (QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement()) { + IShader *shader = QERApp_ActiveShaders_IteratorCurrent(); + + if (!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused)) { + continue; + } + + int x, y; + Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y); + textureBrowser.m_nTotalHeight = std::max(textureBrowser.m_nTotalHeight, + abs(layout.current_y) + TextureBrowser_fontHeight(textureBrowser) + + textureBrowser.getTextureHeight(shader->getTexture()) + 4); + } + } } -int TextureBrowser_getOriginY( TextureBrowser& textureBrowser ){ - if ( textureBrowser.m_originInvalid ) { - textureBrowser.m_originInvalid = false; - TextureBrowser_clampOriginY( textureBrowser ); - TextureBrowser_updateScroll( textureBrowser ); - } - return textureBrowser.originy; +int TextureBrowser_TotalHeight(TextureBrowser &textureBrowser) +{ + TextureBrowser_evaluateHeight(textureBrowser); + return textureBrowser.m_nTotalHeight; } -void TextureBrowser_setOriginY( TextureBrowser& textureBrowser, int originy ){ - textureBrowser.originy = originy; - TextureBrowser_clampOriginY( textureBrowser ); - TextureBrowser_updateScroll( textureBrowser ); - TextureBrowser_queueDraw( textureBrowser ); +inline const int &min_int(const int &left, const int &right) +{ + return std::min(left, right); +} + +void TextureBrowser_clampOriginY(TextureBrowser &textureBrowser) +{ + if (textureBrowser.originy > 0) { + textureBrowser.originy = 0; + } + int lower = min_int(textureBrowser.height - TextureBrowser_TotalHeight(textureBrowser), 0); + if (textureBrowser.originy < lower) { + textureBrowser.originy = lower; + } +} + +int TextureBrowser_getOriginY(TextureBrowser &textureBrowser) +{ + if (textureBrowser.m_originInvalid) { + textureBrowser.m_originInvalid = false; + TextureBrowser_clampOriginY(textureBrowser); + TextureBrowser_updateScroll(textureBrowser); + } + return textureBrowser.originy; +} + +void TextureBrowser_setOriginY(TextureBrowser &textureBrowser, int originy) +{ + textureBrowser.originy = originy; + TextureBrowser_clampOriginY(textureBrowser); + TextureBrowser_updateScroll(textureBrowser); + TextureBrowser_queueDraw(textureBrowser); } Signal0 g_activeShadersChangedCallbacks; -void TextureBrowser_addActiveShadersChangedCallback( const SignalHandler& handler ){ - g_activeShadersChangedCallbacks.connectLast( handler ); +void TextureBrowser_addActiveShadersChangedCallback(const SignalHandler &handler) +{ + g_activeShadersChangedCallbacks.connectLast(handler); } void TextureBrowser_constructTreeStore(); -class ShadersObserver : public ModuleObserver -{ -Signal0 m_realiseCallbacks; +class ShadersObserver : public ModuleObserver { + Signal0 m_realiseCallbacks; public: -void realise(){ - m_realiseCallbacks(); - TextureBrowser_constructTreeStore(); -} -void unrealise(){ -} -void insert( const SignalHandler& handler ){ - m_realiseCallbacks.connectLast( handler ); -} + void realise() + { + m_realiseCallbacks(); + TextureBrowser_constructTreeStore(); + } + + void unrealise() + { + } + + void insert(const SignalHandler &handler) + { + m_realiseCallbacks.connectLast(handler); + } }; -namespace -{ -ShadersObserver g_ShadersObserver; +namespace { + ShadersObserver g_ShadersObserver; } -void TextureBrowser_addShadersRealiseCallback( const SignalHandler& handler ){ - g_ShadersObserver.insert( handler ); +void TextureBrowser_addShadersRealiseCallback(const SignalHandler &handler) +{ + g_ShadersObserver.insert(handler); } -void TextureBrowser_activeShadersChanged( TextureBrowser& textureBrowser ){ - TextureBrowser_heightChanged( textureBrowser ); - textureBrowser.m_originInvalid = true; +void TextureBrowser_activeShadersChanged(TextureBrowser &textureBrowser) +{ + TextureBrowser_heightChanged(textureBrowser); + textureBrowser.m_originInvalid = true; - g_activeShadersChangedCallbacks(); + g_activeShadersChangedCallbacks(); } struct TextureBrowser_ShowScrollbar { - static void Export(const TextureBrowser &self, const Callback &returnz) { - returnz(self.m_showTextureScrollbar); - } - - static void Import(TextureBrowser &self, bool value) { - self.m_showTextureScrollbar = value; - if (self.m_texture_scroll) { - self.m_texture_scroll.visible(self.m_showTextureScrollbar); - TextureBrowser_updateScroll(self); - } - } + static void Export(const TextureBrowser &self, const Callback &returnz) + { + returnz(self.m_showTextureScrollbar); + } + + static void Import(TextureBrowser &self, bool value) + { + self.m_showTextureScrollbar = value; + if (self.m_texture_scroll) { + self.m_texture_scroll.visible(self.m_showTextureScrollbar); + TextureBrowser_updateScroll(self); + } + } }; @@ -701,227 +753,254 @@ struct TextureBrowser_ShowScrollbar { ============== */ -bool endswith( const char *haystack, const char *needle ){ - size_t lh = strlen( haystack ); - size_t ln = strlen( needle ); - if ( lh < ln ) { - return false; - } - return !memcmp( haystack + ( lh - ln ), needle, ln ); -} - -bool texture_name_ignore( const char* name ){ - StringOutputStream strTemp( string_length( name ) ); - strTemp << LowerCase( name ); - - return - endswith( strTemp.c_str(), ".specular" ) || - endswith( strTemp.c_str(), ".glow" ) || - endswith( strTemp.c_str(), ".bump" ) || - endswith( strTemp.c_str(), ".diffuse" ) || - endswith( strTemp.c_str(), ".blend" ) || - endswith( strTemp.c_str(), ".alpha" ) || - endswith( strTemp.c_str(), "_norm" ) || - endswith( strTemp.c_str(), "_bump" ) || - endswith( strTemp.c_str(), "_glow" ) || - endswith( strTemp.c_str(), "_gloss" ) || - endswith( strTemp.c_str(), "_pants" ) || - endswith( strTemp.c_str(), "_shirt" ) || - endswith( strTemp.c_str(), "_reflect" ) || - endswith( strTemp.c_str(), "_alpha" ) || - 0; -} - -class LoadShaderVisitor : public Archive::Visitor +bool endswith(const char *haystack, const char *needle) { -public: -void visit( const char* name ){ - IShader* shader = QERApp_Shader_ForName( CopiedString( StringRange( name, path_get_filename_base_end( name ) ) ).c_str() ); - shader->DecRef(); + size_t lh = strlen(haystack); + size_t ln = strlen(needle); + if (lh < ln) { + return false; + } + return !memcmp(haystack + (lh - ln), needle, ln); } + +bool texture_name_ignore(const char *name) +{ + StringOutputStream strTemp(string_length(name)); + strTemp << LowerCase(name); + + return + endswith(strTemp.c_str(), ".specular") || + endswith(strTemp.c_str(), ".glow") || + endswith(strTemp.c_str(), ".bump") || + endswith(strTemp.c_str(), ".diffuse") || + endswith(strTemp.c_str(), ".blend") || + endswith(strTemp.c_str(), ".alpha") || + endswith(strTemp.c_str(), "_norm") || + endswith(strTemp.c_str(), "_bump") || + endswith(strTemp.c_str(), "_glow") || + endswith(strTemp.c_str(), "_gloss") || + endswith(strTemp.c_str(), "_pants") || + endswith(strTemp.c_str(), "_shirt") || + endswith(strTemp.c_str(), "_reflect") || + endswith(strTemp.c_str(), "_alpha") || + 0; +} + +class LoadShaderVisitor : public Archive::Visitor { +public: + void visit(const char *name) + { + IShader *shader = QERApp_Shader_ForName( + CopiedString(StringRange(name, path_get_filename_base_end(name))).c_str()); + shader->DecRef(); + } }; -void TextureBrowser_SetHideUnused( TextureBrowser& textureBrowser, bool hideUnused ); +void TextureBrowser_SetHideUnused(TextureBrowser &textureBrowser, bool hideUnused); ui::Widget g_page_textures{ui::null}; -void TextureBrowser_toggleShow(){ - GroupDialog_showPage( g_page_textures ); +void TextureBrowser_toggleShow() +{ + GroupDialog_showPage(g_page_textures); } -void TextureBrowser_updateTitle(){ - GroupDialog_updatePageTitle( g_page_textures ); +void TextureBrowser_updateTitle() +{ + GroupDialog_updatePageTitle(g_page_textures); } - -class TextureCategoryLoadShader -{ -const char* m_directory; -std::size_t& m_count; +class TextureCategoryLoadShader { + const char *m_directory; + std::size_t &m_count; public: -using func = void(const char *); - -TextureCategoryLoadShader( const char* directory, std::size_t& count ) - : m_directory( directory ), m_count( count ){ - m_count = 0; -} -void operator()( const char* name ) const { - if ( shader_equal_prefix( name, "textures/" ) - && shader_equal_prefix( name + string_length( "textures/" ), m_directory ) ) { - ++m_count; - // request the shader, this will load the texture if needed - // this Shader_ForName call is a kind of hack - IShader *pFoo = QERApp_Shader_ForName( name ); - pFoo->DecRef(); - } -} + using func = void(const char *); + + TextureCategoryLoadShader(const char *directory, std::size_t &count) + : m_directory(directory), m_count(count) + { + m_count = 0; + } + + void operator()(const char *name) const + { + if (shader_equal_prefix(name, "textures/") + && shader_equal_prefix(name + string_length("textures/"), m_directory)) { + ++m_count; + // request the shader, this will load the texture if needed + // this Shader_ForName call is a kind of hack + IShader *pFoo = QERApp_Shader_ForName(name); + pFoo->DecRef(); + } + } }; -void TextureDirectory_loadTexture( const char* directory, const char* texture ){ - StringOutputStream name( 256 ); - name << directory << StringRange( texture, path_get_filename_base_end( texture ) ); +void TextureDirectory_loadTexture(const char *directory, const char *texture) +{ + StringOutputStream name(256); + name << directory << StringRange(texture, path_get_filename_base_end(texture)); - if ( texture_name_ignore( name.c_str() ) ) { - return; - } + if (texture_name_ignore(name.c_str())) { + return; + } - if ( !shader_valid( name.c_str() ) ) { - globalOutputStream() << "Skipping invalid texture name: [" << name.c_str() << "]\n"; - return; - } + if (!shader_valid(name.c_str())) { + globalOutputStream() << "Skipping invalid texture name: [" << name.c_str() << "]\n"; + return; + } - // if a texture is already in use to represent a shader, ignore it - IShader* shader = QERApp_Shader_ForName( name.c_str() ); - shader->DecRef(); + // if a texture is already in use to represent a shader, ignore it + IShader *shader = QERApp_Shader_ForName(name.c_str()); + shader->DecRef(); } -typedef ConstPointerCaller TextureDirectoryLoadTextureCaller; -class LoadTexturesByTypeVisitor : public ImageModules::Visitor -{ -const char* m_dirstring; +typedef ConstPointerCaller TextureDirectoryLoadTextureCaller; + +class LoadTexturesByTypeVisitor : public ImageModules::Visitor { + const char *m_dirstring; public: -LoadTexturesByTypeVisitor( const char* dirstring ) - : m_dirstring( dirstring ){ -} -void visit( const char* minor, const _QERPlugImageTable& table ) const { - GlobalFileSystem().forEachFile( m_dirstring, minor, TextureDirectoryLoadTextureCaller( m_dirstring ) ); -} + LoadTexturesByTypeVisitor(const char *dirstring) + : m_dirstring(dirstring) + { + } + + void visit(const char *minor, const _QERPlugImageTable &table) const + { + GlobalFileSystem().forEachFile(m_dirstring, minor, TextureDirectoryLoadTextureCaller(m_dirstring)); + } }; -void TextureBrowser_ShowDirectory( TextureBrowser& textureBrowser, const char* directory ){ - if ( TextureBrowser_showWads() ) { - Archive* archive = GlobalFileSystem().getArchive( directory ); - ASSERT_NOTNULL( archive ); - LoadShaderVisitor visitor; - archive->forEachFile( Archive::VisitorFunc( visitor, Archive::eFiles, 0 ), "textures/" ); - } - else - { - g_TextureBrowser_currentDirectory = directory; - TextureBrowser_heightChanged( textureBrowser ); +void TextureBrowser_ShowDirectory(TextureBrowser &textureBrowser, const char *directory) +{ + if (TextureBrowser_showWads()) { + Archive *archive = GlobalFileSystem().getArchive(directory); + ASSERT_NOTNULL(archive); + LoadShaderVisitor visitor; + archive->forEachFile(Archive::VisitorFunc(visitor, Archive::eFiles, 0), "textures/"); + } else { + g_TextureBrowser_currentDirectory = directory; + TextureBrowser_heightChanged(textureBrowser); - std::size_t shaders_count; - GlobalShaderSystem().foreachShaderName(makeCallback( TextureCategoryLoadShader( directory, shaders_count ) ) ); - globalOutputStream() << "Showing " << Unsigned( shaders_count ) << " shaders.\n"; + std::size_t shaders_count; + GlobalShaderSystem().foreachShaderName(makeCallback(TextureCategoryLoadShader(directory, shaders_count))); + globalOutputStream() << "Showing " << Unsigned(shaders_count) << " shaders.\n"; - if ( g_pGameDescription->mGameType != "doom3" ) { - // load remaining texture files + if (g_pGameDescription->mGameType != "doom3") { + // load remaining texture files - StringOutputStream dirstring( 64 ); - dirstring << "textures/" << directory; + StringOutputStream dirstring(64); + dirstring << "textures/" << directory; - Radiant_getImageModules().foreachModule( LoadTexturesByTypeVisitor( dirstring.c_str() ) ); - } - } + Radiant_getImageModules().foreachModule(LoadTexturesByTypeVisitor(dirstring.c_str())); + } + } - // we'll display the newly loaded textures + all the ones already in use - TextureBrowser_SetHideUnused( textureBrowser, false ); + // we'll display the newly loaded textures + all the ones already in use + TextureBrowser_SetHideUnused(textureBrowser, false); - TextureBrowser_updateTitle(); + TextureBrowser_updateTitle(); } -void TextureBrowser_ShowTagSearchResult( TextureBrowser& textureBrowser, const char* directory ){ - g_TextureBrowser_currentDirectory = directory; - TextureBrowser_heightChanged( textureBrowser ); +void TextureBrowser_ShowTagSearchResult(TextureBrowser &textureBrowser, const char *directory) +{ + g_TextureBrowser_currentDirectory = directory; + TextureBrowser_heightChanged(textureBrowser); - std::size_t shaders_count; - GlobalShaderSystem().foreachShaderName(makeCallback( TextureCategoryLoadShader( directory, shaders_count ) ) ); - globalOutputStream() << "Showing " << Unsigned( shaders_count ) << " shaders.\n"; + std::size_t shaders_count; + GlobalShaderSystem().foreachShaderName(makeCallback(TextureCategoryLoadShader(directory, shaders_count))); + globalOutputStream() << "Showing " << Unsigned(shaders_count) << " shaders.\n"; - if ( g_pGameDescription->mGameType != "doom3" ) { - // load remaining texture files - StringOutputStream dirstring( 64 ); - dirstring << "textures/" << directory; + if (g_pGameDescription->mGameType != "doom3") { + // load remaining texture files + StringOutputStream dirstring(64); + dirstring << "textures/" << directory; - { - LoadTexturesByTypeVisitor visitor( dirstring.c_str() ); - Radiant_getImageModules().foreachModule( visitor ); - } - } + { + LoadTexturesByTypeVisitor visitor(dirstring.c_str()); + Radiant_getImageModules().foreachModule(visitor); + } + } - // we'll display the newly loaded textures + all the ones already in use - TextureBrowser_SetHideUnused( textureBrowser, false ); + // we'll display the newly loaded textures + all the ones already in use + TextureBrowser_SetHideUnused(textureBrowser, false); } bool TextureBrowser_hideUnused(); -void TextureBrowser_hideUnusedExport( const Callback & importer ){ - importer( TextureBrowser_hideUnused() ); +void TextureBrowser_hideUnusedExport(const Callback &importer) +{ + importer(TextureBrowser_hideUnused()); } + typedef FreeCaller &), TextureBrowser_hideUnusedExport> TextureBrowserHideUnusedExport; -void TextureBrowser_showShadersExport( const Callback & importer ){ - importer( GlobalTextureBrowser().m_showShaders ); +void TextureBrowser_showShadersExport(const Callback &importer) +{ + importer(GlobalTextureBrowser().m_showShaders); } -typedef FreeCaller &), TextureBrowser_showShadersExport> TextureBrowserShowShadersExport; -void TextureBrowser_showShaderlistOnly( const Callback & importer ){ - importer( g_TextureBrowser_shaderlistOnly ); +typedef FreeCaller &), TextureBrowser_showShadersExport> TextureBrowserShowShadersExport; + +void TextureBrowser_showShaderlistOnly(const Callback &importer) +{ + importer(g_TextureBrowser_shaderlistOnly); } -typedef FreeCaller &), TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport; -void TextureBrowser_fixedSize( const Callback & importer ){ - importer( g_TextureBrowser_fixedSize ); +typedef FreeCaller &), TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport; + +void TextureBrowser_fixedSize(const Callback &importer) +{ + importer(g_TextureBrowser_fixedSize); } + typedef FreeCaller &), TextureBrowser_fixedSize> TextureBrowser_FixedSizeExport; -void TextureBrowser_filterMissing( const Callback & importer ){ - importer( g_TextureBrowser_filterMissing ); +void TextureBrowser_filterMissing(const Callback &importer) +{ + importer(g_TextureBrowser_filterMissing); } + typedef FreeCaller &), TextureBrowser_filterMissing> TextureBrowser_filterMissingExport; -void TextureBrowser_filterFallback( const Callback & importer ){ - importer( g_TextureBrowser_filterFallback ); +void TextureBrowser_filterFallback(const Callback &importer) +{ + importer(g_TextureBrowser_filterFallback); } -typedef FreeCaller &), TextureBrowser_filterFallback> TextureBrowser_filterFallbackExport; -void TextureBrowser_enableAlpha( const Callback & importer ){ - importer( g_TextureBrowser_enableAlpha ); +typedef FreeCaller &), TextureBrowser_filterFallback> TextureBrowser_filterFallbackExport; + +void TextureBrowser_enableAlpha(const Callback &importer) +{ + importer(g_TextureBrowser_enableAlpha); } + typedef FreeCaller &), TextureBrowser_enableAlpha> TextureBrowser_enableAlphaExport; -void TextureBrowser_SetHideUnused( TextureBrowser& textureBrowser, bool hideUnused ){ - if ( hideUnused ) { - textureBrowser.m_hideUnused = true; - } - else - { - textureBrowser.m_hideUnused = false; - } +void TextureBrowser_SetHideUnused(TextureBrowser &textureBrowser, bool hideUnused) +{ + if (hideUnused) { + textureBrowser.m_hideUnused = true; + } else { + textureBrowser.m_hideUnused = false; + } - textureBrowser.m_hideunused_item.update(); + textureBrowser.m_hideunused_item.update(); - TextureBrowser_heightChanged( textureBrowser ); - textureBrowser.m_originInvalid = true; + TextureBrowser_heightChanged(textureBrowser); + textureBrowser.m_originInvalid = true; } -void TextureBrowser_ShowStartupShaders( TextureBrowser& textureBrowser ){ - if ( textureBrowser.m_startupShaders == STARTUPSHADERS_COMMON ) { - TextureBrowser_ShowDirectory( textureBrowser, TextureBrowser_getComonShadersDir() ); - } +void TextureBrowser_ShowStartupShaders(TextureBrowser &textureBrowser) +{ + if (textureBrowser.m_startupShaders == STARTUPSHADERS_COMMON) { + TextureBrowser_ShowDirectory(textureBrowser, TextureBrowser_getComonShadersDir()); + } } @@ -929,76 +1008,76 @@ void TextureBrowser_ShowStartupShaders( TextureBrowser& textureBrowser ){ // it might need to be split in parts or moved out .. dunno // scroll origin so the specified texture is completely on screen // if current texture is not displayed, nothing is changed -void TextureBrowser_Focus( TextureBrowser& textureBrowser, const char* name ){ - TextureLayout layout; - // scroll origin so the texture is completely on screen - Texture_StartPos( layout ); - - for ( QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement() ) - { - IShader* shader = QERApp_ActiveShaders_IteratorCurrent(); - - if ( !Texture_IsShown( shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused ) ) { - continue; - } - - int x, y; - Texture_NextPos( textureBrowser, layout, shader->getTexture(), &x, &y ); - qtexture_t* q = shader->getTexture(); - if ( !q ) { - break; - } - - // we have found when texdef->name and the shader name match - // NOTE: as everywhere else for our comparisons, we are not case sensitive - if ( shader_equal( name, shader->getName() ) ) { - int textureHeight = (int)( q->height * ( (float)textureBrowser.m_textureScale / 100 ) ) - + 2 * TextureBrowser_fontHeight( textureBrowser ); - - int originy = TextureBrowser_getOriginY( textureBrowser ); - if ( y > originy ) { - originy = y; - } - - if ( y - textureHeight < originy - textureBrowser.height ) { - originy = ( y - textureHeight ) + textureBrowser.height; - } - - TextureBrowser_setOriginY( textureBrowser, originy ); - return; - } - } -} - -IShader* Texture_At( TextureBrowser& textureBrowser, int mx, int my ){ - my += TextureBrowser_getOriginY( textureBrowser ) - textureBrowser.height; - - TextureLayout layout; - Texture_StartPos( layout ); - for ( QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement() ) - { - IShader* shader = QERApp_ActiveShaders_IteratorCurrent(); - - if ( !Texture_IsShown( shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused ) ) { - continue; - } - - int x, y; - Texture_NextPos( textureBrowser, layout, shader->getTexture(), &x, &y ); - qtexture_t *q = shader->getTexture(); - if ( !q ) { - break; - } - - int nWidth = textureBrowser.getTextureWidth( q ); - int nHeight = textureBrowser.getTextureHeight( q ); - if ( mx > x && mx - x < nWidth - && my < y && y - my < nHeight + TextureBrowser_fontHeight( textureBrowser ) ) { - return shader; - } - } - - return 0; +void TextureBrowser_Focus(TextureBrowser &textureBrowser, const char *name) +{ + TextureLayout layout; + // scroll origin so the texture is completely on screen + Texture_StartPos(layout); + + for (QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement()) { + IShader *shader = QERApp_ActiveShaders_IteratorCurrent(); + + if (!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused)) { + continue; + } + + int x, y; + Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y); + qtexture_t *q = shader->getTexture(); + if (!q) { + break; + } + + // we have found when texdef->name and the shader name match + // NOTE: as everywhere else for our comparisons, we are not case sensitive + if (shader_equal(name, shader->getName())) { + int textureHeight = (int) (q->height * ((float) textureBrowser.m_textureScale / 100)) + + 2 * TextureBrowser_fontHeight(textureBrowser); + + int originy = TextureBrowser_getOriginY(textureBrowser); + if (y > originy) { + originy = y; + } + + if (y - textureHeight < originy - textureBrowser.height) { + originy = (y - textureHeight) + textureBrowser.height; + } + + TextureBrowser_setOriginY(textureBrowser, originy); + return; + } + } +} + +IShader *Texture_At(TextureBrowser &textureBrowser, int mx, int my) +{ + my += TextureBrowser_getOriginY(textureBrowser) - textureBrowser.height; + + TextureLayout layout; + Texture_StartPos(layout); + for (QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement()) { + IShader *shader = QERApp_ActiveShaders_IteratorCurrent(); + + if (!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused)) { + continue; + } + + int x, y; + Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y); + qtexture_t *q = shader->getTexture(); + if (!q) { + break; + } + + int nWidth = textureBrowser.getTextureWidth(q); + int nHeight = textureBrowser.getTextureHeight(q); + if (mx > x && mx - x < nWidth + && my < y && y - my < nHeight + TextureBrowser_fontHeight(textureBrowser)) { + return shader; + } + } + + return 0; } /* @@ -1008,28 +1087,26 @@ IShader* Texture_At( TextureBrowser& textureBrowser, int mx, int my ){ By mouse click ============== */ -void SelectTexture( TextureBrowser& textureBrowser, int mx, int my, bool bShift ){ - IShader* shader = Texture_At( textureBrowser, mx, my ); - if ( shader != 0 ) { - if ( bShift ) { - if ( shader->IsDefault() ) { - globalOutputStream() << "ERROR: " << shader->getName() << " is not a shader, it's a texture.\n"; - } - else{ - ViewShader( shader->getShaderFileName(), shader->getName() ); - } - } - else - { - TextureBrowser_SetSelectedShader( textureBrowser, shader->getName() ); - TextureBrowser_textureSelected( shader->getName() ); - - if ( !FindTextureDialog_isOpen() && !textureBrowser.m_rmbSelected ) { - UndoableCommand undo( "textureNameSetSelected" ); - Select_SetShader( shader->getName() ); - } - } - } +void SelectTexture(TextureBrowser &textureBrowser, int mx, int my, bool bShift) +{ + IShader *shader = Texture_At(textureBrowser, mx, my); + if (shader != 0) { + if (bShift) { + if (shader->IsDefault()) { + globalOutputStream() << "ERROR: " << shader->getName() << " is not a shader, it's a texture.\n"; + } else { + ViewShader(shader->getShaderFileName(), shader->getName()); + } + } else { + TextureBrowser_SetSelectedShader(textureBrowser, shader->getName()); + TextureBrowser_textureSelected(shader->getName()); + + if (!FindTextureDialog_isOpen() && !textureBrowser.m_rmbSelected) { + UndoableCommand undo("textureNameSetSelected"); + Select_SetShader(shader->getName()); + } + } + } } /* @@ -1040,31 +1117,36 @@ void SelectTexture( TextureBrowser& textureBrowser, int mx, int my, bool bShift ============================================================================ */ -void TextureBrowser_trackingDelta( int x, int y, unsigned int state, void* data ){ - TextureBrowser& textureBrowser = *reinterpret_cast( data ); - if ( y != 0 ) { - int scale = 1; +void TextureBrowser_trackingDelta(int x, int y, unsigned int state, void *data) +{ + TextureBrowser &textureBrowser = *reinterpret_cast( data ); + if (y != 0) { + int scale = 1; - if ( state & GDK_SHIFT_MASK ) { - scale = 4; - } + if (state & GDK_SHIFT_MASK) { + scale = 4; + } - int originy = TextureBrowser_getOriginY( textureBrowser ); - originy += y * scale; - TextureBrowser_setOriginY( textureBrowser, originy ); - } + int originy = TextureBrowser_getOriginY(textureBrowser); + originy += y * scale; + TextureBrowser_setOriginY(textureBrowser, originy); + } } -void TextureBrowser_Tracking_MouseDown( TextureBrowser& textureBrowser ){ - textureBrowser.m_freezePointer.freeze_pointer( textureBrowser.m_parent, TextureBrowser_trackingDelta, &textureBrowser ); +void TextureBrowser_Tracking_MouseDown(TextureBrowser &textureBrowser) +{ + textureBrowser.m_freezePointer.freeze_pointer(textureBrowser.m_parent, TextureBrowser_trackingDelta, + &textureBrowser); } -void TextureBrowser_Tracking_MouseUp( TextureBrowser& textureBrowser ){ - textureBrowser.m_freezePointer.unfreeze_pointer( textureBrowser.m_parent ); +void TextureBrowser_Tracking_MouseUp(TextureBrowser &textureBrowser) +{ + textureBrowser.m_freezePointer.unfreeze_pointer(textureBrowser.m_parent); } -void TextureBrowser_Selection_MouseDown( TextureBrowser& textureBrowser, guint32 flags, int pointx, int pointy ){ - SelectTexture( textureBrowser, pointx, textureBrowser.height - 1 - pointy, ( flags & GDK_SHIFT_MASK ) != 0 ); +void TextureBrowser_Selection_MouseDown(TextureBrowser &textureBrowser, guint32 flags, int pointx, int pointy) +{ + SelectTexture(textureBrowser, pointx, textureBrowser.height - 1 - pointy, (flags & GDK_SHIFT_MASK) != 0); } /* @@ -1083,1524 +1165,1581 @@ void TextureBrowser_Selection_MouseDown( TextureBrowser& textureBrowser, guint32 this allows a plugin to completely override the texture system ============ */ -void Texture_Draw( TextureBrowser& textureBrowser ){ - int originy = TextureBrowser_getOriginY( textureBrowser ); - - glClearColor( textureBrowser.color_textureback[0], - textureBrowser.color_textureback[1], - textureBrowser.color_textureback[2], - 0 ); - glViewport( 0, 0, textureBrowser.width, textureBrowser.height ); - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - glDisable( GL_DEPTH_TEST ); - if ( g_TextureBrowser_enableAlpha ) { - glEnable( GL_BLEND ); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else { - glDisable( GL_BLEND ); - } - glOrtho( 0, textureBrowser.width, originy - textureBrowser.height, originy, -100, 100 ); - glEnable( GL_TEXTURE_2D ); - - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - - int last_y = 0, last_height = 0; - - TextureLayout layout; - Texture_StartPos( layout ); - for ( QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement() ) - { - IShader* shader = QERApp_ActiveShaders_IteratorCurrent(); - - if ( !Texture_IsShown( shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused ) ) { - continue; - } - - int x, y; - Texture_NextPos( textureBrowser, layout, shader->getTexture(), &x, &y ); - qtexture_t *q = shader->getTexture(); - if ( !q ) { - break; - } - - int nWidth = textureBrowser.getTextureWidth( q ); - int nHeight = textureBrowser.getTextureHeight( q ); - - if ( y != last_y ) { - last_y = y; - last_height = 0; - } - last_height = std::max( nHeight, last_height ); - - // Is this texture visible? - if ( ( y - nHeight - TextureBrowser_fontHeight( textureBrowser ) < originy ) - && ( y > originy - textureBrowser.height ) ) { - // borders rules: - // if it's the current texture, draw a thick red line, else: - // shaders have a white border, simple textures don't - // if !texture_showinuse: (some textures displayed may not be in use) - // draw an additional square around with 0.5 1 0.5 color - if ( shader_equal( TextureBrowser_GetSelectedShader( textureBrowser ), shader->getName() ) ) { - glLineWidth( 3 ); - if ( textureBrowser.m_rmbSelected ) { - glColor3f( 0,0,1 ); - } - else { - glColor3f( 1,0,0 ); - } - glDisable( GL_TEXTURE_2D ); - - glBegin( GL_LINE_LOOP ); - glVertex2i( x - 4,y - TextureBrowser_fontHeight( textureBrowser ) + 4 ); - glVertex2i( x - 4,y - TextureBrowser_fontHeight( textureBrowser ) - nHeight - 4 ); - glVertex2i( x + 4 + nWidth,y - TextureBrowser_fontHeight( textureBrowser ) - nHeight - 4 ); - glVertex2i( x + 4 + nWidth,y - TextureBrowser_fontHeight( textureBrowser ) + 4 ); - glEnd(); - - glEnable( GL_TEXTURE_2D ); - glLineWidth( 1 ); - } - else - { - glLineWidth( 1 ); - // shader border: - if ( !shader->IsDefault() ) { - glColor3f( 1,1,1 ); - glDisable( GL_TEXTURE_2D ); - - glBegin( GL_LINE_LOOP ); - glVertex2i( x - 1,y + 1 - TextureBrowser_fontHeight( textureBrowser ) ); - glVertex2i( x - 1,y - nHeight - 1 - TextureBrowser_fontHeight( textureBrowser ) ); - glVertex2i( x + 1 + nWidth,y - nHeight - 1 - TextureBrowser_fontHeight( textureBrowser ) ); - glVertex2i( x + 1 + nWidth,y + 1 - TextureBrowser_fontHeight( textureBrowser ) ); - glEnd(); - glEnable( GL_TEXTURE_2D ); - } - - // highlight in-use textures - if ( !textureBrowser.m_hideUnused && shader->IsInUse() ) { - glColor3f( 0.5,1,0.5 ); - glDisable( GL_TEXTURE_2D ); - glBegin( GL_LINE_LOOP ); - glVertex2i( x - 3,y + 3 - TextureBrowser_fontHeight( textureBrowser ) ); - glVertex2i( x - 3,y - nHeight - 3 - TextureBrowser_fontHeight( textureBrowser ) ); - glVertex2i( x + 3 + nWidth,y - nHeight - 3 - TextureBrowser_fontHeight( textureBrowser ) ); - glVertex2i( x + 3 + nWidth,y + 3 - TextureBrowser_fontHeight( textureBrowser ) ); - glEnd(); - glEnable( GL_TEXTURE_2D ); - } - } - - // draw checkerboard for transparent textures - if ( g_TextureBrowser_enableAlpha ) - { - glDisable( GL_TEXTURE_2D ); - glBegin( GL_QUADS ); - int font_height = TextureBrowser_fontHeight( textureBrowser ); - for ( int i = 0; i < nHeight; i += 8 ) - for ( int j = 0; j < nWidth; j += 8 ) - { - unsigned char color = (i + j) / 8 % 2 ? 0x66 : 0x99; - glColor3ub( color, color, color ); - int left = j; - int right = std::min(j+8, nWidth); - int top = i; - int bottom = std::min(i+8, nHeight); - glVertex2i(x + right, y - nHeight - font_height + top); - glVertex2i(x + left, y - nHeight - font_height + top); - glVertex2i(x + left, y - nHeight - font_height + bottom); - glVertex2i(x + right, y - nHeight - font_height + bottom); - } - glEnd(); - glEnable( GL_TEXTURE_2D ); - } - - // Draw the texture - glBindTexture( GL_TEXTURE_2D, q->texture_number ); - GlobalOpenGL_debugAssertNoErrors(); - glColor3f( 1,1,1 ); - glBegin( GL_QUADS ); - glTexCoord2i( 0,0 ); - glVertex2i( x,y - TextureBrowser_fontHeight( textureBrowser ) ); - glTexCoord2i( 1,0 ); - glVertex2i( x + nWidth,y - TextureBrowser_fontHeight( textureBrowser ) ); - glTexCoord2i( 1,1 ); - glVertex2i( x + nWidth,y - TextureBrowser_fontHeight( textureBrowser ) - nHeight ); - glTexCoord2i( 0,1 ); - glVertex2i( x,y - TextureBrowser_fontHeight( textureBrowser ) - nHeight ); - glEnd(); - - // draw the texture name - glDisable( GL_TEXTURE_2D ); - glColor3f( 1,1,1 ); - - glRasterPos2i( x, y - TextureBrowser_fontHeight( textureBrowser ) + 5 ); - - // don't draw the directory name - const char* name = shader->getName(); - name += strlen( name ); - while ( name != shader->getName() && *( name - 1 ) != '/' && *( name - 1 ) != '\\' ) - name--; - - GlobalOpenGL().drawString( name ); - glEnable( GL_TEXTURE_2D ); - } - - //int totalHeight = abs(y) + last_height + TextureBrowser_fontHeight(textureBrowser) + 4; - } - - - // reset the current texture - glBindTexture( GL_TEXTURE_2D, 0 ); - //qglFinish(); -} - -void TextureBrowser_queueDraw( TextureBrowser& textureBrowser ){ - if ( textureBrowser.m_gl_widget ) { - gtk_widget_queue_draw( textureBrowser.m_gl_widget ); - } -} - - -void TextureBrowser_setScale( TextureBrowser& textureBrowser, std::size_t scale ){ - textureBrowser.m_textureScale = scale; - - TextureBrowser_queueDraw( textureBrowser ); -} - -void TextureBrowser_setUniformSize( TextureBrowser& textureBrowser, std::size_t scale ){ - textureBrowser.m_uniformTextureSize = scale; - - TextureBrowser_queueDraw( textureBrowser ); -} - - -void TextureBrowser_MouseWheel( TextureBrowser& textureBrowser, bool bUp ){ - int originy = TextureBrowser_getOriginY( textureBrowser ); - - if ( bUp ) { - originy += int(textureBrowser.m_mouseWheelScrollIncrement); - } - else - { - originy -= int(textureBrowser.m_mouseWheelScrollIncrement); - } - - TextureBrowser_setOriginY( textureBrowser, originy ); +void Texture_Draw(TextureBrowser &textureBrowser) +{ + int originy = TextureBrowser_getOriginY(textureBrowser); + + glClearColor(textureBrowser.color_textureback[0], + textureBrowser.color_textureback[1], + textureBrowser.color_textureback[2], + 0); + glViewport(0, 0, textureBrowser.width, textureBrowser.height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + if (g_TextureBrowser_enableAlpha) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } else { + glDisable(GL_BLEND); + } + glOrtho(0, textureBrowser.width, originy - textureBrowser.height, originy, -100, 100); + glEnable(GL_TEXTURE_2D); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + int last_y = 0, last_height = 0; + + TextureLayout layout; + Texture_StartPos(layout); + for (QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement()) { + IShader *shader = QERApp_ActiveShaders_IteratorCurrent(); + + if (!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused)) { + continue; + } + + int x, y; + Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y); + qtexture_t *q = shader->getTexture(); + if (!q) { + break; + } + + int nWidth = textureBrowser.getTextureWidth(q); + int nHeight = textureBrowser.getTextureHeight(q); + + if (y != last_y) { + last_y = y; + last_height = 0; + } + last_height = std::max(nHeight, last_height); + + // Is this texture visible? + if ((y - nHeight - TextureBrowser_fontHeight(textureBrowser) < originy) + && (y > originy - textureBrowser.height)) { + // borders rules: + // if it's the current texture, draw a thick red line, else: + // shaders have a white border, simple textures don't + // if !texture_showinuse: (some textures displayed may not be in use) + // draw an additional square around with 0.5 1 0.5 color + if (shader_equal(TextureBrowser_GetSelectedShader(textureBrowser), shader->getName())) { + glLineWidth(3); + if (textureBrowser.m_rmbSelected) { + glColor3f(0, 0, 1); + } else { + glColor3f(1, 0, 0); + } + glDisable(GL_TEXTURE_2D); + + glBegin(GL_LINE_LOOP); + glVertex2i(x - 4, y - TextureBrowser_fontHeight(textureBrowser) + 4); + glVertex2i(x - 4, y - TextureBrowser_fontHeight(textureBrowser) - nHeight - 4); + glVertex2i(x + 4 + nWidth, y - TextureBrowser_fontHeight(textureBrowser) - nHeight - 4); + glVertex2i(x + 4 + nWidth, y - TextureBrowser_fontHeight(textureBrowser) + 4); + glEnd(); + + glEnable(GL_TEXTURE_2D); + glLineWidth(1); + } else { + glLineWidth(1); + // shader border: + if (!shader->IsDefault()) { + glColor3f(1, 1, 1); + glDisable(GL_TEXTURE_2D); + + glBegin(GL_LINE_LOOP); + glVertex2i(x - 1, y + 1 - TextureBrowser_fontHeight(textureBrowser)); + glVertex2i(x - 1, y - nHeight - 1 - TextureBrowser_fontHeight(textureBrowser)); + glVertex2i(x + 1 + nWidth, y - nHeight - 1 - TextureBrowser_fontHeight(textureBrowser)); + glVertex2i(x + 1 + nWidth, y + 1 - TextureBrowser_fontHeight(textureBrowser)); + glEnd(); + glEnable(GL_TEXTURE_2D); + } + + // highlight in-use textures + if (!textureBrowser.m_hideUnused && shader->IsInUse()) { + glColor3f(0.5, 1, 0.5); + glDisable(GL_TEXTURE_2D); + glBegin(GL_LINE_LOOP); + glVertex2i(x - 3, y + 3 - TextureBrowser_fontHeight(textureBrowser)); + glVertex2i(x - 3, y - nHeight - 3 - TextureBrowser_fontHeight(textureBrowser)); + glVertex2i(x + 3 + nWidth, y - nHeight - 3 - TextureBrowser_fontHeight(textureBrowser)); + glVertex2i(x + 3 + nWidth, y + 3 - TextureBrowser_fontHeight(textureBrowser)); + glEnd(); + glEnable(GL_TEXTURE_2D); + } + } + + // draw checkerboard for transparent textures + if (g_TextureBrowser_enableAlpha) { + glDisable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + int font_height = TextureBrowser_fontHeight(textureBrowser); + for (int i = 0; i < nHeight; i += 8) { + for (int j = 0; j < nWidth; j += 8) { + unsigned char color = (i + j) / 8 % 2 ? 0x66 : 0x99; + glColor3ub(color, color, color); + int left = j; + int right = std::min(j + 8, nWidth); + int top = i; + int bottom = std::min(i + 8, nHeight); + glVertex2i(x + right, y - nHeight - font_height + top); + glVertex2i(x + left, y - nHeight - font_height + top); + glVertex2i(x + left, y - nHeight - font_height + bottom); + glVertex2i(x + right, y - nHeight - font_height + bottom); + } + } + glEnd(); + glEnable(GL_TEXTURE_2D); + } + + // Draw the texture + glBindTexture(GL_TEXTURE_2D, q->texture_number); + GlobalOpenGL_debugAssertNoErrors(); + glColor3f(1, 1, 1); + glBegin(GL_QUADS); + glTexCoord2i(0, 0); + glVertex2i(x, y - TextureBrowser_fontHeight(textureBrowser)); + glTexCoord2i(1, 0); + glVertex2i(x + nWidth, y - TextureBrowser_fontHeight(textureBrowser)); + glTexCoord2i(1, 1); + glVertex2i(x + nWidth, y - TextureBrowser_fontHeight(textureBrowser) - nHeight); + glTexCoord2i(0, 1); + glVertex2i(x, y - TextureBrowser_fontHeight(textureBrowser) - nHeight); + glEnd(); + + // draw the texture name + glDisable(GL_TEXTURE_2D); + glColor3f(1, 1, 1); + + glRasterPos2i(x, y - TextureBrowser_fontHeight(textureBrowser) + 5); + + // don't draw the directory name + const char *name = shader->getName(); + name += strlen(name); + while (name != shader->getName() && *(name - 1) != '/' && *(name - 1) != '\\') { + name--; + } + + GlobalOpenGL().drawString(name); + glEnable(GL_TEXTURE_2D); + } + + //int totalHeight = abs(y) + last_height + TextureBrowser_fontHeight(textureBrowser) + 4; + } + + + // reset the current texture + glBindTexture(GL_TEXTURE_2D, 0); + //qglFinish(); +} + +void TextureBrowser_queueDraw(TextureBrowser &textureBrowser) +{ + if (textureBrowser.m_gl_widget) { + gtk_widget_queue_draw(textureBrowser.m_gl_widget); + } } -XmlTagBuilder TagBuilder; -enum +void TextureBrowser_setScale(TextureBrowser &textureBrowser, std::size_t scale) +{ + textureBrowser.m_textureScale = scale; + + TextureBrowser_queueDraw(textureBrowser); +} + +void TextureBrowser_setUniformSize(TextureBrowser &textureBrowser, std::size_t scale) { - TAG_COLUMN, - N_COLUMNS + textureBrowser.m_uniformTextureSize = scale; + + TextureBrowser_queueDraw(textureBrowser); +} + + +void TextureBrowser_MouseWheel(TextureBrowser &textureBrowser, bool bUp) +{ + int originy = TextureBrowser_getOriginY(textureBrowser); + + if (bUp) { + originy += int(textureBrowser.m_mouseWheelScrollIncrement); + } else { + originy -= int(textureBrowser.m_mouseWheelScrollIncrement); + } + + TextureBrowser_setOriginY(textureBrowser, originy); +} + +XmlTagBuilder TagBuilder; + +enum { + TAG_COLUMN, + N_COLUMNS }; -void BuildStoreAssignedTags( ui::ListStore store, const char* shader, TextureBrowser* textureBrowser ){ - GtkTreeIter iter; - - store.clear(); - - std::vector assigned_tags; - TagBuilder.GetShaderTags( shader, assigned_tags ); - - for ( size_t i = 0; i < assigned_tags.size(); i++ ) - { - store.append(TAG_COLUMN, assigned_tags[i].c_str()); - } -} - -void BuildStoreAvailableTags( ui::ListStore storeAvailable, - ui::ListStore storeAssigned, - const std::set& allTags, - TextureBrowser* textureBrowser ){ - GtkTreeIter iterAssigned; - GtkTreeIter iterAvailable; - std::set::const_iterator iterAll; - gchar* tag_assigned; - - storeAvailable.clear(); - - bool row = gtk_tree_model_get_iter_first(storeAssigned, &iterAssigned ) != 0; - - if ( !row ) { // does the shader have tags assigned? - for ( iterAll = allTags.begin(); iterAll != allTags.end(); ++iterAll ) - { - storeAvailable.append(TAG_COLUMN, (*iterAll).c_str()); - } - } - else - { - while ( row ) // available tags = all tags - assigned tags - { - gtk_tree_model_get(storeAssigned, &iterAssigned, TAG_COLUMN, &tag_assigned, -1 ); - - for ( iterAll = allTags.begin(); iterAll != allTags.end(); ++iterAll ) - { - if ( strcmp( (char*)tag_assigned, ( *iterAll ).c_str() ) != 0 ) { - storeAvailable.append(TAG_COLUMN, (*iterAll).c_str()); - } - else - { - row = gtk_tree_model_iter_next(storeAssigned, &iterAssigned ) != 0; - - if ( row ) { - gtk_tree_model_get(storeAssigned, &iterAssigned, TAG_COLUMN, &tag_assigned, -1 ); - } - } - } - } - } -} - -gboolean TextureBrowser_button_press( ui::Widget widget, GdkEventButton* event, TextureBrowser* textureBrowser ){ - if ( event->type == GDK_BUTTON_PRESS ) { - if ( event->button == 3 ) { - if ( GlobalTextureBrowser().m_tags ) { - textureBrowser->m_rmbSelected = true; - TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast( event->x ), static_cast( event->y ) ); - - BuildStoreAssignedTags( textureBrowser->m_assigned_store, textureBrowser->shader.c_str(), textureBrowser ); - BuildStoreAvailableTags( textureBrowser->m_available_store, textureBrowser->m_assigned_store, textureBrowser->m_all_tags, textureBrowser ); - textureBrowser->m_heightChanged = true; - textureBrowser->m_tag_frame.show(); +void BuildStoreAssignedTags(ui::ListStore store, const char *shader, TextureBrowser *textureBrowser) +{ + GtkTreeIter iter; + + store.clear(); + + std::vector assigned_tags; + TagBuilder.GetShaderTags(shader, assigned_tags); + + for (size_t i = 0; i < assigned_tags.size(); i++) { + store.append(TAG_COLUMN, assigned_tags[i].c_str()); + } +} + +void BuildStoreAvailableTags(ui::ListStore storeAvailable, + ui::ListStore storeAssigned, + const std::set &allTags, + TextureBrowser *textureBrowser) +{ + GtkTreeIter iterAssigned; + GtkTreeIter iterAvailable; + std::set::const_iterator iterAll; + gchar *tag_assigned; + + storeAvailable.clear(); + + bool row = gtk_tree_model_get_iter_first(storeAssigned, &iterAssigned) != 0; + + if (!row) { // does the shader have tags assigned? + for (iterAll = allTags.begin(); iterAll != allTags.end(); ++iterAll) { + storeAvailable.append(TAG_COLUMN, (*iterAll).c_str()); + } + } else { + while (row) // available tags = all tags - assigned tags + { + gtk_tree_model_get(storeAssigned, &iterAssigned, TAG_COLUMN, &tag_assigned, -1); + + for (iterAll = allTags.begin(); iterAll != allTags.end(); ++iterAll) { + if (strcmp((char *) tag_assigned, (*iterAll).c_str()) != 0) { + storeAvailable.append(TAG_COLUMN, (*iterAll).c_str()); + } else { + row = gtk_tree_model_iter_next(storeAssigned, &iterAssigned) != 0; + + if (row) { + gtk_tree_model_get(storeAssigned, &iterAssigned, TAG_COLUMN, &tag_assigned, -1); + } + } + } + } + } +} + +gboolean TextureBrowser_button_press(ui::Widget widget, GdkEventButton *event, TextureBrowser *textureBrowser) +{ + if (event->type == GDK_BUTTON_PRESS) { + if (event->button == 3) { + if (GlobalTextureBrowser().m_tags) { + textureBrowser->m_rmbSelected = true; + TextureBrowser_Selection_MouseDown(*textureBrowser, event->state, static_cast( event->x ), + static_cast( event->y )); + + BuildStoreAssignedTags(textureBrowser->m_assigned_store, textureBrowser->shader.c_str(), + textureBrowser); + BuildStoreAvailableTags(textureBrowser->m_available_store, textureBrowser->m_assigned_store, + textureBrowser->m_all_tags, textureBrowser); + textureBrowser->m_heightChanged = true; + textureBrowser->m_tag_frame.show(); ui::process(); - TextureBrowser_Focus( *textureBrowser, textureBrowser->shader.c_str() ); - } - else - { - TextureBrowser_Tracking_MouseDown( *textureBrowser ); - } - } - else if ( event->button == 1 ) { - TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast( event->x ), static_cast( event->y ) ); + TextureBrowser_Focus(*textureBrowser, textureBrowser->shader.c_str()); + } else { + TextureBrowser_Tracking_MouseDown(*textureBrowser); + } + } else if (event->button == 1) { + TextureBrowser_Selection_MouseDown(*textureBrowser, event->state, static_cast( event->x ), + static_cast( event->y )); - if ( GlobalTextureBrowser().m_tags ) { - textureBrowser->m_rmbSelected = false; - textureBrowser->m_tag_frame.hide(); - } - } - } - return FALSE; + if (GlobalTextureBrowser().m_tags) { + textureBrowser->m_rmbSelected = false; + textureBrowser->m_tag_frame.hide(); + } + } + } + return FALSE; } -gboolean TextureBrowser_button_release( ui::Widget widget, GdkEventButton* event, TextureBrowser* textureBrowser ){ - if ( event->type == GDK_BUTTON_RELEASE ) { - if ( event->button == 3 ) { - if ( !GlobalTextureBrowser().m_tags ) { - TextureBrowser_Tracking_MouseUp( *textureBrowser ); - } - } - } - return FALSE; +gboolean TextureBrowser_button_release(ui::Widget widget, GdkEventButton *event, TextureBrowser *textureBrowser) +{ + if (event->type == GDK_BUTTON_RELEASE) { + if (event->button == 3) { + if (!GlobalTextureBrowser().m_tags) { + TextureBrowser_Tracking_MouseUp(*textureBrowser); + } + } + } + return FALSE; } -gboolean TextureBrowser_motion( ui::Widget widget, GdkEventMotion *event, TextureBrowser* textureBrowser ){ - return FALSE; +gboolean TextureBrowser_motion(ui::Widget widget, GdkEventMotion *event, TextureBrowser *textureBrowser) +{ + return FALSE; } -gboolean TextureBrowser_scroll( ui::Widget widget, GdkEventScroll* event, TextureBrowser* textureBrowser ){ - if ( event->direction == GDK_SCROLL_UP ) { - TextureBrowser_MouseWheel( *textureBrowser, true ); - } - else if ( event->direction == GDK_SCROLL_DOWN ) { - TextureBrowser_MouseWheel( *textureBrowser, false ); - } - return FALSE; +gboolean TextureBrowser_scroll(ui::Widget widget, GdkEventScroll *event, TextureBrowser *textureBrowser) +{ + if (event->direction == GDK_SCROLL_UP) { + TextureBrowser_MouseWheel(*textureBrowser, true); + } else if (event->direction == GDK_SCROLL_DOWN) { + TextureBrowser_MouseWheel(*textureBrowser, false); + } + return FALSE; } -void TextureBrowser_scrollChanged( void* data, gdouble value ){ - //globalOutputStream() << "vertical scroll\n"; - TextureBrowser_setOriginY( *reinterpret_cast( data ), -(int)value ); +void TextureBrowser_scrollChanged(void *data, gdouble value) +{ + //globalOutputStream() << "vertical scroll\n"; + TextureBrowser_setOriginY(*reinterpret_cast( data ), -(int) value); } -static void TextureBrowser_verticalScroll(ui::Adjustment adjustment, TextureBrowser* textureBrowser ){ - textureBrowser->m_scrollAdjustment.value_changed( gtk_adjustment_get_value(adjustment) ); +static void TextureBrowser_verticalScroll(ui::Adjustment adjustment, TextureBrowser *textureBrowser) +{ + textureBrowser->m_scrollAdjustment.value_changed(gtk_adjustment_get_value(adjustment)); } -void TextureBrowser_updateScroll( TextureBrowser& textureBrowser ){ - if ( textureBrowser.m_showTextureScrollbar ) { - int totalHeight = TextureBrowser_TotalHeight( textureBrowser ); +void TextureBrowser_updateScroll(TextureBrowser &textureBrowser) +{ + if (textureBrowser.m_showTextureScrollbar) { + int totalHeight = TextureBrowser_TotalHeight(textureBrowser); - totalHeight = std::max( totalHeight, textureBrowser.height ); + totalHeight = std::max(totalHeight, textureBrowser.height); - auto vadjustment = gtk_range_get_adjustment( GTK_RANGE( textureBrowser.m_texture_scroll ) ); + auto vadjustment = gtk_range_get_adjustment(GTK_RANGE(textureBrowser.m_texture_scroll)); - gtk_adjustment_set_value(vadjustment, -TextureBrowser_getOriginY( textureBrowser )); - gtk_adjustment_set_page_size(vadjustment, textureBrowser.height); - gtk_adjustment_set_page_increment(vadjustment, textureBrowser.height / 2); - gtk_adjustment_set_step_increment(vadjustment, 20); - gtk_adjustment_set_lower(vadjustment, 0); - gtk_adjustment_set_upper(vadjustment, totalHeight); + gtk_adjustment_set_value(vadjustment, -TextureBrowser_getOriginY(textureBrowser)); + gtk_adjustment_set_page_size(vadjustment, textureBrowser.height); + gtk_adjustment_set_page_increment(vadjustment, textureBrowser.height / 2); + gtk_adjustment_set_step_increment(vadjustment, 20); + gtk_adjustment_set_lower(vadjustment, 0); + gtk_adjustment_set_upper(vadjustment, totalHeight); - g_signal_emit_by_name( G_OBJECT( vadjustment ), "changed" ); - } + g_signal_emit_by_name(G_OBJECT(vadjustment), "changed"); + } } -gboolean TextureBrowser_size_allocate( ui::Widget widget, GtkAllocation* allocation, TextureBrowser* textureBrowser ){ - textureBrowser->width = allocation->width; - textureBrowser->height = allocation->height; - TextureBrowser_heightChanged( *textureBrowser ); - textureBrowser->m_originInvalid = true; - TextureBrowser_queueDraw( *textureBrowser ); - return FALSE; +gboolean TextureBrowser_size_allocate(ui::Widget widget, GtkAllocation *allocation, TextureBrowser *textureBrowser) +{ + textureBrowser->width = allocation->width; + textureBrowser->height = allocation->height; + TextureBrowser_heightChanged(*textureBrowser); + textureBrowser->m_originInvalid = true; + TextureBrowser_queueDraw(*textureBrowser); + return FALSE; } -gboolean TextureBrowser_expose( ui::Widget widget, GdkEventExpose* event, TextureBrowser* textureBrowser ){ - if ( glwidget_make_current( textureBrowser->m_gl_widget ) != FALSE ) { - GlobalOpenGL_debugAssertNoErrors(); - TextureBrowser_evaluateHeight( *textureBrowser ); - Texture_Draw( *textureBrowser ); - GlobalOpenGL_debugAssertNoErrors(); - glwidget_swap_buffers( textureBrowser->m_gl_widget ); - } - return FALSE; +gboolean TextureBrowser_expose(ui::Widget widget, GdkEventExpose *event, TextureBrowser *textureBrowser) +{ + if (glwidget_make_current(textureBrowser->m_gl_widget) != FALSE) { + GlobalOpenGL_debugAssertNoErrors(); + TextureBrowser_evaluateHeight(*textureBrowser); + Texture_Draw(*textureBrowser); + GlobalOpenGL_debugAssertNoErrors(); + glwidget_swap_buffers(textureBrowser->m_gl_widget); + } + return FALSE; } TextureBrowser g_TextureBrowser; -TextureBrowser& GlobalTextureBrowser(){ - return g_TextureBrowser; -} - -bool TextureBrowser_hideUnused(){ - return g_TextureBrowser.m_hideUnused; +TextureBrowser &GlobalTextureBrowser() +{ + return g_TextureBrowser; } -void TextureBrowser_ToggleHideUnused(){ - if ( g_TextureBrowser.m_hideUnused ) { - TextureBrowser_SetHideUnused( g_TextureBrowser, false ); - } - else - { - TextureBrowser_SetHideUnused( g_TextureBrowser, true ); - } +bool TextureBrowser_hideUnused() +{ + return g_TextureBrowser.m_hideUnused; } -void TextureGroups_constructTreeModel( TextureGroups groups, ui::TreeStore store ){ - // put the information from the old textures menu into a treeview - GtkTreeIter iter, child; - - TextureGroups::const_iterator i = groups.begin(); - while ( i != groups.end() ) - { - const char* dirName = ( *i ).c_str(); - const char* firstUnderscore = strchr( dirName, '_' ); - StringRange dirRoot( dirName, ( firstUnderscore == 0 ) ? dirName : firstUnderscore + 1 ); - - TextureGroups::const_iterator next = i; - ++next; - if ( firstUnderscore != 0 - && next != groups.end() - && string_equal_start( ( *next ).c_str(), dirRoot ) ) { - gtk_tree_store_append( store, &iter, NULL ); - gtk_tree_store_set( store, &iter, 0, CopiedString( StringRange( dirName, firstUnderscore ) ).c_str(), -1 ); - - // keep going... - while ( i != groups.end() && string_equal_start( ( *i ).c_str(), dirRoot ) ) - { - gtk_tree_store_append( store, &child, &iter ); - gtk_tree_store_set( store, &child, 0, ( *i ).c_str(), -1 ); - ++i; - } - } - else - { - gtk_tree_store_append( store, &iter, NULL ); - gtk_tree_store_set( store, &iter, 0, dirName, -1 ); - ++i; - } - } +void TextureBrowser_ToggleHideUnused() +{ + if (g_TextureBrowser.m_hideUnused) { + TextureBrowser_SetHideUnused(g_TextureBrowser, false); + } else { + TextureBrowser_SetHideUnused(g_TextureBrowser, true); + } } -TextureGroups TextureGroups_constructTreeView(){ - TextureGroups groups; +void TextureGroups_constructTreeModel(TextureGroups groups, ui::TreeStore store) +{ + // put the information from the old textures menu into a treeview + GtkTreeIter iter, child; + + TextureGroups::const_iterator i = groups.begin(); + while (i != groups.end()) { + const char *dirName = (*i).c_str(); + const char *firstUnderscore = strchr(dirName, '_'); + StringRange dirRoot(dirName, (firstUnderscore == 0) ? dirName : firstUnderscore + 1); + + TextureGroups::const_iterator next = i; + ++next; + if (firstUnderscore != 0 + && next != groups.end() + && string_equal_start((*next).c_str(), dirRoot)) { + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, 0, CopiedString(StringRange(dirName, firstUnderscore)).c_str(), -1); + + // keep going... + while (i != groups.end() && string_equal_start((*i).c_str(), dirRoot)) { + gtk_tree_store_append(store, &child, &iter); + gtk_tree_store_set(store, &child, 0, (*i).c_str(), -1); + ++i; + } + } else { + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, 0, dirName, -1); + ++i; + } + } +} + +TextureGroups TextureGroups_constructTreeView() +{ + TextureGroups groups; - if ( TextureBrowser_showWads() ) { - GlobalFileSystem().forEachArchive( TextureGroupsAddWadCaller( groups ) ); - } - else - { - // scan texture dirs and pak files only if not restricting to shaderlist - if ( g_pGameDescription->mGameType != "doom3" && !g_TextureBrowser_shaderlistOnly ) { - GlobalFileSystem().forEachDirectory( "textures/", TextureGroupsAddDirectoryCaller( groups ) ); - } + if (TextureBrowser_showWads()) { + GlobalFileSystem().forEachArchive(TextureGroupsAddWadCaller(groups)); + } else { + // scan texture dirs and pak files only if not restricting to shaderlist + if (g_pGameDescription->mGameType != "doom3" && !g_TextureBrowser_shaderlistOnly) { + GlobalFileSystem().forEachDirectory("textures/", TextureGroupsAddDirectoryCaller(groups)); + } - GlobalShaderSystem().foreachShaderName( TextureGroupsAddShaderCaller( groups ) ); - } + GlobalShaderSystem().foreachShaderName(TextureGroupsAddShaderCaller(groups)); + } - return groups; + return groups; } -void TextureBrowser_constructTreeStore(){ - TextureGroups groups = TextureGroups_constructTreeView(); - auto store = ui::TreeStore::from(gtk_tree_store_new( 1, G_TYPE_STRING )); - TextureGroups_constructTreeModel( groups, store ); +void TextureBrowser_constructTreeStore() +{ + TextureGroups groups = TextureGroups_constructTreeView(); + auto store = ui::TreeStore::from(gtk_tree_store_new(1, G_TYPE_STRING)); + TextureGroups_constructTreeModel(groups, store); - gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTree, store); + gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTree, store); - g_object_unref( G_OBJECT( store ) ); + g_object_unref(G_OBJECT(store)); } -void TextureBrowser_constructTreeStoreTags(){ - TextureGroups groups; - auto store = ui::TreeStore::from(gtk_tree_store_new( 1, G_TYPE_STRING )); +void TextureBrowser_constructTreeStoreTags() +{ + TextureGroups groups; + auto store = ui::TreeStore::from(gtk_tree_store_new(1, G_TYPE_STRING)); auto model = g_TextureBrowser.m_all_tags_list; - gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTags, model ); + gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTags, model); - g_object_unref( G_OBJECT( store ) ); + g_object_unref(G_OBJECT(store)); } -void TreeView_onRowActivated( ui::TreeView treeview, ui::TreePath path, ui::TreeViewColumn col, gpointer userdata ){ - GtkTreeIter iter; +void TreeView_onRowActivated(ui::TreeView treeview, ui::TreePath path, ui::TreeViewColumn col, gpointer userdata) +{ + GtkTreeIter iter; - auto model = gtk_tree_view_get_model(treeview ); + auto model = gtk_tree_view_get_model(treeview); - if ( gtk_tree_model_get_iter( model, &iter, path ) ) { - gchar dirName[1024]; + if (gtk_tree_model_get_iter(model, &iter, path)) { + gchar dirName[1024]; - gchar* buffer; - gtk_tree_model_get( model, &iter, 0, &buffer, -1 ); - strcpy( dirName, buffer ); - g_free( buffer ); + gchar *buffer; + gtk_tree_model_get(model, &iter, 0, &buffer, -1); + strcpy(dirName, buffer); + g_free(buffer); - g_TextureBrowser.m_searchedTags = false; + g_TextureBrowser.m_searchedTags = false; - if ( !TextureBrowser_showWads() ) { - strcat( dirName, "/" ); - } + if (!TextureBrowser_showWads()) { + strcat(dirName, "/"); + } - ScopeDisableScreenUpdates disableScreenUpdates( dirName, "Loading Textures" ); - TextureBrowser_ShowDirectory( GlobalTextureBrowser(), dirName ); - TextureBrowser_queueDraw( GlobalTextureBrowser() ); - } + ScopeDisableScreenUpdates disableScreenUpdates(dirName, "Loading Textures"); + TextureBrowser_ShowDirectory(GlobalTextureBrowser(), dirName); + TextureBrowser_queueDraw(GlobalTextureBrowser()); + } } -void TextureBrowser_createTreeViewTree(){ - gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTree, FALSE ); +void TextureBrowser_createTreeViewTree() +{ + gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTree, FALSE); - gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTree, FALSE ); - g_TextureBrowser.m_treeViewTree.connect( "row-activated", (GCallback) TreeView_onRowActivated, NULL ); + gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTree, FALSE); + g_TextureBrowser.m_treeViewTree.connect("row-activated", (GCallback) TreeView_onRowActivated, NULL); - auto renderer = ui::CellRendererText(ui::New); - gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTree, -1, "", renderer, "text", 0, NULL ); + auto renderer = ui::CellRendererText(ui::New); + gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTree, -1, "", renderer, "text", 0, NULL); - TextureBrowser_constructTreeStore(); + TextureBrowser_constructTreeStore(); } void TextureBrowser_addTag(); + void TextureBrowser_renameTag(); + void TextureBrowser_deleteTag(); -void TextureBrowser_createContextMenu( ui::Widget treeview, GdkEventButton *event ){ - ui::Widget menu = ui::Menu(ui::New); +void TextureBrowser_createContextMenu(ui::Widget treeview, GdkEventButton *event) +{ + ui::Widget menu = ui::Menu(ui::New); - ui::Widget menuitem = ui::MenuItem( "Add tag" ); - menuitem.connect( "activate", (GCallback)TextureBrowser_addTag, treeview ); - gtk_menu_shell_append( GTK_MENU_SHELL( menu ), menuitem ); + ui::Widget menuitem = ui::MenuItem("Add tag"); + menuitem.connect("activate", (GCallback) TextureBrowser_addTag, treeview); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - menuitem = ui::MenuItem( "Rename tag" ); - menuitem.connect( "activate", (GCallback)TextureBrowser_renameTag, treeview ); - gtk_menu_shell_append( GTK_MENU_SHELL( menu ), menuitem ); + menuitem = ui::MenuItem("Rename tag"); + menuitem.connect("activate", (GCallback) TextureBrowser_renameTag, treeview); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - menuitem = ui::MenuItem( "Delete tag" ); - menuitem.connect( "activate", (GCallback)TextureBrowser_deleteTag, treeview ); - gtk_menu_shell_append( GTK_MENU_SHELL( menu ), menuitem ); + menuitem = ui::MenuItem("Delete tag"); + menuitem.connect("activate", (GCallback) TextureBrowser_deleteTag, treeview); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show_all( menu ); + gtk_widget_show_all(menu); - gtk_menu_popup( GTK_MENU( menu ), NULL, NULL, NULL, NULL, - ( event != NULL ) ? event->button : 0, - gdk_event_get_time( (GdkEvent*)event ) ); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, + (event != NULL) ? event->button : 0, + gdk_event_get_time((GdkEvent *) event)); } -gboolean TreeViewTags_onButtonPressed( ui::TreeView treeview, GdkEventButton *event ){ - if ( event->type == GDK_BUTTON_PRESS && event->button == 3 ) { - GtkTreePath *path; - auto selection = gtk_tree_view_get_selection(treeview ); +gboolean TreeViewTags_onButtonPressed(ui::TreeView treeview, GdkEventButton *event) +{ + if (event->type == GDK_BUTTON_PRESS && event->button == 3) { + GtkTreePath *path; + auto selection = gtk_tree_view_get_selection(treeview); - if ( gtk_tree_view_get_path_at_pos(treeview, event->x, event->y, &path, NULL, NULL, NULL ) ) { - gtk_tree_selection_unselect_all( selection ); - gtk_tree_selection_select_path( selection, path ); - gtk_tree_path_free( path ); - } + if (gtk_tree_view_get_path_at_pos(treeview, event->x, event->y, &path, NULL, NULL, NULL)) { + gtk_tree_selection_unselect_all(selection); + gtk_tree_selection_select_path(selection, path); + gtk_tree_path_free(path); + } - TextureBrowser_createContextMenu( treeview, event ); - return TRUE; - } - return FALSE; + TextureBrowser_createContextMenu(treeview, event); + return TRUE; + } + return FALSE; } -void TextureBrowser_createTreeViewTags(){ - g_TextureBrowser.m_treeViewTags = ui::TreeView(ui::New); - gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTags, FALSE ); +void TextureBrowser_createTreeViewTags() +{ + g_TextureBrowser.m_treeViewTags = ui::TreeView(ui::New); + gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTags, FALSE); - g_TextureBrowser.m_treeViewTags.connect( "button-press-event", (GCallback)TreeViewTags_onButtonPressed, NULL ); + g_TextureBrowser.m_treeViewTags.connect("button-press-event", (GCallback) TreeViewTags_onButtonPressed, NULL); - gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTags, FALSE ); + gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTags, FALSE); - auto renderer = ui::CellRendererText(ui::New); - gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTags, -1, "", renderer, "text", 0, NULL ); + auto renderer = ui::CellRendererText(ui::New); + gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTags, -1, "", renderer, "text", 0, NULL); - TextureBrowser_constructTreeStoreTags(); + TextureBrowser_constructTreeStoreTags(); } -ui::MenuItem TextureBrowser_constructViewMenu( ui::Menu menu ){ - ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic( "_View" )); +ui::MenuItem TextureBrowser_constructViewMenu(ui::Menu menu) +{ + ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic("_View")); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - create_check_menu_item_with_mnemonic( menu, "Hide _Unused", "ShowInUse" ); - if ( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { - create_check_menu_item_with_mnemonic( menu, "Hide Image Missing", "FilterMissing" ); - } + create_check_menu_item_with_mnemonic(menu, "Hide _Unused", "ShowInUse"); + if (string_empty(g_pGameDescription->getKeyValue("show_wads"))) { + create_check_menu_item_with_mnemonic(menu, "Hide Image Missing", "FilterMissing"); + } - // hide notex and shadernotex on texture browser: no one wants to apply them - create_check_menu_item_with_mnemonic( menu, "Hide Fallback", "FilterFallback" ); + // hide notex and shadernotex on texture browser: no one wants to apply them + create_check_menu_item_with_mnemonic(menu, "Hide Fallback", "FilterFallback"); - menu_separator( menu ); + menu_separator(menu); - create_menu_item_with_mnemonic( menu, "Show All", "ShowAllTextures" ); + create_menu_item_with_mnemonic(menu, "Show All", "ShowAllTextures"); - // we always want to show shaders but don't want a "Show Shaders" menu for doom3 and .wad file games - if ( g_pGameDescription->mGameType == "doom3" || !string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { - g_TextureBrowser.m_showShaders = true; - } - else - { - create_check_menu_item_with_mnemonic( menu, "Show shaders", "ToggleShowShaders" ); - } + // we always want to show shaders but don't want a "Show Shaders" menu for doom3 and .wad file games + if (g_pGameDescription->mGameType == "doom3" || !string_empty(g_pGameDescription->getKeyValue("show_wads"))) { + g_TextureBrowser.m_showShaders = true; + } else { + create_check_menu_item_with_mnemonic(menu, "Show shaders", "ToggleShowShaders"); + } - if ( g_pGameDescription->mGameType != "doom3" && string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { - create_check_menu_item_with_mnemonic( menu, "Shaders Only", "ToggleShowShaderlistOnly" ); - } - if ( g_TextureBrowser.m_tags ) { - create_menu_item_with_mnemonic( menu, "Show Untagged", "ShowUntagged" ); - } + if (g_pGameDescription->mGameType != "doom3" && string_empty(g_pGameDescription->getKeyValue("show_wads"))) { + create_check_menu_item_with_mnemonic(menu, "Shaders Only", "ToggleShowShaderlistOnly"); + } + if (g_TextureBrowser.m_tags) { + create_menu_item_with_mnemonic(menu, "Show Untagged", "ShowUntagged"); + } - menu_separator( menu ); - create_check_menu_item_with_mnemonic( menu, "Fixed Size", "FixedSize" ); - create_check_menu_item_with_mnemonic( menu, "Transparency", "EnableAlpha" ); + menu_separator(menu); + create_check_menu_item_with_mnemonic(menu, "Fixed Size", "FixedSize"); + create_check_menu_item_with_mnemonic(menu, "Transparency", "EnableAlpha"); - if ( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { - menu_separator( menu ); - g_TextureBrowser.m_shader_info_item = ui::Widget(create_menu_item_with_mnemonic( menu, "Shader Info", "ShaderInfo" )); - gtk_widget_set_sensitive( g_TextureBrowser.m_shader_info_item, FALSE ); - } + if (string_empty(g_pGameDescription->getKeyValue("show_wads"))) { + menu_separator(menu); + g_TextureBrowser.m_shader_info_item = ui::Widget( + create_menu_item_with_mnemonic(menu, "Shader Info", "ShaderInfo")); + gtk_widget_set_sensitive(g_TextureBrowser.m_shader_info_item, FALSE); + } - return textures_menu_item; + return textures_menu_item; } -ui::MenuItem TextureBrowser_constructToolsMenu( ui::Menu menu ){ - ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic( "_Tools" )); +ui::MenuItem TextureBrowser_constructToolsMenu(ui::Menu menu) +{ + ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic("_Tools")); - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - create_menu_item_with_mnemonic( menu, "Flush & Reload Shaders", "RefreshShaders" ); - create_menu_item_with_mnemonic( menu, "Find / Replace...", "FindReplaceTextures" ); + create_menu_item_with_mnemonic(menu, "Flush & Reload Shaders", "RefreshShaders"); + create_menu_item_with_mnemonic(menu, "Find / Replace...", "FindReplaceTextures"); - return textures_menu_item; + return textures_menu_item; } -ui::MenuItem TextureBrowser_constructTagsMenu( ui::Menu menu ){ - ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic( "T_ags" )); - - if ( g_Layout_enableDetachableMenus.m_value ) { - menu_tearoff( menu ); - } - - create_menu_item_with_mnemonic( menu, "Add tag", "AddTag" ); - create_menu_item_with_mnemonic( menu, "Rename tag", "RenameTag" ); - create_menu_item_with_mnemonic( menu, "Delete tag", "DeleteTag" ); - menu_separator( menu ); - create_menu_item_with_mnemonic( menu, "Copy tags from selected", "CopyTag" ); - create_menu_item_with_mnemonic( menu, "Paste tags to selected", "PasteTag" ); - - return textures_menu_item; -} +ui::MenuItem TextureBrowser_constructTagsMenu(ui::Menu menu) +{ + ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic("T_ags")); -gboolean TextureBrowser_tagMoveHelper( ui::TreeModel model, ui::TreePath path, GtkTreeIter iter, GSList** selected ){ - g_assert( selected != NULL ); + if (g_Layout_enableDetachableMenus.m_value) { + menu_tearoff(menu); + } - auto rowref = gtk_tree_row_reference_new( model, path ); - *selected = g_slist_append( *selected, rowref ); + create_menu_item_with_mnemonic(menu, "Add tag", "AddTag"); + create_menu_item_with_mnemonic(menu, "Rename tag", "RenameTag"); + create_menu_item_with_mnemonic(menu, "Delete tag", "DeleteTag"); + menu_separator(menu); + create_menu_item_with_mnemonic(menu, "Copy tags from selected", "CopyTag"); + create_menu_item_with_mnemonic(menu, "Paste tags to selected", "PasteTag"); - return FALSE; + return textures_menu_item; } -void TextureBrowser_assignTags(){ - GSList* selected = NULL; - GSList* node; - gchar* tag_assigned; - - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree ); - - gtk_tree_selection_selected_foreach( selection, (GtkTreeSelectionForeachFunc)TextureBrowser_tagMoveHelper, &selected ); - - if ( selected != NULL ) { - for ( node = selected; node != NULL; node = node->next ) - { - auto path = gtk_tree_row_reference_get_path( (GtkTreeRowReference*)node->data ); - - if ( path ) { - GtkTreeIter iter; - - if ( gtk_tree_model_get_iter(g_TextureBrowser.m_available_store, &iter, path ) ) { - gtk_tree_model_get(g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, &tag_assigned, -1 ); - if ( !TagBuilder.CheckShaderTag( g_TextureBrowser.shader.c_str() ) ) { - // create a custom shader/texture entry - IShader* ishader = QERApp_Shader_ForName( g_TextureBrowser.shader.c_str() ); - CopiedString filename = ishader->getShaderFileName(); - - if ( filename.empty() ) { - // it's a texture - TagBuilder.AddShaderNode( g_TextureBrowser.shader.c_str(), CUSTOM, TEXTURE ); - } - else { - // it's a shader - TagBuilder.AddShaderNode( g_TextureBrowser.shader.c_str(), CUSTOM, SHADER ); - } - ishader->DecRef(); - } - TagBuilder.AddShaderTag( g_TextureBrowser.shader.c_str(), (char*)tag_assigned, TAG ); - - gtk_list_store_remove( g_TextureBrowser.m_available_store, &iter ); - g_TextureBrowser.m_assigned_store.append(TAG_COLUMN, tag_assigned); - } - } - } +gboolean TextureBrowser_tagMoveHelper(ui::TreeModel model, ui::TreePath path, GtkTreeIter iter, GSList **selected) +{ + g_assert(selected != NULL); - g_slist_foreach( selected, (GFunc)gtk_tree_row_reference_free, NULL ); + auto rowref = gtk_tree_row_reference_new(model, path); + *selected = g_slist_append(*selected, rowref); - // Save changes - TagBuilder.SaveXmlDoc(); - } - g_slist_free( selected ); + return FALSE; } -void TextureBrowser_removeTags(){ - GSList* selected = NULL; - GSList* node; - gchar* tag; +void TextureBrowser_assignTags() +{ + GSList *selected = NULL; + GSList *node; + gchar *tag_assigned; + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree); + + gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) TextureBrowser_tagMoveHelper, + &selected); + + if (selected != NULL) { + for (node = selected; node != NULL; node = node->next) { + auto path = gtk_tree_row_reference_get_path((GtkTreeRowReference *) node->data); + + if (path) { + GtkTreeIter iter; + + if (gtk_tree_model_get_iter(g_TextureBrowser.m_available_store, &iter, path)) { + gtk_tree_model_get(g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, &tag_assigned, -1); + if (!TagBuilder.CheckShaderTag(g_TextureBrowser.shader.c_str())) { + // create a custom shader/texture entry + IShader *ishader = QERApp_Shader_ForName(g_TextureBrowser.shader.c_str()); + CopiedString filename = ishader->getShaderFileName(); + + if (filename.empty()) { + // it's a texture + TagBuilder.AddShaderNode(g_TextureBrowser.shader.c_str(), CUSTOM, TEXTURE); + } else { + // it's a shader + TagBuilder.AddShaderNode(g_TextureBrowser.shader.c_str(), CUSTOM, SHADER); + } + ishader->DecRef(); + } + TagBuilder.AddShaderTag(g_TextureBrowser.shader.c_str(), (char *) tag_assigned, TAG); + + gtk_list_store_remove(g_TextureBrowser.m_available_store, &iter); + g_TextureBrowser.m_assigned_store.append(TAG_COLUMN, tag_assigned); + } + } + } + + g_slist_foreach(selected, (GFunc) gtk_tree_row_reference_free, NULL); + + // Save changes + TagBuilder.SaveXmlDoc(); + } + g_slist_free(selected); +} + +void TextureBrowser_removeTags() +{ + GSList *selected = NULL; + GSList *node; + gchar *tag; - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree ); + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree); - gtk_tree_selection_selected_foreach( selection, (GtkTreeSelectionForeachFunc)TextureBrowser_tagMoveHelper, &selected ); + gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) TextureBrowser_tagMoveHelper, + &selected); - if ( selected != NULL ) { - for ( node = selected; node != NULL; node = node->next ) - { - auto path = gtk_tree_row_reference_get_path( (GtkTreeRowReference*)node->data ); + if (selected != NULL) { + for (node = selected; node != NULL; node = node->next) { + auto path = gtk_tree_row_reference_get_path((GtkTreeRowReference *) node->data); - if ( path ) { - GtkTreeIter iter; + if (path) { + GtkTreeIter iter; - if ( gtk_tree_model_get_iter(g_TextureBrowser.m_assigned_store, &iter, path ) ) { - gtk_tree_model_get(g_TextureBrowser.m_assigned_store, &iter, TAG_COLUMN, &tag, -1 ); - TagBuilder.DeleteShaderTag( g_TextureBrowser.shader.c_str(), tag ); - gtk_list_store_remove( g_TextureBrowser.m_assigned_store, &iter ); - } - } - } + if (gtk_tree_model_get_iter(g_TextureBrowser.m_assigned_store, &iter, path)) { + gtk_tree_model_get(g_TextureBrowser.m_assigned_store, &iter, TAG_COLUMN, &tag, -1); + TagBuilder.DeleteShaderTag(g_TextureBrowser.shader.c_str(), tag); + gtk_list_store_remove(g_TextureBrowser.m_assigned_store, &iter); + } + } + } - g_slist_foreach( selected, (GFunc)gtk_tree_row_reference_free, NULL ); + g_slist_foreach(selected, (GFunc) gtk_tree_row_reference_free, NULL); - // Update the "available tags list" - BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser ); + // Update the "available tags list" + BuildStoreAvailableTags(g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, + g_TextureBrowser.m_all_tags, &g_TextureBrowser); - // Save changes - TagBuilder.SaveXmlDoc(); - } - g_slist_free( selected ); + // Save changes + TagBuilder.SaveXmlDoc(); + } + g_slist_free(selected); } -void TextureBrowser_buildTagList(){ - g_TextureBrowser.m_all_tags_list.clear(); +void TextureBrowser_buildTagList() +{ + g_TextureBrowser.m_all_tags_list.clear(); - std::set::iterator iter; + std::set::iterator iter; - for ( iter = g_TextureBrowser.m_all_tags.begin(); iter != g_TextureBrowser.m_all_tags.end(); ++iter ) - { - g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, (*iter).c_str()); - } + for (iter = g_TextureBrowser.m_all_tags.begin(); iter != g_TextureBrowser.m_all_tags.end(); ++iter) { + g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, (*iter).c_str()); + } } -void TextureBrowser_searchTags(){ - GSList* selected = NULL; - GSList* node; - gchar* tag; - char buffer[256]; - char tags_searched[256]; +void TextureBrowser_searchTags() +{ + GSList *selected = NULL; + GSList *node; + gchar *tag; + char buffer[256]; + char tags_searched[256]; - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags ); + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags); - gtk_tree_selection_selected_foreach( selection, (GtkTreeSelectionForeachFunc)TextureBrowser_tagMoveHelper, &selected ); + gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) TextureBrowser_tagMoveHelper, + &selected); - if ( selected != NULL ) { - strcpy( buffer, "/root/*/*[tag='" ); - strcpy( tags_searched, "[TAGS] " ); + if (selected != NULL) { + strcpy(buffer, "/root/*/*[tag='"); + strcpy(tags_searched, "[TAGS] "); - for ( node = selected; node != NULL; node = node->next ) - { - auto path = gtk_tree_row_reference_get_path( (GtkTreeRowReference*)node->data ); + for (node = selected; node != NULL; node = node->next) { + auto path = gtk_tree_row_reference_get_path((GtkTreeRowReference *) node->data); - if ( path ) { - GtkTreeIter iter; + if (path) { + GtkTreeIter iter; - if ( gtk_tree_model_get_iter(g_TextureBrowser.m_all_tags_list, &iter, path ) ) { - gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iter, TAG_COLUMN, &tag, -1 ); + if (gtk_tree_model_get_iter(g_TextureBrowser.m_all_tags_list, &iter, path)) { + gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iter, TAG_COLUMN, &tag, -1); - strcat( buffer, tag ); - strcat( tags_searched, tag ); - if ( node != g_slist_last( node ) ) { - strcat( buffer, "' and tag='" ); - strcat( tags_searched, ", " ); - } - } - } - } + strcat(buffer, tag); + strcat(tags_searched, tag); + if (node != g_slist_last(node)) { + strcat(buffer, "' and tag='"); + strcat(tags_searched, ", "); + } + } + } + } - strcat( buffer, "']" ); + strcat(buffer, "']"); - g_slist_foreach( selected, (GFunc)gtk_tree_row_reference_free, NULL ); + g_slist_foreach(selected, (GFunc) gtk_tree_row_reference_free, NULL); - g_TextureBrowser.m_found_shaders.clear(); // delete old list - TagBuilder.TagSearch( buffer, g_TextureBrowser.m_found_shaders ); + g_TextureBrowser.m_found_shaders.clear(); // delete old list + TagBuilder.TagSearch(buffer, g_TextureBrowser.m_found_shaders); - if ( !g_TextureBrowser.m_found_shaders.empty() ) { // found something - size_t shaders_found = g_TextureBrowser.m_found_shaders.size(); + if (!g_TextureBrowser.m_found_shaders.empty()) { // found something + size_t shaders_found = g_TextureBrowser.m_found_shaders.size(); - globalOutputStream() << "Found " << (unsigned int)shaders_found << " textures and shaders with " << tags_searched << "\n"; - ScopeDisableScreenUpdates disableScreenUpdates( "Searching...", "Loading Textures" ); + globalOutputStream() << "Found " << (unsigned int) shaders_found << " textures and shaders with " + << tags_searched << "\n"; + ScopeDisableScreenUpdates disableScreenUpdates("Searching...", "Loading Textures"); - std::set::iterator iter; + std::set::iterator iter; - for ( iter = g_TextureBrowser.m_found_shaders.begin(); iter != g_TextureBrowser.m_found_shaders.end(); iter++ ) - { - std::string path = ( *iter ).c_str(); - size_t pos = path.find_last_of( "/", path.size() ); - std::string name = path.substr( pos + 1, path.size() ); - path = path.substr( 0, pos + 1 ); - TextureDirectory_loadTexture( path.c_str(), name.c_str() ); - } - } - g_TextureBrowser.m_searchedTags = true; - g_TextureBrowser_currentDirectory = tags_searched; + for (iter = g_TextureBrowser.m_found_shaders.begin(); + iter != g_TextureBrowser.m_found_shaders.end(); iter++) { + std::string path = (*iter).c_str(); + size_t pos = path.find_last_of("/", path.size()); + std::string name = path.substr(pos + 1, path.size()); + path = path.substr(0, pos + 1); + TextureDirectory_loadTexture(path.c_str(), name.c_str()); + } + } + g_TextureBrowser.m_searchedTags = true; + g_TextureBrowser_currentDirectory = tags_searched; - g_TextureBrowser.m_nTotalHeight = 0; - TextureBrowser_setOriginY( g_TextureBrowser, 0 ); - TextureBrowser_heightChanged( g_TextureBrowser ); - TextureBrowser_updateTitle(); - } - g_slist_free( selected ); + g_TextureBrowser.m_nTotalHeight = 0; + TextureBrowser_setOriginY(g_TextureBrowser, 0); + TextureBrowser_heightChanged(g_TextureBrowser); + TextureBrowser_updateTitle(); + } + g_slist_free(selected); } -void TextureBrowser_toggleSearchButton(){ - gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK( g_TextureBrowser.m_tag_notebook ) ); +void TextureBrowser_toggleSearchButton() +{ + gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(g_TextureBrowser.m_tag_notebook)); - if ( page == 0 ) { // tag page - gtk_widget_show_all( g_TextureBrowser.m_search_button ); - } - else { - g_TextureBrowser.m_search_button.hide(); - } + if (page == 0) { // tag page + gtk_widget_show_all(g_TextureBrowser.m_search_button); + } else { + g_TextureBrowser.m_search_button.hide(); + } } -void TextureBrowser_constructTagNotebook(){ - g_TextureBrowser.m_tag_notebook = ui::Widget::from(gtk_notebook_new()); - ui::Widget labelTags = ui::Label( "Tags" ); - ui::Widget labelTextures = ui::Label( "Textures" ); +void TextureBrowser_constructTagNotebook() +{ + g_TextureBrowser.m_tag_notebook = ui::Widget::from(gtk_notebook_new()); + ui::Widget labelTags = ui::Label("Tags"); + ui::Widget labelTextures = ui::Label("Textures"); - gtk_notebook_append_page( GTK_NOTEBOOK( g_TextureBrowser.m_tag_notebook ), g_TextureBrowser.m_scr_win_tree, labelTextures ); - gtk_notebook_append_page( GTK_NOTEBOOK( g_TextureBrowser.m_tag_notebook ), g_TextureBrowser.m_scr_win_tags, labelTags ); + gtk_notebook_append_page(GTK_NOTEBOOK(g_TextureBrowser.m_tag_notebook), g_TextureBrowser.m_scr_win_tree, + labelTextures); + gtk_notebook_append_page(GTK_NOTEBOOK(g_TextureBrowser.m_tag_notebook), g_TextureBrowser.m_scr_win_tags, labelTags); - g_TextureBrowser.m_tag_notebook.connect( "switch-page", G_CALLBACK( TextureBrowser_toggleSearchButton ), NULL ); + g_TextureBrowser.m_tag_notebook.connect("switch-page", G_CALLBACK(TextureBrowser_toggleSearchButton), NULL); - gtk_widget_show_all( g_TextureBrowser.m_tag_notebook ); + gtk_widget_show_all(g_TextureBrowser.m_tag_notebook); } -void TextureBrowser_constructSearchButton(){ - auto image = ui::Widget::from(gtk_image_new_from_stock( GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR )); - g_TextureBrowser.m_search_button = ui::Button(ui::New); - g_TextureBrowser.m_search_button.connect( "clicked", G_CALLBACK( TextureBrowser_searchTags ), NULL ); - gtk_widget_set_tooltip_text(g_TextureBrowser.m_search_button, "Search with selected tags"); - g_TextureBrowser.m_search_button.add(image); -} - -void TextureBrowser_checkTagFile(){ - const char SHADERTAG_FILE[] = "shadertags.xml"; - CopiedString default_filename, rc_filename; - StringOutputStream stream( 256 ); - - stream << LocalRcPath_get(); - stream << SHADERTAG_FILE; - rc_filename = stream.c_str(); - - if ( file_exists( rc_filename.c_str() ) ) { - g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc( rc_filename.c_str() ); - - if ( g_TextureBrowser.m_tags ) { - globalOutputStream() << "Loading tag file " << rc_filename.c_str() << ".\n"; - } - } - else - { - // load default tagfile - stream.clear(); - stream << g_pGameDescription->mGameToolsPath.c_str(); - stream << SHADERTAG_FILE; - default_filename = stream.c_str(); - - if ( file_exists( default_filename.c_str() ) ) { - g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc( default_filename.c_str(), rc_filename.c_str() ); - - if ( g_TextureBrowser.m_tags ) { - globalOutputStream() << "Loading default tag file " << default_filename.c_str() << ".\n"; - } - } - else - { - globalErrorStream() << "Unable to find default tag file " << default_filename.c_str() << ". No tag support.\n"; - } - } -} - -void TextureBrowser_SetNotex(){ - StringOutputStream name( 256 ); - name << GlobalRadiant().getAppPath() << "bitmaps/" NOTEX_BASENAME ".png"; - g_notex = name.c_str(); - - name = StringOutputStream(256); - name << GlobalRadiant().getAppPath() << "bitmaps/" SHADERNOTEX_BASENAME " .png"; - g_shadernotex = name.c_str(); -} - -ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){ - // The gl_widget and the tag assignment frame should be packed into a GtkVPaned with the slider - // position stored in local.pref. gtk_paned_get_position() and gtk_paned_set_position() don't - // seem to work in gtk 2.4 and the arrow buttons don't handle GTK_FILL, so here's another thing - // for the "once-the-gtk-libs-are-updated-TODO-list" :x - - TextureBrowser_checkTagFile(); - TextureBrowser_SetNotex(); - - GlobalShaderSystem().setActiveShadersChangedNotify( ReferenceCaller( g_TextureBrowser ) ); - - g_TextureBrowser.m_parent = toplevel; - - auto table = ui::Table(3, 3, FALSE); - auto vbox = ui::VBox(FALSE, 0); - table.attach(vbox, {0, 1, 1, 3}, {GTK_FILL, GTK_FILL}); - vbox.show(); - - ui::Widget menu_bar{ui::null}; - - { // menu bar - menu_bar = ui::Widget::from(gtk_menu_bar_new()); - auto menu_view = ui::Menu(ui::New); - auto view_item = TextureBrowser_constructViewMenu( menu_view ); - gtk_menu_item_set_submenu( GTK_MENU_ITEM( view_item ), menu_view ); - gtk_menu_shell_append( GTK_MENU_SHELL( menu_bar ), view_item ); - - auto menu_tools = ui::Menu(ui::New); - auto tools_item = TextureBrowser_constructToolsMenu( menu_tools ); - gtk_menu_item_set_submenu( GTK_MENU_ITEM( tools_item ), menu_tools ); - gtk_menu_shell_append( GTK_MENU_SHELL( menu_bar ), tools_item ); - - table.attach(menu_bar, {0, 3, 0, 1}, {GTK_FILL, GTK_SHRINK}); - menu_bar.show(); - } - { // Texture TreeView - g_TextureBrowser.m_scr_win_tree = ui::ScrolledWindow(ui::New); - gtk_container_set_border_width( GTK_CONTAINER( g_TextureBrowser.m_scr_win_tree ), 0 ); - - // vertical only scrolling for treeview - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tree ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); - - g_TextureBrowser.m_scr_win_tree.show(); - - TextureBrowser_createTreeViewTree(); - - gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tree ), g_TextureBrowser.m_treeViewTree ); - g_TextureBrowser.m_treeViewTree.show(); - } - { // gl_widget scrollbar - auto w = ui::Widget::from(gtk_vscrollbar_new( ui::Adjustment( 0,0,0,1,1,0 ) )); - table.attach(w, {2, 3, 1, 2}, {GTK_SHRINK, GTK_FILL}); - w.show(); - g_TextureBrowser.m_texture_scroll = w; - - auto vadjustment = ui::Adjustment::from(gtk_range_get_adjustment( GTK_RANGE( g_TextureBrowser.m_texture_scroll ) )); - vadjustment.connect( "value_changed", G_CALLBACK( TextureBrowser_verticalScroll ), &g_TextureBrowser ); - - g_TextureBrowser.m_texture_scroll.visible(g_TextureBrowser.m_showTextureScrollbar); - } - { // gl_widget - g_TextureBrowser.m_gl_widget = glwidget_new( FALSE ); - g_object_ref( g_TextureBrowser.m_gl_widget._handle ); - - gtk_widget_set_events( g_TextureBrowser.m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK ); - gtk_widget_set_can_focus( g_TextureBrowser.m_gl_widget, true ); - - table.attach(g_TextureBrowser.m_gl_widget, {1, 2, 1, 2}); - g_TextureBrowser.m_gl_widget.show(); - - g_TextureBrowser.m_sizeHandler = g_TextureBrowser.m_gl_widget.connect( "size_allocate", G_CALLBACK( TextureBrowser_size_allocate ), &g_TextureBrowser ); - g_TextureBrowser.m_exposeHandler = g_TextureBrowser.m_gl_widget.on_render( G_CALLBACK( TextureBrowser_expose ), &g_TextureBrowser ); - - g_TextureBrowser.m_gl_widget.connect( "button_press_event", G_CALLBACK( TextureBrowser_button_press ), &g_TextureBrowser ); - g_TextureBrowser.m_gl_widget.connect( "button_release_event", G_CALLBACK( TextureBrowser_button_release ), &g_TextureBrowser ); - g_TextureBrowser.m_gl_widget.connect( "motion_notify_event", G_CALLBACK( TextureBrowser_motion ), &g_TextureBrowser ); - g_TextureBrowser.m_gl_widget.connect( "scroll_event", G_CALLBACK( TextureBrowser_scroll ), &g_TextureBrowser ); - } - - // tag stuff - if ( g_TextureBrowser.m_tags ) { - { // fill tag GtkListStore - g_TextureBrowser.m_all_tags_list = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING )); - auto sortable = GTK_TREE_SORTABLE( g_TextureBrowser.m_all_tags_list ); - gtk_tree_sortable_set_sort_column_id( sortable, TAG_COLUMN, GTK_SORT_ASCENDING ); - - TagBuilder.GetAllTags( g_TextureBrowser.m_all_tags ); - TextureBrowser_buildTagList(); - } - { // tag menu bar - auto menu_tags = ui::Menu(ui::New); - auto tags_item = TextureBrowser_constructTagsMenu( menu_tags ); - gtk_menu_item_set_submenu( GTK_MENU_ITEM( tags_item ), menu_tags ); - gtk_menu_shell_append( GTK_MENU_SHELL( menu_bar ), tags_item ); - } - { // Tag TreeView - g_TextureBrowser.m_scr_win_tags = ui::ScrolledWindow(ui::New); - gtk_container_set_border_width( GTK_CONTAINER( g_TextureBrowser.m_scr_win_tags ), 0 ); - - // vertical only scrolling for treeview - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tags ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); - - TextureBrowser_createTreeViewTags(); - - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags ); - gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE ); - - gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tags ), g_TextureBrowser.m_treeViewTags ); - g_TextureBrowser.m_treeViewTags.show(); - } - { // Texture/Tag notebook - TextureBrowser_constructTagNotebook(); - vbox.pack_start( g_TextureBrowser.m_tag_notebook, TRUE, TRUE, 0 ); - } - { // Tag search button - TextureBrowser_constructSearchButton(); - vbox.pack_end(g_TextureBrowser.m_search_button, FALSE, FALSE, 0); - } - auto frame_table = ui::Table(3, 3, FALSE); - { // Tag frame - - g_TextureBrowser.m_tag_frame = ui::Frame( "Tag assignment" ); - gtk_frame_set_label_align( GTK_FRAME( g_TextureBrowser.m_tag_frame ), 0.5, 0.5 ); - gtk_frame_set_shadow_type( GTK_FRAME( g_TextureBrowser.m_tag_frame ), GTK_SHADOW_NONE ); - - table.attach(g_TextureBrowser.m_tag_frame, {1, 3, 2, 3}, {GTK_FILL, GTK_SHRINK}); - - frame_table.show(); - - g_TextureBrowser.m_tag_frame.add(frame_table); - } - { // assigned tag list - ui::Widget scrolled_win = ui::ScrolledWindow(ui::New); - gtk_container_set_border_width( GTK_CONTAINER( scrolled_win ), 0 ); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolled_win ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); - - g_TextureBrowser.m_assigned_store = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING )); - - auto sortable = GTK_TREE_SORTABLE( g_TextureBrowser.m_assigned_store ); - gtk_tree_sortable_set_sort_column_id( sortable, TAG_COLUMN, GTK_SORT_ASCENDING ); - - auto renderer = ui::CellRendererText(ui::New); - - g_TextureBrowser.m_assigned_tree = ui::TreeView(ui::TreeModel::from(g_TextureBrowser.m_assigned_store._handle)); - g_TextureBrowser.m_assigned_store.unref(); - g_TextureBrowser.m_assigned_tree.connect( "row-activated", (GCallback) TextureBrowser_removeTags, NULL ); - gtk_tree_view_set_headers_visible(g_TextureBrowser.m_assigned_tree, FALSE ); - - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree ); - gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE ); - - auto column = ui::TreeViewColumn( "", renderer, {{"text", TAG_COLUMN}} ); - gtk_tree_view_append_column(g_TextureBrowser.m_assigned_tree, column ); - g_TextureBrowser.m_assigned_tree.show(); - - scrolled_win.show(); - gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_win ), g_TextureBrowser.m_assigned_tree ); - - frame_table.attach(scrolled_win, {0, 1, 1, 3}, {GTK_FILL, GTK_FILL}); - } - { // available tag list - ui::Widget scrolled_win = ui::ScrolledWindow(ui::New); - gtk_container_set_border_width( GTK_CONTAINER( scrolled_win ), 0 ); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolled_win ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); - - g_TextureBrowser.m_available_store = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING )); - auto sortable = GTK_TREE_SORTABLE( g_TextureBrowser.m_available_store ); - gtk_tree_sortable_set_sort_column_id( sortable, TAG_COLUMN, GTK_SORT_ASCENDING ); - - auto renderer = ui::CellRendererText(ui::New); - - g_TextureBrowser.m_available_tree = ui::TreeView(ui::TreeModel::from(g_TextureBrowser.m_available_store._handle)); - g_TextureBrowser.m_available_store.unref(); - g_TextureBrowser.m_available_tree.connect( "row-activated", (GCallback) TextureBrowser_assignTags, NULL ); - gtk_tree_view_set_headers_visible(g_TextureBrowser.m_available_tree, FALSE ); - - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree ); - gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE ); - - auto column = ui::TreeViewColumn( "", renderer, {{"text", TAG_COLUMN}} ); - gtk_tree_view_append_column(g_TextureBrowser.m_available_tree, column ); - g_TextureBrowser.m_available_tree.show(); - - scrolled_win.show(); - gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_win ), g_TextureBrowser.m_available_tree ); - - frame_table.attach(scrolled_win, {2, 3, 1, 3}, {GTK_FILL, GTK_FILL}); - } - { // tag arrow buttons - auto m_btn_left = ui::Button(ui::New); - auto m_btn_right = ui::Button(ui::New); - auto m_arrow_left = ui::Widget::from(gtk_arrow_new( GTK_ARROW_LEFT, GTK_SHADOW_OUT )); - auto m_arrow_right = ui::Widget::from(gtk_arrow_new( GTK_ARROW_RIGHT, GTK_SHADOW_OUT )); - m_btn_left.add(m_arrow_left); - m_btn_right.add(m_arrow_right); - - // workaround. the size of the tag frame depends of the requested size of the arrow buttons. - m_arrow_left.dimensions(-1, 68); - m_arrow_right.dimensions(-1, 68); - - frame_table.attach(m_btn_left, {1, 2, 1, 2}, {GTK_SHRINK, GTK_EXPAND}); - frame_table.attach(m_btn_right, {1, 2, 2, 3}, {GTK_SHRINK, GTK_EXPAND}); +void TextureBrowser_constructSearchButton() +{ + auto image = ui::Widget::from(gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR)); + g_TextureBrowser.m_search_button = ui::Button(ui::New); + g_TextureBrowser.m_search_button.connect("clicked", G_CALLBACK(TextureBrowser_searchTags), NULL); + gtk_widget_set_tooltip_text(g_TextureBrowser.m_search_button, "Search with selected tags"); + g_TextureBrowser.m_search_button.add(image); +} - m_btn_left.connect( "clicked", G_CALLBACK( TextureBrowser_assignTags ), NULL ); - m_btn_right.connect( "clicked", G_CALLBACK( TextureBrowser_removeTags ), NULL ); +void TextureBrowser_checkTagFile() +{ + const char SHADERTAG_FILE[] = "shadertags.xml"; + CopiedString default_filename, rc_filename; + StringOutputStream stream(256); + + stream << LocalRcPath_get(); + stream << SHADERTAG_FILE; + rc_filename = stream.c_str(); + + if (file_exists(rc_filename.c_str())) { + g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc(rc_filename.c_str()); + + if (g_TextureBrowser.m_tags) { + globalOutputStream() << "Loading tag file " << rc_filename.c_str() << ".\n"; + } + } else { + // load default tagfile + stream.clear(); + stream << g_pGameDescription->mGameToolsPath.c_str(); + stream << SHADERTAG_FILE; + default_filename = stream.c_str(); + + if (file_exists(default_filename.c_str())) { + g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc(default_filename.c_str(), rc_filename.c_str()); + + if (g_TextureBrowser.m_tags) { + globalOutputStream() << "Loading default tag file " << default_filename.c_str() << ".\n"; + } + } else { + globalErrorStream() << "Unable to find default tag file " << default_filename.c_str() + << ". No tag support.\n"; + } + } +} + +void TextureBrowser_SetNotex() +{ + StringOutputStream name(256); + name << GlobalRadiant().getAppPath() << "bitmaps/" NOTEX_BASENAME ".png"; + g_notex = name.c_str(); - m_btn_left.show(); - m_btn_right.show(); - m_arrow_left.show(); - m_arrow_right.show(); - } - { // tag fram labels - ui::Widget m_lbl_assigned = ui::Label( "Assigned" ); - ui::Widget m_lbl_unassigned = ui::Label( "Available" ); + name = StringOutputStream(256); + name << GlobalRadiant().getAppPath() << "bitmaps/" SHADERNOTEX_BASENAME " .png"; + g_shadernotex = name.c_str(); +} - frame_table.attach(m_lbl_assigned, {0, 1, 0, 1}, {GTK_EXPAND, GTK_SHRINK}); - frame_table.attach(m_lbl_unassigned, {2, 3, 0, 1}, {GTK_EXPAND, GTK_SHRINK}); +ui::Widget TextureBrowser_constructWindow(ui::Window toplevel) +{ + // The gl_widget and the tag assignment frame should be packed into a GtkVPaned with the slider + // position stored in local.pref. gtk_paned_get_position() and gtk_paned_set_position() don't + // seem to work in gtk 2.4 and the arrow buttons don't handle GTK_FILL, so here's another thing + // for the "once-the-gtk-libs-are-updated-TODO-list" :x + + TextureBrowser_checkTagFile(); + TextureBrowser_SetNotex(); + + GlobalShaderSystem().setActiveShadersChangedNotify( + ReferenceCaller(g_TextureBrowser)); + + g_TextureBrowser.m_parent = toplevel; + + auto table = ui::Table(3, 3, FALSE); + auto vbox = ui::VBox(FALSE, 0); + table.attach(vbox, {0, 1, 1, 3}, {GTK_FILL, GTK_FILL}); + vbox.show(); + + ui::Widget menu_bar{ui::null}; + + { // menu bar + menu_bar = ui::Widget::from(gtk_menu_bar_new()); + auto menu_view = ui::Menu(ui::New); + auto view_item = TextureBrowser_constructViewMenu(menu_view); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(view_item), menu_view); + gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), view_item); + + auto menu_tools = ui::Menu(ui::New); + auto tools_item = TextureBrowser_constructToolsMenu(menu_tools); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(tools_item), menu_tools); + gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), tools_item); + + table.attach(menu_bar, {0, 3, 0, 1}, {GTK_FILL, GTK_SHRINK}); + menu_bar.show(); + } + { // Texture TreeView + g_TextureBrowser.m_scr_win_tree = ui::ScrolledWindow(ui::New); + gtk_container_set_border_width(GTK_CONTAINER(g_TextureBrowser.m_scr_win_tree), 0); + + // vertical only scrolling for treeview + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(g_TextureBrowser.m_scr_win_tree), GTK_POLICY_NEVER, + GTK_POLICY_ALWAYS); + + g_TextureBrowser.m_scr_win_tree.show(); + + TextureBrowser_createTreeViewTree(); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(g_TextureBrowser.m_scr_win_tree), + g_TextureBrowser.m_treeViewTree); + g_TextureBrowser.m_treeViewTree.show(); + } + { // gl_widget scrollbar + auto w = ui::Widget::from(gtk_vscrollbar_new(ui::Adjustment(0, 0, 0, 1, 1, 0))); + table.attach(w, {2, 3, 1, 2}, {GTK_SHRINK, GTK_FILL}); + w.show(); + g_TextureBrowser.m_texture_scroll = w; + + auto vadjustment = ui::Adjustment::from(gtk_range_get_adjustment(GTK_RANGE(g_TextureBrowser.m_texture_scroll))); + vadjustment.connect("value_changed", G_CALLBACK(TextureBrowser_verticalScroll), &g_TextureBrowser); + + g_TextureBrowser.m_texture_scroll.visible(g_TextureBrowser.m_showTextureScrollbar); + } + { // gl_widget + g_TextureBrowser.m_gl_widget = glwidget_new(FALSE); + g_object_ref(g_TextureBrowser.m_gl_widget._handle); + + gtk_widget_set_events(g_TextureBrowser.m_gl_widget, + GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK); + gtk_widget_set_can_focus(g_TextureBrowser.m_gl_widget, true); + + table.attach(g_TextureBrowser.m_gl_widget, {1, 2, 1, 2}); + g_TextureBrowser.m_gl_widget.show(); + + g_TextureBrowser.m_sizeHandler = g_TextureBrowser.m_gl_widget.connect("size_allocate", + G_CALLBACK(TextureBrowser_size_allocate), + &g_TextureBrowser); + g_TextureBrowser.m_exposeHandler = g_TextureBrowser.m_gl_widget.on_render(G_CALLBACK(TextureBrowser_expose), + &g_TextureBrowser); + + g_TextureBrowser.m_gl_widget.connect("button_press_event", G_CALLBACK(TextureBrowser_button_press), + &g_TextureBrowser); + g_TextureBrowser.m_gl_widget.connect("button_release_event", G_CALLBACK(TextureBrowser_button_release), + &g_TextureBrowser); + g_TextureBrowser.m_gl_widget.connect("motion_notify_event", G_CALLBACK(TextureBrowser_motion), + &g_TextureBrowser); + g_TextureBrowser.m_gl_widget.connect("scroll_event", G_CALLBACK(TextureBrowser_scroll), &g_TextureBrowser); + } + + // tag stuff + if (g_TextureBrowser.m_tags) { + { // fill tag GtkListStore + g_TextureBrowser.m_all_tags_list = ui::ListStore::from(gtk_list_store_new(N_COLUMNS, G_TYPE_STRING)); + auto sortable = GTK_TREE_SORTABLE(g_TextureBrowser.m_all_tags_list); + gtk_tree_sortable_set_sort_column_id(sortable, TAG_COLUMN, GTK_SORT_ASCENDING); + + TagBuilder.GetAllTags(g_TextureBrowser.m_all_tags); + TextureBrowser_buildTagList(); + } + { // tag menu bar + auto menu_tags = ui::Menu(ui::New); + auto tags_item = TextureBrowser_constructTagsMenu(menu_tags); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(tags_item), menu_tags); + gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), tags_item); + } + { // Tag TreeView + g_TextureBrowser.m_scr_win_tags = ui::ScrolledWindow(ui::New); + gtk_container_set_border_width(GTK_CONTAINER(g_TextureBrowser.m_scr_win_tags), 0); + + // vertical only scrolling for treeview + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(g_TextureBrowser.m_scr_win_tags), GTK_POLICY_NEVER, + GTK_POLICY_ALWAYS); + + TextureBrowser_createTreeViewTags(); + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(g_TextureBrowser.m_scr_win_tags), + g_TextureBrowser.m_treeViewTags); + g_TextureBrowser.m_treeViewTags.show(); + } + { // Texture/Tag notebook + TextureBrowser_constructTagNotebook(); + vbox.pack_start(g_TextureBrowser.m_tag_notebook, TRUE, TRUE, 0); + } + { // Tag search button + TextureBrowser_constructSearchButton(); + vbox.pack_end(g_TextureBrowser.m_search_button, FALSE, FALSE, 0); + } + auto frame_table = ui::Table(3, 3, FALSE); + { // Tag frame + + g_TextureBrowser.m_tag_frame = ui::Frame("Tag assignment"); + gtk_frame_set_label_align(GTK_FRAME(g_TextureBrowser.m_tag_frame), 0.5, 0.5); + gtk_frame_set_shadow_type(GTK_FRAME(g_TextureBrowser.m_tag_frame), GTK_SHADOW_NONE); + + table.attach(g_TextureBrowser.m_tag_frame, {1, 3, 2, 3}, {GTK_FILL, GTK_SHRINK}); + + frame_table.show(); + + g_TextureBrowser.m_tag_frame.add(frame_table); + } + { // assigned tag list + ui::Widget scrolled_win = ui::ScrolledWindow(ui::New); + gtk_container_set_border_width(GTK_CONTAINER(scrolled_win), 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + + g_TextureBrowser.m_assigned_store = ui::ListStore::from(gtk_list_store_new(N_COLUMNS, G_TYPE_STRING)); + + auto sortable = GTK_TREE_SORTABLE(g_TextureBrowser.m_assigned_store); + gtk_tree_sortable_set_sort_column_id(sortable, TAG_COLUMN, GTK_SORT_ASCENDING); + + auto renderer = ui::CellRendererText(ui::New); + + g_TextureBrowser.m_assigned_tree = ui::TreeView( + ui::TreeModel::from(g_TextureBrowser.m_assigned_store._handle)); + g_TextureBrowser.m_assigned_store.unref(); + g_TextureBrowser.m_assigned_tree.connect("row-activated", (GCallback) TextureBrowser_removeTags, NULL); + gtk_tree_view_set_headers_visible(g_TextureBrowser.m_assigned_tree, FALSE); + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); + + auto column = ui::TreeViewColumn("", renderer, {{"text", TAG_COLUMN}}); + gtk_tree_view_append_column(g_TextureBrowser.m_assigned_tree, column); + g_TextureBrowser.m_assigned_tree.show(); + + scrolled_win.show(); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_win), g_TextureBrowser.m_assigned_tree); + + frame_table.attach(scrolled_win, {0, 1, 1, 3}, {GTK_FILL, GTK_FILL}); + } + { // available tag list + ui::Widget scrolled_win = ui::ScrolledWindow(ui::New); + gtk_container_set_border_width(GTK_CONTAINER(scrolled_win), 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + + g_TextureBrowser.m_available_store = ui::ListStore::from(gtk_list_store_new(N_COLUMNS, G_TYPE_STRING)); + auto sortable = GTK_TREE_SORTABLE(g_TextureBrowser.m_available_store); + gtk_tree_sortable_set_sort_column_id(sortable, TAG_COLUMN, GTK_SORT_ASCENDING); + + auto renderer = ui::CellRendererText(ui::New); + + g_TextureBrowser.m_available_tree = ui::TreeView( + ui::TreeModel::from(g_TextureBrowser.m_available_store._handle)); + g_TextureBrowser.m_available_store.unref(); + g_TextureBrowser.m_available_tree.connect("row-activated", (GCallback) TextureBrowser_assignTags, NULL); + gtk_tree_view_set_headers_visible(g_TextureBrowser.m_available_tree, FALSE); + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); + + auto column = ui::TreeViewColumn("", renderer, {{"text", TAG_COLUMN}}); + gtk_tree_view_append_column(g_TextureBrowser.m_available_tree, column); + g_TextureBrowser.m_available_tree.show(); + + scrolled_win.show(); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_win), g_TextureBrowser.m_available_tree); + + frame_table.attach(scrolled_win, {2, 3, 1, 3}, {GTK_FILL, GTK_FILL}); + } + { // tag arrow buttons + auto m_btn_left = ui::Button(ui::New); + auto m_btn_right = ui::Button(ui::New); + auto m_arrow_left = ui::Widget::from(gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_OUT)); + auto m_arrow_right = ui::Widget::from(gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT)); + m_btn_left.add(m_arrow_left); + m_btn_right.add(m_arrow_right); + + // workaround. the size of the tag frame depends of the requested size of the arrow buttons. + m_arrow_left.dimensions(-1, 68); + m_arrow_right.dimensions(-1, 68); + + frame_table.attach(m_btn_left, {1, 2, 1, 2}, {GTK_SHRINK, GTK_EXPAND}); + frame_table.attach(m_btn_right, {1, 2, 2, 3}, {GTK_SHRINK, GTK_EXPAND}); + + m_btn_left.connect("clicked", G_CALLBACK(TextureBrowser_assignTags), NULL); + m_btn_right.connect("clicked", G_CALLBACK(TextureBrowser_removeTags), NULL); + + m_btn_left.show(); + m_btn_right.show(); + m_arrow_left.show(); + m_arrow_right.show(); + } + { // tag fram labels + ui::Widget m_lbl_assigned = ui::Label("Assigned"); + ui::Widget m_lbl_unassigned = ui::Label("Available"); - m_lbl_assigned.show(); - m_lbl_unassigned.show(); - } - } - else { // no tag support, show the texture tree only - vbox.pack_start( g_TextureBrowser.m_scr_win_tree, TRUE, TRUE, 0 ); - } + frame_table.attach(m_lbl_assigned, {0, 1, 0, 1}, {GTK_EXPAND, GTK_SHRINK}); + frame_table.attach(m_lbl_unassigned, {2, 3, 0, 1}, {GTK_EXPAND, GTK_SHRINK}); - // TODO do we need this? - //gtk_container_set_focus_chain(GTK_CONTAINER(hbox_table), NULL); + m_lbl_assigned.show(); + m_lbl_unassigned.show(); + } + } else { // no tag support, show the texture tree only + vbox.pack_start(g_TextureBrowser.m_scr_win_tree, TRUE, TRUE, 0); + } - return table; + // TODO do we need this? + //gtk_container_set_focus_chain(GTK_CONTAINER(hbox_table), NULL); + + return table; } -void TextureBrowser_destroyWindow(){ - GlobalShaderSystem().setActiveShadersChangedNotify( Callback() ); +void TextureBrowser_destroyWindow() +{ + GlobalShaderSystem().setActiveShadersChangedNotify(Callback()); - g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_sizeHandler ); - g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_exposeHandler ); + g_signal_handler_disconnect(G_OBJECT(g_TextureBrowser.m_gl_widget), g_TextureBrowser.m_sizeHandler); + g_signal_handler_disconnect(G_OBJECT(g_TextureBrowser.m_gl_widget), g_TextureBrowser.m_exposeHandler); - g_TextureBrowser.m_gl_widget.unref(); + g_TextureBrowser.m_gl_widget.unref(); } -const Vector3& TextureBrowser_getBackgroundColour( TextureBrowser& textureBrowser ){ - return textureBrowser.color_textureback; +const Vector3 &TextureBrowser_getBackgroundColour(TextureBrowser &textureBrowser) +{ + return textureBrowser.color_textureback; } -void TextureBrowser_setBackgroundColour( TextureBrowser& textureBrowser, const Vector3& colour ){ - textureBrowser.color_textureback = colour; - TextureBrowser_queueDraw( textureBrowser ); +void TextureBrowser_setBackgroundColour(TextureBrowser &textureBrowser, const Vector3 &colour) +{ + textureBrowser.color_textureback = colour; + TextureBrowser_queueDraw(textureBrowser); } -void TextureBrowser_selectionHelper( ui::TreeModel model, ui::TreePath path, GtkTreeIter* iter, GSList** selected ){ - g_assert( selected != NULL ); +void TextureBrowser_selectionHelper(ui::TreeModel model, ui::TreePath path, GtkTreeIter *iter, GSList **selected) +{ + g_assert(selected != NULL); - gchar* name; - gtk_tree_model_get( model, iter, TAG_COLUMN, &name, -1 ); - *selected = g_slist_append( *selected, name ); + gchar *name; + gtk_tree_model_get(model, iter, TAG_COLUMN, &name, -1); + *selected = g_slist_append(*selected, name); } -void TextureBrowser_shaderInfo(){ - const char* name = TextureBrowser_GetSelectedShader( g_TextureBrowser ); - IShader* shader = QERApp_Shader_ForName( name ); +void TextureBrowser_shaderInfo() +{ + const char *name = TextureBrowser_GetSelectedShader(g_TextureBrowser); + IShader *shader = QERApp_Shader_ForName(name); - DoShaderInfoDlg( name, shader->getShaderFileName(), "Shader Info" ); + DoShaderInfoDlg(name, shader->getShaderFileName(), "Shader Info"); - shader->DecRef(); + shader->DecRef(); } -void TextureBrowser_addTag(){ - CopiedString tag; +void TextureBrowser_addTag() +{ + CopiedString tag; - EMessageBoxReturn result = DoShaderTagDlg( &tag, "Add shader tag" ); + EMessageBoxReturn result = DoShaderTagDlg(&tag, "Add shader tag"); - if ( result == eIDOK && !tag.empty() ) { - GtkTreeIter iter; - g_TextureBrowser.m_all_tags.insert( tag.c_str() ); - gtk_list_store_append( g_TextureBrowser.m_available_store, &iter ); - gtk_list_store_set( g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, tag.c_str(), -1 ); + if (result == eIDOK && !tag.empty()) { + GtkTreeIter iter; + g_TextureBrowser.m_all_tags.insert(tag.c_str()); + gtk_list_store_append(g_TextureBrowser.m_available_store, &iter); + gtk_list_store_set(g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, tag.c_str(), -1); - // Select the currently added tag in the available list - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree ); - gtk_tree_selection_select_iter( selection, &iter ); + // Select the currently added tag in the available list + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree); + gtk_tree_selection_select_iter(selection, &iter); - g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, tag.c_str()); - } + g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, tag.c_str()); + } } -void TextureBrowser_renameTag(){ - /* WORKAROUND: The tag treeview is set to GTK_SELECTION_MULTIPLE. Because +void TextureBrowser_renameTag() +{ + /* WORKAROUND: The tag treeview is set to GTK_SELECTION_MULTIPLE. Because gtk_tree_selection_get_selected() doesn't work with GTK_SELECTION_MULTIPLE, we need to count the number of selected rows first and use gtk_tree_selection_selected_foreach() then to go through the list of selected rows (which always containins a single row). */ - GSList* selected = NULL; + GSList *selected = NULL; - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags ); - gtk_tree_selection_selected_foreach( selection, GtkTreeSelectionForeachFunc( TextureBrowser_selectionHelper ), &selected ); + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags); + gtk_tree_selection_selected_foreach(selection, GtkTreeSelectionForeachFunc(TextureBrowser_selectionHelper), + &selected); - if ( g_slist_length( selected ) == 1 ) { // we only rename a single tag - CopiedString newTag; - EMessageBoxReturn result = DoShaderTagDlg( &newTag, "Rename shader tag" ); + if (g_slist_length(selected) == 1) { // we only rename a single tag + CopiedString newTag; + EMessageBoxReturn result = DoShaderTagDlg(&newTag, "Rename shader tag"); - if ( result == eIDOK && !newTag.empty() ) { - GtkTreeIter iterList; - gchar* rowTag; - gchar* oldTag = (char*)selected->data; - - bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterList ) != 0; - - while ( row ) - { - gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, &rowTag, -1 ); - - if ( strcmp( rowTag, oldTag ) == 0 ) { - gtk_list_store_set( g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, newTag.c_str(), -1 ); - } - row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterList ) != 0; - } + if (result == eIDOK && !newTag.empty()) { + GtkTreeIter iterList; + gchar *rowTag; + gchar *oldTag = (char *) selected->data; - TagBuilder.RenameShaderTag( oldTag, newTag.c_str() ); - - g_TextureBrowser.m_all_tags.erase( (CopiedString)oldTag ); - g_TextureBrowser.m_all_tags.insert( newTag ); - - BuildStoreAssignedTags( g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), &g_TextureBrowser ); - BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser ); - } - } - else - { - ui::alert( g_TextureBrowser.m_parent, "Select a single tag for renaming." ); - } -} - -void TextureBrowser_deleteTag(){ - GSList* selected = NULL; - - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags ); - gtk_tree_selection_selected_foreach( selection, GtkTreeSelectionForeachFunc( TextureBrowser_selectionHelper ), &selected ); - - if ( g_slist_length( selected ) == 1 ) { // we only delete a single tag - auto result = ui::alert( g_TextureBrowser.m_parent, "Are you sure you want to delete the selected tag?", "Delete Tag", ui::alert_type::YESNO, ui::alert_icon::Question ); - - if ( result == ui::alert_response::YES ) { - GtkTreeIter iterSelected; - gchar *rowTag; - - gchar* tagSelected = (char*)selected->data; - - bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterSelected ) != 0; - - while ( row ) - { - gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterSelected, TAG_COLUMN, &rowTag, -1 ); - - if ( strcmp( rowTag, tagSelected ) == 0 ) { - gtk_list_store_remove( g_TextureBrowser.m_all_tags_list, &iterSelected ); - break; - } - row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterSelected ) != 0; - } - - TagBuilder.DeleteTag( tagSelected ); - g_TextureBrowser.m_all_tags.erase( (CopiedString)tagSelected ); - - BuildStoreAssignedTags( g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), &g_TextureBrowser ); - BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser ); - } - } - else { - ui::alert( g_TextureBrowser.m_parent, "Select a single tag for deletion." ); - } -} - -void TextureBrowser_copyTag(){ - g_TextureBrowser.m_copied_tags.clear(); - TagBuilder.GetShaderTags( g_TextureBrowser.shader.c_str(), g_TextureBrowser.m_copied_tags ); -} - -void TextureBrowser_pasteTag(){ - IShader* ishader = QERApp_Shader_ForName( g_TextureBrowser.shader.c_str() ); - CopiedString shader = g_TextureBrowser.shader.c_str(); - - if ( !TagBuilder.CheckShaderTag( shader.c_str() ) ) { - CopiedString shaderFile = ishader->getShaderFileName(); - if ( shaderFile.empty() ) { - // it's a texture - TagBuilder.AddShaderNode( shader.c_str(), CUSTOM, TEXTURE ); - } - else - { - // it's a shader - TagBuilder.AddShaderNode( shader.c_str(), CUSTOM, SHADER ); - } - - for ( size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i ) - { - TagBuilder.AddShaderTag( shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG ); - } - } - else - { - for ( size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i ) - { - if ( !TagBuilder.CheckShaderTag( shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str() ) ) { - // the tag doesn't exist - let's add it - TagBuilder.AddShaderTag( shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG ); - } - } - } - - ishader->DecRef(); - - TagBuilder.SaveXmlDoc(); - BuildStoreAssignedTags( g_TextureBrowser.m_assigned_store, shader.c_str(), &g_TextureBrowser ); - BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser ); -} - -void TextureBrowser_RefreshShaders(){ - ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Shaders" ); - GlobalShaderSystem().refresh(); - UpdateAllWindows(); - auto selection = gtk_tree_view_get_selection(GlobalTextureBrowser().m_treeViewTree); - GtkTreeModel* model = NULL; - GtkTreeIter iter; - if ( gtk_tree_selection_get_selected (selection, &model, &iter) ) - { - gchar dirName[1024]; + bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterList) != 0; - gchar* buffer; - gtk_tree_model_get( model, &iter, 0, &buffer, -1 ); - strcpy( dirName, buffer ); - g_free( buffer ); - if ( !TextureBrowser_showWads() ) { - strcat( dirName, "/" ); - } - TextureBrowser_ShowDirectory( GlobalTextureBrowser(), dirName ); - TextureBrowser_queueDraw( GlobalTextureBrowser() ); - } -} + while (row) { + gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, &rowTag, -1); -void TextureBrowser_ToggleShowShaders(){ - g_TextureBrowser.m_showShaders ^= 1; - g_TextureBrowser.m_showshaders_item.update(); - TextureBrowser_queueDraw( g_TextureBrowser ); -} + if (strcmp(rowTag, oldTag) == 0) { + gtk_list_store_set(g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, newTag.c_str(), -1); + } + row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterList) != 0; + } -void TextureBrowser_ToggleShowShaderListOnly(){ - g_TextureBrowser_shaderlistOnly ^= 1; - g_TextureBrowser.m_showshaderlistonly_item.update(); + TagBuilder.RenameShaderTag(oldTag, newTag.c_str()); - TextureBrowser_constructTreeStore(); + g_TextureBrowser.m_all_tags.erase((CopiedString) oldTag); + g_TextureBrowser.m_all_tags.insert(newTag); + + BuildStoreAssignedTags(g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), + &g_TextureBrowser); + BuildStoreAvailableTags(g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, + g_TextureBrowser.m_all_tags, &g_TextureBrowser); + } + } else { + ui::alert(g_TextureBrowser.m_parent, "Select a single tag for renaming."); + } } -void TextureBrowser_showAll(){ - g_TextureBrowser_currentDirectory = ""; - g_TextureBrowser.m_searchedTags = false; - TextureBrowser_heightChanged( g_TextureBrowser ); - TextureBrowser_updateTitle(); +void TextureBrowser_deleteTag() +{ + GSList *selected = NULL; + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags); + gtk_tree_selection_selected_foreach(selection, GtkTreeSelectionForeachFunc(TextureBrowser_selectionHelper), + &selected); + + if (g_slist_length(selected) == 1) { // we only delete a single tag + auto result = ui::alert(g_TextureBrowser.m_parent, "Are you sure you want to delete the selected tag?", + "Delete Tag", ui::alert_type::YESNO, ui::alert_icon::Question); + + if (result == ui::alert_response::YES) { + GtkTreeIter iterSelected; + gchar *rowTag; + + gchar *tagSelected = (char *) selected->data; + + bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterSelected) != 0; + + while (row) { + gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterSelected, TAG_COLUMN, &rowTag, -1); + + if (strcmp(rowTag, tagSelected) == 0) { + gtk_list_store_remove(g_TextureBrowser.m_all_tags_list, &iterSelected); + break; + } + row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterSelected) != 0; + } + + TagBuilder.DeleteTag(tagSelected); + g_TextureBrowser.m_all_tags.erase((CopiedString) tagSelected); + + BuildStoreAssignedTags(g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), + &g_TextureBrowser); + BuildStoreAvailableTags(g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, + g_TextureBrowser.m_all_tags, &g_TextureBrowser); + } + } else { + ui::alert(g_TextureBrowser.m_parent, "Select a single tag for deletion."); + } } -void TextureBrowser_showUntagged(){ - auto result = ui::alert( g_TextureBrowser.m_parent, "WARNING! This function might need a lot of memory and time. Are you sure you want to use it?", "Show Untagged", ui::alert_type::YESNO, ui::alert_icon::Warning ); +void TextureBrowser_copyTag() +{ + g_TextureBrowser.m_copied_tags.clear(); + TagBuilder.GetShaderTags(g_TextureBrowser.shader.c_str(), g_TextureBrowser.m_copied_tags); +} - if ( result == ui::alert_response::YES ) { - g_TextureBrowser.m_found_shaders.clear(); - TagBuilder.GetUntagged( g_TextureBrowser.m_found_shaders ); - std::set::iterator iter; +void TextureBrowser_pasteTag() +{ + IShader *ishader = QERApp_Shader_ForName(g_TextureBrowser.shader.c_str()); + CopiedString shader = g_TextureBrowser.shader.c_str(); + + if (!TagBuilder.CheckShaderTag(shader.c_str())) { + CopiedString shaderFile = ishader->getShaderFileName(); + if (shaderFile.empty()) { + // it's a texture + TagBuilder.AddShaderNode(shader.c_str(), CUSTOM, TEXTURE); + } else { + // it's a shader + TagBuilder.AddShaderNode(shader.c_str(), CUSTOM, SHADER); + } + + for (size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i) { + TagBuilder.AddShaderTag(shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG); + } + } else { + for (size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i) { + if (!TagBuilder.CheckShaderTag(shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str())) { + // the tag doesn't exist - let's add it + TagBuilder.AddShaderTag(shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG); + } + } + } + + ishader->DecRef(); + + TagBuilder.SaveXmlDoc(); + BuildStoreAssignedTags(g_TextureBrowser.m_assigned_store, shader.c_str(), &g_TextureBrowser); + BuildStoreAvailableTags(g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, + g_TextureBrowser.m_all_tags, &g_TextureBrowser); +} + +void TextureBrowser_RefreshShaders() +{ + ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Loading Shaders"); + GlobalShaderSystem().refresh(); + UpdateAllWindows(); + auto selection = gtk_tree_view_get_selection(GlobalTextureBrowser().m_treeViewTree); + GtkTreeModel *model = NULL; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { + gchar dirName[1024]; + + gchar *buffer; + gtk_tree_model_get(model, &iter, 0, &buffer, -1); + strcpy(dirName, buffer); + g_free(buffer); + if (!TextureBrowser_showWads()) { + strcat(dirName, "/"); + } + TextureBrowser_ShowDirectory(GlobalTextureBrowser(), dirName); + TextureBrowser_queueDraw(GlobalTextureBrowser()); + } +} + +void TextureBrowser_ToggleShowShaders() +{ + g_TextureBrowser.m_showShaders ^= 1; + g_TextureBrowser.m_showshaders_item.update(); + TextureBrowser_queueDraw(g_TextureBrowser); +} - ScopeDisableScreenUpdates disableScreenUpdates( "Searching untagged textures...", "Loading Textures" ); +void TextureBrowser_ToggleShowShaderListOnly() +{ + g_TextureBrowser_shaderlistOnly ^= 1; + g_TextureBrowser.m_showshaderlistonly_item.update(); - for ( iter = g_TextureBrowser.m_found_shaders.begin(); iter != g_TextureBrowser.m_found_shaders.end(); iter++ ) - { - std::string path = ( *iter ).c_str(); - size_t pos = path.find_last_of( "/", path.size() ); - std::string name = path.substr( pos + 1, path.size() ); - path = path.substr( 0, pos + 1 ); - TextureDirectory_loadTexture( path.c_str(), name.c_str() ); - globalErrorStream() << path.c_str() << name.c_str() << "\n"; - } + TextureBrowser_constructTreeStore(); +} - g_TextureBrowser_currentDirectory = "Untagged"; - TextureBrowser_queueDraw( GlobalTextureBrowser() ); - TextureBrowser_heightChanged( g_TextureBrowser ); - TextureBrowser_updateTitle(); - } +void TextureBrowser_showAll() +{ + g_TextureBrowser_currentDirectory = ""; + g_TextureBrowser.m_searchedTags = false; + TextureBrowser_heightChanged(g_TextureBrowser); + TextureBrowser_updateTitle(); } -void TextureBrowser_FixedSize(){ - g_TextureBrowser_fixedSize ^= 1; - GlobalTextureBrowser().m_fixedsize_item.update(); - TextureBrowser_activeShadersChanged( GlobalTextureBrowser() ); +void TextureBrowser_showUntagged() +{ + auto result = ui::alert(g_TextureBrowser.m_parent, + "WARNING! This function might need a lot of memory and time. Are you sure you want to use it?", + "Show Untagged", ui::alert_type::YESNO, ui::alert_icon::Warning); + + if (result == ui::alert_response::YES) { + g_TextureBrowser.m_found_shaders.clear(); + TagBuilder.GetUntagged(g_TextureBrowser.m_found_shaders); + std::set::iterator iter; + + ScopeDisableScreenUpdates disableScreenUpdates("Searching untagged textures...", "Loading Textures"); + + for (iter = g_TextureBrowser.m_found_shaders.begin(); iter != g_TextureBrowser.m_found_shaders.end(); iter++) { + std::string path = (*iter).c_str(); + size_t pos = path.find_last_of("/", path.size()); + std::string name = path.substr(pos + 1, path.size()); + path = path.substr(0, pos + 1); + TextureDirectory_loadTexture(path.c_str(), name.c_str()); + globalErrorStream() << path.c_str() << name.c_str() << "\n"; + } + + g_TextureBrowser_currentDirectory = "Untagged"; + TextureBrowser_queueDraw(GlobalTextureBrowser()); + TextureBrowser_heightChanged(g_TextureBrowser); + TextureBrowser_updateTitle(); + } +} + +void TextureBrowser_FixedSize() +{ + g_TextureBrowser_fixedSize ^= 1; + GlobalTextureBrowser().m_fixedsize_item.update(); + TextureBrowser_activeShadersChanged(GlobalTextureBrowser()); } -void TextureBrowser_FilterMissing(){ - g_TextureBrowser_filterMissing ^= 1; - GlobalTextureBrowser().m_filternotex_item.update(); - TextureBrowser_activeShadersChanged( GlobalTextureBrowser() ); - TextureBrowser_RefreshShaders(); +void TextureBrowser_FilterMissing() +{ + g_TextureBrowser_filterMissing ^= 1; + GlobalTextureBrowser().m_filternotex_item.update(); + TextureBrowser_activeShadersChanged(GlobalTextureBrowser()); + TextureBrowser_RefreshShaders(); } -void TextureBrowser_FilterFallback(){ - g_TextureBrowser_filterFallback ^= 1; - GlobalTextureBrowser().m_hidenotex_item.update(); - TextureBrowser_activeShadersChanged( GlobalTextureBrowser() ); - TextureBrowser_RefreshShaders(); +void TextureBrowser_FilterFallback() +{ + g_TextureBrowser_filterFallback ^= 1; + GlobalTextureBrowser().m_hidenotex_item.update(); + TextureBrowser_activeShadersChanged(GlobalTextureBrowser()); + TextureBrowser_RefreshShaders(); } -void TextureBrowser_EnableAlpha(){ - g_TextureBrowser_enableAlpha ^= 1; - GlobalTextureBrowser().m_enablealpha_item.update(); - TextureBrowser_activeShadersChanged( GlobalTextureBrowser() ); +void TextureBrowser_EnableAlpha() +{ + g_TextureBrowser_enableAlpha ^= 1; + GlobalTextureBrowser().m_enablealpha_item.update(); + TextureBrowser_activeShadersChanged(GlobalTextureBrowser()); } -void TextureBrowser_exportTitle( const Callback & importer ){ - StringOutputStream buffer( 64 ); - buffer << "Textures: "; - if ( !string_empty( g_TextureBrowser_currentDirectory.c_str() ) ) { - buffer << g_TextureBrowser_currentDirectory.c_str(); - } - else - { - buffer << "all"; - } - importer( buffer.c_str() ); +void TextureBrowser_exportTitle(const Callback &importer) +{ + StringOutputStream buffer(64); + buffer << "Textures: "; + if (!string_empty(g_TextureBrowser_currentDirectory.c_str())) { + buffer << g_TextureBrowser_currentDirectory.c_str(); + } else { + buffer << "all"; + } + importer(buffer.c_str()); } struct TextureScale { - static void Export(const TextureBrowser &self, const Callback &returnz) { - switch (self.m_textureScale) { - case 10: - returnz(0); - break; - case 25: - returnz(1); - break; - case 50: - returnz(2); - break; - case 100: - returnz(3); - break; - case 200: - returnz(4); - break; - } - } - - static void Import(TextureBrowser &self, int value) { - switch (value) { - case 0: - TextureBrowser_setScale(self, 10); - break; - case 1: - TextureBrowser_setScale(self, 25); - break; - case 2: - TextureBrowser_setScale(self, 50); - break; - case 3: - TextureBrowser_setScale(self, 100); - break; - case 4: - TextureBrowser_setScale(self, 200); - break; - } - } + static void Export(const TextureBrowser &self, const Callback &returnz) + { + switch (self.m_textureScale) { + case 10: + returnz(0); + break; + case 25: + returnz(1); + break; + case 50: + returnz(2); + break; + case 100: + returnz(3); + break; + case 200: + returnz(4); + break; + } + } + + static void Import(TextureBrowser &self, int value) + { + switch (value) { + case 0: + TextureBrowser_setScale(self, 10); + break; + case 1: + TextureBrowser_setScale(self, 25); + break; + case 2: + TextureBrowser_setScale(self, 50); + break; + case 3: + TextureBrowser_setScale(self, 100); + break; + case 4: + TextureBrowser_setScale(self, 200); + break; + } + } }; struct UniformTextureSize { - static void Export(const TextureBrowser &self, const Callback &returnz) { - returnz(g_TextureBrowser.m_uniformTextureSize); - } - - static void Import(TextureBrowser &self, int value) { - if (value > 16) - TextureBrowser_setUniformSize(self, value); - } + static void Export(const TextureBrowser &self, const Callback &returnz) + { + returnz(g_TextureBrowser.m_uniformTextureSize); + } + + static void Import(TextureBrowser &self, int value) + { + if (value > 16) { + TextureBrowser_setUniformSize(self, value); + } + } }; -void TextureBrowser_constructPreferences( PreferencesPage& page ){ - page.appendCheckBox( - "", "Texture scrollbar", - make_property(GlobalTextureBrowser()) - ); - { - const char* texture_scale[] = { "10%", "25%", "50%", "100%", "200%" }; - page.appendCombo( - "Texture Thumbnail Scale", - STRING_ARRAY_RANGE( texture_scale ), - make_property(GlobalTextureBrowser()) - ); - } - page.appendSpinner( - "Texture Thumbnail Size", - GlobalTextureBrowser().m_uniformTextureSize, - GlobalTextureBrowser().m_uniformTextureSize, - 16, 8192 - ); - page.appendEntry( "Mousewheel Increment", GlobalTextureBrowser().m_mouseWheelScrollIncrement ); - { - const char* startup_shaders[] = { "None", TextureBrowser_getComonShadersName() }; - page.appendCombo( "Load Shaders at Startup", reinterpret_cast( GlobalTextureBrowser().m_startupShaders ), STRING_ARRAY_RANGE( startup_shaders ) ); - } -} -void TextureBrowser_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Texture Browser", "Texture Browser Preferences" ) ); - TextureBrowser_constructPreferences( page ); -} -void TextureBrowser_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage( makeCallbackF(TextureBrowser_constructPage) ); +void TextureBrowser_constructPreferences(PreferencesPage &page) +{ + page.appendCheckBox( + "", "Texture scrollbar", + make_property(GlobalTextureBrowser()) + ); + { + const char *texture_scale[] = {"10%", "25%", "50%", "100%", "200%"}; + page.appendCombo( + "Texture Thumbnail Scale", + STRING_ARRAY_RANGE(texture_scale), + make_property(GlobalTextureBrowser()) + ); + } + page.appendSpinner( + "Texture Thumbnail Size", + GlobalTextureBrowser().m_uniformTextureSize, + GlobalTextureBrowser().m_uniformTextureSize, + 16, 8192 + ); + page.appendEntry("Mousewheel Increment", GlobalTextureBrowser().m_mouseWheelScrollIncrement); + { + const char *startup_shaders[] = {"None", TextureBrowser_getComonShadersName()}; + page.appendCombo("Load Shaders at Startup", reinterpret_cast( GlobalTextureBrowser().m_startupShaders ), + STRING_ARRAY_RANGE(startup_shaders)); + } +} + +void TextureBrowser_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Texture Browser", "Texture Browser Preferences")); + TextureBrowser_constructPreferences(page); +} + +void TextureBrowser_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(TextureBrowser_constructPage)); } @@ -2608,51 +2747,69 @@ void TextureBrowser_registerPreferencesPage(){ #include "stringio.h" -void TextureClipboard_textureSelected( const char* shader ); - -void TextureBrowser_Construct(){ - GlobalCommands_insert( "ShaderInfo", makeCallbackF(TextureBrowser_shaderInfo) ); - GlobalCommands_insert( "ShowUntagged", makeCallbackF(TextureBrowser_showUntagged) ); - GlobalCommands_insert( "AddTag", makeCallbackF(TextureBrowser_addTag) ); - GlobalCommands_insert( "RenameTag", makeCallbackF(TextureBrowser_renameTag) ); - GlobalCommands_insert( "DeleteTag", makeCallbackF(TextureBrowser_deleteTag) ); - GlobalCommands_insert( "CopyTag", makeCallbackF(TextureBrowser_copyTag) ); - GlobalCommands_insert( "PasteTag", makeCallbackF(TextureBrowser_pasteTag) ); - GlobalCommands_insert( "RefreshShaders", makeCallbackF(VFS_Refresh) ); - GlobalToggles_insert( "ShowInUse", makeCallbackF(TextureBrowser_ToggleHideUnused), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_hideunused_item ), Accelerator( 'U' ) ); - GlobalCommands_insert( "ShowAllTextures", makeCallbackF(TextureBrowser_showAll), Accelerator( 'A', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "ToggleTextures", makeCallbackF(TextureBrowser_toggleShow), Accelerator( 'T' ) ); - GlobalToggles_insert( "ToggleShowShaders", makeCallbackF(TextureBrowser_ToggleShowShaders), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_showshaders_item ) ); - GlobalToggles_insert( "ToggleShowShaderlistOnly", makeCallbackF(TextureBrowser_ToggleShowShaderListOnly), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_showshaderlistonly_item ) ); - GlobalToggles_insert( "FixedSize", makeCallbackF(TextureBrowser_FixedSize), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_fixedsize_item ) ); - GlobalToggles_insert( "FilterMissing", makeCallbackF(TextureBrowser_FilterMissing), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_filternotex_item ) ); - GlobalToggles_insert( "FilterFallback", makeCallbackF(TextureBrowser_FilterFallback), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_hidenotex_item ) ); - GlobalToggles_insert( "EnableAlpha", makeCallbackF(TextureBrowser_EnableAlpha), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_enablealpha_item ) ); - - GlobalPreferenceSystem().registerPreference( "TextureScale", make_property_string(g_TextureBrowser) ); - GlobalPreferenceSystem().registerPreference( "UniformTextureSize", make_property_string(g_TextureBrowser) ); - GlobalPreferenceSystem().registerPreference( "TextureScrollbar", make_property_string(GlobalTextureBrowser())); - GlobalPreferenceSystem().registerPreference( "ShowShaders", make_property_string( GlobalTextureBrowser().m_showShaders ) ); - GlobalPreferenceSystem().registerPreference( "ShowShaderlistOnly", make_property_string( g_TextureBrowser_shaderlistOnly ) ); - GlobalPreferenceSystem().registerPreference( "FixedSize", make_property_string( g_TextureBrowser_fixedSize ) ); - GlobalPreferenceSystem().registerPreference( "FilterMissing", make_property_string( g_TextureBrowser_filterMissing ) ); - GlobalPreferenceSystem().registerPreference( "EnableAlpha", make_property_string( g_TextureBrowser_enableAlpha ) ); - GlobalPreferenceSystem().registerPreference( "LoadShaders", make_property_string( reinterpret_cast( GlobalTextureBrowser().m_startupShaders ) ) ); - GlobalPreferenceSystem().registerPreference( "WheelMouseInc", make_property_string( GlobalTextureBrowser().m_mouseWheelScrollIncrement ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors0", make_property_string( GlobalTextureBrowser().color_textureback ) ); - - g_TextureBrowser.shader = texdef_name_default(); - - Textures_setModeChangedNotify( ReferenceCaller( g_TextureBrowser ) ); - - TextureBrowser_registerPreferencesPage(); - - GlobalShaderSystem().attach( g_ShadersObserver ); - - TextureBrowser_textureSelected = TextureClipboard_textureSelected; -} -void TextureBrowser_Destroy(){ - GlobalShaderSystem().detach( g_ShadersObserver ); - - Textures_setModeChangedNotify( Callback() ); +void TextureClipboard_textureSelected(const char *shader); + +void TextureBrowser_Construct() +{ + GlobalCommands_insert("ShaderInfo", makeCallbackF(TextureBrowser_shaderInfo)); + GlobalCommands_insert("ShowUntagged", makeCallbackF(TextureBrowser_showUntagged)); + GlobalCommands_insert("AddTag", makeCallbackF(TextureBrowser_addTag)); + GlobalCommands_insert("RenameTag", makeCallbackF(TextureBrowser_renameTag)); + GlobalCommands_insert("DeleteTag", makeCallbackF(TextureBrowser_deleteTag)); + GlobalCommands_insert("CopyTag", makeCallbackF(TextureBrowser_copyTag)); + GlobalCommands_insert("PasteTag", makeCallbackF(TextureBrowser_pasteTag)); + GlobalCommands_insert("RefreshShaders", makeCallbackF(VFS_Refresh)); + GlobalToggles_insert("ShowInUse", makeCallbackF(TextureBrowser_ToggleHideUnused), + ToggleItem::AddCallbackCaller(g_TextureBrowser.m_hideunused_item), Accelerator('U')); + GlobalCommands_insert("ShowAllTextures", makeCallbackF(TextureBrowser_showAll), + Accelerator('A', (GdkModifierType) GDK_CONTROL_MASK)); + GlobalCommands_insert("ToggleTextures", makeCallbackF(TextureBrowser_toggleShow), Accelerator('T')); + GlobalToggles_insert("ToggleShowShaders", makeCallbackF(TextureBrowser_ToggleShowShaders), + ToggleItem::AddCallbackCaller(g_TextureBrowser.m_showshaders_item)); + GlobalToggles_insert("ToggleShowShaderlistOnly", makeCallbackF(TextureBrowser_ToggleShowShaderListOnly), + ToggleItem::AddCallbackCaller(g_TextureBrowser.m_showshaderlistonly_item)); + GlobalToggles_insert("FixedSize", makeCallbackF(TextureBrowser_FixedSize), + ToggleItem::AddCallbackCaller(g_TextureBrowser.m_fixedsize_item)); + GlobalToggles_insert("FilterMissing", makeCallbackF(TextureBrowser_FilterMissing), + ToggleItem::AddCallbackCaller(g_TextureBrowser.m_filternotex_item)); + GlobalToggles_insert("FilterFallback", makeCallbackF(TextureBrowser_FilterFallback), + ToggleItem::AddCallbackCaller(g_TextureBrowser.m_hidenotex_item)); + GlobalToggles_insert("EnableAlpha", makeCallbackF(TextureBrowser_EnableAlpha), + ToggleItem::AddCallbackCaller(g_TextureBrowser.m_enablealpha_item)); + + GlobalPreferenceSystem().registerPreference("TextureScale", make_property_string(g_TextureBrowser)); + GlobalPreferenceSystem().registerPreference("UniformTextureSize", + make_property_string(g_TextureBrowser)); + GlobalPreferenceSystem().registerPreference("TextureScrollbar", make_property_string( + GlobalTextureBrowser())); + GlobalPreferenceSystem().registerPreference("ShowShaders", + make_property_string(GlobalTextureBrowser().m_showShaders)); + GlobalPreferenceSystem().registerPreference("ShowShaderlistOnly", + make_property_string(g_TextureBrowser_shaderlistOnly)); + GlobalPreferenceSystem().registerPreference("FixedSize", make_property_string(g_TextureBrowser_fixedSize)); + GlobalPreferenceSystem().registerPreference("FilterMissing", make_property_string(g_TextureBrowser_filterMissing)); + GlobalPreferenceSystem().registerPreference("EnableAlpha", make_property_string(g_TextureBrowser_enableAlpha)); + GlobalPreferenceSystem().registerPreference("LoadShaders", make_property_string( + reinterpret_cast( GlobalTextureBrowser().m_startupShaders ))); + GlobalPreferenceSystem().registerPreference("WheelMouseInc", make_property_string( + GlobalTextureBrowser().m_mouseWheelScrollIncrement)); + GlobalPreferenceSystem().registerPreference("SI_Colors0", + make_property_string(GlobalTextureBrowser().color_textureback)); + + g_TextureBrowser.shader = texdef_name_default(); + + Textures_setModeChangedNotify(ReferenceCaller(g_TextureBrowser)); + + TextureBrowser_registerPreferencesPage(); + + GlobalShaderSystem().attach(g_ShadersObserver); + + TextureBrowser_textureSelected = TextureClipboard_textureSelected; +} + +void TextureBrowser_Destroy() +{ + GlobalShaderSystem().detach(g_ShadersObserver); + + Textures_setModeChangedNotify(Callback()); } diff --git a/radiant/texwindow.h b/radiant/texwindow.h index 2d5125e4..5c5e5d8f 100644 --- a/radiant/texwindow.h +++ b/radiant/texwindow.h @@ -30,29 +30,38 @@ #include "xml/xmltextags.h" class TextureBrowser; -TextureBrowser& GlobalTextureBrowser(); -ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ); +TextureBrowser &GlobalTextureBrowser(); + +ui::Widget TextureBrowser_constructWindow(ui::Window toplevel); + void TextureBrowser_destroyWindow(); -void TextureBrowser_ShowDirectory( TextureBrowser& textureBrowser, const char* name ); -void TextureBrowser_ShowStartupShaders( TextureBrowser& textureBrowser ); +void TextureBrowser_ShowDirectory(TextureBrowser &textureBrowser, const char *name); -const char* TextureBrowser_GetSelectedShader( TextureBrowser& textureBrower ); +void TextureBrowser_ShowStartupShaders(TextureBrowser &textureBrowser); + +const char *TextureBrowser_GetSelectedShader(TextureBrowser &textureBrower); void TextureBrowser_Construct(); + void TextureBrowser_Destroy(); extern ui::Widget g_page_textures; -void TextureBrowser_exportTitle( const Callback & importer ); -typedef FreeCaller &), TextureBrowser_exportTitle> TextureBrowserExportTitleCaller; -const Vector3& TextureBrowser_getBackgroundColour( TextureBrowser& textureBrowser ); -void TextureBrowser_setBackgroundColour( TextureBrowser& textureBrowser, const Vector3& colour ); +void TextureBrowser_exportTitle(const Callback &importer); + +typedef FreeCaller &), TextureBrowser_exportTitle> TextureBrowserExportTitleCaller; + +const Vector3 &TextureBrowser_getBackgroundColour(TextureBrowser &textureBrowser); + +void TextureBrowser_setBackgroundColour(TextureBrowser &textureBrowser, const Vector3 &colour); + +void TextureBrowser_addActiveShadersChangedCallback(const SignalHandler &handler); -void TextureBrowser_addActiveShadersChangedCallback( const SignalHandler& handler ); -void TextureBrowser_addShadersRealiseCallback( const SignalHandler& handler ); +void TextureBrowser_addShadersRealiseCallback(const SignalHandler &handler); void TextureBrowser_RefreshShaders(); diff --git a/radiant/timer.cpp b/radiant/timer.cpp index 8d10b82b..6978510c 100644 --- a/radiant/timer.cpp +++ b/radiant/timer.cpp @@ -28,36 +28,36 @@ #include MillisecondTime MillisecondTime::current(){ - static class Cached - { - LONGLONG m_frequency; - LONGLONG m_base; + static class Cached + { + LONGLONG m_frequency; + LONGLONG m_base; public: - Cached(){ - QueryPerformanceFrequency( (LARGE_INTEGER *) &m_frequency ); - QueryPerformanceCounter( (LARGE_INTEGER *) &m_base ); - } - LONGLONG frequency(){ - return m_frequency; - } - LONGLONG base(){ - return m_base; - } - } cached; - - if ( cached.frequency() > 0 ) { - LONGLONG count; - QueryPerformanceCounter( (LARGE_INTEGER *) &count ); - return time_from_ticks( count - cached.base(), cached.frequency() ); - } - else - { + Cached(){ + QueryPerformanceFrequency( (LARGE_INTEGER *) &m_frequency ); + QueryPerformanceCounter( (LARGE_INTEGER *) &m_base ); + } + LONGLONG frequency(){ + return m_frequency; + } + LONGLONG base(){ + return m_base; + } + } cached; + + if ( cached.frequency() > 0 ) { + LONGLONG count; + QueryPerformanceCounter( (LARGE_INTEGER *) &count ); + return time_from_ticks( count - cached.base(), cached.frequency() ); + } + else + { #if 1 - return MillisecondTime(); + return MillisecondTime(); #else - return time_from_ticks( timeGetTime(), 1000 ); + return time_from_ticks( timeGetTime(), 1000 ); #endif - } + } } @@ -68,32 +68,34 @@ public: #include #include "sys/time.h" -MillisecondTime MillisecondTime::current(){ - static class Cached - { - time_t m_base; -public: - Cached(){ - time( &m_base ); - } - time_t base(){ - return m_base; - } - } cached; - - timeval time; - gettimeofday( &time, 0 ); - return MillisecondTime( ( time.tv_sec - cached.base() ) * 1000 + time.tv_usec / 1000 ); +MillisecondTime MillisecondTime::current() +{ + static class Cached { + time_t m_base; + public: + Cached() + { + time(&m_base); + } + + time_t base() + { + return m_base; + } + } cached; + + timeval time; + gettimeofday(&time, 0); + return MillisecondTime((time.tv_sec - cached.base()) * 1000 + time.tv_usec / 1000); } - #else #include MillisecondTime MillisecondTime::current(){ - return time_from_ticks( std::clock(), CLOCKS_PER_SEC ); + return time_from_ticks( std::clock(), CLOCKS_PER_SEC ); } diff --git a/radiant/timer.h b/radiant/timer.h index 53280a8c..59d171d8 100644 --- a/radiant/timer.h +++ b/radiant/timer.h @@ -26,25 +26,31 @@ const int msec_per_sec = 1000; -class MillisecondTime -{ -unsigned int m_milliseconds; +class MillisecondTime { + unsigned int m_milliseconds; public: -MillisecondTime( unsigned int milliseconds ) - : m_milliseconds( milliseconds ){ -} -MillisecondTime(){ -} -static MillisecondTime current(); + MillisecondTime(unsigned int milliseconds) + : m_milliseconds(milliseconds) + { + } -unsigned int milliseconds_since( const MillisecondTime& other ) const { - return m_milliseconds - other.m_milliseconds; -} + MillisecondTime() + { + } + + static MillisecondTime current(); + + unsigned int milliseconds_since(const MillisecondTime &other) const + { + return m_milliseconds - other.m_milliseconds; + } }; template -inline MillisecondTime time_from_ticks( tick_type tick_count, tick_type ticks_per_sec ){ - return MillisecondTime( static_cast( tick_count / static_cast( ticks_per_sec / msec_per_sec ) ) ); +inline MillisecondTime time_from_ticks(tick_type tick_count, tick_type ticks_per_sec) +{ + return MillisecondTime( + static_cast( tick_count / static_cast( ticks_per_sec / msec_per_sec ))); } #else @@ -57,37 +63,39 @@ unsigned int m_sec; unsigned int m_usec; public: MillisecondTime( unsigned int sec, unsigned int usec ) - : m_sec( sec ), m_usec( usec ){ + : m_sec( sec ), m_usec( usec ){ } MillisecondTime(){ } staticMillisecondTime current(); unsigned int milliseconds_since( const MillisecondTime& other ) const { - return static_cast( ( m_sec * static_cast( usec_per_sec ) + m_usec ) - - ( other.m_sec * static_cast( usec_per_sec ) + other.m_usec ) ) / 1000; + return static_cast( ( m_sec * static_cast( usec_per_sec ) + m_usec ) + - ( other.m_sec * static_cast( usec_per_sec ) + other.m_usec ) ) / 1000; } }; template inline MillisecondTime time_from_ticks( tick_type tick_count, tick_type ticks_per_sec ){ - return MillisecondTime( static_cast( tick_count / ticks_per_sec ), - static_cast( ( tick_count % ticks_per_sec ) * ( usec_per_sec / static_cast( ticks_per_sec ) ) ) ); + return MillisecondTime( static_cast( tick_count / ticks_per_sec ), + static_cast( ( tick_count % ticks_per_sec ) * ( usec_per_sec / static_cast( ticks_per_sec ) ) ) ); } #endif -class Timer -{ -MillisecondTime m_start; +class Timer { + MillisecondTime m_start; public: -void start(){ - m_start = MillisecondTime::current(); -} -unsigned int elapsed_msec(){ - return MillisecondTime::current().milliseconds_since( m_start ); -} + void start() + { + m_start = MillisecondTime::current(); + } + + unsigned int elapsed_msec() + { + return MillisecondTime::current().milliseconds_since(m_start); + } }; #endif diff --git a/radiant/treemodel.cpp b/radiant/treemodel.cpp index 12441f0e..c0463bee 100644 --- a/radiant/treemodel.cpp +++ b/radiant/treemodel.cpp @@ -36,8 +36,9 @@ #include "string/string.h" #include "generic/reference.h" -inline Nameable* Node_getNameable( scene::Node& node ){ - return NodeTypeCast::cast( node ); +inline Nameable *Node_getNameable(scene::Node &node) +{ + return NodeTypeCast::cast(node); } #if 0 @@ -46,123 +47,123 @@ inline Nameable* Node_getNameable( scene::Node& node ){ template inline void gtk_tree_model_get_pointer( ui::TreeModel 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 ); + GValue value = GValue_default(); + gtk_tree_model_get_value( model, iter, column, &value ); + *pointer = (value_type*)g_value_get_pointer( &value ); } typedef GtkTreeStore GraphTreeModel; ui::TreeStore graph_tree_model_new( graph_type* graph ){ - return gtk_tree_store_new( 2, G_TYPE_POINTER, G_TYPE_POINTER ); + return gtk_tree_store_new( 2, G_TYPE_POINTER, G_TYPE_POINTER ); } void graph_tree_model_delete( GraphTreeModel* model ){ - g_object_unref( G_OBJECT( model ) ); + g_object_unref( G_OBJECT( model ) ); } bool graph_tree_model_subtree_find_node( GraphTreeModel* model, GtkTreeIter* parent, const scene::Node& node, GtkTreeIter* iter ){ - for ( gboolean success = gtk_tree_model_iter_children( model, iter, parent ); - success != FALSE; - success = gtk_tree_model_iter_next( model, iter ) ) - { - scene::Node* current; - gtk_tree_model_get_pointer( model, iter, 0, ¤t ); - if ( current == node ) { - return true; - } - } - return false; + for ( gboolean success = gtk_tree_model_iter_children( model, iter, parent ); + success != FALSE; + success = gtk_tree_model_iter_next( model, iter ) ) + { + scene::Node* current; + gtk_tree_model_get_pointer( model, iter, 0, ¤t ); + if ( current == node ) { + return true; + } + } + return false; } typedef GtkTreeIter DoubleGtkTreeIter[2]; bool graph_tree_model_find_top( GraphTreeModel* model, const scene::Path& path, GtkTreeIter& iter ){ - int swap = 0; - GtkTreeIter* parent_pointer = NULL; - GtkTreeIter parent; - for ( scene::Path::const_iterator i = path.begin(); i != path.end(); ++i ) - { - if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &iter ) ) { - return false; - } - parent = iter; - parent_pointer = &parent; - } - return true; + int swap = 0; + GtkTreeIter* parent_pointer = NULL; + GtkTreeIter parent; + for ( scene::Path::const_iterator i = path.begin(); i != path.end(); ++i ) + { + if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &iter ) ) { + return false; + } + parent = iter; + parent_pointer = &parent; + } + return true; } bool graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path, GtkTreeIter& iter ){ - int swap = 0; - GtkTreeIter* parent_pointer = NULL; - ASSERT_MESSAGE( path.size() > 1, "path too short" ); - for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i ) - { - GtkTreeIter child; - if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &child ) ) { - return false; - } - iter = child; - parent_pointer = &iter; - } - return true; + int swap = 0; + GtkTreeIter* parent_pointer = NULL; + ASSERT_MESSAGE( path.size() > 1, "path too short" ); + for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i ) + { + GtkTreeIter child; + if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &child ) ) { + return false; + } + iter = child; + parent_pointer = &iter; + } + return true; } void node_attach_name_changed_callback( scene::Node& node, const Callback& callback ){ - if ( node != 0 ) { - Nameable* nameable = Node_getNameable( node ); - if ( nameable != 0 ) { - nameable->attach( callback ); - } - } + if ( node != 0 ) { + Nameable* nameable = Node_getNameable( node ); + if ( nameable != 0 ) { + nameable->attach( callback ); + } + } } void node_detach_name_changed_callback( scene::Node& node, const Callback& callback ){ - if ( node != 0 ) { - Nameable* nameable = Node_getNameable( node ); - if ( nameable != 0 ) { - nameable->detach( callback ); - } - } + if ( node != 0 ) { + Nameable* nameable = Node_getNameable( node ); + if ( nameable != 0 ) { + nameable->detach( callback ); + } + } } GraphTreeModel* scene_graph_get_tree_model(); // temp hack void graph_tree_model_row_changed( const scene::Instance& instance ){ - GraphTreeModel* model = scene_graph_get_tree_model(); + GraphTreeModel* model = scene_graph_get_tree_model(); - GtkTreeIter child; - ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" ); + GtkTreeIter child; + ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" ); - gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, instance.path().top(), -1 ); + gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, instance.path().top(), -1 ); } void graph_tree_model_row_inserted( GraphTreeModel* model, const scene::Instance& instance ){ - GtkTreeIter parent; - GtkTreeIter* parent_pointer = NULL; - if ( instance.path().size() != 1 ) { - ASSERT_MESSAGE( graph_tree_model_find_parent( model, instance.path(), parent ), "RUNTIME ERROR" ); - parent_pointer = &parent; - } + GtkTreeIter parent; + GtkTreeIter* parent_pointer = NULL; + if ( instance.path().size() != 1 ) { + ASSERT_MESSAGE( graph_tree_model_find_parent( model, instance.path(), parent ), "RUNTIME ERROR" ); + parent_pointer = &parent; + } - gpointer node = instance.path().top(); - gconstpointer selectable = Instance_getSelectable( instance ); + gpointer node = instance.path().top(); + gconstpointer selectable = Instance_getSelectable( instance ); - GtkTreeIter child; - gtk_tree_store_append( GTK_TREE_STORE( model ), &child, parent_pointer ); - gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, node, 1, selectable, -1 ); + GtkTreeIter child; + gtk_tree_store_append( GTK_TREE_STORE( model ), &child, parent_pointer ); + gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, node, 1, selectable, -1 ); - node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); + node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); } void graph_tree_model_row_deleted( GraphTreeModel* model, const scene::Instance& instance ){ - GtkTreeIter child; - ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" ); + GtkTreeIter child; + ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" ); - node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); + node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); - gtk_tree_store_remove( GTK_TREE_STORE( model ), &child ); + gtk_tree_store_remove( GTK_TREE_STORE( model ), &child ); } #elif 0 @@ -175,17 +176,17 @@ class NodeNameLess { public: bool operator()( const NodePointer& self, const NodePointer& other ) const { - if ( self == 0 ) { - return true; - } - if ( other == 0 ) { - return false; - } - int result = string_compare( node_get_name( self ), node_get_name( other ) ); - if ( result == 0 ) { - return self < other; - } - return result < 0; + if ( self == 0 ) { + return true; + } + if ( other == 0 ) { + return false; + } + int result = string_compare( node_get_name( self ), node_get_name( other ) ); + if ( result == 0 ) { + return self < other; + } + return result < 0; } }; @@ -193,7 +194,7 @@ class PathNameLess { public: bool operator()( const PathConstReference& self, const PathConstReference& other ) const { - return std::lexicographical_compare( self.get().begin(), self.get().end(), other.get().begin(), other.get().end(), NodeNameLess() ); + return std::lexicographical_compare( self.get().begin(), self.get().end(), other.get().begin(), other.get().end(), NodeNameLess() ); } }; @@ -201,433 +202,433 @@ typedef std::map graph_type; struct GraphTreeModel { - GObject parent; + GObject parent; - graph_type* graph; + graph_type* graph; }; struct GraphTreeModelClass { - GObjectClass parent_class; + GObjectClass parent_class; }; #define GRAPH_TREE_MODEL( p ) ( reinterpret_cast( p ) ) static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){ - return GTK_TREE_MODEL_ITERS_PERSIST; + return GTK_TREE_MODEL_ITERS_PERSIST; } static gint graph_tree_model_get_n_columns( ui::TreeModel tree_model ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model; + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model; - return 2; + return 2; } static const gint c_stamp = 0xabcdef; inline graph_type::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){ - ASSERT_MESSAGE( iter != 0, "tree model error" ); - ASSERT_MESSAGE( iter->user_data != 0, "tree model error" ); - ASSERT_MESSAGE( iter->stamp == c_stamp, "tree model error" ); - return *reinterpret_cast( &iter->user_data ); + ASSERT_MESSAGE( iter != 0, "tree model error" ); + ASSERT_MESSAGE( iter->user_data != 0, "tree model error" ); + ASSERT_MESSAGE( iter->stamp == c_stamp, "tree model error" ); + return *reinterpret_cast( &iter->user_data ); } inline void graph_iterator_write_tree_iter( graph_type::iterator i, GtkTreeIter* iter ){ - ASSERT_MESSAGE( iter != 0, "tree model error" ); - iter->stamp = c_stamp; - *reinterpret_cast( &iter->user_data ) = i; - ASSERT_MESSAGE( iter->user_data != 0, "tree model error" ); + ASSERT_MESSAGE( iter != 0, "tree model error" ); + iter->stamp = c_stamp; + *reinterpret_cast( &iter->user_data ) = i; + ASSERT_MESSAGE( iter->user_data != 0, "tree model error" ); } static GType graph_tree_model_get_column_type( ui::TreeModel tree_model, gint index ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model; + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model; - return G_TYPE_POINTER; + return G_TYPE_POINTER; } static gboolean graph_tree_model_get_iter( ui::TreeModel tree_model, GtkTreeIter* iter, ui::TreePath path ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - gint* indices = gtk_tree_path_get_indices( path ); - gint depth = gtk_tree_path_get_depth( path ); + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + gint* indices = gtk_tree_path_get_indices( path ); + gint depth = gtk_tree_path_get_depth( path ); - g_return_val_if_fail( depth > 0, FALSE ); + g_return_val_if_fail( depth > 0, FALSE ); - graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; + graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; - if ( graph.empty() ) { - return FALSE; - } + if ( graph.empty() ) { + return FALSE; + } - GtkTreeIter tmp; - GtkTreeIter* parent = 0; + GtkTreeIter tmp; + GtkTreeIter* parent = 0; - for ( gint i = 0; i < depth; i++ ) - { - if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) { - return FALSE; - } - tmp = *iter; - parent = &tmp; - } + for ( gint i = 0; i < depth; i++ ) + { + if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) { + return FALSE; + } + tmp = *iter; + parent = &tmp; + } - return TRUE; + return TRUE; } static ui::TreePath graph_tree_model_get_path( ui::TreeModel tree_model, GtkTreeIter* iter ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; - graph_type::iterator i = graph_iterator_read_tree_iter( iter ); + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; + graph_type::iterator i = graph_iterator_read_tree_iter( iter ); - auto path = ui::TreePath(); + auto path = ui::TreePath(); - for ( std::size_t depth = ( *i ).first.get().size(); depth != 0; --depth ) - { - std::size_t index = 0; + for ( std::size_t depth = ( *i ).first.get().size(); depth != 0; --depth ) + { + std::size_t index = 0; - while ( i != graph.begin() && ( *i ).first.get().size() >= depth ) - { - --i; - if ( ( *i ).first.get().size() == depth ) { - ++index; - } - } + while ( i != graph.begin() && ( *i ).first.get().size() >= depth ) + { + --i; + if ( ( *i ).first.get().size() == depth ) { + ++index; + } + } - gtk_tree_path_prepend_index( path, index ); - } + gtk_tree_path_prepend_index( path, index ); + } - return path; + return path; } static void graph_tree_model_get_value( ui::TreeModel tree_model, GtkTreeIter *iter, gint column, GValue *value ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" ); + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" ); - graph_type::iterator i = graph_iterator_read_tree_iter( iter ); + graph_type::iterator i = graph_iterator_read_tree_iter( iter ); - g_value_init( value, G_TYPE_POINTER ); + g_value_init( value, G_TYPE_POINTER ); - if ( column == 0 ) { - g_value_set_pointer( value, reinterpret_cast( ( *i ).first.get().top() ) ); - } - else{ - g_value_set_pointer( value, reinterpret_cast( Instance_getSelectable( *( *i ).second ) ) ); - } + if ( column == 0 ) { + g_value_set_pointer( value, reinterpret_cast( ( *i ).first.get().top() ) ); + } + else{ + g_value_set_pointer( value, reinterpret_cast( Instance_getSelectable( *( *i ).second ) ) ); + } } static gboolean graph_tree_model_iter_next( ui::TreeModel tree_model, GtkTreeIter *iter ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; - graph_type::iterator i = graph_iterator_read_tree_iter( iter ); - std::size_t depth = ( *i ).first.get().size(); + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; + graph_type::iterator i = graph_iterator_read_tree_iter( iter ); + std::size_t depth = ( *i ).first.get().size(); - ++i; + ++i; - while ( i != graph.end() && ( *i ).first.get().size() > depth ) - { - ++i; - } + while ( i != graph.end() && ( *i ).first.get().size() > depth ) + { + ++i; + } - if ( i == graph.end() || ( *i ).first.get().size() != depth ) { - return FALSE; - } + if ( i == graph.end() || ( *i ).first.get().size() != depth ) { + return FALSE; + } - graph_iterator_write_tree_iter( i, iter ); + graph_iterator_write_tree_iter( i, iter ); - return TRUE; + return TRUE; } static gboolean graph_tree_model_iter_children( ui::TreeModel tree_model, GtkTreeIter *iter, GtkTreeIter *parent ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; - graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent ); - std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1; + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; + graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent ); + std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1; - if ( parent != 0 ) { - ++i; - } + if ( parent != 0 ) { + ++i; + } - if ( i != graph.end() && ( *i ).first.get().size() == depth ) { - graph_iterator_write_tree_iter( i, iter ); - return TRUE; - } + if ( i != graph.end() && ( *i ).first.get().size() == depth ) { + graph_iterator_write_tree_iter( i, iter ); + return TRUE; + } - return FALSE; + return FALSE; } static gboolean graph_tree_model_iter_has_child( ui::TreeModel tree_model, GtkTreeIter *iter ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; - graph_type::iterator i = graph_iterator_read_tree_iter( iter ); - std::size_t depth = ( *i ).first.get().size() + 1; + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; + graph_type::iterator i = graph_iterator_read_tree_iter( iter ); + std::size_t depth = ( *i ).first.get().size() + 1; - return ++i != graph.end() && ( *i ).first.get().size() == depth; + return ++i != graph.end() && ( *i ).first.get().size() == depth; } static gint graph_tree_model_iter_n_children( ui::TreeModel tree_model, GtkTreeIter *parent ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; - graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent ); - std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1; + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; + graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent ); + std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1; - if ( parent != 0 ) { - ++i; - } + if ( parent != 0 ) { + ++i; + } - gint count = 0; - while ( i != graph.end() && ( *i ).first.get().size() >= depth ) - { - ++count; - ++i; - } + gint count = 0; + while ( i != graph.end() && ( *i ).first.get().size() >= depth ) + { + ++count; + ++i; + } - return count; + return count; } static gboolean graph_tree_model_iter_nth_child( ui::TreeModel tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; - graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent ); - std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1; + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; + graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent ); + std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1; - if ( parent != 0 ) { - ++i; - } + if ( parent != 0 ) { + ++i; + } - while ( i != graph.end() && ( *i ).first.get().size() >= depth ) - { - if ( ( *i ).first.get().size() == depth && n-- == 0 ) { - graph_iterator_write_tree_iter( i, iter ); - return TRUE; - } - ++i; - } + while ( i != graph.end() && ( *i ).first.get().size() >= depth ) + { + if ( ( *i ).first.get().size() == depth && n-- == 0 ) { + graph_iterator_write_tree_iter( i, iter ); + return TRUE; + } + ++i; + } - return FALSE; + return FALSE; } static gboolean graph_tree_model_iter_parent( ui::TreeModel tree_model, GtkTreeIter *iter, GtkTreeIter *child ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; - graph_type::iterator i = graph_iterator_read_tree_iter( child ); - std::size_t depth = ( *i ).first.get().size(); - if ( depth == 1 ) { - return FALSE; - } - else - { - do - { - --i; - } - while ( ( *i ).first.get().size() >= depth ); - graph_iterator_write_tree_iter( i, iter ); - return TRUE; - } + ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); + graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph; + graph_type::iterator i = graph_iterator_read_tree_iter( child ); + std::size_t depth = ( *i ).first.get().size(); + if ( depth == 1 ) { + return FALSE; + } + else + { + do + { + --i; + } + while ( ( *i ).first.get().size() >= depth ); + graph_iterator_write_tree_iter( i, iter ); + return TRUE; + } } static GObjectClass *g_parent_class = 0; static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){ - graph_tree_model->graph = 0; + graph_tree_model->graph = 0; } static void graph_tree_model_finalize( GObject* object ){ - GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object ); + GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object ); - /* must chain up */ - ( *g_parent_class->finalize )( object ); + /* must chain up */ + ( *g_parent_class->finalize )( object ); } static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){ - GObjectClass *object_class; + GObjectClass *object_class; - g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ ); - object_class = (GObjectClass *) class_; + g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ ); + object_class = (GObjectClass *) class_; - object_class->finalize = graph_tree_model_finalize; + object_class->finalize = graph_tree_model_finalize; } static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){ - iface->get_flags = graph_tree_model_get_flags; - iface->get_n_columns = graph_tree_model_get_n_columns; - iface->get_column_type = graph_tree_model_get_column_type; - iface->get_iter = graph_tree_model_get_iter; - iface->get_path = graph_tree_model_get_path; - iface->get_value = graph_tree_model_get_value; - iface->iter_next = graph_tree_model_iter_next; - iface->iter_children = graph_tree_model_iter_children; - iface->iter_has_child = graph_tree_model_iter_has_child; - iface->iter_n_children = graph_tree_model_iter_n_children; - iface->iter_nth_child = graph_tree_model_iter_nth_child; - iface->iter_parent = graph_tree_model_iter_parent; + iface->get_flags = graph_tree_model_get_flags; + iface->get_n_columns = graph_tree_model_get_n_columns; + iface->get_column_type = graph_tree_model_get_column_type; + iface->get_iter = graph_tree_model_get_iter; + iface->get_path = graph_tree_model_get_path; + iface->get_value = graph_tree_model_get_value; + iface->iter_next = graph_tree_model_iter_next; + iface->iter_children = graph_tree_model_iter_children; + iface->iter_has_child = graph_tree_model_iter_has_child; + iface->iter_n_children = graph_tree_model_iter_n_children; + iface->iter_nth_child = graph_tree_model_iter_nth_child; + iface->iter_parent = graph_tree_model_iter_parent; } static gboolean graph_tree_model_row_draggable( GtkTreeDragSource *drag_source, ui::TreePath path ){ #if GDEF_DEBUG - gint depth = gtk_tree_path_get_depth( path ); + gint depth = gtk_tree_path_get_depth( path ); #endif - return gtk_tree_path_get_depth( path ) > 1; + return gtk_tree_path_get_depth( path ) > 1; } static gboolean graph_tree_model_drag_data_delete( GtkTreeDragSource *drag_source, ui::TreePath path ){ - GtkTreeIter iter; + GtkTreeIter iter; - if ( gtk_tree_model_get_iter( drag_source, &iter, path ) ) { - graph_type::iterator i = graph_iterator_read_tree_iter( &iter ); - Path_deleteTop( ( *i ).first ); - return TRUE; - } - else - { - return FALSE; - } + if ( gtk_tree_model_get_iter( drag_source, &iter, path ) ) { + graph_type::iterator i = graph_iterator_read_tree_iter( &iter ); + Path_deleteTop( ( *i ).first ); + return TRUE; + } + else + { + return FALSE; + } } static gboolean graph_tree_model_drag_data_get( GtkTreeDragSource *drag_source, ui::TreePath path, GtkSelectionData *selection_data ){ - if ( gtk_tree_set_row_drag_data( selection_data, drag_source, path ) ) { - return TRUE; - } - else - { - /* FIXME handle text targets at least. */ - } + if ( gtk_tree_set_row_drag_data( selection_data, drag_source, path ) ) { + return TRUE; + } + else + { + /* FIXME handle text targets at least. */ + } - return FALSE; + return FALSE; } static void graph_tree_model_drag_source_init( GtkTreeDragSourceIface *iface ){ - iface->row_draggable = graph_tree_model_row_draggable; - iface->drag_data_delete = graph_tree_model_drag_data_delete; - iface->drag_data_get = graph_tree_model_drag_data_get; + iface->row_draggable = graph_tree_model_row_draggable; + iface->drag_data_delete = graph_tree_model_drag_data_delete; + iface->drag_data_get = graph_tree_model_drag_data_get; } static gboolean graph_tree_model_drag_data_received( GtkTreeDragDest *drag_dest, ui::TreePath dest, GtkSelectionData *selection_data ){ - auto tree_model = drag_dest; + auto tree_model = drag_dest; - GtkTreeModel *src_model = 0; - GtkTreePath *src_path = 0; - if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path ) - && src_model == tree_model ) { - /* Copy the given row to a new position */ - GtkTreeIter iter; + GtkTreeModel *src_model = 0; + GtkTreePath *src_path = 0; + if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path ) + && src_model == tree_model ) { + /* Copy the given row to a new position */ + GtkTreeIter iter; - if ( gtk_tree_model_get_iter( src_model, &iter, src_path ) ) { - int bleh = 0; - } - } - else - { - /* FIXME maybe add some data targets eventually, or handle text - * targets in the simple case. - */ - } + if ( gtk_tree_model_get_iter( src_model, &iter, src_path ) ) { + int bleh = 0; + } + } + else + { + /* FIXME maybe add some data targets eventually, or handle text + * targets in the simple case. + */ + } - return FALSE; + return FALSE; } static gboolean graph_tree_model_row_drop_possible( GtkTreeDragDest *drag_dest, ui::TreePath dest_path, GtkSelectionData *selection_data ){ - gboolean retval = FALSE; + gboolean retval = FALSE; - GtkTreeModel *src_model = 0; - GtkTreePath *src_path = 0; - if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path ) != FALSE ) { - /* can only drag to ourselves */ - if ( src_model == drag_dest ) { - /* Can't drop into ourself. */ - if ( !gtk_tree_path_is_ancestor( src_path, dest_path ) ) { - /* Can't drop if dest_path's parent doesn't exist */ - if ( gtk_tree_path_get_depth( dest_path ) > 1 ) { - auto tmp = gtk_tree_path_copy( dest_path ); - gtk_tree_path_up( tmp ); + GtkTreeModel *src_model = 0; + GtkTreePath *src_path = 0; + if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path ) != FALSE ) { + /* can only drag to ourselves */ + if ( src_model == drag_dest ) { + /* Can't drop into ourself. */ + if ( !gtk_tree_path_is_ancestor( src_path, dest_path ) ) { + /* Can't drop if dest_path's parent doesn't exist */ + if ( gtk_tree_path_get_depth( dest_path ) > 1 ) { + auto tmp = gtk_tree_path_copy( dest_path ); + gtk_tree_path_up( tmp ); - GtkTreeIter iter; - retval = gtk_tree_model_get_iter( drag_dest, &iter, tmp ); + GtkTreeIter iter; + retval = gtk_tree_model_get_iter( drag_dest, &iter, tmp ); - gtk_tree_path_free( tmp ); - } - } - } + gtk_tree_path_free( tmp ); + } + } + } - gtk_tree_path_free( src_path ); - } + gtk_tree_path_free( src_path ); + } - return retval; + return retval; } static void graph_tree_model_drag_dest_init( GtkTreeDragDestIface *iface ){ - iface->drag_data_received = graph_tree_model_drag_data_received; - iface->row_drop_possible = graph_tree_model_row_drop_possible; + iface->drag_data_received = graph_tree_model_drag_data_received; + iface->row_drop_possible = graph_tree_model_row_drop_possible; } GType graph_tree_model_get_type( void ){ - static GType graph_tree_model_type = 0; - - if ( !graph_tree_model_type ) { - static const GTypeInfo graph_tree_model_info = - { - sizeof( GraphTreeModelClass ), - 0, /* base_init */ - 0, /* base_finalize */ - (GClassInitFunc) graph_tree_model_class_init, - 0, /* class_finalize */ - 0, /* class_data */ - sizeof( GraphTreeModel ), - 0, /* n_preallocs */ - (GInstanceInitFunc) graph_tree_model_init - }; - - static const GInterfaceInfo tree_model_info = - { - (GInterfaceInitFunc) graph_tree_model_tree_model_init, - 0, - 0 - }; - - static const GInterfaceInfo drag_source_info = - { - (GInterfaceInitFunc) graph_tree_model_drag_source_init, - 0, - 0 - }; - - static const GInterfaceInfo drag_dest_info = - { - (GInterfaceInitFunc) graph_tree_model_drag_dest_init, - 0, - 0 - }; - - graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel", - &graph_tree_model_info, (GTypeFlags)0 ); - - g_type_add_interface_static( graph_tree_model_type, - GTK_TYPE_TREE_MODEL, - &tree_model_info ); - g_type_add_interface_static( graph_tree_model_type, - GTK_TYPE_TREE_DRAG_SOURCE, - &drag_source_info ); - g_type_add_interface_static( graph_tree_model_type, - GTK_TYPE_TREE_DRAG_DEST, - &drag_dest_info ); - } - - return graph_tree_model_type; + static GType graph_tree_model_type = 0; + + if ( !graph_tree_model_type ) { + static const GTypeInfo graph_tree_model_info = + { + sizeof( GraphTreeModelClass ), + 0, /* base_init */ + 0, /* base_finalize */ + (GClassInitFunc) graph_tree_model_class_init, + 0, /* class_finalize */ + 0, /* class_data */ + sizeof( GraphTreeModel ), + 0, /* n_preallocs */ + (GInstanceInitFunc) graph_tree_model_init + }; + + static const GInterfaceInfo tree_model_info = + { + (GInterfaceInitFunc) graph_tree_model_tree_model_init, + 0, + 0 + }; + + static const GInterfaceInfo drag_source_info = + { + (GInterfaceInitFunc) graph_tree_model_drag_source_init, + 0, + 0 + }; + + static const GInterfaceInfo drag_dest_info = + { + (GInterfaceInitFunc) graph_tree_model_drag_dest_init, + 0, + 0 + }; + + graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel", + &graph_tree_model_info, (GTypeFlags)0 ); + + g_type_add_interface_static( graph_tree_model_type, + GTK_TYPE_TREE_MODEL, + &tree_model_info ); + g_type_add_interface_static( graph_tree_model_type, + GTK_TYPE_TREE_DRAG_SOURCE, + &drag_source_info ); + g_type_add_interface_static( graph_tree_model_type, + GTK_TYPE_TREE_DRAG_DEST, + &drag_dest_info ); + } + + return graph_tree_model_type; } GraphTreeModel* graph_tree_model_new(){ - GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) ); + GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) ); - graph_tree_model->graph = new graph_type; + graph_tree_model->graph = new graph_type; - return graph_tree_model; + return graph_tree_model; } void graph_tree_model_delete( GraphTreeModel* model ){ - delete model->graph; - g_object_unref( G_OBJECT( model ) ); + delete model->graph; + g_object_unref( G_OBJECT( model ) ); } @@ -638,7 +639,7 @@ public: TempNameable( const char* name ) : m_name( name ){ } const char* name() const { - return m_name; + return m_name; } void attach( const NameCallback& callback ){ } @@ -647,776 +648,837 @@ void detach( const NameCallback& callback ){ }; void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){ - // Reference cannot be bound to dereferenced null pointer in well-defined - // C++ code, and Clang will assume that comparison below always evaluates - // to true, resulting in a segmentation fault. Use a dirty hack to force - // Clang to check those "bad" references for null nonetheless. - volatile intptr_t n = (intptr_t)&node; - - if ( n != 0 ) { - Nameable* nameable = Node_getNameable( node ); - if ( nameable != 0 ) { - nameable->attach( callback ); - } - } + // Reference cannot be bound to dereferenced null pointer in well-defined + // C++ code, and Clang will assume that comparison below always evaluates + // to true, resulting in a segmentation fault. Use a dirty hack to force + // Clang to check those "bad" references for null nonetheless. + volatile intptr_t n = (intptr_t)&node; + + if ( n != 0 ) { + Nameable* nameable = Node_getNameable( node ); + if ( nameable != 0 ) { + nameable->attach( callback ); + } + } } void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){ - volatile intptr_t n = (intptr_t)&node; // see the comment on line 650 + volatile intptr_t n = (intptr_t)&node; // see the comment on line 650 - if ( n != 0 ) { - Nameable* nameable = Node_getNameable( node ); - if ( nameable != 0 ) { - nameable->detach( callback ); - } - } + if ( n != 0 ) { + Nameable* nameable = Node_getNameable( node ); + if ( nameable != 0 ) { + nameable->detach( callback ); + } + } } GraphTreeModel* scene_graph_get_tree_model(); // temp hack void graph_tree_model_row_inserted( GraphTreeModel* model, graph_type::iterator i ){ - GtkTreeIter iter; - graph_iterator_write_tree_iter( i, &iter ); + GtkTreeIter iter; + graph_iterator_write_tree_iter( i, &iter ); - auto tree_path = graph_tree_model_get_path( model, &iter ); + auto tree_path = graph_tree_model_get_path( model, &iter ); - gint depth = gtk_tree_path_get_depth( tree_path ); - gint* indices = gtk_tree_path_get_indices( tree_path ); + gint depth = gtk_tree_path_get_depth( tree_path ); + gint* indices = gtk_tree_path_get_indices( tree_path ); - gtk_tree_model_row_inserted( model, tree_path, &iter ); + gtk_tree_model_row_inserted( model, tree_path, &iter ); - gtk_tree_path_free( tree_path ); + gtk_tree_path_free( tree_path ); } void graph_tree_model_row_deleted( GraphTreeModel* model, graph_type::iterator i ){ - GtkTreeIter iter; - graph_iterator_write_tree_iter( i, &iter ); + GtkTreeIter iter; + graph_iterator_write_tree_iter( i, &iter ); - auto tree_path = graph_tree_model_get_path( model, &iter ); + auto tree_path = graph_tree_model_get_path( model, &iter ); - gtk_tree_model_row_deleted( model, tree_path ); + gtk_tree_model_row_deleted( model, tree_path ); - gtk_tree_path_free( tree_path ); + gtk_tree_path_free( tree_path ); } #include "generic/referencecounted.h" void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){ - GraphTreeModel* model = scene_graph_get_tree_model(); + GraphTreeModel* model = scene_graph_get_tree_model(); - if ( string_empty( name ) ) { // hack! - graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) ); - ASSERT_MESSAGE( i != model->graph->end(), "ERROR" ); + if ( string_empty( name ) ) { // hack! + graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) ); + ASSERT_MESSAGE( i != model->graph->end(), "ERROR" ); - graph_tree_model_row_deleted( model, i ); + graph_tree_model_row_deleted( model, i ); - model->graph->erase( i ); - } - else - { - graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast( instance ) ) ).first; + model->graph->erase( i ); + } + else + { + graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast( instance ) ) ).first; - graph_tree_model_row_inserted( model, i ); - } + graph_tree_model_row_inserted( model, i ); + } } void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){ - graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast( instance ) ) ).first; + graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast( instance ) ) ).first; - graph_tree_model_row_inserted( model, i ); + graph_tree_model_row_inserted( model, i ); - node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); + node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); } void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){ - node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); + node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); - graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) ); - ASSERT_MESSAGE( i != model->graph->end(), "ERROR" ); + graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) ); + ASSERT_MESSAGE( i != model->graph->end(), "ERROR" ); - graph_tree_model_row_deleted( model, i ); + graph_tree_model_row_deleted( model, i ); - model->graph->erase( i ); + model->graph->erase( i ); } #elif 1 class GraphTreeNode; -void graph_tree_model_row_changed( GraphTreeNode& node ); - -class GraphTreeNode -{ -typedef std::map, GraphTreeNode*> ChildNodes; -ChildNodes m_childnodes; -public: -Reference m_instance; -GraphTreeNode* m_parent; - -typedef ChildNodes::iterator iterator; -typedef ChildNodes::key_type key_type; -typedef ChildNodes::value_type value_type; -typedef ChildNodes::size_type size_type; - -GraphTreeNode( scene::Instance& instance ) : m_instance( instance ), m_parent( 0 ){ - m_instance.get().setChildSelectedChangedCallback( RowChangedCaller( *this ) ); -} -~GraphTreeNode(){ - m_instance.get().setChildSelectedChangedCallback( Callback() ); - ASSERT_MESSAGE( empty(), "GraphTreeNode::~GraphTreeNode: memory leak" ); -} - -iterator begin(){ - return m_childnodes.begin(); -} -iterator end(){ - return m_childnodes.end(); -} - -size_type size() const { - return m_childnodes.size(); -} -bool empty() const { - return m_childnodes.empty(); -} - -iterator insert( const value_type& value ){ - iterator i = m_childnodes.insert( value ).first; - ( *i ).second->m_parent = this; - return i; -} -void erase( iterator i ){ - m_childnodes.erase( i ); -} -iterator find( const key_type& key ){ - return m_childnodes.find( key ); -} -void swap( GraphTreeNode& other ){ - std::swap( m_parent, other.m_parent ); - std::swap( m_childnodes, other.m_childnodes ); - std::swap( m_instance, other.m_instance ); -} +void graph_tree_model_row_changed(GraphTreeNode &node); -void rowChanged(){ - graph_tree_model_row_changed( *this ); -} -typedef MemberCaller RowChangedCaller; +class GraphTreeNode { + typedef std::map, GraphTreeNode *> ChildNodes; + ChildNodes m_childnodes; +public: + Reference m_instance; + GraphTreeNode *m_parent; + + typedef ChildNodes::iterator iterator; + typedef ChildNodes::key_type key_type; + typedef ChildNodes::value_type value_type; + typedef ChildNodes::size_type size_type; + + GraphTreeNode(scene::Instance &instance) : m_instance(instance), m_parent(0) + { + m_instance.get().setChildSelectedChangedCallback(RowChangedCaller(*this)); + } + + ~GraphTreeNode() + { + m_instance.get().setChildSelectedChangedCallback(Callback()); + ASSERT_MESSAGE(empty(), "GraphTreeNode::~GraphTreeNode: memory leak"); + } + + iterator begin() + { + return m_childnodes.begin(); + } + + iterator end() + { + return m_childnodes.end(); + } + + size_type size() const + { + return m_childnodes.size(); + } + + bool empty() const + { + return m_childnodes.empty(); + } + + iterator insert(const value_type &value) + { + iterator i = m_childnodes.insert(value).first; + (*i).second->m_parent = this; + return i; + } + + void erase(iterator i) + { + m_childnodes.erase(i); + } + + iterator find(const key_type &key) + { + return m_childnodes.find(key); + } + + void swap(GraphTreeNode &other) + { + std::swap(m_parent, other.m_parent); + std::swap(m_childnodes, other.m_childnodes); + std::swap(m_instance, other.m_instance); + } + + void rowChanged() + { + graph_tree_model_row_changed(*this); + } + + typedef MemberCaller RowChangedCaller; }; -struct GraphTreeModel -{ - GObject parent; +struct GraphTreeModel { + GObject parent; - GraphTreeNode* m_graph; + GraphTreeNode *m_graph; }; -struct GraphTreeModelClass -{ - GObjectClass parent_class; +struct GraphTreeModelClass { + GObjectClass parent_class; }; -static GtkTreeModelFlags graph_tree_model_get_flags( ui::TreeModel tree_model ){ - return GTK_TREE_MODEL_ITERS_PERSIST; +static GtkTreeModelFlags graph_tree_model_get_flags(ui::TreeModel tree_model) +{ + return GTK_TREE_MODEL_ITERS_PERSIST; } -static gint graph_tree_model_get_n_columns( ui::TreeModel tree_model ){ - ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" ); - //GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model; +static gint graph_tree_model_get_n_columns(ui::TreeModel tree_model) +{ + ASSERT_MESSAGE(tree_model, "RUNTIME ERROR"); + //GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model; - return 2; + return 2; } static const gint c_stamp = 0xabcdef; -inline GraphTreeNode::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){ - ASSERT_MESSAGE( iter != 0, "tree model error" ); - ASSERT_MESSAGE( iter->user_data != 0, "tree model error" ); - ASSERT_MESSAGE( iter->stamp == c_stamp, "tree model error" ); - return *reinterpret_cast( &iter->user_data ); +inline GraphTreeNode::iterator graph_iterator_read_tree_iter(GtkTreeIter *iter) +{ + ASSERT_MESSAGE(iter != 0, "tree model error"); + ASSERT_MESSAGE(iter->user_data != 0, "tree model error"); + ASSERT_MESSAGE(iter->stamp == c_stamp, "tree model error"); + return *reinterpret_cast( &iter->user_data ); } -inline void graph_iterator_write_tree_iter( GraphTreeNode::iterator i, GtkTreeIter* iter ){ - ASSERT_MESSAGE( iter != 0, "tree model error" ); - iter->stamp = c_stamp; - *reinterpret_cast( &iter->user_data ) = i; - ASSERT_MESSAGE( iter->user_data != 0, "tree model error" ); +inline void graph_iterator_write_tree_iter(GraphTreeNode::iterator i, GtkTreeIter *iter) +{ + ASSERT_MESSAGE(iter != 0, "tree model error"); + iter->stamp = c_stamp; + *reinterpret_cast( &iter->user_data ) = i; + ASSERT_MESSAGE(iter->user_data != 0, "tree model error"); } -static GType graph_tree_model_get_column_type( ui::TreeModel tree_model, gint index ){ - ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" ); - //GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model; +static GType graph_tree_model_get_column_type(ui::TreeModel tree_model, gint index) +{ + ASSERT_MESSAGE(tree_model, "RUNTIME ERROR"); + //GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model; - return G_TYPE_POINTER; + return G_TYPE_POINTER; } -static gboolean graph_tree_model_get_iter( GraphTreeModel* tree_model, GtkTreeIter* iter, ui::TreePath path ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - gint* indices = gtk_tree_path_get_indices( path ); - gint depth = gtk_tree_path_get_depth( path ); +static gboolean graph_tree_model_get_iter(GraphTreeModel *tree_model, GtkTreeIter *iter, ui::TreePath path) +{ + ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR"); + gint *indices = gtk_tree_path_get_indices(path); + gint depth = gtk_tree_path_get_depth(path); - g_return_val_if_fail( depth > 0, FALSE ); + g_return_val_if_fail(depth > 0, FALSE); - GraphTreeNode *graph = tree_model->m_graph; + GraphTreeNode *graph = tree_model->m_graph; - if ( graph->empty() ) { - return FALSE; - } + if (graph->empty()) { + return FALSE; + } - GtkTreeIter tmp; - GtkTreeIter* parent = 0; + GtkTreeIter tmp; + GtkTreeIter *parent = 0; - for ( gint i = 0; i < depth; i++ ) - { - if ( !gtk_tree_model_iter_nth_child( GTK_TREE_MODEL(tree_model), iter, parent, indices[i] ) ) { - return FALSE; - } - tmp = *iter; - parent = &tmp; - } + for (gint i = 0; i < depth; i++) { + if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(tree_model), iter, parent, indices[i])) { + return FALSE; + } + tmp = *iter; + parent = &tmp; + } - return TRUE; + return TRUE; } -static ui::TreePath graph_tree_model_get_path( GraphTreeModel *tree_model, GtkTreeIter* iter ){ - ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" ); - GraphTreeNode* graph = tree_model->m_graph; +static ui::TreePath graph_tree_model_get_path(GraphTreeModel *tree_model, GtkTreeIter *iter) +{ + ASSERT_MESSAGE(tree_model, "RUNTIME ERROR"); + GraphTreeNode *graph = tree_model->m_graph; auto path = ui::TreePath(ui::New); - for ( GraphTreeNode* node = ( *graph_iterator_read_tree_iter( iter ) ).second; node != graph; node = node->m_parent ) - { - std::size_t index = 0; - for ( GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index ) - { - if ( ( *i ).second == node ) { - gtk_tree_path_prepend_index( path, gint( index ) ); - break; - } - } - ASSERT_MESSAGE( index != node->m_parent->size(), "error resolving tree path" ); - } + for (GraphTreeNode *node = (*graph_iterator_read_tree_iter(iter)).second; node != graph; node = node->m_parent) { + std::size_t index = 0; + for (GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index) { + if ((*i).second == node) { + gtk_tree_path_prepend_index(path, gint(index)); + break; + } + } + ASSERT_MESSAGE(index != node->m_parent->size(), "error resolving tree path"); + } - return path; + return path; } -static void graph_tree_model_get_value( ui::TreeModel tree_model, GtkTreeIter *iter, gint column, GValue *value ){ - ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" ); - ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" ); +static void graph_tree_model_get_value(ui::TreeModel tree_model, GtkTreeIter *iter, gint column, GValue *value) +{ + ASSERT_MESSAGE(tree_model, "RUNTIME ERROR"); + ASSERT_MESSAGE(column == 0 || column == 1, "tree model error"); - GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter ); + GraphTreeNode::iterator i = graph_iterator_read_tree_iter(iter); - g_value_init( value, G_TYPE_POINTER ); + g_value_init(value, G_TYPE_POINTER); - if ( column == 0 ) { - g_value_set_pointer( value, reinterpret_cast( ( *i ).first.second ) ); - } - else - { - g_value_set_pointer( value, reinterpret_cast( &( *i ).second->m_instance.get() ) ); - } + if (column == 0) { + g_value_set_pointer(value, reinterpret_cast((*i).first.second )); + } else { + g_value_set_pointer(value, reinterpret_cast( &(*i).second->m_instance.get())); + } } -static gboolean graph_tree_model_iter_next( ui::TreeModel tree_model, GtkTreeIter *iter ){ - ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" ); - GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter ); - GraphTreeNode& parent = *( *i ).second->m_parent; +static gboolean graph_tree_model_iter_next(ui::TreeModel tree_model, GtkTreeIter *iter) +{ + ASSERT_MESSAGE(tree_model, "RUNTIME ERROR"); + GraphTreeNode::iterator i = graph_iterator_read_tree_iter(iter); + GraphTreeNode &parent = *(*i).second->m_parent; - ASSERT_MESSAGE( i != parent.end(), "RUNTIME ERROR" ); + ASSERT_MESSAGE(i != parent.end(), "RUNTIME ERROR"); - if ( ++i == parent.end() ) { - return FALSE; - } + if (++i == parent.end()) { + return FALSE; + } - graph_iterator_write_tree_iter( i, iter ); + graph_iterator_write_tree_iter(i, iter); - return TRUE; + return TRUE; } -static gboolean graph_tree_model_iter_children( GraphTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - GraphTreeNode& node = ( parent == 0 ) ? *tree_model->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second; - if ( !node.empty() ) { - graph_iterator_write_tree_iter( node.begin(), iter ); - return TRUE; - } +static gboolean graph_tree_model_iter_children(GraphTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) +{ + ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR"); + GraphTreeNode &node = (parent == 0) ? *tree_model->m_graph : *(*graph_iterator_read_tree_iter(parent)).second; + if (!node.empty()) { + graph_iterator_write_tree_iter(node.begin(), iter); + return TRUE; + } - return FALSE; + return FALSE; } -static gboolean graph_tree_model_iter_has_child( ui::TreeModel tree_model, GtkTreeIter *iter ){ - ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" ); - GraphTreeNode& node = *( *graph_iterator_read_tree_iter( iter ) ).second; - return !node.empty(); -} - -static gint graph_tree_model_iter_n_children( GraphTreeModel *tree_model, GtkTreeIter *parent ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - GraphTreeNode& node = ( parent == 0 ) ? *tree_model->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second; - return static_cast( node.size() ); -} - -static gboolean graph_tree_model_iter_nth_child( GraphTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - GraphTreeNode& node = ( parent == 0 ) ? *tree_model->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second; - if ( static_cast( n ) < node.size() ) { - GraphTreeNode::iterator i = node.begin(); - std::advance( i, n ); - graph_iterator_write_tree_iter( i, iter ); - return TRUE; - } - - return FALSE; -} - -static gboolean graph_tree_model_iter_parent( GraphTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child ){ - ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" ); - GraphTreeNode& node = *( *graph_iterator_read_tree_iter( child ) ).second; - if ( node.m_parent != tree_model->m_graph ) { - GraphTreeNode& parentParent = *node.m_parent->m_parent; - for ( GraphTreeNode::iterator i = parentParent.begin(); i != parentParent.end(); ++i ) - { - if ( ( *i ).second == node.m_parent ) { - graph_iterator_write_tree_iter( i, iter ); - return TRUE; - } - } - } - return FALSE; +static gboolean graph_tree_model_iter_has_child(ui::TreeModel tree_model, GtkTreeIter *iter) +{ + ASSERT_MESSAGE(tree_model, "RUNTIME ERROR"); + GraphTreeNode &node = *(*graph_iterator_read_tree_iter(iter)).second; + return !node.empty(); } -static GObjectClass *g_parent_class = 0; - -namespace +static gint graph_tree_model_iter_n_children(GraphTreeModel *tree_model, GtkTreeIter *parent) { -scene::Node* g_null_node = 0; + ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR"); + GraphTreeNode &node = (parent == 0) ? *tree_model->m_graph : *(*graph_iterator_read_tree_iter(parent)).second; + return static_cast( node.size()); } -class NullInstance : public scene::Instance +static gboolean +graph_tree_model_iter_nth_child(GraphTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n) { -public: -NullInstance() : scene::Instance( scene::Path( makeReference( *g_null_node ) ), 0, 0, Static::instance() ){ + ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR"); + GraphTreeNode &node = (parent == 0) ? *tree_model->m_graph : *(*graph_iterator_read_tree_iter(parent)).second; + if (static_cast( n ) < node.size()) { + GraphTreeNode::iterator i = node.begin(); + std::advance(i, n); + graph_iterator_write_tree_iter(i, iter); + return TRUE; + } + + return FALSE; } -}; -namespace +static gboolean graph_tree_model_iter_parent(GraphTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child) { -NullInstance g_null_instance; + ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR"); + GraphTreeNode &node = *(*graph_iterator_read_tree_iter(child)).second; + if (node.m_parent != tree_model->m_graph) { + GraphTreeNode &parentParent = *node.m_parent->m_parent; + for (GraphTreeNode::iterator i = parentParent.begin(); i != parentParent.end(); ++i) { + if ((*i).second == node.m_parent) { + graph_iterator_write_tree_iter(i, iter); + return TRUE; + } + } + } + return FALSE; } -static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){ - graph_tree_model->m_graph = new GraphTreeNode( g_null_instance ); +static GObjectClass *g_parent_class = 0; + +namespace { + scene::Node *g_null_node = 0; } -static void graph_tree_model_finalize( GObject* object ){ - auto graph_tree_model = reinterpret_cast(object); +class NullInstance : public scene::Instance { +public: + NullInstance() : scene::Instance(scene::Path(makeReference(*g_null_node)), 0, 0, + Static::instance()) + { + } +}; - delete graph_tree_model->m_graph; +namespace { + NullInstance g_null_instance; +} - /* must chain up */ - ( *g_parent_class->finalize )( object ); +static void graph_tree_model_init(GraphTreeModel *graph_tree_model) +{ + graph_tree_model->m_graph = new GraphTreeNode(g_null_instance); } -static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){ - GObjectClass *object_class; +static void graph_tree_model_finalize(GObject *object) +{ + auto graph_tree_model = reinterpret_cast(object); - g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ ); - object_class = (GObjectClass *) class_; + delete graph_tree_model->m_graph; - object_class->finalize = graph_tree_model_finalize; + /* must chain up */ + (*g_parent_class->finalize)(object); } -static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){ - iface->get_flags = reinterpret_cast(graph_tree_model_get_flags); - iface->get_n_columns = reinterpret_cast(graph_tree_model_get_n_columns); - iface->get_column_type = reinterpret_cast(graph_tree_model_get_column_type); - iface->get_iter = reinterpret_cast(graph_tree_model_get_iter); - iface->get_path = reinterpret_cast(graph_tree_model_get_path); - iface->get_value = reinterpret_cast(graph_tree_model_get_value); - iface->iter_next = reinterpret_cast(graph_tree_model_iter_next); - iface->iter_children = reinterpret_cast(graph_tree_model_iter_children); - iface->iter_has_child = reinterpret_cast(graph_tree_model_iter_has_child); - iface->iter_n_children = reinterpret_cast(graph_tree_model_iter_n_children); - iface->iter_nth_child = reinterpret_cast(graph_tree_model_iter_nth_child); - iface->iter_parent = reinterpret_cast(graph_tree_model_iter_parent); -} +static void graph_tree_model_class_init(GraphTreeModelClass *class_) +{ + GObjectClass *object_class; -GType graph_tree_model_get_type( void ){ - static GType graph_tree_model_type = 0; - - if ( !graph_tree_model_type ) { - static const GTypeInfo graph_tree_model_info = - { - sizeof( GraphTreeModelClass ), - 0, /* base_init */ - 0, /* base_finalize */ - (GClassInitFunc) graph_tree_model_class_init, - 0, /* class_finalize */ - 0, /* class_data */ - sizeof( GraphTreeModel ), - 0, /* n_preallocs */ - (GInstanceInitFunc) graph_tree_model_init, - 0 - }; - - static const GInterfaceInfo tree_model_info = - { - (GInterfaceInitFunc) graph_tree_model_tree_model_init, - 0, - 0 - }; - - graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel", - &graph_tree_model_info, (GTypeFlags)0 ); - - g_type_add_interface_static( graph_tree_model_type, - GTK_TYPE_TREE_MODEL, - &tree_model_info ); - } - - return graph_tree_model_type; + g_parent_class = (GObjectClass *) g_type_class_peek_parent(class_); + object_class = (GObjectClass *) class_; + + object_class->finalize = graph_tree_model_finalize; } -GraphTreeModel* graph_tree_model_new(){ - auto graph_tree_model = reinterpret_cast(g_object_new( graph_tree_model_get_type(), 0 )); +static void graph_tree_model_tree_model_init(GtkTreeModelIface *iface) +{ + iface->get_flags = reinterpret_cast(graph_tree_model_get_flags); + iface->get_n_columns = reinterpret_cast(graph_tree_model_get_n_columns); + iface->get_column_type = reinterpret_cast(graph_tree_model_get_column_type); + iface->get_iter = reinterpret_cast(graph_tree_model_get_iter); + iface->get_path = reinterpret_cast(graph_tree_model_get_path); + iface->get_value = reinterpret_cast(graph_tree_model_get_value); + iface->iter_next = reinterpret_cast(graph_tree_model_iter_next); + iface->iter_children = reinterpret_cast(graph_tree_model_iter_children); + iface->iter_has_child = reinterpret_cast(graph_tree_model_iter_has_child); + iface->iter_n_children = reinterpret_cast(graph_tree_model_iter_n_children); + iface->iter_nth_child = reinterpret_cast(graph_tree_model_iter_nth_child); + iface->iter_parent = reinterpret_cast(graph_tree_model_iter_parent); +} + +GType graph_tree_model_get_type(void) +{ + static GType graph_tree_model_type = 0; + + if (!graph_tree_model_type) { + static const GTypeInfo graph_tree_model_info = + { + sizeof(GraphTreeModelClass), + 0, /* base_init */ + 0, /* base_finalize */ + (GClassInitFunc) graph_tree_model_class_init, + 0, /* class_finalize */ + 0, /* class_data */ + sizeof(GraphTreeModel), + 0, /* n_preallocs */ + (GInstanceInitFunc) graph_tree_model_init, + 0 + }; + + static const GInterfaceInfo tree_model_info = + { + (GInterfaceInitFunc) graph_tree_model_tree_model_init, + 0, + 0 + }; + + graph_tree_model_type = g_type_register_static(G_TYPE_OBJECT, "GraphTreeModel", + &graph_tree_model_info, (GTypeFlags) 0); + + g_type_add_interface_static(graph_tree_model_type, + GTK_TYPE_TREE_MODEL, + &tree_model_info); + } + + return graph_tree_model_type; +} + +GraphTreeModel *graph_tree_model_new() +{ + auto graph_tree_model = reinterpret_cast(g_object_new(graph_tree_model_get_type(), 0)); - return graph_tree_model; + return graph_tree_model; } -void graph_tree_model_delete( GraphTreeModel* model ){ - g_object_unref( G_OBJECT( model ) ); +void graph_tree_model_delete(GraphTreeModel *model) +{ + g_object_unref(G_OBJECT(model)); } -void graph_tree_model_row_changed( GraphTreeModel* model, GraphTreeNode::iterator i ){ - GtkTreeIter iter; - graph_iterator_write_tree_iter( i, &iter ); +void graph_tree_model_row_changed(GraphTreeModel *model, GraphTreeNode::iterator i) +{ + GtkTreeIter iter; + graph_iterator_write_tree_iter(i, &iter); - auto tree_path = graph_tree_model_get_path(model, &iter ); + auto tree_path = graph_tree_model_get_path(model, &iter); - gtk_tree_model_row_changed( GTK_TREE_MODEL( model ), tree_path, &iter ); + gtk_tree_model_row_changed(GTK_TREE_MODEL(model), tree_path, &iter); - gtk_tree_path_free( tree_path ); + gtk_tree_path_free(tree_path); } -void graph_tree_model_row_inserted( GraphTreeModel* model, GraphTreeNode::iterator i ){ - GtkTreeIter iter; - graph_iterator_write_tree_iter( i, &iter ); +void graph_tree_model_row_inserted(GraphTreeModel *model, GraphTreeNode::iterator i) +{ + GtkTreeIter iter; + graph_iterator_write_tree_iter(i, &iter); - auto tree_path = graph_tree_model_get_path(model, &iter ); + auto tree_path = graph_tree_model_get_path(model, &iter); - gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter ); + gtk_tree_model_row_inserted(GTK_TREE_MODEL(model), tree_path, &iter); - gtk_tree_path_free( tree_path ); + gtk_tree_path_free(tree_path); } -void graph_tree_model_row_deleted( GraphTreeModel* model, GraphTreeNode::iterator i ){ - GtkTreeIter iter; - graph_iterator_write_tree_iter( i, &iter ); +void graph_tree_model_row_deleted(GraphTreeModel *model, GraphTreeNode::iterator i) +{ + GtkTreeIter iter; + graph_iterator_write_tree_iter(i, &iter); - auto tree_path = graph_tree_model_get_path(model, &iter ); + auto tree_path = graph_tree_model_get_path(model, &iter); - gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path ); + gtk_tree_model_row_deleted(GTK_TREE_MODEL(model), tree_path); - gtk_tree_path_free( tree_path ); + gtk_tree_path_free(tree_path); } -void graph_tree_model_row_inserted( GraphTreeModel& model, GraphTreeNode::iterator i ){ - graph_tree_model_row_inserted( &model, i ); +void graph_tree_model_row_inserted(GraphTreeModel &model, GraphTreeNode::iterator i) +{ + graph_tree_model_row_inserted(&model, i); } -void graph_tree_model_row_deleted( GraphTreeModel& model, GraphTreeNode::iterator i ){ - graph_tree_model_row_deleted( &model, i ); +void graph_tree_model_row_deleted(GraphTreeModel &model, GraphTreeNode::iterator i) +{ + graph_tree_model_row_deleted(&model, i); } -const char* node_get_name( scene::Node& node ); +const char *node_get_name(scene::Node &node); -const char* node_get_name_safe( scene::Node& node ){ - volatile intptr_t n = (intptr_t)&node; // see the comment on line 650 - if ( n == 0 ) { - return ""; - } - return node_get_name( node ); +const char *node_get_name_safe(scene::Node &node) +{ + volatile intptr_t n = (intptr_t) &node; // see the comment on line 650 + if (n == 0) { + return ""; + } + return node_get_name(node); } -GraphTreeNode* graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path ){ - GraphTreeNode* parent = model->m_graph; - for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i ) - { - GraphTreeNode::iterator child = parent->find( GraphTreeNode::key_type( node_get_name_safe( ( *i ).get() ), ( *i ).get_pointer() ) ); - ASSERT_MESSAGE( child != parent->end(), "ERROR" ); - parent = ( *child ).second; - } - return parent; +GraphTreeNode *graph_tree_model_find_parent(GraphTreeModel *model, const scene::Path &path) +{ + GraphTreeNode *parent = model->m_graph; + for (scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i) { + GraphTreeNode::iterator child = parent->find( + GraphTreeNode::key_type(node_get_name_safe((*i).get()), (*i).get_pointer())); + ASSERT_MESSAGE(child != parent->end(), "ERROR"); + parent = (*child).second; + } + return parent; } -void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){ - volatile intptr_t n = (intptr_t)&node; // see the comment on line 650 - if ( n != 0 ) { - Nameable* nameable = Node_getNameable( node ); - if ( nameable != 0 ) { - nameable->attach( callback ); - } - } +void node_attach_name_changed_callback(scene::Node &node, const NameCallback &callback) +{ + volatile intptr_t n = (intptr_t) &node; // see the comment on line 650 + if (n != 0) { + Nameable *nameable = Node_getNameable(node); + if (nameable != 0) { + nameable->attach(callback); + } + } } -void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){ - volatile intptr_t n = (intptr_t)&node; // see the comment on line 650 - if ( n != 0 ) { - Nameable* nameable = Node_getNameable( node ); - if ( nameable != 0 ) { - nameable->detach( callback ); - } - } + +void node_detach_name_changed_callback(scene::Node &node, const NameCallback &callback) +{ + volatile intptr_t n = (intptr_t) &node; // see the comment on line 650 + if (n != 0) { + Nameable *nameable = Node_getNameable(node); + if (nameable != 0) { + nameable->detach(callback); + } + } } -GraphTreeModel* scene_graph_get_tree_model(); // temp hack +GraphTreeModel *scene_graph_get_tree_model(); // temp hack -void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback& callback ){ - callback( root ); - for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i ) - { - graph_tree_node_foreach_pre( i, callback ); - } +void graph_tree_node_foreach_pre(GraphTreeNode::iterator root, const Callback &callback) +{ + callback(root); + for (GraphTreeNode::iterator i = (*root).second->begin(); i != (*root).second->end(); ++i) { + graph_tree_node_foreach_pre(i, callback); + } } -void graph_tree_node_foreach_post( GraphTreeNode::iterator root, const Callback& callback ){ - for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i ) - { - graph_tree_node_foreach_post( i, callback ); - } - callback( root ); +void graph_tree_node_foreach_post(GraphTreeNode::iterator root, const Callback &callback) +{ + for (GraphTreeNode::iterator i = (*root).second->begin(); i != (*root).second->end(); ++i) { + graph_tree_node_foreach_post(i, callback); + } + callback(root); } -void graph_tree_model_row_changed( GraphTreeNode& node ){ - GraphTreeModel* model = scene_graph_get_tree_model(); - const scene::Instance& instance = node.m_instance.get(); +void graph_tree_model_row_changed(GraphTreeNode &node) +{ + GraphTreeModel *model = scene_graph_get_tree_model(); + const scene::Instance &instance = node.m_instance.get(); - GraphTreeNode::iterator i = node.m_parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) ); + GraphTreeNode::iterator i = node.m_parent->find( + GraphTreeNode::key_type(node_get_name_safe(instance.path().top().get()), + instance.path().top().get_pointer())); - graph_tree_model_row_changed( model, i ); + graph_tree_model_row_changed(model, i); } -void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){ - GraphTreeModel* model = scene_graph_get_tree_model(); - GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() ); +void graph_tree_model_set_name(const scene::Instance &instance, const char *name) +{ + GraphTreeModel *model = scene_graph_get_tree_model(); + GraphTreeNode *parent = graph_tree_model_find_parent(model, instance.path()); - GraphTreeNode::iterator oldNode = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) ); - graph_tree_node_foreach_post( oldNode, ReferenceCaller( *model ) ); - GraphTreeNode* node( ( *oldNode ).second ); - parent->erase( oldNode ); + GraphTreeNode::iterator oldNode = parent->find( + GraphTreeNode::key_type(node_get_name_safe(instance.path().top().get()), + instance.path().top().get_pointer())); + graph_tree_node_foreach_post(oldNode, ReferenceCaller(*model)); + GraphTreeNode *node((*oldNode).second); + parent->erase(oldNode); - GraphTreeNode::iterator newNode = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( name, &instance.path().top().get() ), node ) ); - graph_tree_node_foreach_pre( newNode, ReferenceCaller( *model ) ); + GraphTreeNode::iterator newNode = parent->insert( + GraphTreeNode::value_type(GraphTreeNode::key_type(name, &instance.path().top().get()), node)); + graph_tree_node_foreach_pre(newNode, ReferenceCaller(*model)); } -void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){ - GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() ); +void graph_tree_model_insert(GraphTreeModel *model, const scene::Instance &instance) +{ + GraphTreeNode *parent = graph_tree_model_find_parent(model, instance.path()); - GraphTreeNode::iterator i = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ), new GraphTreeNode( const_cast( instance ) ) ) ); + GraphTreeNode::iterator i = parent->insert(GraphTreeNode::value_type( + GraphTreeNode::key_type(node_get_name_safe(instance.path().top().get()), + instance.path().top().get_pointer()), + new GraphTreeNode(const_cast( instance )))); - graph_tree_model_row_inserted( model, i ); + graph_tree_model_row_inserted(model, i); - node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); + node_attach_name_changed_callback(instance.path().top(), ConstReferenceCaller(instance)); } -void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){ - node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller( instance ) ); +void graph_tree_model_erase(GraphTreeModel *model, const scene::Instance &instance) +{ + node_detach_name_changed_callback(instance.path().top(), ConstReferenceCaller(instance)); - GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() ); + GraphTreeNode *parent = graph_tree_model_find_parent(model, instance.path()); - GraphTreeNode::iterator i = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) ); + GraphTreeNode::iterator i = parent->find(GraphTreeNode::key_type(node_get_name_safe(instance.path().top().get()), + instance.path().top().get_pointer())); - graph_tree_model_row_deleted( model, i ); + graph_tree_model_row_deleted(model, i); - GraphTreeNode* node( ( *i ).second ); - parent->erase( i ); - delete node; + GraphTreeNode *node((*i).second); + parent->erase(i); + delete node; } - #endif - - #if 0 class TestGraphTreeModel { public: TestGraphTreeModel(){ - gtk_init( 0, 0 ); + gtk_init( 0, 0 ); - graph_type graph; + graph_type graph; - scene::Node* root = *(scene::Node*)0xa0000000; - scene::Node* node1 = (scene::Node*)0xa0000001; - scene::Node* node2 = (scene::Node*)0xa0000002; - scene::Node* node3 = (scene::Node*)0xa0000003; - scene::Node* node4 = (scene::Node*)0xa0000004; - scene::Instance* instance = (scene::Instance*)0xaaaaaaaa; + scene::Node* root = *(scene::Node*)0xa0000000; + scene::Node* node1 = (scene::Node*)0xa0000001; + scene::Node* node2 = (scene::Node*)0xa0000002; + scene::Node* node3 = (scene::Node*)0xa0000003; + scene::Node* node4 = (scene::Node*)0xa0000004; + scene::Instance* instance = (scene::Instance*)0xaaaaaaaa; - scene::Path rootpath( root ); + scene::Path rootpath( root ); - graph.insert( graph_type::value_type( rootpath, instance ) ); + graph.insert( graph_type::value_type( rootpath, instance ) ); - rootpath.push( node1 ); - graph.insert( graph_type::value_type( rootpath, instance ) ); - rootpath.pop(); + rootpath.push( node1 ); + graph.insert( graph_type::value_type( rootpath, instance ) ); + rootpath.pop(); - rootpath.push( node2 ); - graph.insert( graph_type::value_type( rootpath, instance ) ); - rootpath.push( node3 ); - graph.insert( graph_type::value_type( rootpath, instance ) ); - rootpath.pop(); - rootpath.push( node4 ); - graph.insert( graph_type::value_type( rootpath, instance ) ); - rootpath.pop(); - rootpath.pop(); + rootpath.push( node2 ); + graph.insert( graph_type::value_type( rootpath, instance ) ); + rootpath.push( node3 ); + graph.insert( graph_type::value_type( rootpath, instance ) ); + rootpath.pop(); + rootpath.push( node4 ); + graph.insert( graph_type::value_type( rootpath, instance ) ); + rootpath.pop(); + rootpath.pop(); - auto model = graph_tree_model_new( &graph ); + auto model = graph_tree_model_new( &graph ); - { - gint n_columns = gtk_tree_model_get_n_columns( model ); - ASSERT_MESSAGE( n_columns == 2, "test failed!" ); - } + { + gint n_columns = gtk_tree_model_get_n_columns( model ); + ASSERT_MESSAGE( n_columns == 2, "test failed!" ); + } - { - GType type = gtk_tree_model_get_column_type( model, 0 ); - ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" ); - } + { + GType type = gtk_tree_model_get_column_type( model, 0 ); + ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" ); + } - { - GType type = gtk_tree_model_get_column_type( model, 1 ); - ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" ); - } + { + GType type = gtk_tree_model_get_column_type( model, 1 ); + ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" ); + } - { - GtkTreeIter iter; - gtk_tree_model_get_iter_first( model, &iter ); + { + GtkTreeIter iter; + gtk_tree_model_get_iter_first( model, &iter ); - graph_type::iterator i = graph_iterator_read_tree_iter( &iter ); - ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" ); - } + graph_type::iterator i = graph_iterator_read_tree_iter( &iter ); + ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" ); + } - { - GtkTreeIter iter; - gtk_tree_model_get_iter_first( model, &iter ); + { + GtkTreeIter iter; + gtk_tree_model_get_iter_first( model, &iter ); - ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) == FALSE, "test failed!" ); + ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) == FALSE, "test failed!" ); - ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 0, "test failed!" ); + ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 0, "test failed!" ); - gtk_tree_model_iter_next( model, &iter ); + gtk_tree_model_iter_next( model, &iter ); - ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) != FALSE, "test failed!" ); + ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) != FALSE, "test failed!" ); - ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 2, "test failed!" ); + ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 2, "test failed!" ); - { - GtkTreeIter child; - gtk_tree_model_iter_nth_child( model, &child, &iter, 0 ); + { + GtkTreeIter child; + gtk_tree_model_iter_nth_child( model, &child, &iter, 0 ); - scene::Node* test; - gtk_tree_model_get_value( model, &child, 0, (GValue*)&test ); - ASSERT_MESSAGE( test == node3, "test failed!" ); + scene::Node* test; + gtk_tree_model_get_value( model, &child, 0, (GValue*)&test ); + ASSERT_MESSAGE( test == node3, "test failed!" ); - { - GtkTreeIter parent; - gtk_tree_model_iter_parent( model, &parent, &child ); + { + GtkTreeIter parent; + gtk_tree_model_iter_parent( model, &parent, &child ); - scene::Node* test; - gtk_tree_model_get_value( model, &parent, 0, (GValue*)&test ); - ASSERT_MESSAGE( test == node2, "test failed!" ); - } - } + scene::Node* test; + gtk_tree_model_get_value( model, &parent, 0, (GValue*)&test ); + ASSERT_MESSAGE( test == node2, "test failed!" ); + } + } - { - GtkTreeIter child; - gtk_tree_model_iter_nth_child( model, &child, &iter, 1 ); + { + GtkTreeIter child; + gtk_tree_model_iter_nth_child( model, &child, &iter, 1 ); - scene::Node* test; - gtk_tree_model_get_value( model, &child, 0, (GValue*)&test ); - ASSERT_MESSAGE( test == node4, "test failed!" ); - } - } + scene::Node* test; + gtk_tree_model_get_value( model, &child, 0, (GValue*)&test ); + ASSERT_MESSAGE( test == node4, "test failed!" ); + } + } - { - GtkTreeIter iter; - std::size_t count = 0; - for ( gboolean good = gtk_tree_model_get_iter_first( model, &iter ); good; good = gtk_tree_model_iter_next( model, &iter ) ) - { - scene::Node* test; - gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test ); + { + GtkTreeIter iter; + std::size_t count = 0; + for ( gboolean good = gtk_tree_model_get_iter_first( model, &iter ); good; good = gtk_tree_model_iter_next( model, &iter ) ) + { + scene::Node* test; + gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test ); - ASSERT_MESSAGE( ( count == 0 && test == node1 ) || ( count == 1 && test == node2 ), "test failed!" ); - ++count; - } + ASSERT_MESSAGE( ( count == 0 && test == node1 ) || ( count == 1 && test == node2 ), "test failed!" ); + ++count; + } - ASSERT_MESSAGE( count == 2, "test failed!" ); + ASSERT_MESSAGE( count == 2, "test failed!" ); - } + } - { - GtkTreeIter iter; - gtk_tree_model_get_iter_first( model, &iter ); + { + GtkTreeIter iter; + gtk_tree_model_get_iter_first( model, &iter ); - scene::Node* test; - gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test ); - ASSERT_MESSAGE( test == node1, "test failed!" ); - } + scene::Node* test; + gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test ); + ASSERT_MESSAGE( test == node1, "test failed!" ); + } - { - GtkTreeIter iter; - auto path = ui::TreePath( "0" ); - gtk_tree_model_get_iter( model, &iter, path ); - gtk_tree_path_free( path ); + { + GtkTreeIter iter; + auto path = ui::TreePath( "0" ); + gtk_tree_model_get_iter( model, &iter, path ); + gtk_tree_path_free( path ); - graph_type::iterator i = graph_iterator_read_tree_iter( &iter ); - ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" ); - } + graph_type::iterator i = graph_iterator_read_tree_iter( &iter ); + ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" ); + } - { - GtkTreeIter iter; - auto path = ui::TreePath( "1" ); - gtk_tree_model_get_iter( model, &iter, path ); - gtk_tree_path_free( path ); + { + GtkTreeIter iter; + auto path = ui::TreePath( "1" ); + gtk_tree_model_get_iter( model, &iter, path ); + gtk_tree_path_free( path ); - graph_type::iterator i = graph_iterator_read_tree_iter( &iter ); - ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node2, "test failed!" ); - } + graph_type::iterator i = graph_iterator_read_tree_iter( &iter ); + ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node2, "test failed!" ); + } - { - GtkTreeIter iter; - graph_type::iterator i = graph.begin(); - ++i; - graph_iterator_write_tree_iter( i, &iter ); + { + GtkTreeIter iter; + graph_type::iterator i = graph.begin(); + ++i; + graph_iterator_write_tree_iter( i, &iter ); - auto path = gtk_tree_model_get_path( model, &iter ); + auto path = gtk_tree_model_get_path( model, &iter ); - gint depth = gtk_tree_path_get_depth( path ); - gint* indices = gtk_tree_path_get_indices( path ); + gint depth = gtk_tree_path_get_depth( path ); + gint* indices = gtk_tree_path_get_indices( path ); - ASSERT_MESSAGE( depth == 1 && indices[0] == 0, "test failed!" ); + ASSERT_MESSAGE( depth == 1 && indices[0] == 0, "test failed!" ); - gtk_tree_path_free( path ); - } + gtk_tree_path_free( path ); + } - { - GtkTreeIter iter; - graph_type::iterator i = graph.begin(); - ++i; - ++i; - graph_iterator_write_tree_iter( i, &iter ); + { + GtkTreeIter iter; + graph_type::iterator i = graph.begin(); + ++i; + ++i; + graph_iterator_write_tree_iter( i, &iter ); - auto path = gtk_tree_model_get_path( model, &iter ); + auto path = gtk_tree_model_get_path( model, &iter ); - gint depth = gtk_tree_path_get_depth( path ); - gint* indices = gtk_tree_path_get_indices( path ); - - ASSERT_MESSAGE( depth == 1 && indices[0] == 1, "test failed!" ); + gint depth = gtk_tree_path_get_depth( path ); + gint* indices = gtk_tree_path_get_indices( path ); + + ASSERT_MESSAGE( depth == 1 && indices[0] == 1, "test failed!" ); - gtk_tree_path_free( path ); - } + gtk_tree_path_free( path ); + } } }; diff --git a/radiant/treemodel.h b/radiant/treemodel.h index 5e8b58b5..a533f3e2 100644 --- a/radiant/treemodel.h +++ b/radiant/treemodel.h @@ -24,14 +24,16 @@ struct GraphTreeModel; -GraphTreeModel* graph_tree_model_new(); -void graph_tree_model_delete( GraphTreeModel* model ); +GraphTreeModel *graph_tree_model_new(); -namespace scene -{ -class Instance; +void graph_tree_model_delete(GraphTreeModel *model); + +namespace scene { + class Instance; } -void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ); -void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ); + +void graph_tree_model_insert(GraphTreeModel *model, const scene::Instance &instance); + +void graph_tree_model_erase(GraphTreeModel *model, const scene::Instance &instance); #endif diff --git a/radiant/undo.cpp b/radiant/undo.cpp index fb741abd..dd92e8ab 100644 --- a/radiant/undo.cpp +++ b/radiant/undo.cpp @@ -37,397 +37,486 @@ #include "timer.h" -class DebugScopeTimer -{ -Timer m_timer; -const char* m_operation; +class DebugScopeTimer { + Timer m_timer; + const char *m_operation; public: -DebugScopeTimer( const char* operation ) - : m_operation( operation ){ - m_timer.start(); -} -~DebugScopeTimer(){ - unsigned int elapsed = m_timer.elapsed_msec(); - if ( elapsed > 0 ) { - globalOutputStream() << m_operation << ": " << elapsed << " msec\n"; - } -} + DebugScopeTimer(const char *operation) + : m_operation(operation) + { + m_timer.start(); + } + + ~DebugScopeTimer() + { + unsigned int elapsed = m_timer.elapsed_msec(); + if (elapsed > 0) { + globalOutputStream() << m_operation << ": " << elapsed << " msec\n"; + } + } }; -class RadiantUndoSystem : public UndoSystem -{ -UINT_CONSTANT( MAX_UNDO_LEVELS, 1024 ); +class RadiantUndoSystem : public UndoSystem { + UINT_CONSTANT(MAX_UNDO_LEVELS, 1024); + + class Snapshot { + class StateApplicator { + public: + Undoable *m_undoable; + private: + UndoMemento *m_data; + public: + + StateApplicator(Undoable *undoable, UndoMemento *data) + : m_undoable(undoable), m_data(data) + { + } + + void restore() + { + m_undoable->importState(m_data); + } + + void release() + { + m_data->release(); + } + }; + + typedef std::list states_t; + states_t m_states; + + public: + bool empty() const + { + return m_states.empty(); + } + + std::size_t size() const + { + return m_states.size(); + } + + void save(Undoable *undoable) + { + m_states.push_front(StateApplicator(undoable, undoable->exportState())); + } + + void restore() + { + for (states_t::iterator i = m_states.begin(); i != m_states.end(); ++i) { + (*i).restore(); + } + } + + void release() + { + for (states_t::iterator i = m_states.begin(); i != m_states.end(); ++i) { + (*i).release(); + } + } + }; + + struct Operation { + Snapshot m_snapshot; + CopiedString m_command; + + Operation(const char *command) + : m_command(command) + { + } + + ~Operation() + { + m_snapshot.release(); + } + }; + + + class UndoStack { +//! Note: using std::list instead of vector/deque, to avoid copying of undos + typedef std::list Operations; + + Operations m_stack; + Operation *m_pending; + + public: + UndoStack() : m_pending(0) + { + } + + ~UndoStack() + { + clear(); + } + + bool empty() const + { + return m_stack.empty(); + } + + std::size_t size() const + { + return m_stack.size(); + } + + Operation *back() + { + return m_stack.back(); + } + + const Operation *back() const + { + return m_stack.back(); + } + + Operation *front() + { + return m_stack.front(); + } + + const Operation *front() const + { + return m_stack.front(); + } + + void pop_front() + { + delete m_stack.front(); + m_stack.pop_front(); + } + + void pop_back() + { + delete m_stack.back(); + m_stack.pop_back(); + } + + void clear() + { + if (!m_stack.empty()) { + for (Operations::iterator i = m_stack.begin(); i != m_stack.end(); ++i) { + delete *i; + } + m_stack.clear(); + } + } + + void start(const char *command) + { + if (m_pending != 0) { + delete m_pending; + } + m_pending = new Operation(command); + } + + bool finish(const char *command) + { + if (m_pending != 0) { + delete m_pending; + m_pending = 0; + return false; + } else { + ASSERT_MESSAGE(!m_stack.empty(), "undo stack empty"); + m_stack.back()->m_command = command; + return true; + } + } + + void save(Undoable *undoable) + { + if (m_pending != 0) { + m_stack.push_back(m_pending); + m_pending = 0; + } + back()->m_snapshot.save(undoable); + } + }; + + UndoStack m_undo_stack; + UndoStack m_redo_stack; + + class UndoStackFiller : public UndoObserver { + UndoStack *m_stack; + public: + + UndoStackFiller() + : m_stack(0) + { + } + + void save(Undoable *undoable) + { + ASSERT_NOTNULL(undoable); + + if (m_stack != 0) { + m_stack->save(undoable); + m_stack = 0; + } + } + + void setStack(UndoStack *stack) + { + m_stack = stack; + } + }; + + typedef std::map undoables_t; + undoables_t m_undoables; + + void mark_undoables(UndoStack *stack) + { + for (undoables_t::iterator i = m_undoables.begin(); i != m_undoables.end(); ++i) { + (*i).second.setStack(stack); + } + } -class Snapshot -{ -class StateApplicator -{ -public: -Undoable* m_undoable; -private: -UndoMemento* m_data; + std::size_t m_undo_levels; + + typedef std::set Trackers; + Trackers m_trackers; public: + RadiantUndoSystem() + : m_undo_levels(64) + { + } -StateApplicator( Undoable* undoable, UndoMemento* data ) - : m_undoable( undoable ), m_data( data ){ -} -void restore(){ - m_undoable->importState( m_data ); -} -void release(){ - m_data->release(); -} -}; + ~RadiantUndoSystem() + { + clear(); + } -typedef std::list states_t; -states_t m_states; + UndoObserver *observer(Undoable *undoable) + { + ASSERT_NOTNULL(undoable); -public: -bool empty() const { - return m_states.empty(); -} -std::size_t size() const { - return m_states.size(); -} -void save( Undoable* undoable ){ - m_states.push_front( StateApplicator( undoable, undoable->exportState() ) ); -} -void restore(){ - for ( states_t::iterator i = m_states.begin(); i != m_states.end(); ++i ) - { - ( *i ).restore(); - } -} -void release(){ - for ( states_t::iterator i = m_states.begin(); i != m_states.end(); ++i ) - { - ( *i ).release(); - } -} -}; + return &m_undoables[undoable]; + } -struct Operation -{ - Snapshot m_snapshot; - CopiedString m_command; - - Operation( const char* command ) - : m_command( command ){ - } - ~Operation(){ - m_snapshot.release(); - } -}; + void release(Undoable *undoable) + { + ASSERT_NOTNULL(undoable); + m_undoables.erase(undoable); + } -class UndoStack -{ -//! Note: using std::list instead of vector/deque, to avoid copying of undos -typedef std::list Operations; + void setLevels(std::size_t levels) + { + if (levels > MAX_UNDO_LEVELS()) { + levels = MAX_UNDO_LEVELS(); + } -Operations m_stack; -Operation* m_pending; + while (m_undo_stack.size() > levels) { + m_undo_stack.pop_front(); + } + m_undo_levels = levels; + } -public: -UndoStack() : m_pending( 0 ){ -} -~UndoStack(){ - clear(); -} -bool empty() const { - return m_stack.empty(); -} -std::size_t size() const { - return m_stack.size(); -} -Operation* back(){ - return m_stack.back(); -} -const Operation* back() const { - return m_stack.back(); -} -Operation* front(){ - return m_stack.front(); -} -const Operation* front() const { - return m_stack.front(); -} -void pop_front(){ - delete m_stack.front(); - m_stack.pop_front(); -} -void pop_back(){ - delete m_stack.back(); - m_stack.pop_back(); -} -void clear(){ - if ( !m_stack.empty() ) { - for ( Operations::iterator i = m_stack.begin(); i != m_stack.end(); ++i ) - { - delete *i; - } - m_stack.clear(); - } -} -void start( const char* command ){ - if ( m_pending != 0 ) { - delete m_pending; - } - m_pending = new Operation( command ); -} -bool finish( const char* command ){ - if ( m_pending != 0 ) { - delete m_pending; - m_pending = 0; - return false; - } - else - { - ASSERT_MESSAGE( !m_stack.empty(), "undo stack empty" ); - m_stack.back()->m_command = command; - return true; - } -} -void save( Undoable* undoable ){ - if ( m_pending != 0 ) { - m_stack.push_back( m_pending ); - m_pending = 0; - } - back()->m_snapshot.save( undoable ); -} -}; + std::size_t getLevels() const + { + return m_undo_levels; + } -UndoStack m_undo_stack; -UndoStack m_redo_stack; + std::size_t size() const + { + return m_undo_stack.size(); + } -class UndoStackFiller : public UndoObserver -{ -UndoStack* m_stack; -public: + void startUndo() + { + m_undo_stack.start("unnamedCommand"); + mark_undoables(&m_undo_stack); + } -UndoStackFiller() - : m_stack( 0 ){ -} -void save( Undoable* undoable ){ - ASSERT_NOTNULL( undoable ); + bool finishUndo(const char *command) + { + bool changed = m_undo_stack.finish(command); + mark_undoables(0); + return changed; + } - if ( m_stack != 0 ) { - m_stack->save( undoable ); - m_stack = 0; - } -} -void setStack( UndoStack* stack ){ - m_stack = stack; -} -}; + void startRedo() + { + m_redo_stack.start("unnamedCommand"); + mark_undoables(&m_redo_stack); + } -typedef std::map undoables_t; -undoables_t m_undoables; + bool finishRedo(const char *command) + { + bool changed = m_redo_stack.finish(command); + mark_undoables(0); + return changed; + } -void mark_undoables( UndoStack* stack ){ - for ( undoables_t::iterator i = m_undoables.begin(); i != m_undoables.end(); ++i ) - { - ( *i ).second.setStack( stack ); - } -} + void start() + { + m_redo_stack.clear(); + if (m_undo_stack.size() == m_undo_levels) { + m_undo_stack.pop_front(); + } + startUndo(); + trackersBegin(); + } -std::size_t m_undo_levels; + void finish(const char *command) + { + if (finishUndo(command)) { + globalOutputStream() << command << '\n'; + } + } -typedef std::set Trackers; -Trackers m_trackers; -public: -RadiantUndoSystem() - : m_undo_levels( 64 ){ -} -~RadiantUndoSystem(){ - clear(); -} -UndoObserver* observer( Undoable* undoable ){ - ASSERT_NOTNULL( undoable ); + void undo() + { + if (m_undo_stack.empty()) { + globalOutputStream() << "Undo: no undo available\n"; + } else { + Operation *operation = m_undo_stack.back(); + globalOutputStream() << "Undo: " << operation->m_command.c_str() << "\n"; + + startRedo(); + trackersUndo(); + operation->m_snapshot.restore(); + finishRedo(operation->m_command.c_str()); + m_undo_stack.pop_back(); + } + } - return &m_undoables[undoable]; -} -void release( Undoable* undoable ){ - ASSERT_NOTNULL( undoable ); + void redo() + { + if (m_redo_stack.empty()) { + globalOutputStream() << "Redo: no redo available\n"; + } else { + Operation *operation = m_redo_stack.back(); + globalOutputStream() << "Redo: " << operation->m_command.c_str() << "\n"; + + startUndo(); + trackersRedo(); + operation->m_snapshot.restore(); + finishUndo(operation->m_command.c_str()); + m_redo_stack.pop_back(); + } + } - m_undoables.erase( undoable ); -} -void setLevels( std::size_t levels ){ - if ( levels > MAX_UNDO_LEVELS() ) { - levels = MAX_UNDO_LEVELS(); - } - - while ( m_undo_stack.size() > levels ) - { - m_undo_stack.pop_front(); - } - m_undo_levels = levels; -} -std::size_t getLevels() const { - return m_undo_levels; -} -std::size_t size() const { - return m_undo_stack.size(); -} -void startUndo(){ - m_undo_stack.start( "unnamedCommand" ); - mark_undoables( &m_undo_stack ); -} -bool finishUndo( const char* command ){ - bool changed = m_undo_stack.finish( command ); - mark_undoables( 0 ); - return changed; -} -void startRedo(){ - m_redo_stack.start( "unnamedCommand" ); - mark_undoables( &m_redo_stack ); -} -bool finishRedo( const char* command ){ - bool changed = m_redo_stack.finish( command ); - mark_undoables( 0 ); - return changed; -} -void start(){ - m_redo_stack.clear(); - if ( m_undo_stack.size() == m_undo_levels ) { - m_undo_stack.pop_front(); - } - startUndo(); - trackersBegin(); -} -void finish( const char* command ){ - if ( finishUndo( command ) ) { - globalOutputStream() << command << '\n'; - } -} -void undo(){ - if ( m_undo_stack.empty() ) { - globalOutputStream() << "Undo: no undo available\n"; - } - else - { - Operation* operation = m_undo_stack.back(); - globalOutputStream() << "Undo: " << operation->m_command.c_str() << "\n"; - - startRedo(); - trackersUndo(); - operation->m_snapshot.restore(); - finishRedo( operation->m_command.c_str() ); - m_undo_stack.pop_back(); - } -} -void redo(){ - if ( m_redo_stack.empty() ) { - globalOutputStream() << "Redo: no redo available\n"; - } - else - { - Operation* operation = m_redo_stack.back(); - globalOutputStream() << "Redo: " << operation->m_command.c_str() << "\n"; - - startUndo(); - trackersRedo(); - operation->m_snapshot.restore(); - finishUndo( operation->m_command.c_str() ); - m_redo_stack.pop_back(); - } -} -void clear(){ - mark_undoables( 0 ); - m_undo_stack.clear(); - m_redo_stack.clear(); - trackersClear(); -} -void trackerAttach( UndoTracker& tracker ){ - ASSERT_MESSAGE( m_trackers.find( &tracker ) == m_trackers.end(), "undo tracker already attached" ); - m_trackers.insert( &tracker ); -} -void trackerDetach( UndoTracker& tracker ){ - ASSERT_MESSAGE( m_trackers.find( &tracker ) != m_trackers.end(), "undo tracker cannot be detached" ); - m_trackers.erase( &tracker ); -} -void trackersClear() const { - for ( Trackers::const_iterator i = m_trackers.begin(); i != m_trackers.end(); ++i ) - { - ( *i )->clear(); - } -} -void trackersBegin() const { - for ( Trackers::const_iterator i = m_trackers.begin(); i != m_trackers.end(); ++i ) - { - ( *i )->begin(); - } -} -void trackersUndo() const { - for ( Trackers::const_iterator i = m_trackers.begin(); i != m_trackers.end(); ++i ) - { - ( *i )->undo(); - } -} -void trackersRedo() const { - for ( Trackers::const_iterator i = m_trackers.begin(); i != m_trackers.end(); ++i ) - { - ( *i )->redo(); - } -} -}; + void clear() + { + mark_undoables(0); + m_undo_stack.clear(); + m_redo_stack.clear(); + trackersClear(); + } + + void trackerAttach(UndoTracker &tracker) + { + ASSERT_MESSAGE(m_trackers.find(&tracker) == m_trackers.end(), "undo tracker already attached"); + m_trackers.insert(&tracker); + } + + void trackerDetach(UndoTracker &tracker) + { + ASSERT_MESSAGE(m_trackers.find(&tracker) != m_trackers.end(), "undo tracker cannot be detached"); + m_trackers.erase(&tracker); + } + void trackersClear() const + { + for (Trackers::const_iterator i = m_trackers.begin(); i != m_trackers.end(); ++i) { + (*i)->clear(); + } + } + + void trackersBegin() const + { + for (Trackers::const_iterator i = m_trackers.begin(); i != m_trackers.end(); ++i) { + (*i)->begin(); + } + } + + void trackersUndo() const + { + for (Trackers::const_iterator i = m_trackers.begin(); i != m_trackers.end(); ++i) { + (*i)->undo(); + } + } + + void trackersRedo() const + { + for (Trackers::const_iterator i = m_trackers.begin(); i != m_trackers.end(); ++i) { + (*i)->redo(); + } + } +}; -void UndoLevels_importString( RadiantUndoSystem& undo, const char* value ){ - int levels; - PropertyImpl::Import( levels, value ); - undo.setLevels( levels ); +void UndoLevels_importString(RadiantUndoSystem &undo, const char *value) +{ + int levels; + PropertyImpl::Import(levels, value); + undo.setLevels(levels); } -typedef ReferenceCaller UndoLevelsImportStringCaller; -void UndoLevels_exportString( const RadiantUndoSystem& undo, const Callback & importer ){ - PropertyImpl::Export( static_cast( undo.getLevels() ), importer ); + +typedef ReferenceCaller UndoLevelsImportStringCaller; + +void UndoLevels_exportString(const RadiantUndoSystem &undo, const Callback &importer) +{ + PropertyImpl::Export(static_cast( undo.getLevels()), importer); } -typedef ConstReferenceCaller &), UndoLevels_exportString> UndoLevelsExportStringCaller; + +typedef ConstReferenceCaller &), UndoLevels_exportString> UndoLevelsExportStringCaller; #include "generic/callback.h" struct UndoLevels { - static void Export(const RadiantUndoSystem &self, const Callback &returnz) { + static void Export(const RadiantUndoSystem &self, const Callback &returnz) + { returnz(static_cast(self.getLevels())); } - static void Import(RadiantUndoSystem &self, int value) { + static void Import(RadiantUndoSystem &self, int value) + { self.setLevels(value); } }; -void Undo_constructPreferences( RadiantUndoSystem& undo, PreferencesPage& page ){ +void Undo_constructPreferences(RadiantUndoSystem &undo, PreferencesPage &page) +{ page.appendSpinner("Undo Queue Size", 64, 0, 1024, make_property(undo)); } -void Undo_constructPage( RadiantUndoSystem& undo, PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Undo", "Undo Queue Settings" ) ); - Undo_constructPreferences( undo, page ); -} -void Undo_registerPreferencesPage( RadiantUndoSystem& undo ){ - PreferencesDialog_addSettingsPage( ReferenceCaller( undo ) ); + +void Undo_constructPage(RadiantUndoSystem &undo, PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Undo", "Undo Queue Settings")); + Undo_constructPreferences(undo, page); } -class UndoSystemDependencies : public GlobalPreferenceSystemModuleRef +void Undo_registerPreferencesPage(RadiantUndoSystem &undo) { + PreferencesDialog_addSettingsPage( + ReferenceCaller(undo)); +} + +class UndoSystemDependencies : public GlobalPreferenceSystemModuleRef { }; -class UndoSystemAPI -{ -RadiantUndoSystem m_undosystem; +class UndoSystemAPI { + RadiantUndoSystem m_undosystem; public: -typedef UndoSystem Type; -STRING_CONSTANT( Name, "*" ); + typedef UndoSystem Type; -UndoSystemAPI(){ - GlobalPreferenceSystem().registerPreference("UndoLevels", make_property_string(m_undosystem)); + STRING_CONSTANT(Name, "*"); - Undo_registerPreferencesPage( m_undosystem ); -} -UndoSystem* getTable(){ - return &m_undosystem; -} + UndoSystemAPI() + { + GlobalPreferenceSystem().registerPreference("UndoLevels", make_property_string(m_undosystem)); + + Undo_registerPreferencesPage(m_undosystem); + } + + UndoSystem *getTable() + { + return &m_undosystem; + } }; #include "modulesystem/singletonmodule.h" @@ -435,54 +524,58 @@ UndoSystem* getTable(){ typedef SingletonModule UndoSystemModule; typedef Static StaticUndoSystemModule; -StaticRegisterModule staticRegisterUndoSystem( StaticUndoSystemModule::instance() ); +StaticRegisterModule staticRegisterUndoSystem(StaticUndoSystemModule::instance()); +class undoable_test : public Undoable { + struct state_type : public UndoMemento { + state_type() : test_data(0) + { + } + state_type(const state_type &other) : UndoMemento(other), test_data(other.test_data) + { + } + void release() + { + delete this; + } + int test_data; + }; + state_type m_state; + UndoObserver *m_observer; +public: + undoable_test() + : m_observer(GlobalUndoSystem().observer(this)) + { + } + ~undoable_test() + { + GlobalUndoSystem().release(this); + } + UndoMemento *exportState() const + { + return new state_type(m_state); + } + void importState(const UndoMemento *state) + { + ASSERT_NOTNULL(state); -class undoable_test : public Undoable -{ -struct state_type : public UndoMemento -{ - state_type() : test_data( 0 ){ - } - state_type( const state_type& other ) : UndoMemento( other ), test_data( other.test_data ){ - } - void release(){ - delete this; - } - - int test_data; -}; -state_type m_state; -UndoObserver* m_observer; -public: -undoable_test() - : m_observer( GlobalUndoSystem().observer( this ) ){ -} -~undoable_test(){ - GlobalUndoSystem().release( this ); -} -UndoMemento* exportState() const { - return new state_type( m_state ); -} -void importState( const UndoMemento* state ){ - ASSERT_NOTNULL( state ); - - m_observer->save( this ); - m_state = *( static_cast( state ) ); -} + m_observer->save(this); + m_state = *(static_cast( state )); + } -void mutate( unsigned int data ){ - m_observer->save( this ); - m_state.test_data = data; -} + void mutate(unsigned int data) + { + m_observer->save(this); + m_state.test_data = data; + } }; #if 0 @@ -491,15 +584,15 @@ class TestUndo { public: TestUndo(){ - undoable_test test; - GlobalUndoSystem().begin( "bleh" ); - test.mutate( 3 ); - GlobalUndoSystem().begin( "blah" ); - test.mutate( 4 ); - GlobalUndoSystem().undo(); - GlobalUndoSystem().undo(); - GlobalUndoSystem().redo(); - GlobalUndoSystem().redo(); + undoable_test test; + GlobalUndoSystem().begin( "bleh" ); + test.mutate( 3 ); + GlobalUndoSystem().begin( "blah" ); + test.mutate( 4 ); + GlobalUndoSystem().undo(); + GlobalUndoSystem().undo(); + GlobalUndoSystem().redo(); + GlobalUndoSystem().redo(); } }; diff --git a/radiant/url.cpp b/radiant/url.cpp index f49cb886..034fc454 100644 --- a/radiant/url.cpp +++ b/radiant/url.cpp @@ -30,33 +30,38 @@ #include #include bool open_url( const char* url ){ - return ShellExecute( (HWND)GDK_WINDOW_HWND( gtk_widget_get_window( MainFrame_getWindow() ) ), "open", url, 0, 0, SW_SHOW ) > (HINSTANCE)32; + return ShellExecute( (HWND)GDK_WINDOW_HWND( gtk_widget_get_window( MainFrame_getWindow() ) ), "open", url, 0, 0, SW_SHOW ) > (HINSTANCE)32; } #endif #if GDEF_OS_LINUX || GDEF_OS_BSD + #include -bool open_url( const char* url ){ - char command[2 * PATH_MAX]; - snprintf( command, sizeof( command ), - "xdg-open \"%s\" &", url ); - return system( command ) == 0; + +bool open_url(const char *url) +{ + char command[2 * PATH_MAX]; + snprintf(command, sizeof(command), + "xdg-open \"%s\" &", url); + return system(command) == 0; } + #endif #if GDEF_OS_MACOS #include bool open_url( const char* url ){ - char command[2 * PATH_MAX]; - snprintf( command, sizeof( command ), "open \"%s\" &", url ); - return system( command ) == 0; + char command[2 * PATH_MAX]; + snprintf( command, sizeof( command ), "open \"%s\" &", url ); + return system( command ) == 0; } #endif -void OpenURL( const char *url ){ - // let's put a little comment - globalOutputStream() << "OpenURL: " << url << "\n"; - if ( !open_url( url ) ) { - ui::alert( MainFrame_getWindow(), "Failed to launch browser!" ); - } +void OpenURL(const char *url) +{ + // let's put a little comment + globalOutputStream() << "OpenURL: " << url << "\n"; + if (!open_url(url)) { + ui::alert(MainFrame_getWindow(), "Failed to launch browser!"); + } } diff --git a/radiant/url.h b/radiant/url.h index 726be705..829b039d 100644 --- a/radiant/url.h +++ b/radiant/url.h @@ -22,6 +22,6 @@ #if !defined( INCLUDED_URL_H ) #define INCLUDED_URL_H -void OpenURL( const char *url ); +void OpenURL(const char *url); #endif diff --git a/radiant/view.cpp b/radiant/view.cpp index a0a48c43..7e6726a8 100644 --- a/radiant/view.cpp +++ b/radiant/view.cpp @@ -34,22 +34,25 @@ int g_count_oriented_bboxs; #endif -void Cull_ResetStats(){ +void Cull_ResetStats() +{ #if defined( DEBUG_CULLING ) - g_count_dots = 0; - g_count_planes = 0; - g_count_oriented_planes = 0; - g_count_bboxs = 0; - g_count_oriented_bboxs = 0; + g_count_dots = 0; + g_count_planes = 0; + g_count_oriented_planes = 0; + g_count_bboxs = 0; + g_count_oriented_bboxs = 0; #endif } -const char* Cull_GetStats(){ +const char *Cull_GetStats() +{ #if defined( DEBUG_CULLING ) - sprintf( g_cull_stats, "dots: %d | planes %d + %d | bboxs %d + %d", g_count_dots, g_count_planes, g_count_oriented_planes, g_count_bboxs, g_count_oriented_bboxs ); - return g_cull_stats; + sprintf(g_cull_stats, "dots: %d | planes %d + %d | bboxs %d + %d", g_count_dots, g_count_planes, + g_count_oriented_planes, g_count_bboxs, g_count_oriented_bboxs); + return g_cull_stats; #else - return ""; + return ""; #endif } diff --git a/radiant/view.h b/radiant/view.h index ad322d5d..7b9ba486 100644 --- a/radiant/view.h +++ b/radiant/view.h @@ -42,151 +42,182 @@ extern int g_count_oriented_bboxs; #endif -inline void debug_count_dot(){ +inline void debug_count_dot() +{ #if defined( DEBUG_CULLING ) - ++g_count_dots; + ++g_count_dots; #endif } -inline void debug_count_plane(){ +inline void debug_count_plane() +{ #if defined( DEBUG_CULLING ) - ++g_count_planes; + ++g_count_planes; #endif } -inline void debug_count_oriented_plane(){ +inline void debug_count_oriented_plane() +{ #if defined( DEBUG_CULLING ) - ++g_count_oriented_planes; + ++g_count_oriented_planes; #endif } -inline void debug_count_bbox(){ +inline void debug_count_bbox() +{ #if defined( DEBUG_CULLING ) - ++g_count_bboxs; + ++g_count_bboxs; #endif } -inline void debug_count_oriented_bbox(){ +inline void debug_count_oriented_bbox() +{ #if defined( DEBUG_CULLING ) - ++g_count_oriented_bboxs; + ++g_count_oriented_bboxs; #endif } - - /// \brief View-volume culling and transformations. -class View : public VolumeTest -{ +class View : public VolumeTest { /// modelview matrix -Matrix4 m_modelview; + Matrix4 m_modelview; /// projection matrix -Matrix4 m_projection; + Matrix4 m_projection; /// device-to-screen transform -Matrix4 m_viewport; + Matrix4 m_viewport; -Matrix4 m_scissor; + Matrix4 m_scissor; /// combined modelview and projection matrix -Matrix4 m_viewproj; + Matrix4 m_viewproj; /// camera position in world space -Vector4 m_viewer; + Vector4 m_viewer; /// view frustum in world space -Frustum m_frustum; - -bool m_fill; - -void construct(){ - m_viewproj = matrix4_multiplied_by_matrix4( matrix4_multiplied_by_matrix4( m_scissor, m_projection ), m_modelview ); - - m_frustum = frustum_from_viewproj( m_viewproj ); - m_viewer = viewer_from_viewproj( m_viewproj ); -} -public: -View( bool fill = false ) : - m_modelview( g_matrix4_identity ), - m_projection( g_matrix4_identity ), - m_scissor( g_matrix4_identity ), - m_fill( fill ){ -} -void Construct( const Matrix4& projection, const Matrix4& modelview, std::size_t width, std::size_t height ){ - // modelview - m_modelview = modelview; - - // projection - m_projection = projection; - - // viewport - m_viewport = g_matrix4_identity; - m_viewport[0] = float(width / 2); - m_viewport[5] = float(height / 2); - if ( fabs( m_projection[11] ) > 0.0000001 ) { - m_viewport[10] = m_projection[0] * m_viewport[0]; - } - else{ - m_viewport[10] = 1 / m_projection[10]; - } - - construct(); -} -void EnableScissor( float min_x, float max_x, float min_y, float max_y ){ - m_scissor = g_matrix4_identity; - m_scissor[0] = static_cast( ( max_x - min_x ) * 0.5 ); - m_scissor[5] = static_cast( ( max_y - min_y ) * 0.5 ); - m_scissor[12] = static_cast( ( min_x + max_x ) * 0.5 ); - m_scissor[13] = static_cast( ( min_y + max_y ) * 0.5 ); - matrix4_full_invert( m_scissor ); - - construct(); -} -void DisableScissor(){ - m_scissor = g_matrix4_identity; + Frustum m_frustum; - construct(); -} + bool m_fill; -bool TestPoint( const Vector3& point ) const { - return viewproj_test_point( m_viewproj, point ); -} -bool TestLine( const Segment& segment ) const { - return frustum_test_line( m_frustum, segment ); -} -bool TestPlane( const Plane3& plane ) const { - debug_count_plane(); - return viewer_test_plane( m_viewer, plane ); -} -bool TestPlane( const Plane3& plane, const Matrix4& localToWorld ) const { - debug_count_oriented_plane(); - return viewer_test_transformed_plane( m_viewer, plane, localToWorld ); -} -VolumeIntersectionValue TestAABB( const AABB& aabb ) const { - debug_count_bbox(); - return frustum_test_aabb( m_frustum, aabb ); -} -VolumeIntersectionValue TestAABB( const AABB& aabb, const Matrix4& localToWorld ) const { - debug_count_oriented_bbox(); - return frustum_intersects_transformed_aabb( m_frustum, aabb, localToWorld ); -} + void construct() + { + m_viewproj = matrix4_multiplied_by_matrix4(matrix4_multiplied_by_matrix4(m_scissor, m_projection), m_modelview); -const Matrix4& GetViewMatrix() const { - return m_viewproj; -} -const Matrix4& GetViewport() const { - return m_viewport; -}; -const Matrix4& GetModelview() const { - return m_modelview; -} -const Matrix4& GetProjection() const { - return m_projection; -} + m_frustum = frustum_from_viewproj(m_viewproj); + m_viewer = viewer_from_viewproj(m_viewproj); + } -bool fill() const { - return m_fill; -} -const Vector3& getViewer() const { - return vector4_to_vector3( m_viewer ); -} +public: + View(bool fill = false) : + m_modelview(g_matrix4_identity), + m_projection(g_matrix4_identity), + m_scissor(g_matrix4_identity), + m_fill(fill) + { + } + + void Construct(const Matrix4 &projection, const Matrix4 &modelview, std::size_t width, std::size_t height) + { + // modelview + m_modelview = modelview; + + // projection + m_projection = projection; + + // viewport + m_viewport = g_matrix4_identity; + m_viewport[0] = float(width / 2); + m_viewport[5] = float(height / 2); + if (fabs(m_projection[11]) > 0.0000001) { + m_viewport[10] = m_projection[0] * m_viewport[0]; + } else { + m_viewport[10] = 1 / m_projection[10]; + } + + construct(); + } + + void EnableScissor(float min_x, float max_x, float min_y, float max_y) + { + m_scissor = g_matrix4_identity; + m_scissor[0] = static_cast((max_x - min_x) * 0.5 ); + m_scissor[5] = static_cast((max_y - min_y) * 0.5 ); + m_scissor[12] = static_cast((min_x + max_x) * 0.5 ); + m_scissor[13] = static_cast((min_y + max_y) * 0.5 ); + matrix4_full_invert(m_scissor); + + construct(); + } + + void DisableScissor() + { + m_scissor = g_matrix4_identity; + + construct(); + } + + bool TestPoint(const Vector3 &point) const + { + return viewproj_test_point(m_viewproj, point); + } + + bool TestLine(const Segment &segment) const + { + return frustum_test_line(m_frustum, segment); + } + + bool TestPlane(const Plane3 &plane) const + { + debug_count_plane(); + return viewer_test_plane(m_viewer, plane); + } + + bool TestPlane(const Plane3 &plane, const Matrix4 &localToWorld) const + { + debug_count_oriented_plane(); + return viewer_test_transformed_plane(m_viewer, plane, localToWorld); + } + + VolumeIntersectionValue TestAABB(const AABB &aabb) const + { + debug_count_bbox(); + return frustum_test_aabb(m_frustum, aabb); + } + + VolumeIntersectionValue TestAABB(const AABB &aabb, const Matrix4 &localToWorld) const + { + debug_count_oriented_bbox(); + return frustum_intersects_transformed_aabb(m_frustum, aabb, localToWorld); + } + + const Matrix4 &GetViewMatrix() const + { + return m_viewproj; + } + + const Matrix4 &GetViewport() const + { + return m_viewport; + }; + + const Matrix4 &GetModelview() const + { + return m_modelview; + } + + const Matrix4 &GetProjection() const + { + return m_projection; + } + + bool fill() const + { + return m_fill; + } + + const Vector3 &getViewer() const + { + return vector4_to_vector3(m_viewer); + } }; #endif diff --git a/radiant/watchbsp.cpp b/radiant/watchbsp.cpp index bbae3fab..2803ce94 100644 --- a/radiant/watchbsp.cpp +++ b/radiant/watchbsp.cpp @@ -52,27 +52,26 @@ #include "mainframe.h" #include "sockets.h" -void message_flush( message_info_t* self ){ - Sys_Print( self->msg_level, self->m_buffer, self->m_length ); - self->m_length = 0; +void message_flush(message_info_t *self) +{ + Sys_Print(self->msg_level, self->m_buffer, self->m_length); + self->m_length = 0; } -void message_print( message_info_t* self, const char* characters, std::size_t length ){ - const char* end = characters + length; - while ( characters != end ) - { - std::size_t space = message_info_t::bufsize - 1 - self->m_length; - if ( space == 0 ) { - message_flush( self ); - } - else - { - std::size_t size = std::min( space, std::size_t( end - characters ) ); - memcpy( self->m_buffer + self->m_length, characters, size ); - self->m_length += size; - characters += size; - } - } +void message_print(message_info_t *self, const char *characters, std::size_t length) +{ + const char *end = characters + length; + while (characters != end) { + std::size_t space = message_info_t::bufsize - 1 - self->m_length; + if (space == 0) { + message_flush(self); + } else { + std::size_t size = std::min(space, std::size_t(end - characters)); + memcpy(self->m_buffer + self->m_length, characters, size); + self->m_length += size; + characters += size; + } + } } @@ -80,87 +79,97 @@ void message_print( message_info_t* self, const char* characters, std::size_t le #include #include "xmlstuff.h" -class CWatchBSP -{ +class CWatchBSP { private: - // a flag we have set to true when using an external BSP plugin - // the resulting code with that is a bit dirty, cleaner solution would be to seperate the succession of commands from the listening loop - // (in two seperate classes probably) - bool m_bBSPPlugin; - - // EIdle: we are not listening - // DoMonitoringLoop will change state to EBeginStep - // EBeginStep: the socket is up for listening, we are expecting incoming connection - // incoming connection will change state to EWatching - // EWatching: we have a connection, monitor it - // connection closed will see if we start a new step (EBeginStep) or launch Quake3 and end (EIdle) - enum EWatchBSPState { EIdle, EBeginStep, EWatching } m_eState; - socket_t *m_pListenSocket; - socket_t *m_pInSocket; - netmessage_t msg; - GPtrArray *m_pCmd; - // used to timeout EBeginStep - GTimer *m_pTimer; - std::size_t m_iCurrentStep; - // name of the map so we can run the engine - char *m_sBSPName; - // buffer we use in push mode to receive data directly from the network - xmlParserInputBufferPtr m_xmlInputBuffer; - xmlParserInputPtr m_xmlInput; - xmlParserCtxtPtr m_xmlParserCtxt; - // call this to switch the set listening mode - bool SetupListening(); - // start a new EBeginStep - void DoEBeginStep(); - // the xml and sax parser state - char m_xmlBuf[MAX_NETMESSAGE]; - bool m_bNeedCtxtInit; - message_info_t m_message_info; + // a flag we have set to true when using an external BSP plugin + // the resulting code with that is a bit dirty, cleaner solution would be to seperate the succession of commands from the listening loop + // (in two seperate classes probably) + bool m_bBSPPlugin; + + // EIdle: we are not listening + // DoMonitoringLoop will change state to EBeginStep + // EBeginStep: the socket is up for listening, we are expecting incoming connection + // incoming connection will change state to EWatching + // EWatching: we have a connection, monitor it + // connection closed will see if we start a new step (EBeginStep) or launch Quake3 and end (EIdle) + enum EWatchBSPState { EIdle, EBeginStep, EWatching } m_eState; + socket_t *m_pListenSocket; + socket_t *m_pInSocket; + netmessage_t msg; + GPtrArray *m_pCmd; + // used to timeout EBeginStep + GTimer *m_pTimer; + std::size_t m_iCurrentStep; + // name of the map so we can run the engine + char *m_sBSPName; + // buffer we use in push mode to receive data directly from the network + xmlParserInputBufferPtr m_xmlInputBuffer; + xmlParserInputPtr m_xmlInput; + xmlParserCtxtPtr m_xmlParserCtxt; + + // call this to switch the set listening mode + bool SetupListening(); + + // start a new EBeginStep + void DoEBeginStep(); + + // the xml and sax parser state + char m_xmlBuf[MAX_NETMESSAGE]; + bool m_bNeedCtxtInit; + message_info_t m_message_info; public: - CWatchBSP(){ - m_pCmd = 0; - m_bBSPPlugin = false; - m_pListenSocket = NULL; - m_pInSocket = NULL; - m_eState = EIdle; - m_pTimer = g_timer_new(); - m_sBSPName = NULL; - m_xmlInputBuffer = NULL; - m_bNeedCtxtInit = true; - } - virtual ~CWatchBSP(){ - EndMonitoringLoop(); - Net_Shutdown(); - - g_timer_destroy( m_pTimer ); - } - - bool HasBSPPlugin() const - { return m_bBSPPlugin; } - - // called regularly to keep listening - void RoutineProcessing(); - // start a monitoring loop with the following steps - void DoMonitoringLoop( GPtrArray *pCmd, const char *sBSPName ); - void EndMonitoringLoop(){ - Reset(); - if ( m_sBSPName ) { - string_release( m_sBSPName, string_length( m_sBSPName ) ); - m_sBSPName = 0; - } - if ( m_pCmd ) { - g_ptr_array_free( m_pCmd, TRUE ); - m_pCmd = 0; - } - } - // close everything - may be called from the outside to abort the process - void Reset(); - // start a listening loop for an external process, possibly a BSP plugin - void ExternalListen(); + CWatchBSP() + { + m_pCmd = 0; + m_bBSPPlugin = false; + m_pListenSocket = NULL; + m_pInSocket = NULL; + m_eState = EIdle; + m_pTimer = g_timer_new(); + m_sBSPName = NULL; + m_xmlInputBuffer = NULL; + m_bNeedCtxtInit = true; + } + + virtual ~CWatchBSP() + { + EndMonitoringLoop(); + Net_Shutdown(); + + g_timer_destroy(m_pTimer); + } + + bool HasBSPPlugin() const + { return m_bBSPPlugin; } + + // called regularly to keep listening + void RoutineProcessing(); + + // start a monitoring loop with the following steps + void DoMonitoringLoop(GPtrArray *pCmd, const char *sBSPName); + + void EndMonitoringLoop() + { + Reset(); + if (m_sBSPName) { + string_release(m_sBSPName, string_length(m_sBSPName)); + m_sBSPName = 0; + } + if (m_pCmd) { + g_ptr_array_free(m_pCmd, TRUE); + m_pCmd = 0; + } + } + + // close everything - may be called from the outside to abort the process + void Reset(); + + // start a listening loop for an external process, possibly a BSP plugin + void ExternalListen(); }; -CWatchBSP* g_pWatchBSP; +CWatchBSP *g_pWatchBSP; // watch the BSP process through network connections // true: trigger the BSP steps one by one and monitor them through the network @@ -176,373 +185,390 @@ bool g_WatchBSP_DoSleep = true; int g_WatchBSP_Timeout = 10; -void Build_constructPreferences( PreferencesPage& page ){ - ui::CheckButton monitorbsp = page.appendCheckBox( "", "Enable Build Process Monitoring", g_WatchBSP_Enabled ); - ui::CheckButton leakstop = page.appendCheckBox( "", "Stop Compilation on Leak", g_WatchBSP_LeakStop ); - ui::CheckButton runengine = page.appendCheckBox( "", "Run Engine After Compile", g_WatchBSP_RunQuake ); - ui::CheckButton sleep = page.appendCheckBox ( "", "Sleep When Running the Engine", g_WatchBSP_DoSleep ); - Widget_connectToggleDependency( leakstop, monitorbsp ); - Widget_connectToggleDependency( runengine, monitorbsp ); - Widget_connectToggleDependency( sleep, runengine ); +void Build_constructPreferences(PreferencesPage &page) +{ + ui::CheckButton monitorbsp = page.appendCheckBox("", "Enable Build Process Monitoring", g_WatchBSP_Enabled); + ui::CheckButton leakstop = page.appendCheckBox("", "Stop Compilation on Leak", g_WatchBSP_LeakStop); + ui::CheckButton runengine = page.appendCheckBox("", "Run Engine After Compile", g_WatchBSP_RunQuake); + ui::CheckButton sleep = page.appendCheckBox("", "Sleep When Running the Engine", g_WatchBSP_DoSleep); + Widget_connectToggleDependency(leakstop, monitorbsp); + Widget_connectToggleDependency(runengine, monitorbsp); + Widget_connectToggleDependency(sleep, runengine); } -void Build_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Build", "Build Preferences" ) ); - Build_constructPreferences( page ); + +void Build_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Build", "Build Preferences")); + Build_constructPreferences(page); } -void Build_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage( makeCallbackF(Build_constructPage) ); + +void Build_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(Build_constructPage)); } #include "preferencesystem.h" #include "stringio.h" -void BuildMonitor_Construct(){ - g_pWatchBSP = new CWatchBSP(); +void BuildMonitor_Construct() +{ + g_pWatchBSP = new CWatchBSP(); - g_WatchBSP_Enabled = !string_equal( g_pGameDescription->getKeyValue( "no_bsp_monitor" ), "1" ); + g_WatchBSP_Enabled = !string_equal(g_pGameDescription->getKeyValue("no_bsp_monitor"), "1"); - GlobalPreferenceSystem().registerPreference( "WatchBSP", make_property_string( g_WatchBSP_Enabled ) ); - GlobalPreferenceSystem().registerPreference( "RunQuake2Run", make_property_string( g_WatchBSP_RunQuake ) ); - GlobalPreferenceSystem().registerPreference( "LeakStop", make_property_string( g_WatchBSP_LeakStop ) ); - GlobalPreferenceSystem().registerPreference( "SleepMode", make_property_string( g_WatchBSP_DoSleep ) ); + GlobalPreferenceSystem().registerPreference("WatchBSP", make_property_string(g_WatchBSP_Enabled)); + GlobalPreferenceSystem().registerPreference("RunQuake2Run", make_property_string(g_WatchBSP_RunQuake)); + GlobalPreferenceSystem().registerPreference("LeakStop", make_property_string(g_WatchBSP_LeakStop)); + GlobalPreferenceSystem().registerPreference("SleepMode", make_property_string(g_WatchBSP_DoSleep)); - Build_registerPreferencesPage(); + Build_registerPreferencesPage(); } -void BuildMonitor_Destroy(){ - delete g_pWatchBSP; +void BuildMonitor_Destroy() +{ + delete g_pWatchBSP; } -CWatchBSP *GetWatchBSP(){ - return g_pWatchBSP; +CWatchBSP *GetWatchBSP() +{ + return g_pWatchBSP; } -void BuildMonitor_Run( GPtrArray* commands, const char* mapName ){ - GetWatchBSP()->DoMonitoringLoop( commands, mapName ); +void BuildMonitor_Run(GPtrArray *commands, const char *mapName) +{ + GetWatchBSP()->DoMonitoringLoop(commands, mapName); } // Static functions for the SAX callbacks ------------------------------------------------------- // utility for saxStartElement below -static void abortStream( message_info_t *data ){ - GetWatchBSP()->EndMonitoringLoop(); - // tell there has been an error +static void abortStream(message_info_t *data) +{ + GetWatchBSP()->EndMonitoringLoop(); + // tell there has been an error #if 0 - if ( GetWatchBSP()->HasBSPPlugin() ) { - g_BSPFrontendTable.m_pfnEndListen( 2 ); - } + if ( GetWatchBSP()->HasBSPPlugin() ) { + g_BSPFrontendTable.m_pfnEndListen( 2 ); + } #endif - // yeah this doesn't look good.. but it's needed so that everything will be ignored until the stream goes out - data->ignore_depth = -1; - data->recurse++; + // yeah this doesn't look good.. but it's needed so that everything will be ignored until the stream goes out + data->ignore_depth = -1; + data->recurse++; } #include "stream_version.h" -static void saxStartElement( message_info_t *data, const xmlChar *name, const xmlChar **attrs ){ +static void saxStartElement(message_info_t *data, const xmlChar *name, const xmlChar **attrs) +{ #if 0 - globalOutputStream() << "<" << name; - if ( attrs != 0 ) { - for ( const xmlChar** p = attrs; *p != 0; p += 2 ) - { - globalOutputStream() << " " << p[0] << "=" << makeQuoted( p[1] ); - } - } - globalOutputStream() << ">\n"; + globalOutputStream() << "<" << name; + if ( attrs != 0 ) { + for ( const xmlChar** p = attrs; *p != 0; p += 2 ) + { + globalOutputStream() << " " << p[0] << "=" << makeQuoted( p[1] ); + } + } + globalOutputStream() << ">\n"; #endif - if ( data->ignore_depth == 0 ) { - if ( data->pGeometry != 0 ) { - // we have a handler - data->pGeometry->saxStartElement( data, name, attrs ); - } - else - { - if ( strcmp( reinterpret_cast( name ), "q3map_feedback" ) == 0 ) { - // check the correct version - // old q3map don't send a version attribute - // the ones we support .. send Q3MAP_STREAM_VERSION - if ( !attrs[0] || !attrs[1] || ( strcmp( reinterpret_cast( attrs[0] ), "version" ) != 0 ) ) { - message_flush( data ); - globalErrorStream() << "No stream version given in the feedback stream, this is an old q3map version.\n" - "Please turn off monitored compiling if you still wish to use this q3map executable\n"; - abortStream( data ); - return; - } - else if ( strcmp( reinterpret_cast( attrs[1] ), Q3MAP_STREAM_VERSION ) != 0 ) { - message_flush( data ); - globalErrorStream() << - "This version of Radiant reads version " Q3MAP_STREAM_VERSION " debug streams, I got an incoming connection with version " << reinterpret_cast( attrs[1] ) << "\n" - "Please make sure your versions of Radiant and q3map are matching.\n"; - abortStream( data ); - return; - } - } - // we don't treat locally - else if ( strcmp( reinterpret_cast( name ), "message" ) == 0 ) { - int msg_level = atoi( reinterpret_cast( attrs[1] ) ); - if ( msg_level != data->msg_level ) { - message_flush( data ); - data->msg_level = msg_level; - } - } - else if ( strcmp( reinterpret_cast( name ), "polyline" ) == 0 ) { - // polyline has a particular status .. right now we only use it for leakfile .. - data->geometry_depth = data->recurse; - data->pGeometry = &g_pointfile; - data->pGeometry->saxStartElement( data, name, attrs ); - } - else if ( strcmp( reinterpret_cast( name ), "select" ) == 0 ) { - CSelectMsg *pSelect = new CSelectMsg(); - data->geometry_depth = data->recurse; - data->pGeometry = pSelect; - data->pGeometry->saxStartElement( data, name, attrs ); - } - else if ( strcmp( reinterpret_cast( name ), "pointmsg" ) == 0 ) { - CPointMsg *pPoint = new CPointMsg(); - data->geometry_depth = data->recurse; - data->pGeometry = pPoint; - data->pGeometry->saxStartElement( data, name, attrs ); - } - else if ( strcmp( reinterpret_cast( name ), "windingmsg" ) == 0 ) { - CWindingMsg *pWinding = new CWindingMsg(); - data->geometry_depth = data->recurse; - data->pGeometry = pWinding; - data->pGeometry->saxStartElement( data, name, attrs ); - } - else - { - globalErrorStream() << "Warning: ignoring unrecognized node in XML stream (" << reinterpret_cast( name ) << ")\n"; - // we don't recognize this node, jump over it - // (NOTE: the ignore mechanism is a bit screwed, only works when starting an ignore at the highest level) - data->ignore_depth = data->recurse; - } - } - } - data->recurse++; + if (data->ignore_depth == 0) { + if (data->pGeometry != 0) { + // we have a handler + data->pGeometry->saxStartElement(data, name, attrs); + } else { + if (strcmp(reinterpret_cast( name ), "q3map_feedback") == 0) { + // check the correct version + // old q3map don't send a version attribute + // the ones we support .. send Q3MAP_STREAM_VERSION + if (!attrs[0] || !attrs[1] || (strcmp(reinterpret_cast( attrs[0] ), "version") != 0)) { + message_flush(data); + globalErrorStream() + << "No stream version given in the feedback stream, this is an old q3map version.\n" + "Please turn off monitored compiling if you still wish to use this q3map executable\n"; + abortStream(data); + return; + } else if (strcmp(reinterpret_cast( attrs[1] ), Q3MAP_STREAM_VERSION) != 0) { + message_flush(data); + globalErrorStream() << + "This version of Radiant reads version " Q3MAP_STREAM_VERSION " debug streams, I got an incoming connection with version " + << reinterpret_cast( attrs[1] ) << "\n" + "Please make sure your versions of Radiant and q3map are matching.\n"; + abortStream(data); + return; + } + } + // we don't treat locally + else if (strcmp(reinterpret_cast( name ), "message") == 0) { + int msg_level = atoi(reinterpret_cast( attrs[1] )); + if (msg_level != data->msg_level) { + message_flush(data); + data->msg_level = msg_level; + } + } else if (strcmp(reinterpret_cast( name ), "polyline") == 0) { + // polyline has a particular status .. right now we only use it for leakfile .. + data->geometry_depth = data->recurse; + data->pGeometry = &g_pointfile; + data->pGeometry->saxStartElement(data, name, attrs); + } else if (strcmp(reinterpret_cast( name ), "select") == 0) { + CSelectMsg *pSelect = new CSelectMsg(); + data->geometry_depth = data->recurse; + data->pGeometry = pSelect; + data->pGeometry->saxStartElement(data, name, attrs); + } else if (strcmp(reinterpret_cast( name ), "pointmsg") == 0) { + CPointMsg *pPoint = new CPointMsg(); + data->geometry_depth = data->recurse; + data->pGeometry = pPoint; + data->pGeometry->saxStartElement(data, name, attrs); + } else if (strcmp(reinterpret_cast( name ), "windingmsg") == 0) { + CWindingMsg *pWinding = new CWindingMsg(); + data->geometry_depth = data->recurse; + data->pGeometry = pWinding; + data->pGeometry->saxStartElement(data, name, attrs); + } else { + globalErrorStream() << "Warning: ignoring unrecognized node in XML stream (" + << reinterpret_cast( name ) << ")\n"; + // we don't recognize this node, jump over it + // (NOTE: the ignore mechanism is a bit screwed, only works when starting an ignore at the highest level) + data->ignore_depth = data->recurse; + } + } + } + data->recurse++; } -static void saxEndElement( message_info_t *data, const xmlChar *name ){ +static void saxEndElement(message_info_t *data, const xmlChar *name) +{ #if 0 - globalOutputStream() << "<" << name << "/>\n"; + globalOutputStream() << "<" << name << "/>\n"; #endif - data->recurse--; - // we are out of an ignored chunk - if ( data->recurse == data->ignore_depth ) { - data->ignore_depth = 0; - return; - } - if ( data->pGeometry != 0 ) { - data->pGeometry->saxEndElement( data, name ); - // we add the object to the debug window - if ( data->geometry_depth == data->recurse ) { - g_DbgDlg.Push( data->pGeometry ); - data->pGeometry = 0; - } - } - if ( data->recurse == data->stop_depth ) { - message_flush( data ); + data->recurse--; + // we are out of an ignored chunk + if (data->recurse == data->ignore_depth) { + data->ignore_depth = 0; + return; + } + if (data->pGeometry != 0) { + data->pGeometry->saxEndElement(data, name); + // we add the object to the debug window + if (data->geometry_depth == data->recurse) { + g_DbgDlg.Push(data->pGeometry); + data->pGeometry = 0; + } + } + if (data->recurse == data->stop_depth) { + message_flush(data); #if GDEF_DEBUG - globalOutputStream() << "Received error msg .. shutting down..\n"; + globalOutputStream() << "Received error msg .. shutting down..\n"; #endif - GetWatchBSP()->EndMonitoringLoop(); - // tell there has been an error + GetWatchBSP()->EndMonitoringLoop(); + // tell there has been an error #if 0 - if ( GetWatchBSP()->HasBSPPlugin() ) { - g_BSPFrontendTable.m_pfnEndListen( 2 ); - } + if ( GetWatchBSP()->HasBSPPlugin() ) { + g_BSPFrontendTable.m_pfnEndListen( 2 ); + } #endif - return; - } + return; + } } -class MessageOutputStream : public TextOutputStream -{ - message_info_t* m_data; +class MessageOutputStream : public TextOutputStream { + message_info_t *m_data; public: - MessageOutputStream( message_info_t* data ) : m_data( data ){ - } - - std::size_t write( const char* buffer, std::size_t length ){ - if ( m_data->pGeometry != 0 ) { - m_data->pGeometry->saxCharacters( m_data, reinterpret_cast( buffer ), int(length) ); - } - else - { - if ( m_data->ignore_depth == 0 ) { - // output the message using the level - message_print( m_data, buffer, length ); - // if this message has error level flag, we mark the depth to stop the compilation when we get out - // we don't set the msg level if we don't stop on leak - if ( m_data->msg_level == 3 ) { - m_data->stop_depth = m_data->recurse - 1; - } - } - } - - return length; - } + MessageOutputStream(message_info_t *data) : m_data(data) + { + } + + std::size_t write(const char *buffer, std::size_t length) + { + if (m_data->pGeometry != 0) { + m_data->pGeometry->saxCharacters(m_data, reinterpret_cast( buffer ), int(length)); + } else { + if (m_data->ignore_depth == 0) { + // output the message using the level + message_print(m_data, buffer, length); + // if this message has error level flag, we mark the depth to stop the compilation when we get out + // we don't set the msg level if we don't stop on leak + if (m_data->msg_level == 3) { + m_data->stop_depth = m_data->recurse - 1; + } + } + } + + return length; + } }; template -inline MessageOutputStream& operator<<( MessageOutputStream& ostream, const T& t ){ - return ostream_write( ostream, t ); +inline MessageOutputStream &operator<<(MessageOutputStream &ostream, const T &t) +{ + return ostream_write(ostream, t); } -static void saxCharacters( message_info_t *data, const xmlChar *ch, int len ){ - MessageOutputStream ostream( data ); - ostream << StringRange( reinterpret_cast( ch ), reinterpret_cast( ch + len ) ); +static void saxCharacters(message_info_t *data, const xmlChar *ch, int len) +{ + MessageOutputStream ostream(data); + ostream << StringRange(reinterpret_cast( ch ), reinterpret_cast( ch + len )); } -static void saxComment( void *ctx, const xmlChar *msg ){ - globalOutputStream() << "XML comment: " << reinterpret_cast( msg ) << "\n"; +static void saxComment(void *ctx, const xmlChar *msg) +{ + globalOutputStream() << "XML comment: " << reinterpret_cast( msg ) << "\n"; } -static void saxWarning( void *ctx, const char *msg, ... ){ - char saxMsgBuffer[4096]; - va_list args; +static void saxWarning(void *ctx, const char *msg, ...) +{ + char saxMsgBuffer[4096]; + va_list args; - va_start( args, msg ); - vsprintf( saxMsgBuffer, msg, args ); - va_end( args ); - globalOutputStream() << "XML warning: " << saxMsgBuffer << "\n"; + va_start(args, msg); + vsprintf(saxMsgBuffer, msg, args); + va_end(args); + globalOutputStream() << "XML warning: " << saxMsgBuffer << "\n"; } -static void saxError( void *ctx, const char *msg, ... ){ - char saxMsgBuffer[4096]; - va_list args; +static void saxError(void *ctx, const char *msg, ...) +{ + char saxMsgBuffer[4096]; + va_list args; - va_start( args, msg ); - vsprintf( saxMsgBuffer, msg, args ); - va_end( args ); - globalErrorStream() << "XML error: " << saxMsgBuffer << "\n"; + va_start(args, msg); + vsprintf(saxMsgBuffer, msg, args); + va_end(args); + globalErrorStream() << "XML error: " << saxMsgBuffer << "\n"; } -static void saxFatal( void *ctx, const char *msg, ... ){ - char buffer[4096]; +static void saxFatal(void *ctx, const char *msg, ...) +{ + char buffer[4096]; - va_list args; + va_list args; - va_start( args, msg ); - vsprintf( buffer, msg, args ); - va_end( args ); - globalErrorStream() << "XML fatal error: " << buffer << "\n"; + va_start(args, msg); + vsprintf(buffer, msg, args); + va_end(args); + globalErrorStream() << "XML fatal error: " << buffer << "\n"; } static xmlSAXHandler saxParser = { - 0, /* internalSubset */ - 0, /* isStandalone */ - 0, /* hasInternalSubset */ - 0, /* hasExternalSubset */ - 0, /* resolveEntity */ - 0, /* getEntity */ - 0, /* entityDecl */ - 0, /* notationDecl */ - 0, /* attributeDecl */ - 0, /* elementDecl */ - 0, /* unparsedEntityDecl */ - 0, /* setDocumentLocator */ - 0, /* startDocument */ - 0, /* endDocument */ - (startElementSAXFunc)saxStartElement, /* startElement */ - (endElementSAXFunc)saxEndElement, /* endElement */ - 0, /* reference */ - (charactersSAXFunc)saxCharacters, /* characters */ - 0, /* ignorableWhitespace */ - 0, /* processingInstruction */ - (commentSAXFunc)saxComment, /* comment */ - (warningSAXFunc)saxWarning, /* warning */ - (errorSAXFunc)saxError, /* error */ - (fatalErrorSAXFunc)saxFatal, /* fatalError */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 + 0, /* internalSubset */ + 0, /* isStandalone */ + 0, /* hasInternalSubset */ + 0, /* hasExternalSubset */ + 0, /* resolveEntity */ + 0, /* getEntity */ + 0, /* entityDecl */ + 0, /* notationDecl */ + 0, /* attributeDecl */ + 0, /* elementDecl */ + 0, /* unparsedEntityDecl */ + 0, /* setDocumentLocator */ + 0, /* startDocument */ + 0, /* endDocument */ + (startElementSAXFunc) saxStartElement, /* startElement */ + (endElementSAXFunc) saxEndElement, /* endElement */ + 0, /* reference */ + (charactersSAXFunc) saxCharacters, /* characters */ + 0, /* ignorableWhitespace */ + 0, /* processingInstruction */ + (commentSAXFunc) saxComment, /* comment */ + (warningSAXFunc) saxWarning, /* warning */ + (errorSAXFunc) saxError, /* error */ + (fatalErrorSAXFunc) saxFatal, /* fatalError */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 }; // ------------------------------------------------------------------------------------------------ guint s_routine_id; -static gint watchbsp_routine( gpointer data ){ - reinterpret_cast( data )->RoutineProcessing(); - return TRUE; + +static gint watchbsp_routine(gpointer data) +{ + reinterpret_cast( data )->RoutineProcessing(); + return TRUE; } -void CWatchBSP::Reset(){ - if ( m_pInSocket ) { - Net_Disconnect( m_pInSocket ); - m_pInSocket = NULL; - } - if ( m_pListenSocket ) { - Net_Disconnect( m_pListenSocket ); - m_pListenSocket = NULL; - } - if ( m_xmlInputBuffer ) { - xmlFreeParserInputBuffer( m_xmlInputBuffer ); - m_xmlInputBuffer = NULL; - } - m_eState = EIdle; - if ( s_routine_id ) { - g_source_remove( s_routine_id ); - } +void CWatchBSP::Reset() +{ + if (m_pInSocket) { + Net_Disconnect(m_pInSocket); + m_pInSocket = NULL; + } + if (m_pListenSocket) { + Net_Disconnect(m_pListenSocket); + m_pListenSocket = NULL; + } + if (m_xmlInputBuffer) { + xmlFreeParserInputBuffer(m_xmlInputBuffer); + m_xmlInputBuffer = NULL; + } + m_eState = EIdle; + if (s_routine_id) { + g_source_remove(s_routine_id); + } } -bool CWatchBSP::SetupListening(){ +bool CWatchBSP::SetupListening() +{ #if GDEF_DEBUG - if ( m_pListenSocket ) { - globalOutputStream() << "ERROR: m_pListenSocket != NULL in CWatchBSP::SetupListening\n"; - return false; - } + if (m_pListenSocket) { + globalOutputStream() << "ERROR: m_pListenSocket != NULL in CWatchBSP::SetupListening\n"; + return false; + } #endif - globalOutputStream() << "Setting up\n"; - Net_Setup(); - m_pListenSocket = Net_ListenSocket( 39000 ); - if ( m_pListenSocket == NULL ) { - return false; - } - globalOutputStream() << "Listening...\n"; - return true; + globalOutputStream() << "Setting up\n"; + Net_Setup(); + m_pListenSocket = Net_ListenSocket(39000); + if (m_pListenSocket == NULL) { + return false; + } + globalOutputStream() << "Listening...\n"; + return true; } -void CWatchBSP::DoEBeginStep(){ - Reset(); - if ( SetupListening() == false ) { - const char* msg = "Failed to get a listening socket on port 39000.\nTry running with Build monitoring disabled if you can't fix this.\n"; - globalOutputStream() << msg; - ui::alert( MainFrame_getWindow(), msg, "Build monitoring", ui::alert_type::OK, ui::alert_icon::Error ); - return; - } - // set the timer for timeouts and step cancellation - g_timer_reset( m_pTimer ); - g_timer_start( m_pTimer ); - - if ( !m_bBSPPlugin ) { - globalOutputStream() << "=== running build command ===\n" - << static_cast( g_ptr_array_index( m_pCmd, m_iCurrentStep ) ) << "\n"; - - if ( !Q_Exec( NULL, (char *)g_ptr_array_index( m_pCmd, m_iCurrentStep ), NULL, true, false ) ) { - StringOutputStream msg( 256 ); - msg << "Failed to execute the following command: "; - msg << reinterpret_cast( g_ptr_array_index( m_pCmd, m_iCurrentStep ) ); - msg << "\nCheck that the file exists and that you don't run out of system resources.\n"; - globalOutputStream() << msg.c_str(); - ui::alert( MainFrame_getWindow(), msg.c_str(), "Build monitoring", ui::alert_type::OK, ui::alert_icon::Error ); - return; - } - // re-initialise the debug window - if ( m_iCurrentStep == 0 ) { - g_DbgDlg.Init(); - } - } - m_eState = EBeginStep; - s_routine_id = g_timeout_add( 25, watchbsp_routine, this ); +void CWatchBSP::DoEBeginStep() +{ + Reset(); + if (SetupListening() == false) { + const char *msg = "Failed to get a listening socket on port 39000.\nTry running with Build monitoring disabled if you can't fix this.\n"; + globalOutputStream() << msg; + ui::alert(MainFrame_getWindow(), msg, "Build monitoring", ui::alert_type::OK, ui::alert_icon::Error); + return; + } + // set the timer for timeouts and step cancellation + g_timer_reset(m_pTimer); + g_timer_start(m_pTimer); + + if (!m_bBSPPlugin) { + globalOutputStream() << "=== running build command ===\n" + << static_cast(g_ptr_array_index(m_pCmd, m_iCurrentStep) ) << "\n"; + + if (!Q_Exec(NULL, (char *) g_ptr_array_index(m_pCmd, m_iCurrentStep), NULL, true, false)) { + StringOutputStream msg(256); + msg << "Failed to execute the following command: "; + msg << reinterpret_cast(g_ptr_array_index(m_pCmd, m_iCurrentStep) ); + msg << "\nCheck that the file exists and that you don't run out of system resources.\n"; + globalOutputStream() << msg.c_str(); + ui::alert(MainFrame_getWindow(), msg.c_str(), "Build monitoring", ui::alert_type::OK, + ui::alert_icon::Error); + return; + } + // re-initialise the debug window + if (m_iCurrentStep == 0) { + g_DbgDlg.Init(); + } + } + m_eState = EBeginStep; + s_routine_id = g_timeout_add(25, watchbsp_routine, this); } @@ -559,241 +585,235 @@ const char *MP_ENGINE_ATTRIBUTE = "mp_engine_macos"; #error "unsupported platform" #endif -class RunEngineConfiguration -{ +class RunEngineConfiguration { public: - const char* executable; - const char* mp_executable; - bool do_sp_mp; - - RunEngineConfiguration() : - executable( g_pGameDescription->getRequiredKeyValue( ENGINE_ATTRIBUTE ) ), - mp_executable( g_pGameDescription->getKeyValue( MP_ENGINE_ATTRIBUTE ) ){ - do_sp_mp = !string_empty( mp_executable ); - } + const char *executable; + const char *mp_executable; + bool do_sp_mp; + + RunEngineConfiguration() : + executable(g_pGameDescription->getRequiredKeyValue(ENGINE_ATTRIBUTE)), + mp_executable(g_pGameDescription->getKeyValue(MP_ENGINE_ATTRIBUTE)) + { + do_sp_mp = !string_empty(mp_executable); + } }; -inline void GlobalGameDescription_string_write_mapparameter( StringOutputStream& string, const char* mapname ){ - if ( g_pGameDescription->mGameType == "q2" - || g_pGameDescription->mGameType == "heretic2" ) { - string << ". +exec radiant.cfg +map " << mapname; - } - else - { - string << "+set sv_pure 0 "; - // TTimo: a check for vm_* but that's all fine - //cmdline = "+set sv_pure 0 +set vm_ui 0 +set vm_cgame 0 +set vm_game 0 "; - const char* fs_game = gamename_get(); - if ( !string_equal( fs_game, basegame_get() ) ) { - string << "+set fs_game " << fs_game << " "; - } - if ( g_pGameDescription->mGameType == "wolf" ) { - //|| g_pGameDescription->mGameType == "et") - if ( string_equal( gamemode_get(), "mp" ) ) { - // MP - string << "+devmap " << mapname; - } - else - { - // SP - string << "+set nextmap \"spdevmap " << mapname << "\""; - } - } - else - { - string << "+devmap " << mapname; - } - } +inline void GlobalGameDescription_string_write_mapparameter(StringOutputStream &string, const char *mapname) +{ + if (g_pGameDescription->mGameType == "q2" + || g_pGameDescription->mGameType == "heretic2") { + string << ". +exec radiant.cfg +map " << mapname; + } else { + string << "+set sv_pure 0 "; + // TTimo: a check for vm_* but that's all fine + //cmdline = "+set sv_pure 0 +set vm_ui 0 +set vm_cgame 0 +set vm_game 0 "; + const char *fs_game = gamename_get(); + if (!string_equal(fs_game, basegame_get())) { + string << "+set fs_game " << fs_game << " "; + } + if (g_pGameDescription->mGameType == "wolf") { + //|| g_pGameDescription->mGameType == "et") + if (string_equal(gamemode_get(), "mp")) { + // MP + string << "+devmap " << mapname; + } else { + // SP + string << "+set nextmap \"spdevmap " << mapname << "\""; + } + } else { + string << "+devmap " << mapname; + } + } } -void CWatchBSP::RoutineProcessing(){ - switch ( m_eState ) - { - case EBeginStep: - // timeout: if we don't get an incoming connection fast enough, go back to idle - if ( g_timer_elapsed( m_pTimer, NULL ) > g_WatchBSP_Timeout ) { - ui::alert( MainFrame_getWindow(), "The connection timed out, assuming the build process failed\nMake sure you are using a networked version of Q3Map?\nOtherwise you need to disable BSP Monitoring in prefs.", "BSP process monitoring", ui::alert_type::OK ); - EndMonitoringLoop(); +void CWatchBSP::RoutineProcessing() +{ + switch (m_eState) { + case EBeginStep: + // timeout: if we don't get an incoming connection fast enough, go back to idle + if (g_timer_elapsed(m_pTimer, NULL) > g_WatchBSP_Timeout) { + ui::alert(MainFrame_getWindow(), + "The connection timed out, assuming the build process failed\nMake sure you are using a networked version of Q3Map?\nOtherwise you need to disable BSP Monitoring in prefs.", + "BSP process monitoring", ui::alert_type::OK); + EndMonitoringLoop(); #if 0 - if ( m_bBSPPlugin ) { - // status == 1 : didn't get the connection - g_BSPFrontendTable.m_pfnEndListen( 1 ); - } + if ( m_bBSPPlugin ) { + // status == 1 : didn't get the connection + g_BSPFrontendTable.m_pfnEndListen( 1 ); + } #endif - return; - } + return; + } #if GDEF_DEBUG - // some debug checks - if ( !m_pListenSocket ) { - globalErrorStream() << "ERROR: m_pListenSocket == NULL in CWatchBSP::RoutineProcessing EBeginStep state\n"; - return; - } + // some debug checks + if (!m_pListenSocket) { + globalErrorStream() + << "ERROR: m_pListenSocket == NULL in CWatchBSP::RoutineProcessing EBeginStep state\n"; + return; + } #endif - // we are not connected yet, accept any incoming connection - m_pInSocket = Net_Accept( m_pListenSocket ); - if ( m_pInSocket ) { - globalOutputStream() << "Connected.\n"; - // prepare the message info struct for diving in - memset( &m_message_info, 0, sizeof( message_info_t ) ); - // a dumb flag to make sure we init the push parser context when first getting a msg - m_bNeedCtxtInit = true; - m_eState = EWatching; - } - break; - case EWatching: - { + // we are not connected yet, accept any incoming connection + m_pInSocket = Net_Accept(m_pListenSocket); + if (m_pInSocket) { + globalOutputStream() << "Connected.\n"; + // prepare the message info struct for diving in + memset(&m_message_info, 0, sizeof(message_info_t)); + // a dumb flag to make sure we init the push parser context when first getting a msg + m_bNeedCtxtInit = true; + m_eState = EWatching; + } + break; + case EWatching: { #if GDEF_DEBUG - // some debug checks - if ( !m_pInSocket ) { - globalErrorStream() << "ERROR: m_pInSocket == NULL in CWatchBSP::RoutineProcessing EWatching state\n"; - return; - } + // some debug checks + if (!m_pInSocket) { + globalErrorStream() << "ERROR: m_pInSocket == NULL in CWatchBSP::RoutineProcessing EWatching state\n"; + return; + } #endif - int ret = Net_Wait( m_pInSocket, 0, 0 ); - if ( ret == -1 ) { - globalOutputStream() << "WARNING: SOCKET_ERROR in CWatchBSP::RoutineProcessing\n"; - globalOutputStream() << "Terminating the connection.\n"; - EndMonitoringLoop(); - return; - } - - if ( ret == 1 ) { - // the socket has been identified, there's something (message or disconnection) - // see if there's anything in input - ret = Net_Receive( m_pInSocket, &msg ); - if ( ret > 0 ) { - // unsigned int size = msg.size; //++timo just a check - strcpy( m_xmlBuf, NMSG_ReadString( &msg ) ); - if ( m_bNeedCtxtInit ) { - m_xmlParserCtxt = NULL; - m_xmlParserCtxt = xmlCreatePushParserCtxt( &saxParser, &m_message_info, m_xmlBuf, static_cast( strlen( m_xmlBuf ) ), NULL ); - - if ( m_xmlParserCtxt == NULL ) { - globalErrorStream() << "Failed to create the XML parser (incoming stream began with: " << m_xmlBuf << ")\n"; - EndMonitoringLoop(); - } - m_bNeedCtxtInit = false; - } - else - { - xmlParseChunk( m_xmlParserCtxt, m_xmlBuf, static_cast( strlen( m_xmlBuf ) ), 0 ); - } - } - else - { - message_flush( &m_message_info ); - // error or connection closed/reset - // NOTE: if we get an error down the XML stream we don't reach here - Net_Disconnect( m_pInSocket ); - m_pInSocket = NULL; - globalOutputStream() << "Connection closed.\n"; + int ret = Net_Wait(m_pInSocket, 0, 0); + if (ret == -1) { + globalOutputStream() << "WARNING: SOCKET_ERROR in CWatchBSP::RoutineProcessing\n"; + globalOutputStream() << "Terminating the connection.\n"; + EndMonitoringLoop(); + return; + } + + if (ret == 1) { + // the socket has been identified, there's something (message or disconnection) + // see if there's anything in input + ret = Net_Receive(m_pInSocket, &msg); + if (ret > 0) { + // unsigned int size = msg.size; //++timo just a check + strcpy(m_xmlBuf, NMSG_ReadString(&msg)); + if (m_bNeedCtxtInit) { + m_xmlParserCtxt = NULL; + m_xmlParserCtxt = xmlCreatePushParserCtxt(&saxParser, &m_message_info, m_xmlBuf, + static_cast( strlen(m_xmlBuf)), NULL); + + if (m_xmlParserCtxt == NULL) { + globalErrorStream() << "Failed to create the XML parser (incoming stream began with: " + << m_xmlBuf << ")\n"; + EndMonitoringLoop(); + } + m_bNeedCtxtInit = false; + } else { + xmlParseChunk(m_xmlParserCtxt, m_xmlBuf, static_cast( strlen(m_xmlBuf)), 0); + } + } else { + message_flush(&m_message_info); + // error or connection closed/reset + // NOTE: if we get an error down the XML stream we don't reach here + Net_Disconnect(m_pInSocket); + m_pInSocket = NULL; + globalOutputStream() << "Connection closed.\n"; #if 0 - if ( m_bBSPPlugin ) { - EndMonitoringLoop(); - // let the BSP plugin know that the job is done - g_BSPFrontendTable.m_pfnEndListen( 0 ); - return; - } + if ( m_bBSPPlugin ) { + EndMonitoringLoop(); + // let the BSP plugin know that the job is done + g_BSPFrontendTable.m_pfnEndListen( 0 ); + return; + } #endif - // move to next step or finish - m_iCurrentStep++; - if ( m_iCurrentStep < m_pCmd->len ) { - DoEBeginStep(); - } - else - { - // launch the engine .. OMG - if ( g_WatchBSP_RunQuake ) { + // move to next step or finish + m_iCurrentStep++; + if (m_iCurrentStep < m_pCmd->len) { + DoEBeginStep(); + } else { + // launch the engine .. OMG + if (g_WatchBSP_RunQuake) { #if 0 - // do we enter sleep mode before? - if ( g_WatchBSP_DoSleep ) { - globalOutputStream() << "Going into sleep mode..\n"; - g_pParentWnd->OnSleep(); - } + // do we enter sleep mode before? + if ( g_WatchBSP_DoSleep ) { + globalOutputStream() << "Going into sleep mode..\n"; + g_pParentWnd->OnSleep(); + } #endif - globalOutputStream() << "Running engine...\n"; - StringOutputStream cmd( 256 ); - // build the command line - cmd << EnginePath_get(); - // this is game dependant - - RunEngineConfiguration engineConfig; - - if ( engineConfig.do_sp_mp ) { - if ( string_equal( gamemode_get(), "mp" ) ) { - cmd << engineConfig.mp_executable; - } - else - { - cmd << engineConfig.executable; - } - } - else - { - cmd << engineConfig.executable; - } - - StringOutputStream cmdline; - - GlobalGameDescription_string_write_mapparameter( cmdline, m_sBSPName ); - - globalOutputStream() << cmd.c_str() << " " << cmdline.c_str() << "\n"; - - // execute now - if ( !Q_Exec( cmd.c_str(), (char *)cmdline.c_str(), EnginePath_get(), false, false ) ) { - StringOutputStream msg; - msg << "Failed to execute the following command: " << cmd.c_str() << cmdline.c_str(); - globalOutputStream() << msg.c_str(); - ui::alert( MainFrame_getWindow(), msg.c_str(), "Build monitoring", ui::alert_type::OK, ui::alert_icon::Error ); - } - } - EndMonitoringLoop(); - } - } - } - } - break; - default: - break; - } + globalOutputStream() << "Running engine...\n"; + StringOutputStream cmd(256); + // build the command line + cmd << EnginePath_get(); + // this is game dependant + + RunEngineConfiguration engineConfig; + + if (engineConfig.do_sp_mp) { + if (string_equal(gamemode_get(), "mp")) { + cmd << engineConfig.mp_executable; + } else { + cmd << engineConfig.executable; + } + } else { + cmd << engineConfig.executable; + } + + StringOutputStream cmdline; + + GlobalGameDescription_string_write_mapparameter(cmdline, m_sBSPName); + + globalOutputStream() << cmd.c_str() << " " << cmdline.c_str() << "\n"; + + // execute now + if (!Q_Exec(cmd.c_str(), (char *) cmdline.c_str(), EnginePath_get(), false, false)) { + StringOutputStream msg; + msg << "Failed to execute the following command: " << cmd.c_str() << cmdline.c_str(); + globalOutputStream() << msg.c_str(); + ui::alert(MainFrame_getWindow(), msg.c_str(), "Build monitoring", ui::alert_type::OK, + ui::alert_icon::Error); + } + } + EndMonitoringLoop(); + } + } + } + } + break; + default: + break; + } } -GPtrArray* str_ptr_array_clone( GPtrArray* array ){ - GPtrArray* cloned = g_ptr_array_sized_new( array->len ); - for ( guint i = 0; i < array->len; ++i ) - { - g_ptr_array_add( cloned, g_strdup( (char*)g_ptr_array_index( array, i ) ) ); - } - return cloned; +GPtrArray *str_ptr_array_clone(GPtrArray *array) +{ + GPtrArray *cloned = g_ptr_array_sized_new(array->len); + for (guint i = 0; i < array->len; ++i) { + g_ptr_array_add(cloned, g_strdup((char *) g_ptr_array_index(array, i))); + } + return cloned; } -void CWatchBSP::DoMonitoringLoop( GPtrArray *pCmd, const char *sBSPName ){ - m_sBSPName = string_clone( sBSPName ); - if ( m_eState != EIdle ) { - globalOutputStream() << "WatchBSP got a monitoring request while not idling...\n"; - // prompt the user, should we cancel the current process and go ahead? - if ( ui::alert( MainFrame_getWindow(), "I am already monitoring a Build process.\nDo you want me to override and start a new compilation?", - "Build process monitoring", ui::alert_type::YESNO ) == ui::alert_response::YES ) { - // disconnect and set EIdle state - Reset(); - } - } - m_pCmd = str_ptr_array_clone( pCmd ); - m_iCurrentStep = 0; - DoEBeginStep(); +void CWatchBSP::DoMonitoringLoop(GPtrArray *pCmd, const char *sBSPName) +{ + m_sBSPName = string_clone(sBSPName); + if (m_eState != EIdle) { + globalOutputStream() << "WatchBSP got a monitoring request while not idling...\n"; + // prompt the user, should we cancel the current process and go ahead? + if (ui::alert(MainFrame_getWindow(), + "I am already monitoring a Build process.\nDo you want me to override and start a new compilation?", + "Build process monitoring", ui::alert_type::YESNO) == ui::alert_response::YES) { + // disconnect and set EIdle state + Reset(); + } + } + m_pCmd = str_ptr_array_clone(pCmd); + m_iCurrentStep = 0; + DoEBeginStep(); } -void CWatchBSP::ExternalListen(){ - m_bBSPPlugin = true; - DoEBeginStep(); +void CWatchBSP::ExternalListen() +{ + m_bBSPPlugin = true; + DoEBeginStep(); } // the part of the watchbsp interface we export to plugins // NOTE: in the long run, the whole watchbsp.cpp interface needs to go out and be handled at the BSP plugin level // for now we provide something really basic and limited, the essential is to have something that works fine and fast (for 1.1 final) -void QERApp_Listen(){ - // open the listening socket - GetWatchBSP()->ExternalListen(); +void QERApp_Listen() +{ + // open the listening socket + GetWatchBSP()->ExternalListen(); } diff --git a/radiant/watchbsp.h b/radiant/watchbsp.h index 94b5a584..b8f43450 100644 --- a/radiant/watchbsp.h +++ b/radiant/watchbsp.h @@ -32,10 +32,12 @@ #define INCLUDED_WATCHBSP_H void BuildMonitor_Construct(); + void BuildMonitor_Destroy(); typedef struct _GPtrArray GPtrArray; -void BuildMonitor_Run( GPtrArray* commands, const char* mapName ); + +void BuildMonitor_Run(GPtrArray *commands, const char *mapName); extern bool g_WatchBSP_Enabled; extern bool g_WatchBSP_LeakStop; diff --git a/radiant/winding.cpp b/radiant/winding.cpp index 9651af2c..d027f52d 100644 --- a/radiant/winding.cpp +++ b/radiant/winding.cpp @@ -26,161 +26,173 @@ #include "math/line.h" -inline double plane3_distance_to_point( const Plane3& plane, const DoubleVector3& point ){ - return vector3_dot( point, plane.normal() ) - plane.dist(); +inline double plane3_distance_to_point(const Plane3 &plane, const DoubleVector3 &point) +{ + return vector3_dot(point, plane.normal()) - plane.dist(); } -inline double plane3_distance_to_point( const Plane3& plane, const Vector3& point ){ - return vector3_dot( point, plane.normal() ) - plane.dist(); +inline double plane3_distance_to_point(const Plane3 &plane, const Vector3 &point) +{ + return vector3_dot(point, plane.normal()) - plane.dist(); } /// \brief Returns the point at which \p line intersects \p plane, or an undefined value if there is no intersection. -inline DoubleVector3 line_intersect_plane( const DoubleLine& line, const Plane3& plane ){ - return line.origin + vector3_scaled( - line.direction, - -plane3_distance_to_point( plane, line.origin ) - / vector3_dot( line.direction, plane.normal() ) - ); +inline DoubleVector3 line_intersect_plane(const DoubleLine &line, const Plane3 &plane) +{ + return line.origin + vector3_scaled( + line.direction, + -plane3_distance_to_point(plane, line.origin) + / vector3_dot(line.direction, plane.normal()) + ); } -inline bool float_is_largest_absolute( double axis, double other ){ - return fabs( axis ) > fabs( other ); +inline bool float_is_largest_absolute(double axis, double other) +{ + return fabs(axis) > fabs(other); } /// \brief Returns the index of the component of \p v that has the largest absolute value. -inline int vector3_largest_absolute_component_index( const DoubleVector3& v ){ - return ( float_is_largest_absolute( v[1], v[0] ) ) - ? ( float_is_largest_absolute( v[1], v[2] ) ) - ? 1 - : 2 - : ( float_is_largest_absolute( v[0], v[2] ) ) - ? 0 - : 2; +inline int vector3_largest_absolute_component_index(const DoubleVector3 &v) +{ + return (float_is_largest_absolute(v[1], v[0])) + ? (float_is_largest_absolute(v[1], v[2])) + ? 1 + : 2 + : (float_is_largest_absolute(v[0], v[2])) + ? 0 + : 2; } /// \brief Returns the infinite line that is the intersection of \p plane and \p other. -inline DoubleLine plane3_intersect_plane3( const Plane3& plane, const Plane3& other ){ - DoubleLine line; - line.direction = vector3_cross( plane.normal(), other.normal() ); - switch ( vector3_largest_absolute_component_index( line.direction ) ) - { - case 0: - line.origin.x() = 0; - line.origin.y() = ( -other.dist() * plane.normal().z() - -plane.dist() * other.normal().z() ) / line.direction.x(); - line.origin.z() = ( -plane.dist() * other.normal().y() - -other.dist() * plane.normal().y() ) / line.direction.x(); - break; - case 1: - line.origin.x() = ( -plane.dist() * other.normal().z() - -other.dist() * plane.normal().z() ) / line.direction.y(); - line.origin.y() = 0; - line.origin.z() = ( -other.dist() * plane.normal().x() - -plane.dist() * other.normal().x() ) / line.direction.y(); - break; - case 2: - line.origin.x() = ( -other.dist() * plane.normal().y() - -plane.dist() * other.normal().y() ) / line.direction.z(); - line.origin.y() = ( -plane.dist() * other.normal().x() - -other.dist() * plane.normal().x() ) / line.direction.z(); - line.origin.z() = 0; - break; - default: - break; - } - - return line; +inline DoubleLine plane3_intersect_plane3(const Plane3 &plane, const Plane3 &other) +{ + DoubleLine line; + line.direction = vector3_cross(plane.normal(), other.normal()); + switch (vector3_largest_absolute_component_index(line.direction)) { + case 0: + line.origin.x() = 0; + line.origin.y() = + (-other.dist() * plane.normal().z() - -plane.dist() * other.normal().z()) / line.direction.x(); + line.origin.z() = + (-plane.dist() * other.normal().y() - -other.dist() * plane.normal().y()) / line.direction.x(); + break; + case 1: + line.origin.x() = + (-plane.dist() * other.normal().z() - -other.dist() * plane.normal().z()) / line.direction.y(); + line.origin.y() = 0; + line.origin.z() = + (-other.dist() * plane.normal().x() - -plane.dist() * other.normal().x()) / line.direction.y(); + break; + case 2: + line.origin.x() = + (-other.dist() * plane.normal().y() - -plane.dist() * other.normal().y()) / line.direction.z(); + line.origin.y() = + (-plane.dist() * other.normal().x() - -other.dist() * plane.normal().x()) / line.direction.z(); + line.origin.z() = 0; + break; + default: + break; + } + + return line; } /// \brief Keep the value of \p infinity as small as possible to improve precision in Winding_Clip. -void Winding_createInfinite( FixedWinding& winding, const Plane3& plane, double infinity ){ - double max = -infinity; - int x = -1; - for ( int i = 0 ; i < 3; i++ ) - { - double d = fabs( plane.normal()[i] ); - if ( d > max ) { - x = i; - max = d; - } - } - if ( x == -1 ) { - globalErrorStream() << "invalid plane\n"; - return; - } - - DoubleVector3 vup = g_vector3_identity; - switch ( x ) - { - case 0: - case 1: - vup[2] = 1; - break; - case 2: - vup[0] = 1; - break; - } - - - vector3_add( vup, vector3_scaled( plane.normal(), -vector3_dot( vup, plane.normal() ) ) ); - vector3_normalise( vup ); - - DoubleVector3 org = vector3_scaled( plane.normal(), plane.dist() ); - - DoubleVector3 vright = vector3_cross( vup, plane.normal() ); - - vector3_scale( vup, infinity ); - vector3_scale( vright, infinity ); - - // project a really big axis aligned box onto the plane - - DoubleLine r1, r2, r3, r4; - r1.origin = vector3_added( vector3_subtracted( org, vright ), vup ); - r1.direction = vector3_normalised( vright ); - winding.push_back( FixedWindingVertex( r1.origin, r1, c_brush_maxFaces ) ); - r2.origin = vector3_added( vector3_added( org, vright ), vup ); - r2.direction = vector3_normalised( vector3_negated( vup ) ); - winding.push_back( FixedWindingVertex( r2.origin, r2, c_brush_maxFaces ) ); - r3.origin = vector3_subtracted( vector3_added( org, vright ), vup ); - r3.direction = vector3_normalised( vector3_negated( vright ) ); - winding.push_back( FixedWindingVertex( r3.origin, r3, c_brush_maxFaces ) ); - r4.origin = vector3_subtracted( vector3_subtracted( org, vright ), vup ); - r4.direction = vector3_normalised( vup ); - winding.push_back( FixedWindingVertex( r4.origin, r4, c_brush_maxFaces ) ); +void Winding_createInfinite(FixedWinding &winding, const Plane3 &plane, double infinity) +{ + double max = -infinity; + int x = -1; + for (int i = 0; i < 3; i++) { + double d = fabs(plane.normal()[i]); + if (d > max) { + x = i; + max = d; + } + } + if (x == -1) { + globalErrorStream() << "invalid plane\n"; + return; + } + + DoubleVector3 vup = g_vector3_identity; + switch (x) { + case 0: + case 1: + vup[2] = 1; + break; + case 2: + vup[0] = 1; + break; + } + + + vector3_add(vup, vector3_scaled(plane.normal(), -vector3_dot(vup, plane.normal()))); + vector3_normalise(vup); + + DoubleVector3 org = vector3_scaled(plane.normal(), plane.dist()); + + DoubleVector3 vright = vector3_cross(vup, plane.normal()); + + vector3_scale(vup, infinity); + vector3_scale(vright, infinity); + + // project a really big axis aligned box onto the plane + + DoubleLine r1, r2, r3, r4; + r1.origin = vector3_added(vector3_subtracted(org, vright), vup); + r1.direction = vector3_normalised(vright); + winding.push_back(FixedWindingVertex(r1.origin, r1, c_brush_maxFaces)); + r2.origin = vector3_added(vector3_added(org, vright), vup); + r2.direction = vector3_normalised(vector3_negated(vup)); + winding.push_back(FixedWindingVertex(r2.origin, r2, c_brush_maxFaces)); + r3.origin = vector3_subtracted(vector3_added(org, vright), vup); + r3.direction = vector3_normalised(vector3_negated(vright)); + winding.push_back(FixedWindingVertex(r3.origin, r3, c_brush_maxFaces)); + r4.origin = vector3_subtracted(vector3_subtracted(org, vright), vup); + r4.direction = vector3_normalised(vup); + winding.push_back(FixedWindingVertex(r4.origin, r4, c_brush_maxFaces)); } -inline PlaneClassification Winding_ClassifyDistance( const double distance, const double epsilon ){ - if ( distance > epsilon ) { - return ePlaneFront; - } - if ( distance < -epsilon ) { - return ePlaneBack; - } - return ePlaneOn; +inline PlaneClassification Winding_ClassifyDistance(const double distance, const double epsilon) +{ + if (distance > epsilon) { + return ePlaneFront; + } + if (distance < -epsilon) { + return ePlaneBack; + } + return ePlaneOn; } /// \brief Returns true if /// !flipped && winding is completely BACK or ON /// or flipped && winding is completely FRONT or ON -bool Winding_TestPlane( const Winding& winding, const Plane3& plane, bool flipped ){ - const int test = ( flipped ) ? ePlaneBack : ePlaneFront; - for ( Winding::const_iterator i = winding.begin(); i != winding.end(); ++i ) - { - if ( test == Winding_ClassifyDistance( plane3_distance_to_point( plane, ( *i ).vertex ), ON_EPSILON ) ) { - return false; - } - } - return true; +bool Winding_TestPlane(const Winding &winding, const Plane3 &plane, bool flipped) +{ + const int test = (flipped) ? ePlaneBack : ePlaneFront; + for (Winding::const_iterator i = winding.begin(); i != winding.end(); ++i) { + if (test == Winding_ClassifyDistance(plane3_distance_to_point(plane, (*i).vertex), ON_EPSILON)) { + return false; + } + } + return true; } /// \brief Returns true if any point in \p w1 is in front of plane2, or any point in \p w2 is in front of plane1 -bool Winding_PlanesConcave( const Winding& w1, const Winding& w2, const Plane3& plane1, const Plane3& plane2 ){ - return !Winding_TestPlane( w1, plane2, false ) || !Winding_TestPlane( w2, plane1, false ); +bool Winding_PlanesConcave(const Winding &w1, const Winding &w2, const Plane3 &plane1, const Plane3 &plane2) +{ + return !Winding_TestPlane(w1, plane2, false) || !Winding_TestPlane(w2, plane1, false); } -brushsplit_t Winding_ClassifyPlane( const Winding& winding, const Plane3& plane ){ - brushsplit_t split; - for ( Winding::const_iterator i = winding.begin(); i != winding.end(); ++i ) - { - ++split.counts[Winding_ClassifyDistance( plane3_distance_to_point( plane, ( *i ).vertex ), ON_EPSILON )]; - } - return split; +brushsplit_t Winding_ClassifyPlane(const Winding &winding, const Plane3 &plane) +{ + brushsplit_t split; + for (Winding::const_iterator i = winding.begin(); i != winding.end(); ++i) { + ++split.counts[Winding_ClassifyDistance(plane3_distance_to_point(plane, (*i).vertex), ON_EPSILON)]; + } + return split; } @@ -193,123 +205,125 @@ const double DEBUG_EPSILON_SQUARED = DEBUG_EPSILON * DEBUG_EPSILON; /// If \p winding is completely in front of the plane, \p clipped will be identical to \p winding. /// If \p winding is completely in back of the plane, \p clipped will be empty. /// If \p winding intersects the plane, the edge of \p clipped which lies on \p clipPlane will store the value of \p adjacent. -void Winding_Clip( const FixedWinding& winding, const Plane3& plane, const Plane3& clipPlane, std::size_t adjacent, FixedWinding& clipped ){ - PlaneClassification classification = Winding_ClassifyDistance( plane3_distance_to_point( clipPlane, winding.back().vertex ), ON_EPSILON ); - PlaneClassification nextClassification; - // for each edge - for ( std::size_t next = 0, i = winding.size() - 1; next != winding.size(); i = next, ++next, classification = nextClassification ) - { - nextClassification = Winding_ClassifyDistance( plane3_distance_to_point( clipPlane, winding[next].vertex ), ON_EPSILON ); - const FixedWindingVertex& vertex = winding[i]; - - // if first vertex of edge is ON - if ( classification == ePlaneOn ) { - // append first vertex to output winding - if ( nextClassification == ePlaneBack ) { - // this edge lies on the clip plane - clipped.push_back( FixedWindingVertex( vertex.vertex, plane3_intersect_plane3( plane, clipPlane ), adjacent ) ); - } - else - { - clipped.push_back( vertex ); - } - continue; - } - - // if first vertex of edge is FRONT - if ( classification == ePlaneFront ) { - // add first vertex to output winding - clipped.push_back( vertex ); - } - // if second vertex of edge is ON - if ( nextClassification == ePlaneOn ) { - continue; - } - // else if second vertex of edge is same as first - else if ( nextClassification == classification ) { - continue; - } - // else if first vertex of edge is FRONT and there are only two edges - else if ( classification == ePlaneFront && winding.size() == 2 ) { - continue; - } - // else first vertex is FRONT and second is BACK or vice versa - else - { - // append intersection point of line and plane to output winding - DoubleVector3 mid( line_intersect_plane( vertex.edge, clipPlane ) ); - - if ( classification == ePlaneFront ) { - // this edge lies on the clip plane - clipped.push_back( FixedWindingVertex( mid, plane3_intersect_plane3( plane, clipPlane ), adjacent ) ); - } - else - { - clipped.push_back( FixedWindingVertex( mid, vertex.edge, vertex.adjacent ) ); - } - } - } +void Winding_Clip(const FixedWinding &winding, const Plane3 &plane, const Plane3 &clipPlane, std::size_t adjacent, + FixedWinding &clipped) +{ + PlaneClassification classification = Winding_ClassifyDistance( + plane3_distance_to_point(clipPlane, winding.back().vertex), ON_EPSILON); + PlaneClassification nextClassification; + // for each edge + for (std::size_t next = 0, i = winding.size() - 1; + next != winding.size(); i = next, ++next, classification = nextClassification) { + nextClassification = Winding_ClassifyDistance(plane3_distance_to_point(clipPlane, winding[next].vertex), + ON_EPSILON); + const FixedWindingVertex &vertex = winding[i]; + + // if first vertex of edge is ON + if (classification == ePlaneOn) { + // append first vertex to output winding + if (nextClassification == ePlaneBack) { + // this edge lies on the clip plane + clipped.push_back( + FixedWindingVertex(vertex.vertex, plane3_intersect_plane3(plane, clipPlane), adjacent)); + } else { + clipped.push_back(vertex); + } + continue; + } + + // if first vertex of edge is FRONT + if (classification == ePlaneFront) { + // add first vertex to output winding + clipped.push_back(vertex); + } + // if second vertex of edge is ON + if (nextClassification == ePlaneOn) { + continue; + } + // else if second vertex of edge is same as first + else if (nextClassification == classification) { + continue; + } + // else if first vertex of edge is FRONT and there are only two edges + else if (classification == ePlaneFront && winding.size() == 2) { + continue; + } + // else first vertex is FRONT and second is BACK or vice versa + else { + // append intersection point of line and plane to output winding + DoubleVector3 mid(line_intersect_plane(vertex.edge, clipPlane)); + + if (classification == ePlaneFront) { + // this edge lies on the clip plane + clipped.push_back(FixedWindingVertex(mid, plane3_intersect_plane3(plane, clipPlane), adjacent)); + } else { + clipped.push_back(FixedWindingVertex(mid, vertex.edge, vertex.adjacent)); + } + } + } } -std::size_t Winding_FindAdjacent( const Winding& winding, std::size_t face ){ - for ( std::size_t i = 0; i < winding.numpoints; ++i ) - { - ASSERT_MESSAGE( winding[i].adjacent != c_brush_maxFaces, "edge connectivity data is invalid" ); - if ( winding[i].adjacent == face ) { - return i; - } - } - return c_brush_maxFaces; +std::size_t Winding_FindAdjacent(const Winding &winding, std::size_t face) +{ + for (std::size_t i = 0; i < winding.numpoints; ++i) { + ASSERT_MESSAGE(winding[i].adjacent != c_brush_maxFaces, "edge connectivity data is invalid"); + if (winding[i].adjacent == face) { + return i; + } + } + return c_brush_maxFaces; } -std::size_t Winding_Opposite( const Winding& winding, const std::size_t index, const std::size_t other ){ - ASSERT_MESSAGE( index < winding.numpoints && other < winding.numpoints, "Winding_Opposite: index out of range" ); +std::size_t Winding_Opposite(const Winding &winding, const std::size_t index, const std::size_t other) +{ + ASSERT_MESSAGE(index < winding.numpoints && other < winding.numpoints, "Winding_Opposite: index out of range"); - double dist_best = 0; - std::size_t index_best = c_brush_maxFaces; + double dist_best = 0; + std::size_t index_best = c_brush_maxFaces; - Ray edge( ray_for_points( winding[index].vertex, winding[other].vertex ) ); + Ray edge(ray_for_points(winding[index].vertex, winding[other].vertex)); - for ( std::size_t i = 0; i < winding.numpoints; ++i ) - { - if ( i == index || i == other ) { - continue; - } + for (std::size_t i = 0; i < winding.numpoints; ++i) { + if (i == index || i == other) { + continue; + } - double dist_squared = ray_squared_distance_to_point( edge, winding[i].vertex ); + double dist_squared = ray_squared_distance_to_point(edge, winding[i].vertex); - if ( dist_squared > dist_best ) { - dist_best = dist_squared; - index_best = i; - } - } - return index_best; + if (dist_squared > dist_best) { + dist_best = dist_squared; + index_best = i; + } + } + return index_best; } -std::size_t Winding_Opposite( const Winding& winding, const std::size_t index ){ - return Winding_Opposite( winding, index, Winding_next( winding, index ) ); +std::size_t Winding_Opposite(const Winding &winding, const std::size_t index) +{ + return Winding_Opposite(winding, index, Winding_next(winding, index)); } /// \brief Calculate the \p centroid of the polygon defined by \p winding which lies on plane \p plane. -void Winding_Centroid( const Winding& winding, const Plane3& plane, Vector3& centroid ){ - double area2 = 0, x_sum = 0, y_sum = 0; - const ProjectionAxis axis = projectionaxis_for_normal( plane.normal() ); - const indexremap_t remap = indexremap_for_projectionaxis( axis ); - for ( std::size_t i = winding.numpoints - 1, j = 0; j < winding.numpoints; i = j, ++j ) - { - const double ai = winding[i].vertex[remap.x] * winding[j].vertex[remap.y] - winding[j].vertex[remap.x] * winding[i].vertex[remap.y]; - area2 += ai; - x_sum += ( winding[j].vertex[remap.x] + winding[i].vertex[remap.x] ) * ai; - y_sum += ( winding[j].vertex[remap.y] + winding[i].vertex[remap.y] ) * ai; - } - - centroid[remap.x] = static_cast( x_sum / ( 3 * area2 ) ); - centroid[remap.y] = static_cast( y_sum / ( 3 * area2 ) ); - { - Ray ray( Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ) ); - ray.origin[remap.x] = centroid[remap.x]; - ray.origin[remap.y] = centroid[remap.y]; - ray.direction[remap.z] = 1; - centroid[remap.z] = static_cast( ray_distance_to_plane( ray, plane ) ); - } +void Winding_Centroid(const Winding &winding, const Plane3 &plane, Vector3 ¢roid) +{ + double area2 = 0, x_sum = 0, y_sum = 0; + const ProjectionAxis axis = projectionaxis_for_normal(plane.normal()); + const indexremap_t remap = indexremap_for_projectionaxis(axis); + for (std::size_t i = winding.numpoints - 1, j = 0; j < winding.numpoints; i = j, ++j) { + const double ai = winding[i].vertex[remap.x] * winding[j].vertex[remap.y] - + winding[j].vertex[remap.x] * winding[i].vertex[remap.y]; + area2 += ai; + x_sum += (winding[j].vertex[remap.x] + winding[i].vertex[remap.x]) * ai; + y_sum += (winding[j].vertex[remap.y] + winding[i].vertex[remap.y]) * ai; + } + + centroid[remap.x] = static_cast( x_sum / (3 * area2)); + centroid[remap.y] = static_cast( y_sum / (3 * area2)); + { + Ray ray(Vector3(0, 0, 0), Vector3(0, 0, 0)); + ray.origin[remap.x] = centroid[remap.x]; + ray.origin[remap.y] = centroid[remap.y]; + ray.direction[remap.z] = 1; + centroid[remap.z] = static_cast( ray_distance_to_plane(ray, plane)); + } } diff --git a/radiant/winding.h b/radiant/winding.h index e4ad6ebc..85fdd22e 100644 --- a/radiant/winding.h +++ b/radiant/winding.h @@ -29,261 +29,301 @@ #include "math/vector.h" #include "container/array.h" -enum ProjectionAxis -{ - eProjectionAxisX = 0, - eProjectionAxisY = 1, - eProjectionAxisZ = 2, +enum ProjectionAxis { + eProjectionAxisX = 0, + eProjectionAxisY = 1, + eProjectionAxisZ = 2, }; const float ProjectionAxisEpsilon = static_cast( 0.0001 ); -inline bool projectionaxis_better( float axis, float other ){ - return fabs( axis ) > fabs( other ) + ProjectionAxisEpsilon; +inline bool projectionaxis_better(float axis, float other) +{ + return fabs(axis) > fabs(other) + ProjectionAxisEpsilon; } /// \brief Texture axis precedence: Z > X > Y -inline ProjectionAxis projectionaxis_for_normal( const Vector3& normal ){ - return ( projectionaxis_better( normal[eProjectionAxisY], normal[eProjectionAxisX] ) ) - ? ( projectionaxis_better( normal[eProjectionAxisY], normal[eProjectionAxisZ] ) ) - ? eProjectionAxisY - : eProjectionAxisZ - : ( projectionaxis_better( normal[eProjectionAxisX], normal[eProjectionAxisZ] ) ) - ? eProjectionAxisX - : eProjectionAxisZ; +inline ProjectionAxis projectionaxis_for_normal(const Vector3 &normal) +{ + return (projectionaxis_better(normal[eProjectionAxisY], normal[eProjectionAxisX])) + ? (projectionaxis_better(normal[eProjectionAxisY], normal[eProjectionAxisZ])) + ? eProjectionAxisY + : eProjectionAxisZ + : (projectionaxis_better(normal[eProjectionAxisX], normal[eProjectionAxisZ])) + ? eProjectionAxisX + : eProjectionAxisZ; } -struct indexremap_t -{ - indexremap_t( std::size_t _x, std::size_t _y, std::size_t _z ) - : x( _x ), y( _y ), z( _z ){ - } - std::size_t x, y, z; +struct indexremap_t { + indexremap_t(std::size_t _x, std::size_t _y, std::size_t _z) + : x(_x), y(_y), z(_z) + { + } + + std::size_t x, y, z; }; -inline indexremap_t indexremap_for_projectionaxis( const ProjectionAxis axis ){ - switch ( axis ) - { - case eProjectionAxisX: return indexremap_t( 1, 2, 0 ); - case eProjectionAxisY: return indexremap_t( 2, 0, 1 ); - default: return indexremap_t( 0, 1, 2 ); - } +inline indexremap_t indexremap_for_projectionaxis(const ProjectionAxis axis) +{ + switch (axis) { + case eProjectionAxisX: + return indexremap_t(1, 2, 0); + case eProjectionAxisY: + return indexremap_t(2, 0, 1); + default: + return indexremap_t(0, 1, 2); + } } -enum PlaneClassification -{ - ePlaneFront = 0, - ePlaneBack = 1, - ePlaneOn = 2, +enum PlaneClassification { + ePlaneFront = 0, + ePlaneBack = 1, + ePlaneOn = 2, }; #define MAX_POINTS_ON_WINDING 64 const std::size_t c_brush_maxFaces = 1024; -class WindingVertex -{ +class WindingVertex { public: -Vector3 vertex; -Vector2 texcoord; -Vector3 tangent; -Vector3 bitangent; -std::size_t adjacent; + Vector3 vertex; + Vector2 texcoord; + Vector3 tangent; + Vector3 bitangent; + std::size_t adjacent; }; - -struct Winding -{ - typedef Array container_type; - - std::size_t numpoints; - container_type points; - - typedef container_type::iterator iterator; - typedef container_type::const_iterator const_iterator; - - Winding() : numpoints( 0 ){ - } - Winding( std::size_t size ) : numpoints( 0 ), points( size ){ - } - void resize( std::size_t size ){ - points.resize( size ); - numpoints = 0; - } - - iterator begin(){ - return points.begin(); - } - const_iterator begin() const { - return points.begin(); - } - iterator end(){ - return points.begin() + numpoints; - } - const_iterator end() const { - return points.begin() + numpoints; - } - - WindingVertex& operator[]( std::size_t index ){ - ASSERT_MESSAGE( index < points.size(), "winding: index out of bounds" ); - return points[index]; - } - const WindingVertex& operator[]( std::size_t index ) const { - ASSERT_MESSAGE( index < points.size(), "winding: index out of bounds" ); - return points[index]; - } - - void push_back( const WindingVertex& point ){ - points[numpoints] = point; - ++numpoints; - } - void erase( iterator point ){ - for ( iterator i = point + 1; i != end(); point = i, ++i ) - { - *point = *i; - } - --numpoints; - } +struct Winding { + typedef Array container_type; + + std::size_t numpoints; + container_type points; + + typedef container_type::iterator iterator; + typedef container_type::const_iterator const_iterator; + + Winding() : numpoints(0) + { + } + + Winding(std::size_t size) : numpoints(0), points(size) + { + } + + void resize(std::size_t size) + { + points.resize(size); + numpoints = 0; + } + + iterator begin() + { + return points.begin(); + } + + const_iterator begin() const + { + return points.begin(); + } + + iterator end() + { + return points.begin() + numpoints; + } + + const_iterator end() const + { + return points.begin() + numpoints; + } + + WindingVertex &operator[](std::size_t index) + { + ASSERT_MESSAGE(index < points.size(), "winding: index out of bounds"); + return points[index]; + } + + const WindingVertex &operator[](std::size_t index) const + { + ASSERT_MESSAGE(index < points.size(), "winding: index out of bounds"); + return points[index]; + } + + void push_back(const WindingVertex &point) + { + points[numpoints] = point; + ++numpoints; + } + + void erase(iterator point) + { + for (iterator i = point + 1; i != end(); point = i, ++i) { + *point = *i; + } + --numpoints; + } }; typedef BasicVector3 DoubleVector3; -class DoubleLine -{ +class DoubleLine { public: -DoubleVector3 origin; -DoubleVector3 direction; + DoubleVector3 origin; + DoubleVector3 direction; }; -class FixedWindingVertex -{ +class FixedWindingVertex { public: -DoubleVector3 vertex; -DoubleLine edge; -std::size_t adjacent; - -FixedWindingVertex( const DoubleVector3& vertex_, const DoubleLine& edge_, std::size_t adjacent_ ) - : vertex( vertex_ ), edge( edge_ ), adjacent( adjacent_ ){ -} + DoubleVector3 vertex; + DoubleLine edge; + std::size_t adjacent; + + FixedWindingVertex(const DoubleVector3 &vertex_, const DoubleLine &edge_, std::size_t adjacent_) + : vertex(vertex_), edge(edge_), adjacent(adjacent_) + { + } }; -struct FixedWinding -{ - typedef std::vector Points; - Points points; - - FixedWinding(){ - points.reserve( MAX_POINTS_ON_WINDING ); - } - - FixedWindingVertex& front(){ - return points.front(); - } - const FixedWindingVertex& front() const { - return points.front(); - } - FixedWindingVertex& back(){ - return points.back(); - } - const FixedWindingVertex& back() const { - return points.back(); - } - - void clear(){ - points.clear(); - } - - void push_back( const FixedWindingVertex& point ){ - points.push_back( point ); - } - std::size_t size() const { - return points.size(); - } - - FixedWindingVertex& operator[]( std::size_t index ){ - //ASSERT_MESSAGE(index < MAX_POINTS_ON_WINDING, "winding: index out of bounds"); - return points[index]; - } - const FixedWindingVertex& operator[]( std::size_t index ) const { - //ASSERT_MESSAGE(index < MAX_POINTS_ON_WINDING, "winding: index out of bounds"); - return points[index]; - } +struct FixedWinding { + typedef std::vector Points; + Points points; + + FixedWinding() + { + points.reserve(MAX_POINTS_ON_WINDING); + } + + FixedWindingVertex &front() + { + return points.front(); + } + + const FixedWindingVertex &front() const + { + return points.front(); + } + + FixedWindingVertex &back() + { + return points.back(); + } + + const FixedWindingVertex &back() const + { + return points.back(); + } + + void clear() + { + points.clear(); + } + + void push_back(const FixedWindingVertex &point) + { + points.push_back(point); + } + + std::size_t size() const + { + return points.size(); + } + + FixedWindingVertex &operator[](std::size_t index) + { + //ASSERT_MESSAGE(index < MAX_POINTS_ON_WINDING, "winding: index out of bounds"); + return points[index]; + } + + const FixedWindingVertex &operator[](std::size_t index) const + { + //ASSERT_MESSAGE(index < MAX_POINTS_ON_WINDING, "winding: index out of bounds"); + return points[index]; + } }; -inline void Winding_forFixedWinding( Winding& winding, const FixedWinding& fixed ){ - winding.resize( fixed.size() ); - winding.numpoints = fixed.size(); - for ( std::size_t i = 0; i < fixed.size(); ++i ) - { - winding[i].vertex[0] = static_cast( fixed[i].vertex[0] ); - winding[i].vertex[1] = static_cast( fixed[i].vertex[1] ); - winding[i].vertex[2] = static_cast( fixed[i].vertex[2] ); - winding[i].adjacent = fixed[i].adjacent; - } +inline void Winding_forFixedWinding(Winding &winding, const FixedWinding &fixed) +{ + winding.resize(fixed.size()); + winding.numpoints = fixed.size(); + for (std::size_t i = 0; i < fixed.size(); ++i) { + winding[i].vertex[0] = static_cast( fixed[i].vertex[0] ); + winding[i].vertex[1] = static_cast( fixed[i].vertex[1] ); + winding[i].vertex[2] = static_cast( fixed[i].vertex[2] ); + winding[i].adjacent = fixed[i].adjacent; + } } -inline std::size_t Winding_wrap( const Winding& winding, std::size_t i ){ - ASSERT_MESSAGE( winding.numpoints != 0, "Winding_wrap: empty winding" ); - return i % winding.numpoints; +inline std::size_t Winding_wrap(const Winding &winding, std::size_t i) +{ + ASSERT_MESSAGE(winding.numpoints != 0, "Winding_wrap: empty winding"); + return i % winding.numpoints; } -inline std::size_t Winding_next( const Winding& winding, std::size_t i ){ - return Winding_wrap( winding, ++i ); +inline std::size_t Winding_next(const Winding &winding, std::size_t i) +{ + return Winding_wrap(winding, ++i); } class Plane3; -void Winding_createInfinite( FixedWinding& w, const Plane3& plane, double infinity ); +void Winding_createInfinite(FixedWinding &w, const Plane3 &plane, double infinity); -const double ON_EPSILON = 1.0 / ( 1 << 8 ); +const double ON_EPSILON = 1.0 / (1 << 8); /// \brief Returns true if edge (\p x, \p y) is smaller than the epsilon used to classify winding points against a plane. -inline bool Edge_isDegenerate( const Vector3& x, const Vector3& y ){ - return vector3_length_squared( y - x ) < ( ON_EPSILON * ON_EPSILON ); +inline bool Edge_isDegenerate(const Vector3 &x, const Vector3 &y) +{ + return vector3_length_squared(y - x) < (ON_EPSILON * ON_EPSILON); } -void Winding_Clip( const FixedWinding& winding, const Plane3& plane, const Plane3& clipPlane, std::size_t adjacent, FixedWinding& clipped ); - -struct brushsplit_t -{ - brushsplit_t(){ - counts[0] = 0; - counts[1] = 0; - counts[2] = 0; - } - brushsplit_t& operator+=( const brushsplit_t& other ){ - counts[0] += other.counts[0]; - counts[1] += other.counts[1]; - counts[2] += other.counts[2]; - return *this; - } - std::size_t counts[3]; +void Winding_Clip(const FixedWinding &winding, const Plane3 &plane, const Plane3 &clipPlane, std::size_t adjacent, + FixedWinding &clipped); + +struct brushsplit_t { + brushsplit_t() + { + counts[0] = 0; + counts[1] = 0; + counts[2] = 0; + } + + brushsplit_t &operator+=(const brushsplit_t &other) + { + counts[0] += other.counts[0]; + counts[1] += other.counts[1]; + counts[2] += other.counts[2]; + return *this; + } + + std::size_t counts[3]; }; -brushsplit_t Winding_ClassifyPlane( const Winding& w, const Plane3& plane ); +brushsplit_t Winding_ClassifyPlane(const Winding &w, const Plane3 &plane); -bool Winding_PlanesConcave( const Winding& w1, const Winding& w2, const Plane3& plane1, const Plane3& plane2 ); -bool Winding_TestPlane( const Winding& w, const Plane3& plane, bool flipped ); +bool Winding_PlanesConcave(const Winding &w1, const Winding &w2, const Plane3 &plane1, const Plane3 &plane2); -std::size_t Winding_FindAdjacent( const Winding& w, std::size_t face ); +bool Winding_TestPlane(const Winding &w, const Plane3 &plane, bool flipped); -std::size_t Winding_Opposite( const Winding& w, const std::size_t index, const std::size_t other ); -std::size_t Winding_Opposite( const Winding& w, std::size_t index ); +std::size_t Winding_FindAdjacent(const Winding &w, std::size_t face); -void Winding_Centroid( const Winding& w, const Plane3& plane, Vector3& centroid ); +std::size_t Winding_Opposite(const Winding &w, const std::size_t index, const std::size_t other); +std::size_t Winding_Opposite(const Winding &w, std::size_t index); -inline void Winding_printConnectivity( Winding& winding ){ - for ( Winding::iterator i = winding.begin(); i != winding.end(); ++i ) - { - std::size_t vertexIndex = std::distance( winding.begin(), i ); - globalOutputStream() << "vertex: " << Unsigned( vertexIndex ) << " adjacent: " << Unsigned( ( *i ).adjacent ) << "\n"; - } +void Winding_Centroid(const Winding &w, const Plane3 &plane, Vector3 ¢roid); + + +inline void Winding_printConnectivity(Winding &winding) +{ + for (Winding::iterator i = winding.begin(); i != winding.end(); ++i) { + std::size_t vertexIndex = std::distance(winding.begin(), i); + globalOutputStream() << "vertex: " << Unsigned(vertexIndex) << " adjacent: " << Unsigned((*i).adjacent) << "\n"; + } } #endif diff --git a/radiant/windowobservers.cpp b/radiant/windowobservers.cpp index 3bd2334d..9dc75a56 100644 --- a/radiant/windowobservers.cpp +++ b/radiant/windowobservers.cpp @@ -25,142 +25,150 @@ #include #include "generic/bitfield.h" -namespace -{ -ModifierFlags g_modifier_state = c_modifierNone; +namespace { + ModifierFlags g_modifier_state = c_modifierNone; } -typedef std::vector WindowObservers; +typedef std::vector WindowObservers; -inline void WindowObservers_OnModifierDown( WindowObservers& observers, ModifierFlags type ){ - g_modifier_state = bitfield_enable( g_modifier_state, type ); - for ( WindowObservers::iterator i = observers.begin(); i != observers.end(); ++i ) - { - ( *i )->onModifierDown( type ); - } +inline void WindowObservers_OnModifierDown(WindowObservers &observers, ModifierFlags type) +{ + g_modifier_state = bitfield_enable(g_modifier_state, type); + for (WindowObservers::iterator i = observers.begin(); i != observers.end(); ++i) { + (*i)->onModifierDown(type); + } } -inline void WindowObservers_OnModifierUp( WindowObservers& observers, ModifierFlags type ){ - g_modifier_state = bitfield_disable( g_modifier_state, type ); - for ( WindowObservers::iterator i = observers.begin(); i != observers.end(); ++i ) - { - ( *i )->onModifierUp( type ); - } +inline void WindowObservers_OnModifierUp(WindowObservers &observers, ModifierFlags type) +{ + g_modifier_state = bitfield_disable(g_modifier_state, type); + for (WindowObservers::iterator i = observers.begin(); i != observers.end(); ++i) { + (*i)->onModifierUp(type); + } } #include -gboolean selection_modifier_key_press( ui::Widget widget, GdkEventKey* event, WindowObservers& observers ){ - switch ( event->keyval ) - { - case GDK_KEY_Alt_L: - case GDK_KEY_Alt_R: - //globalOutputStream() << "Alt PRESSED\n"; - WindowObservers_OnModifierDown( observers, c_modifierAlt ); - break; - case GDK_KEY_Shift_L: - case GDK_KEY_Shift_R: - //globalOutputStream() << "Shift PRESSED\n"; - WindowObservers_OnModifierDown( observers, c_modifierShift ); - break; - case GDK_KEY_Control_L: - case GDK_KEY_Control_R: - //globalOutputStream() << "Control PRESSED\n"; - WindowObservers_OnModifierDown( observers, c_modifierControl ); - break; - } - return FALSE; +gboolean selection_modifier_key_press(ui::Widget widget, GdkEventKey *event, WindowObservers &observers) +{ + switch (event->keyval) { + case GDK_KEY_Alt_L: + case GDK_KEY_Alt_R: + //globalOutputStream() << "Alt PRESSED\n"; + WindowObservers_OnModifierDown(observers, c_modifierAlt); + break; + case GDK_KEY_Shift_L: + case GDK_KEY_Shift_R: + //globalOutputStream() << "Shift PRESSED\n"; + WindowObservers_OnModifierDown(observers, c_modifierShift); + break; + case GDK_KEY_Control_L: + case GDK_KEY_Control_R: + //globalOutputStream() << "Control PRESSED\n"; + WindowObservers_OnModifierDown(observers, c_modifierControl); + break; + } + return FALSE; } -gboolean selection_modifier_key_release( ui::Widget widget, GdkEventKey* event, WindowObservers& observers ){ - switch ( event->keyval ) - { - case GDK_KEY_Alt_L: - case GDK_KEY_Alt_R: - //globalOutputStream() << "Alt RELEASED\n"; - WindowObservers_OnModifierUp( observers, c_modifierAlt ); - break; - case GDK_KEY_Shift_L: - case GDK_KEY_Shift_R: - //globalOutputStream() << "Shift RELEASED\n"; - WindowObservers_OnModifierUp( observers, c_modifierShift ); - break; - case GDK_KEY_Control_L: - case GDK_KEY_Control_R: - //globalOutputStream() << "Control RELEASED\n"; - WindowObservers_OnModifierUp( observers, c_modifierControl ); - break; - } - return FALSE; +gboolean selection_modifier_key_release(ui::Widget widget, GdkEventKey *event, WindowObservers &observers) +{ + switch (event->keyval) { + case GDK_KEY_Alt_L: + case GDK_KEY_Alt_R: + //globalOutputStream() << "Alt RELEASED\n"; + WindowObservers_OnModifierUp(observers, c_modifierAlt); + break; + case GDK_KEY_Shift_L: + case GDK_KEY_Shift_R: + //globalOutputStream() << "Shift RELEASED\n"; + WindowObservers_OnModifierUp(observers, c_modifierShift); + break; + case GDK_KEY_Control_L: + case GDK_KEY_Control_R: + //globalOutputStream() << "Control RELEASED\n"; + WindowObservers_OnModifierUp(observers, c_modifierControl); + break; + } + return FALSE; } -void WindowObservers_UpdateModifier( WindowObservers& observers, ModifierFlags modifiers, ModifierFlags modifier ){ - if ( !bitfield_enabled( g_modifier_state, modifier ) && bitfield_enabled( modifiers, modifier ) ) { - WindowObservers_OnModifierDown( observers, modifier ); - } - if ( bitfield_enabled( g_modifier_state, modifier ) && !bitfield_enabled( modifiers, modifier ) ) { - WindowObservers_OnModifierUp( observers, modifier ); - } +void WindowObservers_UpdateModifier(WindowObservers &observers, ModifierFlags modifiers, ModifierFlags modifier) +{ + if (!bitfield_enabled(g_modifier_state, modifier) && bitfield_enabled(modifiers, modifier)) { + WindowObservers_OnModifierDown(observers, modifier); + } + if (bitfield_enabled(g_modifier_state, modifier) && !bitfield_enabled(modifiers, modifier)) { + WindowObservers_OnModifierUp(observers, modifier); + } } -void WindowObservers_UpdateModifiers( WindowObservers& observers, ModifierFlags modifiers ){ - WindowObservers_UpdateModifier( observers, modifiers, c_modifierAlt ); - WindowObservers_UpdateModifier( observers, modifiers, c_modifierShift ); - WindowObservers_UpdateModifier( observers, modifiers, c_modifierControl ); +void WindowObservers_UpdateModifiers(WindowObservers &observers, ModifierFlags modifiers) +{ + WindowObservers_UpdateModifier(observers, modifiers, c_modifierAlt); + WindowObservers_UpdateModifier(observers, modifiers, c_modifierShift); + WindowObservers_UpdateModifier(observers, modifiers, c_modifierControl); } -gboolean modifiers_button_press( ui::Widget widget, GdkEventButton* event, WindowObservers* observers ){ - if ( event->type == GDK_BUTTON_PRESS ) { - WindowObservers_UpdateModifiers( *observers, modifiers_for_state( event->state ) ); - } - return FALSE; +gboolean modifiers_button_press(ui::Widget widget, GdkEventButton *event, WindowObservers *observers) +{ + if (event->type == GDK_BUTTON_PRESS) { + WindowObservers_UpdateModifiers(*observers, modifiers_for_state(event->state)); + } + return FALSE; } -gboolean modifiers_button_release( ui::Widget widget, GdkEventButton* event, WindowObservers* observers ){ - if ( event->type == GDK_BUTTON_RELEASE ) { - WindowObservers_UpdateModifiers( *observers, modifiers_for_state( event->state ) ); - } - return FALSE; +gboolean modifiers_button_release(ui::Widget widget, GdkEventButton *event, WindowObservers *observers) +{ + if (event->type == GDK_BUTTON_RELEASE) { + WindowObservers_UpdateModifiers(*observers, modifiers_for_state(event->state)); + } + return FALSE; } -gboolean modifiers_motion( ui::Widget widget, GdkEventMotion *event, WindowObservers* observers ){ - WindowObservers_UpdateModifiers( *observers, modifiers_for_state( event->state ) ); - return FALSE; +gboolean modifiers_motion(ui::Widget widget, GdkEventMotion *event, WindowObservers *observers) +{ + WindowObservers_UpdateModifiers(*observers, modifiers_for_state(event->state)); + return FALSE; } WindowObservers g_window_observers; -void GlobalWindowObservers_updateModifiers( ModifierFlags modifiers ){ - WindowObservers_UpdateModifiers( g_window_observers, modifiers ); +void GlobalWindowObservers_updateModifiers(ModifierFlags modifiers) +{ + WindowObservers_UpdateModifiers(g_window_observers, modifiers); } -void GlobalWindowObservers_add( WindowObserver* observer ){ - g_window_observers.push_back( observer ); +void GlobalWindowObservers_add(WindowObserver *observer) +{ + g_window_observers.push_back(observer); } -void GlobalWindowObservers_connectTopLevel( ui::Window window ){ - window.connect( "key_press_event", G_CALLBACK( selection_modifier_key_press ), &g_window_observers ); - window.connect( "key_release_event", G_CALLBACK( selection_modifier_key_release ), &g_window_observers ); +void GlobalWindowObservers_connectTopLevel(ui::Window window) +{ + window.connect("key_press_event", G_CALLBACK(selection_modifier_key_press), &g_window_observers); + window.connect("key_release_event", G_CALLBACK(selection_modifier_key_release), &g_window_observers); } -void GlobalWindowObservers_connectWidget( ui::Widget widget ){ - widget.connect( "button_press_event", G_CALLBACK( modifiers_button_press ), &g_window_observers ); - widget.connect( "button_release_event", G_CALLBACK( modifiers_button_release ), &g_window_observers ); - widget.connect( "motion_notify_event", G_CALLBACK( modifiers_motion ), &g_window_observers ); +void GlobalWindowObservers_connectWidget(ui::Widget widget) +{ + widget.connect("button_press_event", G_CALLBACK(modifiers_button_press), &g_window_observers); + widget.connect("button_release_event", G_CALLBACK(modifiers_button_release), &g_window_observers); + widget.connect("motion_notify_event", G_CALLBACK(modifiers_motion), &g_window_observers); } ModifierFlags modifiers_for_state(unsigned int state) { - ModifierFlags modifiers = c_modifierNone; - if ( state & GDK_SHIFT_MASK ) { - modifiers |= c_modifierShift; - } - if ( state & GDK_CONTROL_MASK ) { - modifiers |= c_modifierControl; - } - if ( state & GDK_MOD1_MASK ) { - modifiers |= c_modifierAlt; - } - return modifiers; + ModifierFlags modifiers = c_modifierNone; + if (state & GDK_SHIFT_MASK) { + modifiers |= c_modifierShift; + } + if (state & GDK_CONTROL_MASK) { + modifiers |= c_modifierControl; + } + if (state & GDK_MOD1_MASK) { + modifiers |= c_modifierAlt; + } + return modifiers; } diff --git a/radiant/windowobservers.h b/radiant/windowobservers.h index 37fe2f15..4ac90b44 100644 --- a/radiant/windowobservers.h +++ b/radiant/windowobservers.h @@ -29,27 +29,31 @@ #include "math/vector.h" class WindowObserver; -void GlobalWindowObservers_add( WindowObserver* observer ); -void GlobalWindowObservers_connectWidget( ui::Widget widget ); -void GlobalWindowObservers_connectTopLevel( ui::Window window ); - -inline ButtonIdentifier button_for_button( unsigned int button ){ - switch ( button ) - { - case 1: - return c_buttonLeft; - case 2: - return c_buttonMiddle; - case 3: - return c_buttonRight; - } - return c_buttonInvalid; + +void GlobalWindowObservers_add(WindowObserver *observer); + +void GlobalWindowObservers_connectWidget(ui::Widget widget); + +void GlobalWindowObservers_connectTopLevel(ui::Window window); + +inline ButtonIdentifier button_for_button(unsigned int button) +{ + switch (button) { + case 1: + return c_buttonLeft; + case 2: + return c_buttonMiddle; + case 3: + return c_buttonRight; + } + return c_buttonInvalid; } -ModifierFlags modifiers_for_state( unsigned int state ); +ModifierFlags modifiers_for_state(unsigned int state); -inline WindowVector WindowVector_forDouble( double x, double y ){ - return WindowVector( static_cast( x ), static_cast( y ) ); +inline WindowVector WindowVector_forDouble(double x, double y) +{ + return WindowVector(static_cast( x ), static_cast( y )); } #endif diff --git a/radiant/xmlstuff.h b/radiant/xmlstuff.h index 7fe6120f..7baf6cbe 100644 --- a/radiant/xmlstuff.h +++ b/radiant/xmlstuff.h @@ -49,38 +49,47 @@ class ISAXHandler; // if msg_level == SYS_ERR, then we will reset the listening at the end of the current node // the level for stopping the feed is stored in stop_depth // unkown nodes are ignored, we use ignore_depth to track the level we start ignoring from -struct message_info_t -{ - int msg_level; // current message level (SYS_MSG, SYS_WRN, SYS_ERR) - int recurse; // current recursion depth (used to track various things) - int ignore_depth; // the ignore depth limit when we are jumping over unknown nodes (0 means we are not ignoring) - int stop_depth; // the depth we need to stop at the end - int geometry_depth; // are we parsing some geometry information (i.e. do we forward the SAX calls?) - ISAXHandler* pGeometry; // the handler - - enum unnamed0 { bufsize = 1024 }; - char m_buffer[bufsize]; - std::size_t m_length; +struct message_info_t { + int msg_level; // current message level (SYS_MSG, SYS_WRN, SYS_ERR) + int recurse; // current recursion depth (used to track various things) + int ignore_depth; // the ignore depth limit when we are jumping over unknown nodes (0 means we are not ignoring) + int stop_depth; // the depth we need to stop at the end + int geometry_depth; // are we parsing some geometry information (i.e. do we forward the SAX calls?) + ISAXHandler *pGeometry; // the handler + + enum unnamed0 { bufsize = 1024 }; + char m_buffer[bufsize]; + std::size_t m_length; }; class IGL2DWindow; -class ISAXHandler -{ +class ISAXHandler { public: -virtual ~ISAXHandler() = default; -virtual void Release(){} -virtual void saxStartElement( message_info_t* ctx, const xmlChar* name, const xmlChar** attrs ) = 0; -virtual void saxEndElement( message_info_t* ctx, const xmlChar* name ) = 0; -virtual void saxCharacters( message_info_t* ctx, const xmlChar* ch, int len ) = 0; -virtual const char* getName(){ - return NULL; -} -virtual IGL2DWindow* Highlight(){ - return 0; -} -virtual void DropHighlight(){ -} + virtual ~ISAXHandler() = default; + + virtual void Release() + {} + + virtual void saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs) = 0; + + virtual void saxEndElement(message_info_t *ctx, const xmlChar *name) = 0; + + virtual void saxCharacters(message_info_t *ctx, const xmlChar *ch, int len) = 0; + + virtual const char *getName() + { + return NULL; + } + + virtual IGL2DWindow *Highlight() + { + return 0; + } + + virtual void DropHighlight() + { + } }; #endif diff --git a/radiant/xywindow.cpp b/radiant/xywindow.cpp index 54d121f3..2bd7fe24 100644 --- a/radiant/xywindow.cpp +++ b/radiant/xywindow.cpp @@ -73,40 +73,48 @@ #include "grid.h" #include "windowobservers.h" -void LoadTextureRGBA( qtexture_t* q, unsigned char* pPixels, int nWidth, int nHeight ); +void LoadTextureRGBA(qtexture_t *q, unsigned char *pPixels, int nWidth, int nHeight); // d1223m extern bool g_brush_always_caulk; //!\todo Rewrite. -class ClipPoint -{ +class ClipPoint { public: -Vector3 m_ptClip; // the 3d point -bool m_bSet; - -ClipPoint(){ - Reset(); -}; -void Reset(){ - m_ptClip[0] = m_ptClip[1] = m_ptClip[2] = 0.0; - m_bSet = false; -} -bool Set(){ - return m_bSet; -} -void Set( bool b ){ - m_bSet = b; -} -operator Vector3&() -{ - return m_ptClip; -}; + Vector3 m_ptClip; // the 3d point + bool m_bSet; + + ClipPoint() + { + Reset(); + }; + + void Reset() + { + m_ptClip[0] = m_ptClip[1] = m_ptClip[2] = 0.0; + m_bSet = false; + } + + bool Set() + { + return m_bSet; + } + + void Set(bool b) + { + m_bSet = b; + } + + operator Vector3 &() + { + return m_ptClip; + }; /*! Draw clip/path point with rasterized number label */ -void Draw( int num, float scale ); + void Draw(int num, float scale); + /*! Draw clip/path point with rasterized string label */ -void Draw( const char *label, float scale ); + void Draw(const char *label, float scale); }; VIEWTYPE g_clip_viewtype; @@ -115,423 +123,451 @@ bool g_clip_useCaulk = false; ClipPoint g_Clip1; ClipPoint g_Clip2; ClipPoint g_Clip3; -ClipPoint* g_pMovingClip = 0; +ClipPoint *g_pMovingClip = 0; /* Drawing clip points */ -void ClipPoint::Draw( int num, float scale ){ - StringOutputStream label( 4 ); - label << num; - Draw( label.c_str(), scale ); -} - -void ClipPoint::Draw( const char *label, float scale ){ - // draw point - glPointSize( 4 ); - glColor3fv( vector3_to_array( g_xywindow_globals.color_clipper ) ); - glBegin( GL_POINTS ); - glVertex3fv( vector3_to_array( m_ptClip ) ); - glEnd(); - glPointSize( 1 ); - - float offset = 2.0f / scale; - - // draw label - glRasterPos3f( m_ptClip[0] + offset, m_ptClip[1] + offset, m_ptClip[2] + offset ); - glCallLists( GLsizei( strlen( label ) ), GL_UNSIGNED_BYTE, label ); -} - -float fDiff( float f1, float f2 ){ - if ( f1 > f2 ) { - return f1 - f2; - } - else{ - return f2 - f1; - } -} - -inline double ClipPoint_Intersect( const ClipPoint& clip, const Vector3& point, VIEWTYPE viewtype, float scale ){ - int nDim1 = ( viewtype == YZ ) ? 1 : 0; - int nDim2 = ( viewtype == XY ) ? 1 : 2; - double screenDistanceSquared( vector2_length_squared( Vector2( fDiff( clip.m_ptClip[nDim1], point[nDim1] ) * scale, fDiff( clip.m_ptClip[nDim2], point[nDim2] ) * scale ) ) ); - if ( screenDistanceSquared < 8 * 8 ) { - return screenDistanceSquared; - } - return FLT_MAX; +void ClipPoint::Draw(int num, float scale) +{ + StringOutputStream label(4); + label << num; + Draw(label.c_str(), scale); } -inline void ClipPoint_testSelect( ClipPoint& clip, const Vector3& point, VIEWTYPE viewtype, float scale, double& bestDistance, ClipPoint*& bestClip ){ - if ( clip.Set() ) { - double distance = ClipPoint_Intersect( clip, point, viewtype, scale ); - if ( distance < bestDistance ) { - bestDistance = distance; - bestClip = &clip; - } - } -} +void ClipPoint::Draw(const char *label, float scale) +{ + // draw point + glPointSize(4); + glColor3fv(vector3_to_array(g_xywindow_globals.color_clipper)); + glBegin(GL_POINTS); + glVertex3fv(vector3_to_array(m_ptClip)); + glEnd(); + glPointSize(1); -inline ClipPoint* GlobalClipPoints_Find( const Vector3& point, VIEWTYPE viewtype, float scale ){ - double bestDistance = FLT_MAX; - ClipPoint* bestClip = 0; - ClipPoint_testSelect( g_Clip1, point, viewtype, scale, bestDistance, bestClip ); - ClipPoint_testSelect( g_Clip2, point, viewtype, scale, bestDistance, bestClip ); - ClipPoint_testSelect( g_Clip3, point, viewtype, scale, bestDistance, bestClip ); - return bestClip; -} + float offset = 2.0f / scale; -inline void GlobalClipPoints_Draw( float scale ){ - // Draw clip points - if ( g_Clip1.Set() ) { - g_Clip1.Draw( 1, scale ); - } - if ( g_Clip2.Set() ) { - g_Clip2.Draw( 2, scale ); - } - if ( g_Clip3.Set() ) { - g_Clip3.Draw( 3, scale ); - } + // draw label + glRasterPos3f(m_ptClip[0] + offset, m_ptClip[1] + offset, m_ptClip[2] + offset); + glCallLists(GLsizei(strlen(label)), GL_UNSIGNED_BYTE, label); } -inline bool GlobalClipPoints_valid(){ - return g_Clip1.Set() && g_Clip2.Set(); -} - -void PlanePointsFromClipPoints( Vector3 planepts[3], const AABB& bounds, int viewtype ){ - ASSERT_MESSAGE( GlobalClipPoints_valid(), "clipper points not initialised" ); - planepts[0] = g_Clip1.m_ptClip; - planepts[1] = g_Clip2.m_ptClip; - planepts[2] = g_Clip3.m_ptClip; - Vector3 maxs( vector3_added( bounds.origin, bounds.extents ) ); - Vector3 mins( vector3_subtracted( bounds.origin, bounds.extents ) ); - if ( !g_Clip3.Set() ) { - int n = ( viewtype == XY ) ? 2 : ( viewtype == YZ ) ? 0 : 1; - int x = ( n == 0 ) ? 1 : 0; - int y = ( n == 2 ) ? 1 : 2; - - if ( n == 1 ) { // on viewtype XZ, flip clip points - planepts[0][n] = maxs[n]; - planepts[1][n] = maxs[n]; - planepts[2][x] = g_Clip1.m_ptClip[x]; - planepts[2][y] = g_Clip1.m_ptClip[y]; - planepts[2][n] = mins[n]; - } - else - { - planepts[0][n] = mins[n]; - planepts[1][n] = mins[n]; - planepts[2][x] = g_Clip1.m_ptClip[x]; - planepts[2][y] = g_Clip1.m_ptClip[y]; - planepts[2][n] = maxs[n]; - } - } +float fDiff(float f1, float f2) +{ + if (f1 > f2) { + return f1 - f2; + } else { + return f2 - f1; + } } -void Clip_Update(){ - Vector3 planepts[3]; - if ( !GlobalClipPoints_valid() ) { - planepts[0] = Vector3( 0, 0, 0 ); - planepts[1] = Vector3( 0, 0, 0 ); - planepts[2] = Vector3( 0, 0, 0 ); - Scene_BrushSetClipPlane( GlobalSceneGraph(), Plane3( 0, 0, 0, 0 ) ); - } - else - { - AABB bounds( Vector3( 0, 0, 0 ), Vector3( 64, 64, 64 ) ); - PlanePointsFromClipPoints( planepts, bounds, g_clip_viewtype ); - if ( g_bSwitch ) { - std::swap( planepts[0], planepts[1] ); - } - Scene_BrushSetClipPlane( GlobalSceneGraph(), plane3_for_points( planepts[0], planepts[1], planepts[2] ) ); - } - ClipperChangeNotify(); +inline double ClipPoint_Intersect(const ClipPoint &clip, const Vector3 &point, VIEWTYPE viewtype, float scale) +{ + int nDim1 = (viewtype == YZ) ? 1 : 0; + int nDim2 = (viewtype == XY) ? 1 : 2; + double screenDistanceSquared(vector2_length_squared(Vector2(fDiff(clip.m_ptClip[nDim1], point[nDim1]) * scale, + fDiff(clip.m_ptClip[nDim2], point[nDim2]) * scale))); + if (screenDistanceSquared < 8 * 8) { + return screenDistanceSquared; + } + return FLT_MAX; +} + +inline void +ClipPoint_testSelect(ClipPoint &clip, const Vector3 &point, VIEWTYPE viewtype, float scale, double &bestDistance, + ClipPoint *&bestClip) +{ + if (clip.Set()) { + double distance = ClipPoint_Intersect(clip, point, viewtype, scale); + if (distance < bestDistance) { + bestDistance = distance; + bestClip = &clip; + } + } } -const char* Clip_getShader(){ - return g_clip_useCaulk ? "textures/common/caulk" : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ); +inline ClipPoint *GlobalClipPoints_Find(const Vector3 &point, VIEWTYPE viewtype, float scale) +{ + double bestDistance = FLT_MAX; + ClipPoint *bestClip = 0; + ClipPoint_testSelect(g_Clip1, point, viewtype, scale, bestDistance, bestClip); + ClipPoint_testSelect(g_Clip2, point, viewtype, scale, bestDistance, bestClip); + ClipPoint_testSelect(g_Clip3, point, viewtype, scale, bestDistance, bestClip); + return bestClip; } -void Clip(){ - if ( ClipMode() && GlobalClipPoints_valid() ) { - Vector3 planepts[3]; - AABB bounds( Vector3( 0, 0, 0 ), Vector3( 64, 64, 64 ) ); - PlanePointsFromClipPoints( planepts, bounds, g_clip_viewtype ); - Scene_BrushSplitByPlane( GlobalSceneGraph(), planepts[0], planepts[1], planepts[2], Clip_getShader(), ( !g_bSwitch ) ? eFront : eBack ); - g_Clip1.Reset(); - g_Clip2.Reset(); - g_Clip3.Reset(); - Clip_Update(); - ClipperChangeNotify(); - } +inline void GlobalClipPoints_Draw(float scale) +{ + // Draw clip points + if (g_Clip1.Set()) { + g_Clip1.Draw(1, scale); + } + if (g_Clip2.Set()) { + g_Clip2.Draw(2, scale); + } + if (g_Clip3.Set()) { + g_Clip3.Draw(3, scale); + } +} + +inline bool GlobalClipPoints_valid() +{ + return g_Clip1.Set() && g_Clip2.Set(); } -void SplitClip(){ - if ( ClipMode() && GlobalClipPoints_valid() ) { - Vector3 planepts[3]; - AABB bounds( Vector3( 0, 0, 0 ), Vector3( 64, 64, 64 ) ); - PlanePointsFromClipPoints( planepts, bounds, g_clip_viewtype ); - Scene_BrushSplitByPlane( GlobalSceneGraph(), planepts[0], planepts[1], planepts[2], Clip_getShader(), eFrontAndBack ); - g_Clip1.Reset(); - g_Clip2.Reset(); - g_Clip3.Reset(); - Clip_Update(); - ClipperChangeNotify(); - } +void PlanePointsFromClipPoints(Vector3 planepts[3], const AABB &bounds, int viewtype) +{ + ASSERT_MESSAGE(GlobalClipPoints_valid(), "clipper points not initialised"); + planepts[0] = g_Clip1.m_ptClip; + planepts[1] = g_Clip2.m_ptClip; + planepts[2] = g_Clip3.m_ptClip; + Vector3 maxs(vector3_added(bounds.origin, bounds.extents)); + Vector3 mins(vector3_subtracted(bounds.origin, bounds.extents)); + if (!g_Clip3.Set()) { + int n = (viewtype == XY) ? 2 : (viewtype == YZ) ? 0 : 1; + int x = (n == 0) ? 1 : 0; + int y = (n == 2) ? 1 : 2; + + if (n == 1) { // on viewtype XZ, flip clip points + planepts[0][n] = maxs[n]; + planepts[1][n] = maxs[n]; + planepts[2][x] = g_Clip1.m_ptClip[x]; + planepts[2][y] = g_Clip1.m_ptClip[y]; + planepts[2][n] = mins[n]; + } else { + planepts[0][n] = mins[n]; + planepts[1][n] = mins[n]; + planepts[2][x] = g_Clip1.m_ptClip[x]; + planepts[2][y] = g_Clip1.m_ptClip[y]; + planepts[2][n] = maxs[n]; + } + } +} + +void Clip_Update() +{ + Vector3 planepts[3]; + if (!GlobalClipPoints_valid()) { + planepts[0] = Vector3(0, 0, 0); + planepts[1] = Vector3(0, 0, 0); + planepts[2] = Vector3(0, 0, 0); + Scene_BrushSetClipPlane(GlobalSceneGraph(), Plane3(0, 0, 0, 0)); + } else { + AABB bounds(Vector3(0, 0, 0), Vector3(64, 64, 64)); + PlanePointsFromClipPoints(planepts, bounds, g_clip_viewtype); + if (g_bSwitch) { + std::swap(planepts[0], planepts[1]); + } + Scene_BrushSetClipPlane(GlobalSceneGraph(), plane3_for_points(planepts[0], planepts[1], planepts[2])); + } + ClipperChangeNotify(); +} + +const char *Clip_getShader() +{ + return g_clip_useCaulk ? "textures/common/caulk" : TextureBrowser_GetSelectedShader(GlobalTextureBrowser()); } -void FlipClip(){ - g_bSwitch = !g_bSwitch; - Clip_Update(); - ClipperChangeNotify(); +void Clip() +{ + if (ClipMode() && GlobalClipPoints_valid()) { + Vector3 planepts[3]; + AABB bounds(Vector3(0, 0, 0), Vector3(64, 64, 64)); + PlanePointsFromClipPoints(planepts, bounds, g_clip_viewtype); + Scene_BrushSplitByPlane(GlobalSceneGraph(), planepts[0], planepts[1], planepts[2], Clip_getShader(), + (!g_bSwitch) ? eFront : eBack); + g_Clip1.Reset(); + g_Clip2.Reset(); + g_Clip3.Reset(); + Clip_Update(); + ClipperChangeNotify(); + } +} + +void SplitClip() +{ + if (ClipMode() && GlobalClipPoints_valid()) { + Vector3 planepts[3]; + AABB bounds(Vector3(0, 0, 0), Vector3(64, 64, 64)); + PlanePointsFromClipPoints(planepts, bounds, g_clip_viewtype); + Scene_BrushSplitByPlane(GlobalSceneGraph(), planepts[0], planepts[1], planepts[2], Clip_getShader(), + eFrontAndBack); + g_Clip1.Reset(); + g_Clip2.Reset(); + g_Clip3.Reset(); + Clip_Update(); + ClipperChangeNotify(); + } +} + +void FlipClip() +{ + g_bSwitch = !g_bSwitch; + Clip_Update(); + ClipperChangeNotify(); } -void OnClipMode( bool enabled ){ - g_Clip1.Reset(); - g_Clip2.Reset(); - g_Clip3.Reset(); - - if ( !enabled && g_pMovingClip ) { - g_pMovingClip = 0; - } +void OnClipMode(bool enabled) +{ + g_Clip1.Reset(); + g_Clip2.Reset(); + g_Clip3.Reset(); - Clip_Update(); - ClipperChangeNotify(); -} + if (!enabled && g_pMovingClip) { + g_pMovingClip = 0; + } -bool ClipMode(){ - return GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip; + Clip_Update(); + ClipperChangeNotify(); } -void NewClipPoint( const Vector3& point ){ - if ( g_Clip1.Set() == false ) { - g_Clip1.m_ptClip = point; - g_Clip1.Set( true ); - } - else if ( g_Clip2.Set() == false ) { - g_Clip2.m_ptClip = point; - g_Clip2.Set( true ); - } - else if ( g_Clip3.Set() == false ) { - g_Clip3.m_ptClip = point; - g_Clip3.Set( true ); - } - else - { - g_Clip1.Reset(); - g_Clip2.Reset(); - g_Clip3.Reset(); - g_Clip1.m_ptClip = point; - g_Clip1.Set( true ); - } - - Clip_Update(); - ClipperChangeNotify(); +bool ClipMode() +{ + return GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip; } - - -struct xywindow_globals_private_t +void NewClipPoint(const Vector3 &point) { - bool d_showgrid; - - // these are in the View > Show menu with Show coordinates - bool show_names; - bool show_coordinates; - bool show_angles; - bool show_outline; - bool show_axis; - - bool d_show_work; - - bool show_blocks; - int blockSize; - - bool m_bCamXYUpdate; - bool m_bChaseMouse; - bool m_bSizePaint; - - xywindow_globals_private_t() : - d_showgrid( true ), - - show_names( false ), - show_coordinates( true ), - show_angles( true ), - show_outline( false ), - show_axis( true ), - - d_show_work( false ), - - show_blocks( false ), - - m_bCamXYUpdate( true ), - m_bChaseMouse( true ), - m_bSizePaint( true ){ - } + if (g_Clip1.Set() == false) { + g_Clip1.m_ptClip = point; + g_Clip1.Set(true); + } else if (g_Clip2.Set() == false) { + g_Clip2.m_ptClip = point; + g_Clip2.Set(true); + } else if (g_Clip3.Set() == false) { + g_Clip3.m_ptClip = point; + g_Clip3.Set(true); + } else { + g_Clip1.Reset(); + g_Clip2.Reset(); + g_Clip3.Reset(); + g_Clip1.m_ptClip = point; + g_Clip1.Set(true); + } + + Clip_Update(); + ClipperChangeNotify(); +} + + +struct xywindow_globals_private_t { + bool d_showgrid; + + // these are in the View > Show menu with Show coordinates + bool show_names; + bool show_coordinates; + bool show_angles; + bool show_outline; + bool show_axis; + + bool d_show_work; + + bool show_blocks; + int blockSize; + + bool m_bCamXYUpdate; + bool m_bChaseMouse; + bool m_bSizePaint; + + xywindow_globals_private_t() : + d_showgrid(true), + + show_names(false), + show_coordinates(true), + show_angles(true), + show_outline(false), + show_axis(true), + + d_show_work(false), + + show_blocks(false), + + m_bCamXYUpdate(true), + m_bChaseMouse(true), + m_bSizePaint(true) + { + } }; xywindow_globals_t g_xywindow_globals; xywindow_globals_private_t g_xywindow_globals_private; -const unsigned int RAD_NONE = 0x00; -const unsigned int RAD_SHIFT = 0x01; -const unsigned int RAD_ALT = 0x02; +const unsigned int RAD_NONE = 0x00; +const unsigned int RAD_SHIFT = 0x01; +const unsigned int RAD_ALT = 0x02; const unsigned int RAD_CONTROL = 0x04; -const unsigned int RAD_PRESS = 0x08; +const unsigned int RAD_PRESS = 0x08; const unsigned int RAD_LBUTTON = 0x10; const unsigned int RAD_MBUTTON = 0x20; const unsigned int RAD_RBUTTON = 0x40; -inline ButtonIdentifier button_for_flags( unsigned int flags ){ - if ( flags & RAD_LBUTTON ) { - return c_buttonLeft; - } - if ( flags & RAD_RBUTTON ) { - return c_buttonRight; - } - if ( flags & RAD_MBUTTON ) { - return c_buttonMiddle; - } - return c_buttonInvalid; -} - -inline ModifierFlags modifiers_for_flags( unsigned int flags ){ - ModifierFlags modifiers = c_modifierNone; - if ( flags & RAD_SHIFT ) { - modifiers |= c_modifierShift; - } - if ( flags & RAD_CONTROL ) { - modifiers |= c_modifierControl; - } - if ( flags & RAD_ALT ) { - modifiers |= c_modifierAlt; - } - return modifiers; -} - -inline unsigned int buttons_for_button_and_modifiers( ButtonIdentifier button, ModifierFlags flags ){ - unsigned int buttons = 0; - - switch ( button.get() ) - { - case ButtonEnumeration::INVALID: break; - case ButtonEnumeration::LEFT: buttons |= RAD_LBUTTON; break; - case ButtonEnumeration::MIDDLE: buttons |= RAD_MBUTTON; break; - case ButtonEnumeration::RIGHT: buttons |= RAD_RBUTTON; break; - } - - if ( bitfield_enabled( flags, c_modifierControl ) ) { - buttons |= RAD_CONTROL; - } - - if ( bitfield_enabled( flags, c_modifierShift ) ) { - buttons |= RAD_SHIFT; - } - - if ( bitfield_enabled( flags, c_modifierAlt ) ) { - buttons |= RAD_ALT; - } - - return buttons; -} - -inline unsigned int buttons_for_event_button( GdkEventButton* event ){ - unsigned int flags = 0; +inline ButtonIdentifier button_for_flags(unsigned int flags) +{ + if (flags & RAD_LBUTTON) { + return c_buttonLeft; + } + if (flags & RAD_RBUTTON) { + return c_buttonRight; + } + if (flags & RAD_MBUTTON) { + return c_buttonMiddle; + } + return c_buttonInvalid; +} + +inline ModifierFlags modifiers_for_flags(unsigned int flags) +{ + ModifierFlags modifiers = c_modifierNone; + if (flags & RAD_SHIFT) { + modifiers |= c_modifierShift; + } + if (flags & RAD_CONTROL) { + modifiers |= c_modifierControl; + } + if (flags & RAD_ALT) { + modifiers |= c_modifierAlt; + } + return modifiers; +} + +inline unsigned int buttons_for_button_and_modifiers(ButtonIdentifier button, ModifierFlags flags) +{ + unsigned int buttons = 0; + + switch (button.get()) { + case ButtonEnumeration::INVALID: + break; + case ButtonEnumeration::LEFT: + buttons |= RAD_LBUTTON; + break; + case ButtonEnumeration::MIDDLE: + buttons |= RAD_MBUTTON; + break; + case ButtonEnumeration::RIGHT: + buttons |= RAD_RBUTTON; + break; + } + + if (bitfield_enabled(flags, c_modifierControl)) { + buttons |= RAD_CONTROL; + } + + if (bitfield_enabled(flags, c_modifierShift)) { + buttons |= RAD_SHIFT; + } + + if (bitfield_enabled(flags, c_modifierAlt)) { + buttons |= RAD_ALT; + } + + return buttons; +} + +inline unsigned int buttons_for_event_button(GdkEventButton *event) +{ + unsigned int flags = 0; - switch ( event->button ) - { - case 1: flags |= RAD_LBUTTON; break; - case 2: flags |= RAD_MBUTTON; break; - case 3: flags |= RAD_RBUTTON; break; - } + switch (event->button) { + case 1: + flags |= RAD_LBUTTON; + break; + case 2: + flags |= RAD_MBUTTON; + break; + case 3: + flags |= RAD_RBUTTON; + break; + } - if ( ( event->state & GDK_CONTROL_MASK ) != 0 ) { - flags |= RAD_CONTROL; - } + if ((event->state & GDK_CONTROL_MASK) != 0) { + flags |= RAD_CONTROL; + } - if ( ( event->state & GDK_SHIFT_MASK ) != 0 ) { - flags |= RAD_SHIFT; - } + if ((event->state & GDK_SHIFT_MASK) != 0) { + flags |= RAD_SHIFT; + } - if ( ( event->state & GDK_MOD1_MASK ) != 0 ) { - flags |= RAD_ALT; - } + if ((event->state & GDK_MOD1_MASK) != 0) { + flags |= RAD_ALT; + } - return flags; + return flags; } -inline unsigned int buttons_for_state( guint state ){ - unsigned int flags = 0; +inline unsigned int buttons_for_state(guint state) +{ + unsigned int flags = 0; - if ( ( state & GDK_BUTTON1_MASK ) != 0 ) { - flags |= RAD_LBUTTON; - } + if ((state & GDK_BUTTON1_MASK) != 0) { + flags |= RAD_LBUTTON; + } - if ( ( state & GDK_BUTTON2_MASK ) != 0 ) { - flags |= RAD_MBUTTON; - } + if ((state & GDK_BUTTON2_MASK) != 0) { + flags |= RAD_MBUTTON; + } - if ( ( state & GDK_BUTTON3_MASK ) != 0 ) { - flags |= RAD_RBUTTON; - } + if ((state & GDK_BUTTON3_MASK) != 0) { + flags |= RAD_RBUTTON; + } - if ( ( state & GDK_CONTROL_MASK ) != 0 ) { - flags |= RAD_CONTROL; - } + if ((state & GDK_CONTROL_MASK) != 0) { + flags |= RAD_CONTROL; + } - if ( ( state & GDK_SHIFT_MASK ) != 0 ) { - flags |= RAD_SHIFT; - } + if ((state & GDK_SHIFT_MASK) != 0) { + flags |= RAD_SHIFT; + } - if ( ( state & GDK_MOD1_MASK ) != 0 ) { - flags |= RAD_ALT; - } + if ((state & GDK_MOD1_MASK) != 0) { + flags |= RAD_ALT; + } - return flags; + return flags; } -void XYWnd::SetScale( float f ){ - m_fScale = f; - updateProjection(); - updateModelview(); - XYWnd_Update( *this ); +void XYWnd::SetScale(float f) +{ + m_fScale = f; + updateProjection(); + updateModelview(); + XYWnd_Update(*this); } -void XYWnd_ZoomIn( XYWnd* xy ){ - float max_scale = 64; - float scale = xy->Scale() * 5.0f / 4.0f; - if ( scale > max_scale ) { - if ( xy->Scale() != max_scale ) { - xy->SetScale( max_scale ); - } - } - else - { - xy->SetScale( scale ); - } +void XYWnd_ZoomIn(XYWnd *xy) +{ + float max_scale = 64; + float scale = xy->Scale() * 5.0f / 4.0f; + if (scale > max_scale) { + if (xy->Scale() != max_scale) { + xy->SetScale(max_scale); + } + } else { + xy->SetScale(scale); + } } // NOTE: the zoom out factor is 4/5, we could think about customizing it // we don't go below a zoom factor corresponding to 10% of the max world size // (this has to be computed against the window size) -void XYWnd_ZoomOut( XYWnd* xy ){ - float min_scale = MIN( xy->Width(),xy->Height() ) / ( 1.1f * ( g_MaxWorldCoord - g_MinWorldCoord ) ); - float scale = xy->Scale() * 4.0f / 5.0f; - if ( scale < min_scale ) { - if ( xy->Scale() != min_scale ) { - xy->SetScale( min_scale ); - } - } - else - { - xy->SetScale( scale ); - } -} - -VIEWTYPE GlobalXYWnd_getCurrentViewType(){ - ASSERT_NOTNULL( g_pParentWnd ); - ASSERT_NOTNULL( g_pParentWnd->ActiveXY() ); - return g_pParentWnd->ActiveXY()->GetViewType(); +void XYWnd_ZoomOut(XYWnd *xy) +{ + float min_scale = MIN(xy->Width(), xy->Height()) / (1.1f * (g_MaxWorldCoord - g_MinWorldCoord)); + float scale = xy->Scale() * 4.0f / 5.0f; + if (scale < min_scale) { + if (xy->Scale() != min_scale) { + xy->SetScale(min_scale); + } + } else { + xy->SetScale(scale); + } +} + +VIEWTYPE GlobalXYWnd_getCurrentViewType() +{ + ASSERT_NOTNULL(g_pParentWnd); + ASSERT_NOTNULL(g_pParentWnd->ActiveXY()); + return g_pParentWnd->ActiveXY()->GetViewType(); } // ============================================================================= @@ -544,7 +580,7 @@ ui::Menu XYWnd::m_mnuDrop(ui::null); // this is disabled, and broken // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394 #if 0 -void WXY_Print(){ + void WXY_Print(){ long width, height; width = g_pParentWnd->ActiveXY()->Width(); height = g_pParentWnd->ActiveXY()->Height(); @@ -632,362 +668,387 @@ void WXY_Print(){ Timer g_chasemouse_timer; -void XYWnd::ChaseMouse(){ - float multiplier = g_chasemouse_timer.elapsed_msec() / 10.0f; - Scroll( float_to_integer( multiplier * m_chasemouse_delta_x ), float_to_integer( multiplier * -m_chasemouse_delta_y ) ); +void XYWnd::ChaseMouse() +{ + float multiplier = g_chasemouse_timer.elapsed_msec() / 10.0f; + Scroll(float_to_integer(multiplier * m_chasemouse_delta_x), float_to_integer(multiplier * -m_chasemouse_delta_y)); - //globalOutputStream() << "chasemouse: multiplier=" << multiplier << " x=" << m_chasemouse_delta_x << " y=" << m_chasemouse_delta_y << '\n'; + //globalOutputStream() << "chasemouse: multiplier=" << multiplier << " x=" << m_chasemouse_delta_x << " y=" << m_chasemouse_delta_y << '\n'; - XY_MouseMoved( m_chasemouse_current_x, m_chasemouse_current_y, getButtonState() ); - g_chasemouse_timer.start(); + XY_MouseMoved(m_chasemouse_current_x, m_chasemouse_current_y, getButtonState()); + g_chasemouse_timer.start(); } -gboolean xywnd_chasemouse( gpointer data ){ - reinterpret_cast( data )->ChaseMouse(); - return TRUE; +gboolean xywnd_chasemouse(gpointer data) +{ + reinterpret_cast( data )->ChaseMouse(); + return TRUE; } -inline const int& min_int( const int& left, const int& right ){ - return std::min( left, right ); +inline const int &min_int(const int &left, const int &right) +{ + return std::min(left, right); } -bool XYWnd::chaseMouseMotion( int pointx, int pointy ){ - m_chasemouse_delta_x = 0; - m_chasemouse_delta_y = 0; - - if ( g_xywindow_globals_private.m_bChaseMouse && getButtonState() == RAD_LBUTTON ) { - const int epsilon = 16; - - if ( pointx < epsilon ) { - m_chasemouse_delta_x = std::max( pointx, 0 ) - epsilon; - } - else if ( ( pointx - m_nWidth ) > -epsilon ) { - m_chasemouse_delta_x = min_int( ( pointx - m_nWidth ), 0 ) + epsilon; - } - - if ( pointy < epsilon ) { - m_chasemouse_delta_y = std::max( pointy, 0 ) - epsilon; - } - else if ( ( pointy - m_nHeight ) > -epsilon ) { - m_chasemouse_delta_y = min_int( ( pointy - m_nHeight ), 0 ) + epsilon; - } - - if ( m_chasemouse_delta_y != 0 || m_chasemouse_delta_x != 0 ) { - //globalOutputStream() << "chasemouse motion: x=" << pointx << " y=" << pointy << "... "; - m_chasemouse_current_x = pointx; - m_chasemouse_current_y = pointy; - if ( m_chasemouse_handler == 0 ) { - //globalOutputStream() << "chasemouse timer start... "; - g_chasemouse_timer.start(); - m_chasemouse_handler = g_idle_add( xywnd_chasemouse, this ); - } - return true; - } - else - { - if ( m_chasemouse_handler != 0 ) { - //globalOutputStream() << "chasemouse cancel\n"; - g_source_remove( m_chasemouse_handler ); - m_chasemouse_handler = 0; - } - } - } - else - { - if ( m_chasemouse_handler != 0 ) { - //globalOutputStream() << "chasemouse cancel\n"; - g_source_remove( m_chasemouse_handler ); - m_chasemouse_handler = 0; - } - } - return false; +bool XYWnd::chaseMouseMotion(int pointx, int pointy) +{ + m_chasemouse_delta_x = 0; + m_chasemouse_delta_y = 0; + + if (g_xywindow_globals_private.m_bChaseMouse && getButtonState() == RAD_LBUTTON) { + const int epsilon = 16; + + if (pointx < epsilon) { + m_chasemouse_delta_x = std::max(pointx, 0) - epsilon; + } else if ((pointx - m_nWidth) > -epsilon) { + m_chasemouse_delta_x = min_int((pointx - m_nWidth), 0) + epsilon; + } + + if (pointy < epsilon) { + m_chasemouse_delta_y = std::max(pointy, 0) - epsilon; + } else if ((pointy - m_nHeight) > -epsilon) { + m_chasemouse_delta_y = min_int((pointy - m_nHeight), 0) + epsilon; + } + + if (m_chasemouse_delta_y != 0 || m_chasemouse_delta_x != 0) { + //globalOutputStream() << "chasemouse motion: x=" << pointx << " y=" << pointy << "... "; + m_chasemouse_current_x = pointx; + m_chasemouse_current_y = pointy; + if (m_chasemouse_handler == 0) { + //globalOutputStream() << "chasemouse timer start... "; + g_chasemouse_timer.start(); + m_chasemouse_handler = g_idle_add(xywnd_chasemouse, this); + } + return true; + } else { + if (m_chasemouse_handler != 0) { + //globalOutputStream() << "chasemouse cancel\n"; + g_source_remove(m_chasemouse_handler); + m_chasemouse_handler = 0; + } + } + } else { + if (m_chasemouse_handler != 0) { + //globalOutputStream() << "chasemouse cancel\n"; + g_source_remove(m_chasemouse_handler); + m_chasemouse_handler = 0; + } + } + return false; } // ============================================================================= // XYWnd class -Shader* XYWnd::m_state_selected = 0; +Shader *XYWnd::m_state_selected = 0; -void xy_update_xor_rectangle( XYWnd& self, rect_t area ){ - if ( self.GetWidget().visible() ) { - self.m_XORRectangle.set( rectangle_from_area( area.min, area.max, self.Width(), self.Height() ) ); - } +void xy_update_xor_rectangle(XYWnd &self, rect_t area) +{ + if (self.GetWidget().visible()) { + self.m_XORRectangle.set(rectangle_from_area(area.min, area.max, self.Width(), self.Height())); + } } -gboolean xywnd_button_press( ui::Widget widget, GdkEventButton* event, XYWnd* xywnd ){ - if ( event->type == GDK_BUTTON_PRESS ) { - g_pParentWnd->SetActiveXY( xywnd ); +gboolean xywnd_button_press(ui::Widget widget, GdkEventButton *event, XYWnd *xywnd) +{ + if (event->type == GDK_BUTTON_PRESS) { + g_pParentWnd->SetActiveXY(xywnd); - xywnd->ButtonState_onMouseDown( buttons_for_event_button( event ) ); + xywnd->ButtonState_onMouseDown(buttons_for_event_button(event)); - xywnd->onMouseDown( WindowVector( event->x, event->y ), button_for_button( event->button ), modifiers_for_state( event->state ) ); - } - return FALSE; + xywnd->onMouseDown(WindowVector(event->x, event->y), button_for_button(event->button), + modifiers_for_state(event->state)); + } + return FALSE; } -gboolean xywnd_button_release( ui::Widget widget, GdkEventButton* event, XYWnd* xywnd ){ - if ( event->type == GDK_BUTTON_RELEASE ) { - xywnd->XY_MouseUp( static_cast( event->x ), static_cast( event->y ), buttons_for_event_button( event ) ); +gboolean xywnd_button_release(ui::Widget widget, GdkEventButton *event, XYWnd *xywnd) +{ + if (event->type == GDK_BUTTON_RELEASE) { + xywnd->XY_MouseUp(static_cast( event->x ), static_cast( event->y ), buttons_for_event_button(event)); - xywnd->ButtonState_onMouseUp( buttons_for_event_button( event ) ); - } - return FALSE; + xywnd->ButtonState_onMouseUp(buttons_for_event_button(event)); + } + return FALSE; } -gboolean xywnd_focus_in( ui::Widget widget, GdkEventFocus* event, XYWnd* xywnd ){ - if ( event->type == GDK_FOCUS_CHANGE ) { - if ( event->in ) { - g_pParentWnd->SetActiveXY( xywnd ); - } - } - return FALSE; +gboolean xywnd_focus_in(ui::Widget widget, GdkEventFocus *event, XYWnd *xywnd) +{ + if (event->type == GDK_FOCUS_CHANGE) { + if (event->in) { + g_pParentWnd->SetActiveXY(xywnd); + } + } + return FALSE; } -void xywnd_motion( gdouble x, gdouble y, guint state, void* data ){ - if ( reinterpret_cast( data )->chaseMouseMotion( static_cast( x ), static_cast( y ) ) ) { - return; - } - reinterpret_cast( data )->XY_MouseMoved( static_cast( x ), static_cast( y ), buttons_for_state( state ) ); +void xywnd_motion(gdouble x, gdouble y, guint state, void *data) +{ + if (reinterpret_cast( data )->chaseMouseMotion(static_cast( x ), static_cast( y ))) { + return; + } + reinterpret_cast( data )->XY_MouseMoved(static_cast( x ), static_cast( y ), + buttons_for_state(state)); } -gboolean xywnd_wheel_scroll( ui::Widget widget, GdkEventScroll* event, XYWnd* xywnd ){ - if ( event->direction == GDK_SCROLL_UP ) { - XYWnd_ZoomIn( xywnd ); - } - else if ( event->direction == GDK_SCROLL_DOWN ) { - XYWnd_ZoomOut( xywnd ); - } - return FALSE; +gboolean xywnd_wheel_scroll(ui::Widget widget, GdkEventScroll *event, XYWnd *xywnd) +{ + if (event->direction == GDK_SCROLL_UP) { + XYWnd_ZoomIn(xywnd); + } else if (event->direction == GDK_SCROLL_DOWN) { + XYWnd_ZoomOut(xywnd); + } + return FALSE; } -gboolean xywnd_size_allocate( ui::Widget widget, GtkAllocation* allocation, XYWnd* xywnd ){ - xywnd->m_nWidth = allocation->width; - xywnd->m_nHeight = allocation->height; - xywnd->updateProjection(); - xywnd->m_window_observer->onSizeChanged( xywnd->Width(), xywnd->Height() ); - return FALSE; +gboolean xywnd_size_allocate(ui::Widget widget, GtkAllocation *allocation, XYWnd *xywnd) +{ + xywnd->m_nWidth = allocation->width; + xywnd->m_nHeight = allocation->height; + xywnd->updateProjection(); + xywnd->m_window_observer->onSizeChanged(xywnd->Width(), xywnd->Height()); + return FALSE; } -gboolean xywnd_expose( ui::Widget widget, GdkEventExpose* event, XYWnd* xywnd ){ - if ( glwidget_make_current( xywnd->GetWidget() ) != FALSE ) { - if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) { - GlobalOpenGL_debugAssertNoErrors(); - xywnd->XY_Draw(); - GlobalOpenGL_debugAssertNoErrors(); +gboolean xywnd_expose(ui::Widget widget, GdkEventExpose *event, XYWnd *xywnd) +{ + if (glwidget_make_current(xywnd->GetWidget()) != FALSE) { + if (Map_Valid(g_map) && ScreenUpdates_Enabled()) { + GlobalOpenGL_debugAssertNoErrors(); + xywnd->XY_Draw(); + GlobalOpenGL_debugAssertNoErrors(); - xywnd->m_XORRectangle.set( rectangle_t() ); - } - glwidget_swap_buffers( xywnd->GetWidget() ); - } - return FALSE; + xywnd->m_XORRectangle.set(rectangle_t()); + } + glwidget_swap_buffers(xywnd->GetWidget()); + } + return FALSE; } -void XYWnd_CameraMoved( XYWnd& xywnd ){ - if ( g_xywindow_globals_private.m_bCamXYUpdate ) { - XYWnd_Update( xywnd ); - } +void XYWnd_CameraMoved(XYWnd &xywnd) +{ + if (g_xywindow_globals_private.m_bCamXYUpdate) { + XYWnd_Update(xywnd); + } } XYWnd::XYWnd() : - m_gl_widget( glwidget_new( FALSE ) ), - m_deferredDraw( WidgetQueueDrawCaller( m_gl_widget ) ), - m_deferred_motion( xywnd_motion, this ), - m_parent( ui::null ), - m_window_observer( NewWindowObserver() ), - m_XORRectangle( m_gl_widget ), - m_chasemouse_handler( 0 ){ - m_bActive = false; - m_buttonstate = 0; + m_gl_widget(glwidget_new(FALSE)), + m_deferredDraw(WidgetQueueDrawCaller(m_gl_widget)), + m_deferred_motion(xywnd_motion, this), + m_parent(ui::null), + m_window_observer(NewWindowObserver()), + m_XORRectangle(m_gl_widget), + m_chasemouse_handler(0) +{ + m_bActive = false; + m_buttonstate = 0; - m_bNewBrushDrag = false; - m_move_started = false; - m_zoom_started = false; + m_bNewBrushDrag = false; + m_move_started = false; + m_zoom_started = false; - m_nWidth = 0; - m_nHeight = 0; + m_nWidth = 0; + m_nHeight = 0; - m_vOrigin[0] = 0; - m_vOrigin[1] = 20; - m_vOrigin[2] = 46; - m_fScale = 1; - m_viewType = XY; + m_vOrigin[0] = 0; + m_vOrigin[1] = 20; + m_vOrigin[2] = 46; + m_fScale = 1; + m_viewType = XY; - m_backgroundActivated = false; - m_alpha = 1.0f; - m_xmin = 0.0f; - m_ymin = 0.0f; - m_xmax = 0.0f; - m_ymax = 0.0f; + m_backgroundActivated = false; + m_alpha = 1.0f; + m_xmin = 0.0f; + m_ymin = 0.0f; + m_xmax = 0.0f; + m_ymax = 0.0f; - m_entityCreate = false; + m_entityCreate = false; - m_mnuDrop = ui::Menu(ui::null); + m_mnuDrop = ui::Menu(ui::null); - GlobalWindowObservers_add( m_window_observer ); - GlobalWindowObservers_connectWidget( m_gl_widget ); + GlobalWindowObservers_add(m_window_observer); + GlobalWindowObservers_connectWidget(m_gl_widget); - m_window_observer->setRectangleDrawCallback( ReferenceCaller( *this ) ); - m_window_observer->setView( m_view ); + m_window_observer->setRectangleDrawCallback(ReferenceCaller(*this)); + m_window_observer->setView(m_view); - g_object_ref( m_gl_widget._handle ); + g_object_ref(m_gl_widget._handle); - gtk_widget_set_events( m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK ); - gtk_widget_set_can_focus( m_gl_widget, true ); + gtk_widget_set_events(m_gl_widget, + GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK); + gtk_widget_set_can_focus(m_gl_widget, true); - m_sizeHandler = m_gl_widget.connect( "size_allocate", G_CALLBACK( xywnd_size_allocate ), this ); - m_exposeHandler = m_gl_widget.on_render( G_CALLBACK( xywnd_expose ), this ); + m_sizeHandler = m_gl_widget.connect("size_allocate", G_CALLBACK(xywnd_size_allocate), this); + m_exposeHandler = m_gl_widget.on_render(G_CALLBACK(xywnd_expose), this); - m_gl_widget.connect( "button_press_event", G_CALLBACK( xywnd_button_press ), this ); - m_gl_widget.connect( "button_release_event", G_CALLBACK( xywnd_button_release ), this ); - m_gl_widget.connect( "focus_in_event", G_CALLBACK( xywnd_focus_in ), this ); - m_gl_widget.connect( "motion_notify_event", G_CALLBACK( DeferredMotion::gtk_motion ), &m_deferred_motion ); + m_gl_widget.connect("button_press_event", G_CALLBACK(xywnd_button_press), this); + m_gl_widget.connect("button_release_event", G_CALLBACK(xywnd_button_release), this); + m_gl_widget.connect("focus_in_event", G_CALLBACK(xywnd_focus_in), this); + m_gl_widget.connect("motion_notify_event", G_CALLBACK(DeferredMotion::gtk_motion), &m_deferred_motion); - m_gl_widget.connect( "scroll_event", G_CALLBACK( xywnd_wheel_scroll ), this ); + m_gl_widget.connect("scroll_event", G_CALLBACK(xywnd_wheel_scroll), this); - Map_addValidCallback( g_map, DeferredDrawOnMapValidChangedCaller( m_deferredDraw ) ); + Map_addValidCallback(g_map, DeferredDrawOnMapValidChangedCaller(m_deferredDraw)); - updateProjection(); - updateModelview(); + updateProjection(); + updateModelview(); - AddSceneChangeCallback( ReferenceCaller( *this ) ); - AddCameraMovedCallback( ReferenceCaller( *this ) ); + AddSceneChangeCallback(ReferenceCaller(*this)); + AddCameraMovedCallback(ReferenceCaller(*this)); - PressedButtons_connect( g_pressedButtons, m_gl_widget ); + PressedButtons_connect(g_pressedButtons, m_gl_widget); - onMouseDown.connectLast( makeSignalHandler3( MouseDownCaller(), *this ) ); + onMouseDown.connectLast(makeSignalHandler3(MouseDownCaller(), *this)); } -XYWnd::~XYWnd(){ - onDestroyed(); +XYWnd::~XYWnd() +{ + onDestroyed(); - if ( m_mnuDrop ) { - m_mnuDrop.destroy(); - m_mnuDrop = ui::Menu(ui::null); - } + if (m_mnuDrop) { + m_mnuDrop.destroy(); + m_mnuDrop = ui::Menu(ui::null); + } - g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_sizeHandler ); - g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_exposeHandler ); + g_signal_handler_disconnect(G_OBJECT(m_gl_widget), m_sizeHandler); + g_signal_handler_disconnect(G_OBJECT(m_gl_widget), m_exposeHandler); - m_gl_widget.unref(); + m_gl_widget.unref(); - m_window_observer->release(); + m_window_observer->release(); } -void XYWnd::captureStates(){ - m_state_selected = GlobalShaderCache().capture( "$XY_OVERLAY" ); +void XYWnd::captureStates() +{ + m_state_selected = GlobalShaderCache().capture("$XY_OVERLAY"); } -void XYWnd::releaseStates(){ - GlobalShaderCache().release( "$XY_OVERLAY" ); +void XYWnd::releaseStates() +{ + GlobalShaderCache().release("$XY_OVERLAY"); } -const Vector3& XYWnd::GetOrigin(){ - return m_vOrigin; +const Vector3 &XYWnd::GetOrigin() +{ + return m_vOrigin; } -void XYWnd::SetOrigin( const Vector3& origin ){ - m_vOrigin = origin; - updateModelview(); +void XYWnd::SetOrigin(const Vector3 &origin) +{ + m_vOrigin = origin; + updateModelview(); } -void XYWnd::Scroll( int x, int y ){ - int nDim1 = ( m_viewType == YZ ) ? 1 : 0; - int nDim2 = ( m_viewType == XY ) ? 1 : 2; - m_vOrigin[nDim1] += x / m_fScale; - m_vOrigin[nDim2] += y / m_fScale; - updateModelview(); - queueDraw(); +void XYWnd::Scroll(int x, int y) +{ + int nDim1 = (m_viewType == YZ) ? 1 : 0; + int nDim2 = (m_viewType == XY) ? 1 : 2; + m_vOrigin[nDim1] += x / m_fScale; + m_vOrigin[nDim2] += y / m_fScale; + updateModelview(); + queueDraw(); } -unsigned int Clipper_buttons(){ - return RAD_LBUTTON; +unsigned int Clipper_buttons() +{ + return RAD_LBUTTON; } -void XYWnd::DropClipPoint( int pointx, int pointy ){ - Vector3 point; +void XYWnd::DropClipPoint(int pointx, int pointy) +{ + Vector3 point; - XY_ToPoint( pointx, pointy, point ); + XY_ToPoint(pointx, pointy, point); - Vector3 mid; - Select_GetMid( mid ); - g_clip_viewtype = static_cast( GetViewType() ); - const int nDim = ( g_clip_viewtype == YZ ) ? 0 : ( ( g_clip_viewtype == XZ ) ? 1 : 2 ); - point[nDim] = mid[nDim]; - vector3_snap( point, GetSnapGridSize() ); - NewClipPoint( point ); + Vector3 mid; + Select_GetMid(mid); + g_clip_viewtype = static_cast( GetViewType()); + const int nDim = (g_clip_viewtype == YZ) ? 0 : ((g_clip_viewtype == XZ) ? 1 : 2); + point[nDim] = mid[nDim]; + vector3_snap(point, GetSnapGridSize()); + NewClipPoint(point); } -void XYWnd::Clipper_OnLButtonDown( int x, int y ){ - Vector3 mousePosition; - XY_ToPoint( x, y, mousePosition ); - g_pMovingClip = GlobalClipPoints_Find( mousePosition, (VIEWTYPE)m_viewType, m_fScale ); - if ( !g_pMovingClip ) { - DropClipPoint( x, y ); - } +void XYWnd::Clipper_OnLButtonDown(int x, int y) +{ + Vector3 mousePosition; + XY_ToPoint(x, y, mousePosition); + g_pMovingClip = GlobalClipPoints_Find(mousePosition, (VIEWTYPE) m_viewType, m_fScale); + if (!g_pMovingClip) { + DropClipPoint(x, y); + } } -void XYWnd::Clipper_OnLButtonUp( int x, int y ){ - if ( g_pMovingClip ) { - g_pMovingClip = 0; - } +void XYWnd::Clipper_OnLButtonUp(int x, int y) +{ + if (g_pMovingClip) { + g_pMovingClip = 0; + } } -void XYWnd::Clipper_OnMouseMoved( int x, int y ){ - if ( g_pMovingClip ) { - XY_ToPoint( x, y, g_pMovingClip->m_ptClip ); - XY_SnapToGrid( g_pMovingClip->m_ptClip ); - Clip_Update(); - ClipperChangeNotify(); - } +void XYWnd::Clipper_OnMouseMoved(int x, int y) +{ + if (g_pMovingClip) { + XY_ToPoint(x, y, g_pMovingClip->m_ptClip); + XY_SnapToGrid(g_pMovingClip->m_ptClip); + Clip_Update(); + ClipperChangeNotify(); + } } -void XYWnd::Clipper_Crosshair_OnMouseMoved( int x, int y ){ - Vector3 mousePosition; - XY_ToPoint( x, y, mousePosition ); - if ( ClipMode() && GlobalClipPoints_Find( mousePosition, (VIEWTYPE)m_viewType, m_fScale ) != 0 ) { - GdkCursor *cursor; - cursor = gdk_cursor_new( GDK_CROSSHAIR ); - gdk_window_set_cursor( gtk_widget_get_window(m_gl_widget), cursor ); - gdk_cursor_unref( cursor ); - } - else - { - gdk_window_set_cursor( gtk_widget_get_window(m_gl_widget), 0 ); - } +void XYWnd::Clipper_Crosshair_OnMouseMoved(int x, int y) +{ + Vector3 mousePosition; + XY_ToPoint(x, y, mousePosition); + if (ClipMode() && GlobalClipPoints_Find(mousePosition, (VIEWTYPE) m_viewType, m_fScale) != 0) { + GdkCursor *cursor; + cursor = gdk_cursor_new(GDK_CROSSHAIR); + gdk_window_set_cursor(gtk_widget_get_window(m_gl_widget), cursor); + gdk_cursor_unref(cursor); + } else { + gdk_window_set_cursor(gtk_widget_get_window(m_gl_widget), 0); + } +} + +unsigned int MoveCamera_buttons() +{ + return RAD_CONTROL | (g_glwindow_globals.m_nMouseType == ETwoButton ? RAD_RBUTTON : RAD_MBUTTON); } -unsigned int MoveCamera_buttons(){ - return RAD_CONTROL | ( g_glwindow_globals.m_nMouseType == ETwoButton ? RAD_RBUTTON : RAD_MBUTTON ); +void XYWnd_PositionCamera(XYWnd *xywnd, int x, int y, CamWnd &camwnd) +{ + Vector3 origin(Camera_getOrigin(camwnd)); + xywnd->XY_ToPoint(x, y, origin); + xywnd->XY_SnapToGrid(origin); + Camera_setOrigin(camwnd, origin); } -void XYWnd_PositionCamera( XYWnd* xywnd, int x, int y, CamWnd& camwnd ){ - Vector3 origin( Camera_getOrigin( camwnd ) ); - xywnd->XY_ToPoint( x, y, origin ); - xywnd->XY_SnapToGrid( origin ); - Camera_setOrigin( camwnd, origin ); +unsigned int OrientCamera_buttons() +{ + if (g_glwindow_globals.m_nMouseType == ETwoButton) { + return RAD_RBUTTON | RAD_SHIFT | RAD_CONTROL; + } + return RAD_MBUTTON; } -unsigned int OrientCamera_buttons(){ - if ( g_glwindow_globals.m_nMouseType == ETwoButton ) { - return RAD_RBUTTON | RAD_SHIFT | RAD_CONTROL; - } - return RAD_MBUTTON; -} - -void XYWnd_OrientCamera( XYWnd* xywnd, int x, int y, CamWnd& camwnd ){ - Vector3 point = g_vector3_identity; - xywnd->XY_ToPoint( x, y, point ); - xywnd->XY_SnapToGrid( point ); - vector3_subtract( point, Camera_getOrigin( camwnd ) ); - - int n1 = ( xywnd->GetViewType() == XY ) ? 1 : 2; - int n2 = ( xywnd->GetViewType() == YZ ) ? 1 : 0; - int nAngle = ( xywnd->GetViewType() == XY ) ? CAMERA_YAW : CAMERA_PITCH; - if ( point[n1] || point[n2] ) { - Vector3 angles( Camera_getAngles( camwnd ) ); - angles[nAngle] = static_cast( radians_to_degrees( atan2( point[n1], point[n2] ) ) ); - Camera_setAngles( camwnd, angles ); - } +void XYWnd_OrientCamera(XYWnd *xywnd, int x, int y, CamWnd &camwnd) +{ + Vector3 point = g_vector3_identity; + xywnd->XY_ToPoint(x, y, point); + xywnd->XY_SnapToGrid(point); + vector3_subtract(point, Camera_getOrigin(camwnd)); + + int n1 = (xywnd->GetViewType() == XY) ? 1 : 2; + int n2 = (xywnd->GetViewType() == YZ) ? 1 : 0; + int nAngle = (xywnd->GetViewType() == XY) ? CAMERA_YAW : CAMERA_PITCH; + if (point[n1] || point[n2]) { + Vector3 angles(Camera_getAngles(camwnd)); + angles[nAngle] = static_cast( radians_to_degrees(atan2(point[n1], point[n2]))); + Camera_setAngles(camwnd, angles); + } } /* @@ -995,509 +1056,528 @@ void XYWnd_OrientCamera( XYWnd* xywnd, int x, int y, CamWnd& camwnd ){ NewBrushDrag ============== */ -unsigned int NewBrushDrag_buttons(){ - return RAD_LBUTTON; +unsigned int NewBrushDrag_buttons() +{ + return RAD_LBUTTON; } -void XYWnd::NewBrushDrag_Begin( int x, int y ){ - m_NewBrushDrag = 0; - m_nNewBrushPressx = x; - m_nNewBrushPressy = y; +void XYWnd::NewBrushDrag_Begin(int x, int y) +{ + m_NewBrushDrag = 0; + m_nNewBrushPressx = x; + m_nNewBrushPressy = y; - m_bNewBrushDrag = true; - GlobalUndoSystem().start(); + m_bNewBrushDrag = true; + GlobalUndoSystem().start(); } -void XYWnd::NewBrushDrag_End( int x, int y ){ - if ( m_NewBrushDrag != 0 ) { - GlobalUndoSystem().finish( "brushDragNew" ); - } +void XYWnd::NewBrushDrag_End(int x, int y) +{ + if (m_NewBrushDrag != 0) { + GlobalUndoSystem().finish("brushDragNew"); + } } -void XYWnd::NewBrushDrag( int x, int y ){ - Vector3 mins, maxs; - XY_ToPoint( m_nNewBrushPressx, m_nNewBrushPressy, mins ); - XY_SnapToGrid( mins ); - XY_ToPoint( x, y, maxs ); - XY_SnapToGrid( maxs ); - - int nDim = ( m_viewType == XY ) ? 2 : ( m_viewType == YZ ) ? 0 : 1; +void XYWnd::NewBrushDrag(int x, int y) +{ + Vector3 mins, maxs; + XY_ToPoint(m_nNewBrushPressx, m_nNewBrushPressy, mins); + XY_SnapToGrid(mins); + XY_ToPoint(x, y, maxs); + XY_SnapToGrid(maxs); + + int nDim = (m_viewType == XY) ? 2 : (m_viewType == YZ) ? 0 : 1; + + mins[nDim] = float_snapped(Select_getWorkZone().d_work_min[nDim], GetSnapGridSize()); + maxs[nDim] = float_snapped(Select_getWorkZone().d_work_max[nDim], GetSnapGridSize()); + + if (maxs[nDim] <= mins[nDim]) { + maxs[nDim] = mins[nDim] + GetGridSize(); + } + + for (int i = 0; i < 3; i++) { + if (mins[i] == maxs[i]) { + return; // don't create a degenerate brush + } + if (mins[i] > maxs[i]) { + float temp = mins[i]; + mins[i] = maxs[i]; + maxs[i] = temp; + } + } + + if (m_NewBrushDrag == 0) { + NodeSmartReference node(GlobalBrushCreator().createBrush()); + Node_getTraversable(Map_FindOrInsertWorldspawn(g_map))->insert(node); + + scene::Path brushpath(makeReference(GlobalSceneGraph().root())); + brushpath.push(makeReference(*Map_GetWorldspawn(g_map))); + brushpath.push(makeReference(node.get())); + selectPath(brushpath, true); + + m_NewBrushDrag = node.get_pointer(); + } + + // d1223m + //Scene_BrushResize_Selected(GlobalSceneGraph(), aabb_for_minmax(mins, maxs), TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); + Scene_BrushResize_Selected(GlobalSceneGraph(), aabb_for_minmax(mins, maxs), + g_brush_always_caulk ? + "textures/common/caulk" : TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); +} + +void entitycreate_activated(ui::Widget item) +{ + scene::Node *world_node = Map_FindWorldspawn(g_map); + const char *entity_name = gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item)))); - mins[nDim] = float_snapped( Select_getWorkZone().d_work_min[nDim], GetSnapGridSize() ); - maxs[nDim] = float_snapped( Select_getWorkZone().d_work_max[nDim], GetSnapGridSize() ); + if (!(world_node && string_equal(entity_name, "worldspawn"))) { + g_pParentWnd->ActiveXY()->OnEntityCreate(entity_name); + } else { + GlobalRadiant().m_pfnMessageBox(MainFrame_getWindow(), "There's already a worldspawn in your map!" + "", + "Info", + eMB_OK, + eMB_ICONDEFAULT); + } +} - if ( maxs[nDim] <= mins[nDim] ) { - maxs[nDim] = mins[nDim] + GetGridSize(); - } +void EntityClassMenu_addItem(ui::Menu menu, const char *name) +{ + auto item = ui::MenuItem(name); + item.connect("activate", G_CALLBACK(entitycreate_activated), item); + item.show(); + menu_add_item(menu, item); +} - for ( int i = 0 ; i < 3 ; i++ ) - { - if ( mins[i] == maxs[i] ) { - return; // don't create a degenerate brush - } - if ( mins[i] > maxs[i] ) { - float temp = mins[i]; - mins[i] = maxs[i]; - maxs[i] = temp; - } - } +class EntityClassMenuInserter : public EntityClassVisitor { + typedef std::pair MenuPair; + typedef std::vector MenuStack; + MenuStack m_stack; + CopiedString m_previous; +public: + EntityClassMenuInserter(ui::Menu menu) + { + m_stack.reserve(2); + m_stack.push_back(MenuPair(menu, "")); + } + + ~EntityClassMenuInserter() + { + if (!string_empty(m_previous.c_str())) { + addItem(m_previous.c_str(), ""); + } + } + + void visit(EntityClass *e) + { + ASSERT_MESSAGE(!string_empty(e->name()), "entity-class has no name"); + if (!string_empty(m_previous.c_str())) { + addItem(m_previous.c_str(), e->name()); + } + m_previous = e->name(); + } + + void pushMenu(const CopiedString &name) + { + auto item = ui::MenuItem(name.c_str()); + item.show(); + m_stack.back().first.add(item); + + auto submenu = ui::Menu(ui::New); + gtk_menu_item_set_submenu(item, submenu); + + m_stack.push_back(MenuPair(submenu, name)); + } + + void popMenu() + { + m_stack.pop_back(); + } + + void addItem(const char *name, const char *next) + { + const char *underscore = strchr(name, '_'); + + if (underscore != 0 && underscore != name) { + bool nextEqual = string_equal_n(name, next, (underscore + 1) - name); + const char *parent = m_stack.back().second.c_str(); + + if (!string_empty(parent) + && string_length(parent) == std::size_t(underscore - name) + && string_equal_n(name, parent, underscore - name)) { // this is a child + } else if (nextEqual) { + if (m_stack.size() == 2) { + popMenu(); + } + pushMenu(CopiedString(StringRange(name, underscore))); + } else if (m_stack.size() == 2) { + popMenu(); + } + } else if (m_stack.size() == 2) { + popMenu(); + } + + EntityClassMenu_addItem(m_stack.back().first, name); + } +}; - if ( m_NewBrushDrag == 0 ) { - NodeSmartReference node( GlobalBrushCreator().createBrush() ); - Node_getTraversable( Map_FindOrInsertWorldspawn( g_map ) )->insert( node ); +void XYWnd::OnContextMenu() +{ + if (g_xywindow_globals.m_bRightClick == false) { + return; + } - scene::Path brushpath( makeReference( GlobalSceneGraph().root() ) ); - brushpath.push( makeReference( *Map_GetWorldspawn( g_map ) ) ); - brushpath.push( makeReference( node.get() ) ); - selectPath( brushpath, true ); + if (!m_mnuDrop) { // first time, load it up + auto menu = m_mnuDrop = ui::Menu(ui::New); - m_NewBrushDrag = node.get_pointer(); - } + EntityClassMenuInserter inserter(menu); + GlobalEntityClassManager().forEach(inserter); + } - // d1223m - //Scene_BrushResize_Selected(GlobalSceneGraph(), aabb_for_minmax(mins, maxs), TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); - Scene_BrushResize_Selected( GlobalSceneGraph(), aabb_for_minmax( mins, maxs ), - g_brush_always_caulk ? - "textures/common/caulk" : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); + gtk_menu_popup(m_mnuDrop, 0, 0, 0, 0, 1, GDK_CURRENT_TIME); } -void entitycreate_activated( ui::Widget item ){ - scene::Node* world_node = Map_FindWorldspawn( g_map ); - const char* entity_name = gtk_label_get_text( GTK_LABEL( gtk_bin_get_child(GTK_BIN( item )) ) ); +FreezePointer g_xywnd_freezePointer; - if ( !( world_node && string_equal( entity_name, "worldspawn" ) ) ) { - g_pParentWnd->ActiveXY()->OnEntityCreate( entity_name ); - } - else { - GlobalRadiant().m_pfnMessageBox( MainFrame_getWindow(), "There's already a worldspawn in your map!" - "", - "Info", - eMB_OK, - eMB_ICONDEFAULT ); - } +unsigned int Move_buttons() +{ + return RAD_RBUTTON; } -void EntityClassMenu_addItem( ui::Menu menu, const char* name ){ - auto item = ui::MenuItem( name ); - item.connect( "activate", G_CALLBACK( entitycreate_activated ), item ); - item.show(); - menu_add_item( menu, item ); +void XYWnd_moveDelta(int x, int y, unsigned int state, void *data) +{ + reinterpret_cast( data )->EntityCreate_MouseMove(x, y); + reinterpret_cast( data )->Scroll(-x, y); } -class EntityClassMenuInserter : public EntityClassVisitor +gboolean XYWnd_Move_focusOut(ui::Widget widget, GdkEventFocus *event, XYWnd *xywnd) { -typedef std::pair MenuPair; -typedef std::vector MenuStack; -MenuStack m_stack; -CopiedString m_previous; -public: -EntityClassMenuInserter( ui::Menu menu ){ - m_stack.reserve( 2 ); - m_stack.push_back( MenuPair( menu, "" ) ); + xywnd->Move_End(); + return FALSE; } -~EntityClassMenuInserter(){ - if ( !string_empty( m_previous.c_str() ) ) { - addItem( m_previous.c_str(), "" ); - } + +void XYWnd::Move_Begin() +{ + if (m_move_started) { + Move_End(); + } + m_move_started = true; + g_xywnd_freezePointer.freeze_pointer(m_parent ? m_parent : MainFrame_getWindow(), XYWnd_moveDelta, this); + m_move_focusOut = m_gl_widget.connect("focus_out_event", G_CALLBACK(XYWnd_Move_focusOut), this); } -void visit( EntityClass* e ){ - ASSERT_MESSAGE( !string_empty( e->name() ), "entity-class has no name" ); - if ( !string_empty( m_previous.c_str() ) ) { - addItem( m_previous.c_str(), e->name() ); - } - m_previous = e->name(); + +void XYWnd::Move_End() +{ + m_move_started = false; + g_xywnd_freezePointer.unfreeze_pointer(m_parent ? m_parent : MainFrame_getWindow()); + g_signal_handler_disconnect(G_OBJECT(m_gl_widget), m_move_focusOut); +} + +unsigned int Zoom_buttons() +{ + return RAD_RBUTTON | RAD_SHIFT; } -void pushMenu( const CopiedString& name ){ - auto item = ui::MenuItem( name.c_str() ); - item.show(); - m_stack.back().first.add(item); - auto submenu = ui::Menu(ui::New); - gtk_menu_item_set_submenu( item, submenu ); +int g_dragZoom = 0; - m_stack.push_back( MenuPair( submenu, name ) ); +void XYWnd_zoomDelta(int x, int y, unsigned int state, void *data) +{ + if (y != 0) { + g_dragZoom += y; + + while (abs(g_dragZoom) > 8) { + if (g_dragZoom > 0) { + XYWnd_ZoomOut(reinterpret_cast( data )); + g_dragZoom -= 8; + } else { + XYWnd_ZoomIn(reinterpret_cast( data )); + g_dragZoom += 8; + } + } + } +} + +gboolean XYWnd_Zoom_focusOut(ui::Widget widget, GdkEventFocus *event, XYWnd *xywnd) +{ + xywnd->Zoom_End(); + return FALSE; } -void popMenu(){ - m_stack.pop_back(); + +void XYWnd::Zoom_Begin() +{ + if (m_zoom_started) { + Zoom_End(); + } + m_zoom_started = true; + g_dragZoom = 0; + g_xywnd_freezePointer.freeze_pointer(m_parent ? m_parent : MainFrame_getWindow(), XYWnd_zoomDelta, this); + m_zoom_focusOut = m_gl_widget.connect("focus_out_event", G_CALLBACK(XYWnd_Zoom_focusOut), this); } -void addItem( const char* name, const char* next ){ - const char* underscore = strchr( name, '_' ); - if ( underscore != 0 && underscore != name ) { - bool nextEqual = string_equal_n( name, next, ( underscore + 1 ) - name ); - const char* parent = m_stack.back().second.c_str(); +void XYWnd::Zoom_End() +{ + m_zoom_started = false; + g_xywnd_freezePointer.unfreeze_pointer(m_parent ? m_parent : MainFrame_getWindow()); + g_signal_handler_disconnect(G_OBJECT(m_gl_widget), m_zoom_focusOut); +} - if ( !string_empty( parent ) - && string_length( parent ) == std::size_t( underscore - name ) - && string_equal_n( name, parent, underscore - name ) ) { // this is a child - } - else if ( nextEqual ) { - if ( m_stack.size() == 2 ) { - popMenu(); - } - pushMenu( CopiedString( StringRange( name, underscore ) ) ); - } - else if ( m_stack.size() == 2 ) { - popMenu(); - } - } - else if ( m_stack.size() == 2 ) { - popMenu(); - } +// makes sure the selected brush or camera is in view +void XYWnd::PositionView(const Vector3 &position) +{ + int nDim1 = (m_viewType == YZ) ? 1 : 0; + int nDim2 = (m_viewType == XY) ? 1 : 2; - EntityClassMenu_addItem( m_stack.back().first, name ); -} -}; + m_vOrigin[nDim1] = position[nDim1]; + m_vOrigin[nDim2] = position[nDim2]; -void XYWnd::OnContextMenu(){ - if ( g_xywindow_globals.m_bRightClick == false ) { - return; - } + updateModelview(); - if ( !m_mnuDrop ) { // first time, load it up - auto menu = m_mnuDrop = ui::Menu(ui::New); + XYWnd_Update(*this); +} - EntityClassMenuInserter inserter( menu ); - GlobalEntityClassManager().forEach( inserter ); - } +void XYWnd::SetViewType(VIEWTYPE viewType) +{ + m_viewType = viewType; + updateModelview(); - gtk_menu_popup( m_mnuDrop, 0, 0, 0, 0, 1, GDK_CURRENT_TIME ); + if (m_parent) { + gtk_window_set_title(m_parent, ViewType_getTitle(m_viewType)); + } } -FreezePointer g_xywnd_freezePointer; -unsigned int Move_buttons(){ - return RAD_RBUTTON; +inline WindowVector WindowVector_forInteger(int x, int y) +{ + return WindowVector(static_cast( x ), static_cast( y )); } -void XYWnd_moveDelta( int x, int y, unsigned int state, void* data ){ - reinterpret_cast( data )->EntityCreate_MouseMove( x, y ); - reinterpret_cast( data )->Scroll( -x, y ); +void XYWnd::mouseDown(const WindowVector &position, ButtonIdentifier button, ModifierFlags modifiers) +{ + XY_MouseDown(static_cast( position.x()), static_cast( position.y()), + buttons_for_button_and_modifiers(button, modifiers)); } -gboolean XYWnd_Move_focusOut( ui::Widget widget, GdkEventFocus* event, XYWnd* xywnd ){ - xywnd->Move_End(); - return FALSE; +void XYWnd::XY_MouseDown(int x, int y, unsigned int buttons) +{ + if (buttons == Move_buttons()) { + Move_Begin(); + EntityCreate_MouseDown(x, y); + } else if (buttons == Zoom_buttons()) { + Zoom_Begin(); + } else if (ClipMode() && buttons == Clipper_buttons()) { + Clipper_OnLButtonDown(x, y); + } else if (buttons == NewBrushDrag_buttons() && GlobalSelectionSystem().countSelected() == 0) { + NewBrushDrag_Begin(x, y); + } + // control mbutton = move camera + else if (buttons == MoveCamera_buttons()) { + XYWnd_PositionCamera(this, x, y, *g_pParentWnd->GetCamWnd()); + } + // mbutton = angle camera + else if (buttons == OrientCamera_buttons()) { + XYWnd_OrientCamera(this, x, y, *g_pParentWnd->GetCamWnd()); + } else { + m_window_observer->onMouseDown(WindowVector_forInteger(x, y), button_for_flags(buttons), + modifiers_for_flags(buttons)); + } +} + +void XYWnd::XY_MouseUp(int x, int y, unsigned int buttons) +{ + if (m_move_started) { + Move_End(); + EntityCreate_MouseUp(x, y); + } else if (m_zoom_started) { + Zoom_End(); + } else if (ClipMode() && buttons == Clipper_buttons()) { + Clipper_OnLButtonUp(x, y); + } else if (m_bNewBrushDrag) { + m_bNewBrushDrag = false; + NewBrushDrag_End(x, y); + } else { + m_window_observer->onMouseUp(WindowVector_forInteger(x, y), button_for_flags(buttons), + modifiers_for_flags(buttons)); + } +} + +void XYWnd::XY_MouseMoved(int x, int y, unsigned int buttons) +{ + // rbutton = drag xy origin + if (m_move_started) { + } + // zoom in/out + else if (m_zoom_started) { + } else if (ClipMode() && g_pMovingClip != 0) { + Clipper_OnMouseMoved(x, y); + } + // lbutton without selection = drag new brush + else if (m_bNewBrushDrag) { + NewBrushDrag(x, y); + } + + // control mbutton = move camera + else if (getButtonState() == MoveCamera_buttons()) { + XYWnd_PositionCamera(this, x, y, *g_pParentWnd->GetCamWnd()); + } + + // mbutton = angle camera + else if (getButtonState() == OrientCamera_buttons()) { + XYWnd_OrientCamera(this, x, y, *g_pParentWnd->GetCamWnd()); + } else { + m_window_observer->onMouseMotion(WindowVector_forInteger(x, y), modifiers_for_flags(buttons)); + + m_mousePosition[0] = m_mousePosition[1] = m_mousePosition[2] = 0.0; + XY_ToPoint(x, y, m_mousePosition); + XY_SnapToGrid(m_mousePosition); + + StringOutputStream status(64); + status << "x:: " << FloatFormat(m_mousePosition[0], 6, 1) + << " y:: " << FloatFormat(m_mousePosition[1], 6, 1) + << " z:: " << FloatFormat(m_mousePosition[2], 6, 1); + g_pParentWnd->SetStatusText(g_pParentWnd->m_position_status, status.c_str()); + + if (g_bCrossHairs) { + XYWnd_Update(*this); + } + + Clipper_Crosshair_OnMouseMoved(x, y); + } +} + +void XYWnd::EntityCreate_MouseDown(int x, int y) +{ + m_entityCreate = true; + m_entityCreate_x = x; + m_entityCreate_y = y; } -void XYWnd::Move_Begin(){ - if ( m_move_started ) { - Move_End(); - } - m_move_started = true; - g_xywnd_freezePointer.freeze_pointer( m_parent ? m_parent : MainFrame_getWindow(), XYWnd_moveDelta, this ); - m_move_focusOut = m_gl_widget.connect( "focus_out_event", G_CALLBACK( XYWnd_Move_focusOut ), this ); +void XYWnd::EntityCreate_MouseMove(int x, int y) +{ + if (m_entityCreate && (m_entityCreate_x != x || m_entityCreate_y != y)) { + m_entityCreate = false; + } } -void XYWnd::Move_End(){ - m_move_started = false; - g_xywnd_freezePointer.unfreeze_pointer( m_parent ? m_parent : MainFrame_getWindow() ); - g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_move_focusOut ); +void XYWnd::EntityCreate_MouseUp(int x, int y) +{ + if (m_entityCreate) { + m_entityCreate = false; + OnContextMenu(); + } } -unsigned int Zoom_buttons(){ - return RAD_RBUTTON | RAD_SHIFT; +inline float screen_normalised(int pos, unsigned int size) +{ + return ((2.0f * pos) / size) - 1.0f; } -int g_dragZoom = 0; - -void XYWnd_zoomDelta( int x, int y, unsigned int state, void* data ){ - if ( y != 0 ) { - g_dragZoom += y; - - while ( abs( g_dragZoom ) > 8 ) - { - if ( g_dragZoom > 0 ) { - XYWnd_ZoomOut( reinterpret_cast( data ) ); - g_dragZoom -= 8; - } - else - { - XYWnd_ZoomIn( reinterpret_cast( data ) ); - g_dragZoom += 8; - } - } - } -} - -gboolean XYWnd_Zoom_focusOut( ui::Widget widget, GdkEventFocus* event, XYWnd* xywnd ){ - xywnd->Zoom_End(); - return FALSE; -} - -void XYWnd::Zoom_Begin(){ - if ( m_zoom_started ) { - Zoom_End(); - } - m_zoom_started = true; - g_dragZoom = 0; - g_xywnd_freezePointer.freeze_pointer( m_parent ? m_parent : MainFrame_getWindow(), XYWnd_zoomDelta, this ); - m_zoom_focusOut = m_gl_widget.connect( "focus_out_event", G_CALLBACK( XYWnd_Zoom_focusOut ), this ); -} - -void XYWnd::Zoom_End(){ - m_zoom_started = false; - g_xywnd_freezePointer.unfreeze_pointer( m_parent ? m_parent : MainFrame_getWindow() ); - g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_zoom_focusOut ); -} - -// makes sure the selected brush or camera is in view -void XYWnd::PositionView( const Vector3& position ){ - int nDim1 = ( m_viewType == YZ ) ? 1 : 0; - int nDim2 = ( m_viewType == XY ) ? 1 : 2; - - m_vOrigin[nDim1] = position[nDim1]; - m_vOrigin[nDim2] = position[nDim2]; - - updateModelview(); - - XYWnd_Update( *this ); -} - -void XYWnd::SetViewType( VIEWTYPE viewType ){ - m_viewType = viewType; - updateModelview(); - - if ( m_parent ) { - gtk_window_set_title( m_parent, ViewType_getTitle( m_viewType ) ); - } -} - - -inline WindowVector WindowVector_forInteger( int x, int y ){ - return WindowVector( static_cast( x ), static_cast( y ) ); -} - -void XYWnd::mouseDown( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ){ - XY_MouseDown( static_cast( position.x() ), static_cast( position.y() ), buttons_for_button_and_modifiers( button, modifiers ) ); -} -void XYWnd::XY_MouseDown( int x, int y, unsigned int buttons ){ - if ( buttons == Move_buttons() ) { - Move_Begin(); - EntityCreate_MouseDown( x, y ); - } - else if ( buttons == Zoom_buttons() ) { - Zoom_Begin(); - } - else if ( ClipMode() && buttons == Clipper_buttons() ) { - Clipper_OnLButtonDown( x, y ); - } - else if ( buttons == NewBrushDrag_buttons() && GlobalSelectionSystem().countSelected() == 0 ) { - NewBrushDrag_Begin( x, y ); - } - // control mbutton = move camera - else if ( buttons == MoveCamera_buttons() ) { - XYWnd_PositionCamera( this, x, y, *g_pParentWnd->GetCamWnd() ); - } - // mbutton = angle camera - else if ( buttons == OrientCamera_buttons() ) { - XYWnd_OrientCamera( this, x, y, *g_pParentWnd->GetCamWnd() ); - } - else - { - m_window_observer->onMouseDown( WindowVector_forInteger( x, y ), button_for_flags( buttons ), modifiers_for_flags( buttons ) ); - } -} - -void XYWnd::XY_MouseUp( int x, int y, unsigned int buttons ){ - if ( m_move_started ) { - Move_End(); - EntityCreate_MouseUp( x, y ); - } - else if ( m_zoom_started ) { - Zoom_End(); - } - else if ( ClipMode() && buttons == Clipper_buttons() ) { - Clipper_OnLButtonUp( x, y ); - } - else if ( m_bNewBrushDrag ) { - m_bNewBrushDrag = false; - NewBrushDrag_End( x, y ); - } - else - { - m_window_observer->onMouseUp( WindowVector_forInteger( x, y ), button_for_flags( buttons ), modifiers_for_flags( buttons ) ); - } -} - -void XYWnd::XY_MouseMoved( int x, int y, unsigned int buttons ){ - // rbutton = drag xy origin - if ( m_move_started ) { - } - // zoom in/out - else if ( m_zoom_started ) { - } - - else if ( ClipMode() && g_pMovingClip != 0 ) { - Clipper_OnMouseMoved( x, y ); - } - // lbutton without selection = drag new brush - else if ( m_bNewBrushDrag ) { - NewBrushDrag( x, y ); - } - - // control mbutton = move camera - else if ( getButtonState() == MoveCamera_buttons() ) { - XYWnd_PositionCamera( this, x, y, *g_pParentWnd->GetCamWnd() ); - } - - // mbutton = angle camera - else if ( getButtonState() == OrientCamera_buttons() ) { - XYWnd_OrientCamera( this, x, y, *g_pParentWnd->GetCamWnd() ); - } - - else - { - m_window_observer->onMouseMotion( WindowVector_forInteger( x, y ), modifiers_for_flags( buttons ) ); - - m_mousePosition[0] = m_mousePosition[1] = m_mousePosition[2] = 0.0; - XY_ToPoint( x, y, m_mousePosition ); - XY_SnapToGrid( m_mousePosition ); - - StringOutputStream status( 64 ); - status << "x:: " << FloatFormat( m_mousePosition[0], 6, 1 ) - << " y:: " << FloatFormat( m_mousePosition[1], 6, 1 ) - << " z:: " << FloatFormat( m_mousePosition[2], 6, 1 ); - g_pParentWnd->SetStatusText( g_pParentWnd->m_position_status, status.c_str() ); - - if ( g_bCrossHairs ) { - XYWnd_Update( *this ); - } - - Clipper_Crosshair_OnMouseMoved( x, y ); - } -} - -void XYWnd::EntityCreate_MouseDown( int x, int y ){ - m_entityCreate = true; - m_entityCreate_x = x; - m_entityCreate_y = y; -} - -void XYWnd::EntityCreate_MouseMove( int x, int y ){ - if ( m_entityCreate && ( m_entityCreate_x != x || m_entityCreate_y != y ) ) { - m_entityCreate = false; - } -} - -void XYWnd::EntityCreate_MouseUp( int x, int y ){ - if ( m_entityCreate ) { - m_entityCreate = false; - OnContextMenu(); - } -} - -inline float screen_normalised( int pos, unsigned int size ){ - return ( ( 2.0f * pos ) / size ) - 1.0f; -} - -inline float normalised_to_world( float normalised, float world_origin, float normalised2world_scale ){ - return world_origin + normalised * normalised2world_scale; -} +inline float normalised_to_world(float normalised, float world_origin, float normalised2world_scale) +{ + return world_origin + normalised * normalised2world_scale; +} // TTimo: watch it, this doesn't init one of the 3 coords -void XYWnd::XY_ToPoint( int x, int y, Vector3& point ){ - float normalised2world_scale_x = m_nWidth / 2 / m_fScale; - float normalised2world_scale_y = m_nHeight / 2 / m_fScale; - if ( m_viewType == XY ) { - point[0] = normalised_to_world( screen_normalised( x, m_nWidth ), m_vOrigin[0], normalised2world_scale_x ); - point[1] = normalised_to_world( -screen_normalised( y, m_nHeight ), m_vOrigin[1], normalised2world_scale_y ); - } - else if ( m_viewType == YZ ) { - point[1] = normalised_to_world( screen_normalised( x, m_nWidth ), m_vOrigin[1], normalised2world_scale_x ); - point[2] = normalised_to_world( -screen_normalised( y, m_nHeight ), m_vOrigin[2], normalised2world_scale_y ); - } - else - { - point[0] = normalised_to_world( screen_normalised( x, m_nWidth ), m_vOrigin[0], normalised2world_scale_x ); - point[2] = normalised_to_world( -screen_normalised( y, m_nHeight ), m_vOrigin[2], normalised2world_scale_y ); - } -} - -void XYWnd::XY_SnapToGrid( Vector3& point ){ - if ( m_viewType == XY ) { - point[0] = float_snapped( point[0], GetSnapGridSize() ); - point[1] = float_snapped( point[1], GetSnapGridSize() ); - } - else if ( m_viewType == YZ ) { - point[1] = float_snapped( point[1], GetSnapGridSize() ); - point[2] = float_snapped( point[2], GetSnapGridSize() ); - } - else - { - point[0] = float_snapped( point[0], GetSnapGridSize() ); - point[2] = float_snapped( point[2], GetSnapGridSize() ); - } -} - -void XYWnd::XY_LoadBackgroundImage( const char *name ){ - const char* relative = path_make_relative( name, GlobalFileSystem().findRoot( name ) ); - if ( relative == name ) { - globalOutputStream() << "WARNING: could not extract the relative path, using full path instead\n"; - } - - char fileNameWithoutExt[512]; - strncpy( fileNameWithoutExt, relative, sizeof( fileNameWithoutExt ) - 1 ); - fileNameWithoutExt[512 - 1] = '\0'; - fileNameWithoutExt[strlen( fileNameWithoutExt ) - 4] = '\0'; - - Image *image = QERApp_LoadImage( 0, fileNameWithoutExt ); - if ( !image ) { - globalOutputStream() << "Could not load texture " << fileNameWithoutExt << "\n"; - return; - } - g_pParentWnd->ActiveXY()->m_tex = (qtexture_t*)malloc( sizeof( qtexture_t ) ); - LoadTextureRGBA( g_pParentWnd->ActiveXY()->XYWnd::m_tex, image->getRGBAPixels(), image->getWidth(), image->getHeight() ); - globalOutputStream() << "Loaded background texture " << relative << "\n"; - g_pParentWnd->ActiveXY()->m_backgroundActivated = true; - - int m_ix, m_iy; - switch ( g_pParentWnd->ActiveXY()->m_viewType ) - { - case XY: - m_ix = 0; - m_iy = 1; - break; - case XZ: - m_ix = 0; - m_iy = 2; - break; - case YZ: - m_ix = 1; - m_iy = 2; - break; - } - - Vector3 min, max; - Select_GetBounds( min, max ); - g_pParentWnd->ActiveXY()->m_xmin = min[m_ix]; - g_pParentWnd->ActiveXY()->m_ymin = min[m_iy]; - g_pParentWnd->ActiveXY()->m_xmax = max[m_ix]; - g_pParentWnd->ActiveXY()->m_ymax = max[m_iy]; -} - -void XYWnd::XY_DisableBackground( void ){ - g_pParentWnd->ActiveXY()->m_backgroundActivated = false; - if ( g_pParentWnd->ActiveXY()->m_tex ) { - free( g_pParentWnd->ActiveXY()->m_tex ); - } - g_pParentWnd->ActiveXY()->m_tex = NULL; +void XYWnd::XY_ToPoint(int x, int y, Vector3 &point) +{ + float normalised2world_scale_x = m_nWidth / 2 / m_fScale; + float normalised2world_scale_y = m_nHeight / 2 / m_fScale; + if (m_viewType == XY) { + point[0] = normalised_to_world(screen_normalised(x, m_nWidth), m_vOrigin[0], normalised2world_scale_x); + point[1] = normalised_to_world(-screen_normalised(y, m_nHeight), m_vOrigin[1], normalised2world_scale_y); + } else if (m_viewType == YZ) { + point[1] = normalised_to_world(screen_normalised(x, m_nWidth), m_vOrigin[1], normalised2world_scale_x); + point[2] = normalised_to_world(-screen_normalised(y, m_nHeight), m_vOrigin[2], normalised2world_scale_y); + } else { + point[0] = normalised_to_world(screen_normalised(x, m_nWidth), m_vOrigin[0], normalised2world_scale_x); + point[2] = normalised_to_world(-screen_normalised(y, m_nHeight), m_vOrigin[2], normalised2world_scale_y); + } +} + +void XYWnd::XY_SnapToGrid(Vector3 &point) +{ + if (m_viewType == XY) { + point[0] = float_snapped(point[0], GetSnapGridSize()); + point[1] = float_snapped(point[1], GetSnapGridSize()); + } else if (m_viewType == YZ) { + point[1] = float_snapped(point[1], GetSnapGridSize()); + point[2] = float_snapped(point[2], GetSnapGridSize()); + } else { + point[0] = float_snapped(point[0], GetSnapGridSize()); + point[2] = float_snapped(point[2], GetSnapGridSize()); + } +} + +void XYWnd::XY_LoadBackgroundImage(const char *name) +{ + const char *relative = path_make_relative(name, GlobalFileSystem().findRoot(name)); + if (relative == name) { + globalOutputStream() << "WARNING: could not extract the relative path, using full path instead\n"; + } + + char fileNameWithoutExt[512]; + strncpy(fileNameWithoutExt, relative, sizeof(fileNameWithoutExt) - 1); + fileNameWithoutExt[512 - 1] = '\0'; + fileNameWithoutExt[strlen(fileNameWithoutExt) - 4] = '\0'; + + Image *image = QERApp_LoadImage(0, fileNameWithoutExt); + if (!image) { + globalOutputStream() << "Could not load texture " << fileNameWithoutExt << "\n"; + return; + } + g_pParentWnd->ActiveXY()->m_tex = (qtexture_t *) malloc(sizeof(qtexture_t)); + LoadTextureRGBA(g_pParentWnd->ActiveXY()->XYWnd::m_tex, image->getRGBAPixels(), image->getWidth(), + image->getHeight()); + globalOutputStream() << "Loaded background texture " << relative << "\n"; + g_pParentWnd->ActiveXY()->m_backgroundActivated = true; + + int m_ix, m_iy; + switch (g_pParentWnd->ActiveXY()->m_viewType) { + case XY: + m_ix = 0; + m_iy = 1; + break; + case XZ: + m_ix = 0; + m_iy = 2; + break; + case YZ: + m_ix = 1; + m_iy = 2; + break; + } + + Vector3 min, max; + Select_GetBounds(min, max); + g_pParentWnd->ActiveXY()->m_xmin = min[m_ix]; + g_pParentWnd->ActiveXY()->m_ymin = min[m_iy]; + g_pParentWnd->ActiveXY()->m_xmax = max[m_ix]; + g_pParentWnd->ActiveXY()->m_ymax = max[m_iy]; +} + +void XYWnd::XY_DisableBackground(void) +{ + g_pParentWnd->ActiveXY()->m_backgroundActivated = false; + if (g_pParentWnd->ActiveXY()->m_tex) { + free(g_pParentWnd->ActiveXY()->m_tex); + } + g_pParentWnd->ActiveXY()->m_tex = NULL; } -void WXY_BackgroundSelect( void ){ - bool brushesSelected = Scene_countSelectedBrushes( GlobalSceneGraph() ) != 0; - if ( !brushesSelected ) { - ui::alert( ui::root, "You have to select some brushes to get the bounding box for.\n", - "No selection", ui::alert_type::OK, ui::alert_icon::Error ); - return; - } +void WXY_BackgroundSelect(void) +{ + bool brushesSelected = Scene_countSelectedBrushes(GlobalSceneGraph()) != 0; + if (!brushesSelected) { + ui::alert(ui::root, "You have to select some brushes to get the bounding box for.\n", + "No selection", ui::alert_type::OK, ui::alert_icon::Error); + return; + } - const char *filename = MainFrame_getWindow().file_dialog( TRUE, "Background Image", NULL, NULL ); - g_pParentWnd->ActiveXY()->XY_DisableBackground(); - if ( filename ) { - g_pParentWnd->ActiveXY()->XY_LoadBackgroundImage( filename ); - } + const char *filename = MainFrame_getWindow().file_dialog(TRUE, "Background Image", NULL, NULL); + g_pParentWnd->ActiveXY()->XY_DisableBackground(); + if (filename) { + g_pParentWnd->ActiveXY()->XY_LoadBackgroundImage(filename); + } } /* @@ -1514,247 +1594,254 @@ void WXY_BackgroundSelect( void ){ ============== */ -double two_to_the_power( int power ){ - return pow( 2.0f, power ); -} - -void XYWnd::XY_DrawAxis( void ){ - if ( g_xywindow_globals_private.show_axis ) { - const char g_AxisName[3] = { 'X', 'Y', 'Z' }; - const int nDim1 = ( m_viewType == YZ ) ? 1 : 0; - const int nDim2 = ( m_viewType == XY ) ? 1 : 2; - const int w = ( m_nWidth / 2 / m_fScale ); - const int h = ( m_nHeight / 2 / m_fScale ); - - const Vector3& colourX = ( m_viewType == YZ ) ? g_xywindow_globals.AxisColorY : g_xywindow_globals.AxisColorX; - const Vector3& colourY = ( m_viewType == XY ) ? g_xywindow_globals.AxisColorY : g_xywindow_globals.AxisColorZ; - - // draw two lines with corresponding axis colors to highlight current view - // horizontal line: nDim1 color - glLineWidth( 2 ); - glBegin( GL_LINES ); - glColor3fv( vector3_to_array( colourX ) ); - glVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale ); - glVertex2f( m_vOrigin[nDim1] - w + 65 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale ); - glVertex2f( 0, 0 ); - glVertex2f( 32 / m_fScale, 0 ); - glColor3fv( vector3_to_array( colourY ) ); - glVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale ); - glVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale ); - glVertex2f( 0, 0 ); - glVertex2f( 0, 32 / m_fScale ); - glEnd(); - glLineWidth( 1 ); - // now print axis symbols - glColor3fv( vector3_to_array( colourX ) ); - glRasterPos2f( m_vOrigin[nDim1] - w + 55 / m_fScale, m_vOrigin[nDim2] + h - 55 / m_fScale ); - GlobalOpenGL().drawChar( g_AxisName[nDim1] ); - glRasterPos2f( 28 / m_fScale, -10 / m_fScale ); - GlobalOpenGL().drawChar( g_AxisName[nDim1] ); - glColor3fv( vector3_to_array( colourY ) ); - glRasterPos2f( m_vOrigin[nDim1] - w + 25 / m_fScale, m_vOrigin[nDim2] + h - 30 / m_fScale ); - GlobalOpenGL().drawChar( g_AxisName[nDim2] ); - glRasterPos2f( -10 / m_fScale, 28 / m_fScale ); - GlobalOpenGL().drawChar( g_AxisName[nDim2] ); - } +double two_to_the_power(int power) +{ + return pow(2.0f, power); } -void XYWnd::XY_DrawBackground( void ){ - glPushAttrib( GL_ALL_ATTRIB_BITS ); +void XYWnd::XY_DrawAxis(void) +{ + if (g_xywindow_globals_private.show_axis) { + const char g_AxisName[3] = {'X', 'Y', 'Z'}; + const int nDim1 = (m_viewType == YZ) ? 1 : 0; + const int nDim2 = (m_viewType == XY) ? 1 : 2; + const int w = (m_nWidth / 2 / m_fScale); + const int h = (m_nHeight / 2 / m_fScale); + + const Vector3 &colourX = (m_viewType == YZ) ? g_xywindow_globals.AxisColorY : g_xywindow_globals.AxisColorX; + const Vector3 &colourY = (m_viewType == XY) ? g_xywindow_globals.AxisColorY : g_xywindow_globals.AxisColorZ; + + // draw two lines with corresponding axis colors to highlight current view + // horizontal line: nDim1 color + glLineWidth(2); + glBegin(GL_LINES); + glColor3fv(vector3_to_array(colourX)); + glVertex2f(m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale); + glVertex2f(m_vOrigin[nDim1] - w + 65 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale); + glVertex2f(0, 0); + glVertex2f(32 / m_fScale, 0); + glColor3fv(vector3_to_array(colourY)); + glVertex2f(m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale); + glVertex2f(m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale); + glVertex2f(0, 0); + glVertex2f(0, 32 / m_fScale); + glEnd(); + glLineWidth(1); + // now print axis symbols + glColor3fv(vector3_to_array(colourX)); + glRasterPos2f(m_vOrigin[nDim1] - w + 55 / m_fScale, m_vOrigin[nDim2] + h - 55 / m_fScale); + GlobalOpenGL().drawChar(g_AxisName[nDim1]); + glRasterPos2f(28 / m_fScale, -10 / m_fScale); + GlobalOpenGL().drawChar(g_AxisName[nDim1]); + glColor3fv(vector3_to_array(colourY)); + glRasterPos2f(m_vOrigin[nDim1] - w + 25 / m_fScale, m_vOrigin[nDim2] + h - 30 / m_fScale); + GlobalOpenGL().drawChar(g_AxisName[nDim2]); + glRasterPos2f(-10 / m_fScale, 28 / m_fScale); + GlobalOpenGL().drawChar(g_AxisName[nDim2]); + } +} + +void XYWnd::XY_DrawBackground(void) +{ + glPushAttrib(GL_ALL_ATTRIB_BITS); - glEnable( GL_TEXTURE_2D ); - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glPolygonMode( GL_FRONT, GL_FILL ); + glPolygonMode(GL_FRONT, GL_FILL); - glBindTexture( GL_TEXTURE_2D, m_tex->texture_number ); - glBegin( GL_QUADS ); + glBindTexture(GL_TEXTURE_2D, m_tex->texture_number); + glBegin(GL_QUADS); - glColor4f( 1.0, 1.0, 1.0, m_alpha ); - glTexCoord2f( 0.0, 1.0 ); - glVertex2f( m_xmin, m_ymin ); + glColor4f(1.0, 1.0, 1.0, m_alpha); + glTexCoord2f(0.0, 1.0); + glVertex2f(m_xmin, m_ymin); - glTexCoord2f( 1.0, 1.0 ); - glVertex2f( m_xmax, m_ymin ); + glTexCoord2f(1.0, 1.0); + glVertex2f(m_xmax, m_ymin); - glTexCoord2f( 1.0, 0.0 ); - glVertex2f( m_xmax, m_ymax ); + glTexCoord2f(1.0, 0.0); + glVertex2f(m_xmax, m_ymax); - glTexCoord2f( 0.0, 0.0 ); - glVertex2f( m_xmin, m_ymax ); + glTexCoord2f(0.0, 0.0); + glVertex2f(m_xmin, m_ymax); - glEnd(); - glBindTexture( GL_TEXTURE_2D, 0 ); + glEnd(); + glBindTexture(GL_TEXTURE_2D, 0); - glPopAttrib(); + glPopAttrib(); } -void XYWnd::XY_DrawGrid( void ) { - float x, y, xb, xe, yb, ye; - float w, h, a; - char text[32]; - float step, minor_step, stepx, stepy; - step = minor_step = stepx = stepy = GetGridSize(); - - int minor_power = Grid_getPower(); - int mask; - - while ( ( minor_step * m_fScale ) <= 4.0f ) { // make sure minor grid spacing is at least 4 pixels on the screen - ++minor_power; - minor_step *= 2; - } - int power = minor_power; - while ( ( power % 3 ) != 0 || ( step * m_fScale ) <= 32.0f ) { // make sure major grid spacing is at least 32 pixels on the screen - ++power; - step = float(two_to_the_power( power ) ); - } - mask = ( 1 << ( power - minor_power ) ) - 1; - while ( ( stepx * m_fScale ) <= 32.0f ) // text step x must be at least 32 - stepx *= 2; - while ( ( stepy * m_fScale ) <= 32.0f ) // text step y must be at least 32 - stepy *= 2; - - a = ( ( GetSnapGridSize() > 0.0f ) ? 1.0f : 0.3f ); - - glDisable( GL_TEXTURE_2D ); - glDisable( GL_TEXTURE_1D ); - glDisable( GL_DEPTH_TEST ); - glDisable( GL_BLEND ); - glLineWidth( 1 ); - - w = ( m_nWidth / 2 / m_fScale ); - h = ( m_nHeight / 2 / m_fScale ); - - const int nDim1 = ( m_viewType == YZ ) ? 1 : 0; - const int nDim2 = ( m_viewType == XY ) ? 1 : 2; - - xb = m_vOrigin[nDim1] - w; - if ( xb < region_mins[nDim1] ) { - xb = region_mins[nDim1]; - } - xb = step * floor( xb / step ); - - xe = m_vOrigin[nDim1] + w; - if ( xe > region_maxs[nDim1] ) { - xe = region_maxs[nDim1]; - } - xe = step * ceil( xe / step ); - - yb = m_vOrigin[nDim2] - h; - if ( yb < region_mins[nDim2] ) { - yb = region_mins[nDim2]; - } - yb = step * floor( yb / step ); - - ye = m_vOrigin[nDim2] + h; - if ( ye > region_maxs[nDim2] ) { - ye = region_maxs[nDim2]; - } - ye = step * ceil( ye / step ); - -#define COLORS_DIFFER( a,b ) \ - ( ( a )[0] != ( b )[0] || \ - ( a )[1] != ( b )[1] || \ - ( a )[2] != ( b )[2] ) - - // djbob - // draw minor blocks - if ( g_xywindow_globals_private.d_showgrid || a < 1.0f ) { - if ( a < 1.0f ) { - glEnable( GL_BLEND ); - } - - if ( COLORS_DIFFER( g_xywindow_globals.color_gridminor, g_xywindow_globals.color_gridback ) ) { - glColor4fv( vector4_to_array( Vector4( g_xywindow_globals.color_gridminor, a ) ) ); - - glBegin( GL_LINES ); - int i = 0; - for ( x = xb ; x < xe ; x += minor_step, ++i ) { - if ( ( i & mask ) != 0 ) { - glVertex2f( x, yb ); - glVertex2f( x, ye ); - } - } - i = 0; - for ( y = yb ; y < ye ; y += minor_step, ++i ) { - if ( ( i & mask ) != 0 ) { - glVertex2f( xb, y ); - glVertex2f( xe, y ); - } - } - glEnd(); - } - - // draw major blocks - if ( COLORS_DIFFER( g_xywindow_globals.color_gridmajor, g_xywindow_globals.color_gridminor ) ) { - glColor4fv( vector4_to_array( Vector4( g_xywindow_globals.color_gridmajor, a ) ) ); - - glBegin( GL_LINES ); - for ( x = xb ; x <= xe ; x += step ) { - glVertex2f( x, yb ); - glVertex2f( x, ye ); - } - for ( y = yb ; y <= ye ; y += step ) { - glVertex2f( xb, y ); - glVertex2f( xe, y ); - } - glEnd(); - } - - if ( a < 1.0f ) { - glDisable( GL_BLEND ); - } - } - - // draw coordinate text if needed - if ( g_xywindow_globals_private.show_coordinates ) { - glColor4fv( vector4_to_array( Vector4( g_xywindow_globals.color_gridtext, 1.0f ) ) ); - float offx = m_vOrigin[nDim2] + h - ( 4 + GlobalOpenGL().m_font->getPixelAscent() ) / m_fScale; - float offy = m_vOrigin[nDim1] - w + 4 / m_fScale; - for ( x = xb - fmod( xb, stepx ); x <= xe ; x += stepx ) { - glRasterPos2f( x, offx ); - sprintf( text, "%g", x ); - GlobalOpenGL().drawString( text ); - } - for ( y = yb - fmod( yb, stepy ); y <= ye ; y += stepy ) { - glRasterPos2f( offy, y ); - sprintf( text, "%g", y ); - GlobalOpenGL().drawString( text ); - } - - if ( Active() ) { - glColor3fv( vector3_to_array( g_xywindow_globals.color_viewname ) ); - } - - // we do this part (the old way) only if show_axis is disabled - if ( !g_xywindow_globals_private.show_axis ) { - glRasterPos2f( m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale ); - - GlobalOpenGL().drawString( ViewType_getTitle( m_viewType ) ); - } - } - - XYWnd::XY_DrawAxis(); - - // show current work zone? - // the work zone is used to place dropped points and brushes - if ( g_xywindow_globals_private.d_show_work ) { - glColor4f( 1.0f, 0.0f, 0.0f, 1.0f ); - glBegin( GL_LINES ); - glVertex2f( xb, Select_getWorkZone().d_work_min[nDim2] ); - glVertex2f( xe, Select_getWorkZone().d_work_min[nDim2] ); - glVertex2f( xb, Select_getWorkZone().d_work_max[nDim2] ); - glVertex2f( xe, Select_getWorkZone().d_work_max[nDim2] ); - glVertex2f( Select_getWorkZone().d_work_min[nDim1], yb ); - glVertex2f( Select_getWorkZone().d_work_min[nDim1], ye ); - glVertex2f( Select_getWorkZone().d_work_max[nDim1], yb ); - glVertex2f( Select_getWorkZone().d_work_max[nDim1], ye ); - glEnd(); - } +void XYWnd::XY_DrawGrid(void) +{ + float x, y, xb, xe, yb, ye; + float w, h, a; + char text[32]; + float step, minor_step, stepx, stepy; + step = minor_step = stepx = stepy = GetGridSize(); + + int minor_power = Grid_getPower(); + int mask; + + while ((minor_step * m_fScale) <= 4.0f) { // make sure minor grid spacing is at least 4 pixels on the screen + ++minor_power; + minor_step *= 2; + } + int power = minor_power; + while ((power % 3) != 0 || + (step * m_fScale) <= 32.0f) { // make sure major grid spacing is at least 32 pixels on the screen + ++power; + step = float(two_to_the_power(power)); + } + mask = (1 << (power - minor_power)) - 1; + while ((stepx * m_fScale) <= 32.0f) { // text step x must be at least 32 + stepx *= 2; + } + while ((stepy * m_fScale) <= 32.0f) { // text step y must be at least 32 + stepy *= 2; + } + + a = ((GetSnapGridSize() > 0.0f) ? 1.0f : 0.3f); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_1D); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glLineWidth(1); + + w = (m_nWidth / 2 / m_fScale); + h = (m_nHeight / 2 / m_fScale); + + const int nDim1 = (m_viewType == YZ) ? 1 : 0; + const int nDim2 = (m_viewType == XY) ? 1 : 2; + + xb = m_vOrigin[nDim1] - w; + if (xb < region_mins[nDim1]) { + xb = region_mins[nDim1]; + } + xb = step * floor(xb / step); + + xe = m_vOrigin[nDim1] + w; + if (xe > region_maxs[nDim1]) { + xe = region_maxs[nDim1]; + } + xe = step * ceil(xe / step); + + yb = m_vOrigin[nDim2] - h; + if (yb < region_mins[nDim2]) { + yb = region_mins[nDim2]; + } + yb = step * floor(yb / step); + + ye = m_vOrigin[nDim2] + h; + if (ye > region_maxs[nDim2]) { + ye = region_maxs[nDim2]; + } + ye = step * ceil(ye / step); + +#define COLORS_DIFFER(a, b) \ + ( ( a )[0] != ( b )[0] || \ + ( a )[1] != ( b )[1] || \ + ( a )[2] != ( b )[2] ) + + // djbob + // draw minor blocks + if (g_xywindow_globals_private.d_showgrid || a < 1.0f) { + if (a < 1.0f) { + glEnable(GL_BLEND); + } + + if (COLORS_DIFFER(g_xywindow_globals.color_gridminor, g_xywindow_globals.color_gridback)) { + glColor4fv(vector4_to_array(Vector4(g_xywindow_globals.color_gridminor, a))); + + glBegin(GL_LINES); + int i = 0; + for (x = xb; x < xe; x += minor_step, ++i) { + if ((i & mask) != 0) { + glVertex2f(x, yb); + glVertex2f(x, ye); + } + } + i = 0; + for (y = yb; y < ye; y += minor_step, ++i) { + if ((i & mask) != 0) { + glVertex2f(xb, y); + glVertex2f(xe, y); + } + } + glEnd(); + } + + // draw major blocks + if (COLORS_DIFFER(g_xywindow_globals.color_gridmajor, g_xywindow_globals.color_gridminor)) { + glColor4fv(vector4_to_array(Vector4(g_xywindow_globals.color_gridmajor, a))); + + glBegin(GL_LINES); + for (x = xb; x <= xe; x += step) { + glVertex2f(x, yb); + glVertex2f(x, ye); + } + for (y = yb; y <= ye; y += step) { + glVertex2f(xb, y); + glVertex2f(xe, y); + } + glEnd(); + } + + if (a < 1.0f) { + glDisable(GL_BLEND); + } + } + + // draw coordinate text if needed + if (g_xywindow_globals_private.show_coordinates) { + glColor4fv(vector4_to_array(Vector4(g_xywindow_globals.color_gridtext, 1.0f))); + float offx = m_vOrigin[nDim2] + h - (4 + GlobalOpenGL().m_font->getPixelAscent()) / m_fScale; + float offy = m_vOrigin[nDim1] - w + 4 / m_fScale; + for (x = xb - fmod(xb, stepx); x <= xe; x += stepx) { + glRasterPos2f(x, offx); + sprintf(text, "%g", x); + GlobalOpenGL().drawString(text); + } + for (y = yb - fmod(yb, stepy); y <= ye; y += stepy) { + glRasterPos2f(offy, y); + sprintf(text, "%g", y); + GlobalOpenGL().drawString(text); + } + + if (Active()) { + glColor3fv(vector3_to_array(g_xywindow_globals.color_viewname)); + } + + // we do this part (the old way) only if show_axis is disabled + if (!g_xywindow_globals_private.show_axis) { + glRasterPos2f(m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale); + + GlobalOpenGL().drawString(ViewType_getTitle(m_viewType)); + } + } + + XYWnd::XY_DrawAxis(); + + // show current work zone? + // the work zone is used to place dropped points and brushes + if (g_xywindow_globals_private.d_show_work) { + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + glBegin(GL_LINES); + glVertex2f(xb, Select_getWorkZone().d_work_min[nDim2]); + glVertex2f(xe, Select_getWorkZone().d_work_min[nDim2]); + glVertex2f(xb, Select_getWorkZone().d_work_max[nDim2]); + glVertex2f(xe, Select_getWorkZone().d_work_max[nDim2]); + glVertex2f(Select_getWorkZone().d_work_min[nDim1], yb); + glVertex2f(Select_getWorkZone().d_work_min[nDim1], ye); + glVertex2f(Select_getWorkZone().d_work_max[nDim1], yb); + glVertex2f(Select_getWorkZone().d_work_max[nDim1], ye); + glEnd(); + } } /* @@ -1762,429 +1849,446 @@ void XYWnd::XY_DrawGrid( void ) { XY_DrawBlockGrid ============== */ -void XYWnd::XY_DrawBlockGrid(){ - if ( Map_FindWorldspawn( g_map ) == 0 ) { - return; - } - const char *value = Node_getEntity( *Map_GetWorldspawn( g_map ) )->getKeyValue( "_blocksize" ); - if ( strlen( value ) ) { - sscanf( value, "%i", &g_xywindow_globals_private.blockSize ); - } - - if ( !g_xywindow_globals_private.blockSize || g_xywindow_globals_private.blockSize > 65536 || g_xywindow_globals_private.blockSize < 1024 ) { - // don't use custom blocksize if it is less than the default, or greater than the maximum world coordinate - g_xywindow_globals_private.blockSize = 1024; - } - - float x, y, xb, xe, yb, ye; - float w, h; - char text[32]; - - glDisable( GL_TEXTURE_2D ); - glDisable( GL_TEXTURE_1D ); - glDisable( GL_DEPTH_TEST ); - glDisable( GL_BLEND ); - - w = ( m_nWidth / 2 / m_fScale ); - h = ( m_nHeight / 2 / m_fScale ); - - int nDim1 = ( m_viewType == YZ ) ? 1 : 0; - int nDim2 = ( m_viewType == XY ) ? 1 : 2; - - xb = m_vOrigin[nDim1] - w; - if ( xb < region_mins[nDim1] ) { - xb = region_mins[nDim1]; - } - xb = static_cast( g_xywindow_globals_private.blockSize * floor( xb / g_xywindow_globals_private.blockSize ) ); - - xe = m_vOrigin[nDim1] + w; - if ( xe > region_maxs[nDim1] ) { - xe = region_maxs[nDim1]; - } - xe = static_cast( g_xywindow_globals_private.blockSize * ceil( xe / g_xywindow_globals_private.blockSize ) ); - - yb = m_vOrigin[nDim2] - h; - if ( yb < region_mins[nDim2] ) { - yb = region_mins[nDim2]; - } - yb = static_cast( g_xywindow_globals_private.blockSize * floor( yb / g_xywindow_globals_private.blockSize ) ); - - ye = m_vOrigin[nDim2] + h; - if ( ye > region_maxs[nDim2] ) { - ye = region_maxs[nDim2]; - } - ye = static_cast( g_xywindow_globals_private.blockSize * ceil( ye / g_xywindow_globals_private.blockSize ) ); - - // draw major blocks - - glColor3fv( vector3_to_array( g_xywindow_globals.color_gridblock ) ); - glLineWidth( 2 ); - - glBegin( GL_LINES ); - - for ( x = xb ; x <= xe ; x += g_xywindow_globals_private.blockSize ) - { - glVertex2f( x, yb ); - glVertex2f( x, ye ); - } - - if ( m_viewType == XY ) { - for ( y = yb ; y <= ye ; y += g_xywindow_globals_private.blockSize ) - { - glVertex2f( xb, y ); - glVertex2f( xe, y ); - } - } - - glEnd(); - glLineWidth( 1 ); - - // draw coordinate text if needed - - if ( m_viewType == XY && m_fScale > .1 ) { - for ( x = xb ; x < xe ; x += g_xywindow_globals_private.blockSize ) - for ( y = yb ; y < ye ; y += g_xywindow_globals_private.blockSize ) - { - glRasterPos2f( x + ( g_xywindow_globals_private.blockSize / 2 ), y + ( g_xywindow_globals_private.blockSize / 2 ) ); - sprintf( text, "%i,%i",(int)floor( x / g_xywindow_globals_private.blockSize ), (int)floor( y / g_xywindow_globals_private.blockSize ) ); - GlobalOpenGL().drawString( text ); - } - } - - glColor4f( 0, 0, 0, 0 ); -} - -void XYWnd::DrawCameraIcon( const Vector3& origin, const Vector3& angles ){ - float x, y, fov, box; - double a; - - fov = 48 / m_fScale; - box = 16 / m_fScale; - - if ( m_viewType == XY ) { - x = origin[0]; - y = origin[1]; - a = degrees_to_radians( angles[CAMERA_YAW] ); - } - else if ( m_viewType == YZ ) { - x = origin[1]; - y = origin[2]; - a = degrees_to_radians( angles[CAMERA_PITCH] ); - } - else - { - x = origin[0]; - y = origin[2]; - a = degrees_to_radians( angles[CAMERA_PITCH] ); - } - - glColor3f( 0.0, 0.0, 1.0 ); - glBegin( GL_LINE_STRIP ); - glVertex3f( x - box,y,0 ); - glVertex3f( x,y + ( box / 2 ),0 ); - glVertex3f( x + box,y,0 ); - glVertex3f( x,y - ( box / 2 ),0 ); - glVertex3f( x - box,y,0 ); - glVertex3f( x + box,y,0 ); - glEnd(); - - glBegin( GL_LINE_STRIP ); - glVertex3f( x + static_cast( fov * cos( a + c_pi / 4 ) ), y + static_cast( fov * sin( a + c_pi / 4 ) ), 0 ); - glVertex3f( x, y, 0 ); - glVertex3f( x + static_cast( fov * cos( a - c_pi / 4 ) ), y + static_cast( fov * sin( a - c_pi / 4 ) ), 0 ); - glEnd(); - -} - - -float Betwixt( float f1, float f2 ){ - if ( f1 > f2 ) { - return f2 + ( ( f1 - f2 ) / 2 ); - } - else{ - return f1 + ( ( f2 - f1 ) / 2 ); - } +void XYWnd::XY_DrawBlockGrid() +{ + if (Map_FindWorldspawn(g_map) == 0) { + return; + } + const char *value = Node_getEntity(*Map_GetWorldspawn(g_map))->getKeyValue("_blocksize"); + if (strlen(value)) { + sscanf(value, "%i", &g_xywindow_globals_private.blockSize); + } + + if (!g_xywindow_globals_private.blockSize || g_xywindow_globals_private.blockSize > 65536 || + g_xywindow_globals_private.blockSize < 1024) { + // don't use custom blocksize if it is less than the default, or greater than the maximum world coordinate + g_xywindow_globals_private.blockSize = 1024; + } + + float x, y, xb, xe, yb, ye; + float w, h; + char text[32]; + + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_1D); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + + w = (m_nWidth / 2 / m_fScale); + h = (m_nHeight / 2 / m_fScale); + + int nDim1 = (m_viewType == YZ) ? 1 : 0; + int nDim2 = (m_viewType == XY) ? 1 : 2; + + xb = m_vOrigin[nDim1] - w; + if (xb < region_mins[nDim1]) { + xb = region_mins[nDim1]; + } + xb = static_cast( g_xywindow_globals_private.blockSize * floor(xb / g_xywindow_globals_private.blockSize)); + + xe = m_vOrigin[nDim1] + w; + if (xe > region_maxs[nDim1]) { + xe = region_maxs[nDim1]; + } + xe = static_cast( g_xywindow_globals_private.blockSize * ceil(xe / g_xywindow_globals_private.blockSize)); + + yb = m_vOrigin[nDim2] - h; + if (yb < region_mins[nDim2]) { + yb = region_mins[nDim2]; + } + yb = static_cast( g_xywindow_globals_private.blockSize * floor(yb / g_xywindow_globals_private.blockSize)); + + ye = m_vOrigin[nDim2] + h; + if (ye > region_maxs[nDim2]) { + ye = region_maxs[nDim2]; + } + ye = static_cast( g_xywindow_globals_private.blockSize * ceil(ye / g_xywindow_globals_private.blockSize)); + + // draw major blocks + + glColor3fv(vector3_to_array(g_xywindow_globals.color_gridblock)); + glLineWidth(2); + + glBegin(GL_LINES); + + for (x = xb; x <= xe; x += g_xywindow_globals_private.blockSize) { + glVertex2f(x, yb); + glVertex2f(x, ye); + } + + if (m_viewType == XY) { + for (y = yb; y <= ye; y += g_xywindow_globals_private.blockSize) { + glVertex2f(xb, y); + glVertex2f(xe, y); + } + } + + glEnd(); + glLineWidth(1); + + // draw coordinate text if needed + + if (m_viewType == XY && m_fScale > .1) { + for (x = xb; x < xe; x += g_xywindow_globals_private.blockSize) { + for (y = yb; y < ye; y += g_xywindow_globals_private.blockSize) { + glRasterPos2f(x + (g_xywindow_globals_private.blockSize / 2), + y + (g_xywindow_globals_private.blockSize / 2)); + sprintf(text, "%i,%i", (int) floor(x / g_xywindow_globals_private.blockSize), + (int) floor(y / g_xywindow_globals_private.blockSize)); + GlobalOpenGL().drawString(text); + } + } + } + + glColor4f(0, 0, 0, 0); +} + +void XYWnd::DrawCameraIcon(const Vector3 &origin, const Vector3 &angles) +{ + float x, y, fov, box; + double a; + + fov = 48 / m_fScale; + box = 16 / m_fScale; + + if (m_viewType == XY) { + x = origin[0]; + y = origin[1]; + a = degrees_to_radians(angles[CAMERA_YAW]); + } else if (m_viewType == YZ) { + x = origin[1]; + y = origin[2]; + a = degrees_to_radians(angles[CAMERA_PITCH]); + } else { + x = origin[0]; + y = origin[2]; + a = degrees_to_radians(angles[CAMERA_PITCH]); + } + + glColor3f(0.0, 0.0, 1.0); + glBegin(GL_LINE_STRIP); + glVertex3f(x - box, y, 0); + glVertex3f(x, y + (box / 2), 0); + glVertex3f(x + box, y, 0); + glVertex3f(x, y - (box / 2), 0); + glVertex3f(x - box, y, 0); + glVertex3f(x + box, y, 0); + glEnd(); + + glBegin(GL_LINE_STRIP); + glVertex3f(x + static_cast( fov * cos(a + c_pi / 4)), y + static_cast( fov * sin(a + c_pi / 4)), 0); + glVertex3f(x, y, 0); + glVertex3f(x + static_cast( fov * cos(a - c_pi / 4)), y + static_cast( fov * sin(a - c_pi / 4)), 0); + glEnd(); + +} + + +float Betwixt(float f1, float f2) +{ + if (f1 > f2) { + return f2 + ((f1 - f2) / 2); + } else { + return f1 + ((f2 - f1) / 2); + } } // can be greatly simplified but per usual i am in a hurry // which is not an excuse, just a fact -void XYWnd::PaintSizeInfo( int nDim1, int nDim2, Vector3& vMinBounds, Vector3& vMaxBounds ){ - if ( vector3_equal( vMinBounds, vMaxBounds ) ) { - return; - } - const char* g_pDimStrings[] = {"x:", "y:", "z:"}; - typedef const char* OrgStrings[2]; - const OrgStrings g_pOrgStrings[] = { { "x:", "y:", }, { "x:", "z:", }, { "y:", "z:", } }; +void XYWnd::PaintSizeInfo(int nDim1, int nDim2, Vector3 &vMinBounds, Vector3 &vMaxBounds) +{ + if (vector3_equal(vMinBounds, vMaxBounds)) { + return; + } + const char *g_pDimStrings[] = {"x:", "y:", "z:"}; + typedef const char *OrgStrings[2]; + const OrgStrings g_pOrgStrings[] = {{"x:", "y:",}, + {"x:", "z:",}, + {"y:", "z:",}}; - Vector3 vSize( vector3_subtracted( vMaxBounds, vMinBounds ) ); + Vector3 vSize(vector3_subtracted(vMaxBounds, vMinBounds)); - glColor3f( g_xywindow_globals.color_selbrushes[0] * .65f, - g_xywindow_globals.color_selbrushes[1] * .65f, - g_xywindow_globals.color_selbrushes[2] * .65f ); + glColor3f(g_xywindow_globals.color_selbrushes[0] * .65f, + g_xywindow_globals.color_selbrushes[1] * .65f, + g_xywindow_globals.color_selbrushes[2] * .65f); - StringOutputStream dimensions( 16 ); + StringOutputStream dimensions(16); - if ( m_viewType == XY ) { - glBegin( GL_LINES ); + if (m_viewType == XY) { + glBegin(GL_LINES); - glVertex3f( vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f ); - glVertex3f( vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f ); + glVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f); + glVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f); - glVertex3f( vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f ); - glVertex3f( vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f ); + glVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f); + glVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f); - glVertex3f( vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f ); - glVertex3f( vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f ); + glVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f); + glVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f); - glVertex3f( vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f ); - glVertex3f( vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f ); + glVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f); + glVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f); - glVertex3f( vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f ); - glVertex3f( vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f ); + glVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f); + glVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f); - glVertex3f( vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f ); - glVertex3f( vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f ); + glVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f); + glVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f); - glEnd(); + glEnd(); - glRasterPos3f( Betwixt( vMinBounds[nDim1], vMaxBounds[nDim1] ), vMinBounds[nDim2] - 20.0f / m_fScale, 0.0f ); - dimensions << g_pDimStrings[nDim1] << vSize[nDim1]; - GlobalOpenGL().drawString( dimensions.c_str() ); - dimensions.clear(); + glRasterPos3f(Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0f / m_fScale, 0.0f); + dimensions << g_pDimStrings[nDim1] << vSize[nDim1]; + GlobalOpenGL().drawString(dimensions.c_str()); + dimensions.clear(); - glRasterPos3f( vMaxBounds[nDim1] + 16.0f / m_fScale, Betwixt( vMinBounds[nDim2], vMaxBounds[nDim2] ), 0.0f ); - dimensions << g_pDimStrings[nDim2] << vSize[nDim2]; - GlobalOpenGL().drawString( dimensions.c_str() ); - dimensions.clear(); + glRasterPos3f(vMaxBounds[nDim1] + 16.0f / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f); + dimensions << g_pDimStrings[nDim2] << vSize[nDim2]; + GlobalOpenGL().drawString(dimensions.c_str()); + dimensions.clear(); - glRasterPos3f( vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f ); - dimensions << "(" << g_pOrgStrings[0][0] << vMinBounds[nDim1] << " " << g_pOrgStrings[0][1] << vMaxBounds[nDim2] << ")"; - GlobalOpenGL().drawString( dimensions.c_str() ); - } - else if ( m_viewType == XZ ) { - glBegin( GL_LINES ); + glRasterPos3f(vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f); + dimensions << "(" << g_pOrgStrings[0][0] << vMinBounds[nDim1] << " " << g_pOrgStrings[0][1] + << vMaxBounds[nDim2] << ")"; + GlobalOpenGL().drawString(dimensions.c_str()); + } else if (m_viewType == XZ) { + glBegin(GL_LINES); - glVertex3f( vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale ); - glVertex3f( vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale ); + glVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale); + glVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale); - glVertex3f( vMinBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale ); - glVertex3f( vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale ); + glVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale); + glVertex3f(vMaxBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale); - glVertex3f( vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 6.0f / m_fScale ); - glVertex3f( vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale ); + glVertex3f(vMaxBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale); + glVertex3f(vMaxBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale); - glVertex3f( vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMinBounds[nDim2] ); - glVertex3f( vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2] ); + glVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0, vMinBounds[nDim2]); + glVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMinBounds[nDim2]); - glVertex3f( vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2] ); - glVertex3f( vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2] ); + glVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMinBounds[nDim2]); + glVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMaxBounds[nDim2]); - glVertex3f( vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMaxBounds[nDim2] ); - glVertex3f( vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2] ); + glVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0, vMaxBounds[nDim2]); + glVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMaxBounds[nDim2]); - glEnd(); + glEnd(); - glRasterPos3f( Betwixt( vMinBounds[nDim1], vMaxBounds[nDim1] ), 0, vMinBounds[nDim2] - 20.0f / m_fScale ); - dimensions << g_pDimStrings[nDim1] << vSize[nDim1]; - GlobalOpenGL().drawString( dimensions.c_str() ); - dimensions.clear(); + glRasterPos3f(Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0f / m_fScale); + dimensions << g_pDimStrings[nDim1] << vSize[nDim1]; + GlobalOpenGL().drawString(dimensions.c_str()); + dimensions.clear(); - glRasterPos3f( vMaxBounds[nDim1] + 16.0f / m_fScale, 0, Betwixt( vMinBounds[nDim2], vMaxBounds[nDim2] ) ); - dimensions << g_pDimStrings[nDim2] << vSize[nDim2]; - GlobalOpenGL().drawString( dimensions.c_str() ); - dimensions.clear(); + glRasterPos3f(vMaxBounds[nDim1] + 16.0f / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2])); + dimensions << g_pDimStrings[nDim2] << vSize[nDim2]; + GlobalOpenGL().drawString(dimensions.c_str()); + dimensions.clear(); - glRasterPos3f( vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale ); - dimensions << "(" << g_pOrgStrings[1][0] << vMinBounds[nDim1] << " " << g_pOrgStrings[1][1] << vMaxBounds[nDim2] << ")"; - GlobalOpenGL().drawString( dimensions.c_str() ); - } - else - { - glBegin( GL_LINES ); + glRasterPos3f(vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale); + dimensions << "(" << g_pOrgStrings[1][0] << vMinBounds[nDim1] << " " << g_pOrgStrings[1][1] + << vMaxBounds[nDim2] << ")"; + GlobalOpenGL().drawString(dimensions.c_str()); + } else { + glBegin(GL_LINES); - glVertex3f( 0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale ); - glVertex3f( 0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale ); + glVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale); + glVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale); - glVertex3f( 0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale ); - glVertex3f( 0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale ); + glVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale); + glVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale); - glVertex3f( 0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale ); - glVertex3f( 0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale ); + glVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale); + glVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale); - glVertex3f( 0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2] ); - glVertex3f( 0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2] ); + glVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2]); + glVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]); - glVertex3f( 0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2] ); - glVertex3f( 0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2] ); + glVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]); + glVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]); - glVertex3f( 0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2] ); - glVertex3f( 0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2] ); + glVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2]); + glVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]); - glEnd(); + glEnd(); - glRasterPos3f( 0, Betwixt( vMinBounds[nDim1], vMaxBounds[nDim1] ), vMinBounds[nDim2] - 20.0f / m_fScale ); - dimensions << g_pDimStrings[nDim1] << vSize[nDim1]; - GlobalOpenGL().drawString( dimensions.c_str() ); - dimensions.clear(); + glRasterPos3f(0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0f / m_fScale); + dimensions << g_pDimStrings[nDim1] << vSize[nDim1]; + GlobalOpenGL().drawString(dimensions.c_str()); + dimensions.clear(); - glRasterPos3f( 0, vMaxBounds[nDim1] + 16.0f / m_fScale, Betwixt( vMinBounds[nDim2], vMaxBounds[nDim2] ) ); - dimensions << g_pDimStrings[nDim2] << vSize[nDim2]; - GlobalOpenGL().drawString( dimensions.c_str() ); - dimensions.clear(); + glRasterPos3f(0, vMaxBounds[nDim1] + 16.0f / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2])); + dimensions << g_pDimStrings[nDim2] << vSize[nDim2]; + GlobalOpenGL().drawString(dimensions.c_str()); + dimensions.clear(); - glRasterPos3f( 0, vMinBounds[nDim1] + 4.0f, vMaxBounds[nDim2] + 8 / m_fScale ); - dimensions << "(" << g_pOrgStrings[2][0] << vMinBounds[nDim1] << " " << g_pOrgStrings[2][1] << vMaxBounds[nDim2] << ")"; - GlobalOpenGL().drawString( dimensions.c_str() ); - } + glRasterPos3f(0, vMinBounds[nDim1] + 4.0f, vMaxBounds[nDim2] + 8 / m_fScale); + dimensions << "(" << g_pOrgStrings[2][0] << vMinBounds[nDim1] << " " << g_pOrgStrings[2][1] + << vMaxBounds[nDim2] << ")"; + GlobalOpenGL().drawString(dimensions.c_str()); + } } -class XYRenderer : public Renderer -{ -struct state_type -{ - state_type() : - m_highlight( 0 ), - m_state( 0 ){ - } - unsigned int m_highlight; - Shader* m_state; -}; -public: -XYRenderer( RenderStateFlags globalstate, Shader* selected ) : - m_globalstate( globalstate ), - m_state_selected( selected ){ - ASSERT_NOTNULL( selected ); - m_state_stack.push_back( state_type() ); -} +class XYRenderer : public Renderer { + struct state_type { + state_type() : + m_highlight(0), + m_state(0) + { + } -void SetState( Shader* state, EStyle style ){ - ASSERT_NOTNULL( state ); - if ( style == eWireframeOnly ) { - m_state_stack.back().m_state = state; - } -} -EStyle getStyle() const { - return eWireframeOnly; -} -void PushState(){ - m_state_stack.push_back( m_state_stack.back() ); -} -void PopState(){ - ASSERT_MESSAGE( !m_state_stack.empty(), "popping empty stack" ); - m_state_stack.pop_back(); -} -void Highlight( EHighlightMode mode, bool bEnable = true ){ - ( bEnable ) - ? m_state_stack.back().m_highlight |= mode - : m_state_stack.back().m_highlight &= ~mode; -} -void addRenderable( const OpenGLRenderable& renderable, const Matrix4& localToWorld ){ - if ( m_state_stack.back().m_highlight & ePrimitive ) { - m_state_selected->addRenderable( renderable, localToWorld ); - } - else - { - m_state_stack.back().m_state->addRenderable( renderable, localToWorld ); - } -} + unsigned int m_highlight; + Shader *m_state; + }; + +public: + XYRenderer(RenderStateFlags globalstate, Shader *selected) : + m_globalstate(globalstate), + m_state_selected(selected) + { + ASSERT_NOTNULL(selected); + m_state_stack.push_back(state_type()); + } + + void SetState(Shader *state, EStyle style) + { + ASSERT_NOTNULL(state); + if (style == eWireframeOnly) { + m_state_stack.back().m_state = state; + } + } + + EStyle getStyle() const + { + return eWireframeOnly; + } + + void PushState() + { + m_state_stack.push_back(m_state_stack.back()); + } + + void PopState() + { + ASSERT_MESSAGE(!m_state_stack.empty(), "popping empty stack"); + m_state_stack.pop_back(); + } + + void Highlight(EHighlightMode mode, bool bEnable = true) + { + (bEnable) + ? m_state_stack.back().m_highlight |= mode + : m_state_stack.back().m_highlight &= ~mode; + } + + void addRenderable(const OpenGLRenderable &renderable, const Matrix4 &localToWorld) + { + if (m_state_stack.back().m_highlight & ePrimitive) { + m_state_selected->addRenderable(renderable, localToWorld); + } else { + m_state_stack.back().m_state->addRenderable(renderable, localToWorld); + } + } + + void render(const Matrix4 &modelview, const Matrix4 &projection) + { + GlobalShaderCache().render(m_globalstate, modelview, projection); + } -void render( const Matrix4& modelview, const Matrix4& projection ){ - GlobalShaderCache().render( m_globalstate, modelview, projection ); -} private: -std::vector m_state_stack; -RenderStateFlags m_globalstate; -Shader* m_state_selected; + std::vector m_state_stack; + RenderStateFlags m_globalstate; + Shader *m_state_selected; }; -void XYWnd::updateProjection(){ - m_projection[0] = 1.0f / static_cast( m_nWidth / 2 ); - m_projection[5] = 1.0f / static_cast( m_nHeight / 2 ); - m_projection[10] = 1.0f / ( g_MaxWorldCoord * m_fScale ); +void XYWnd::updateProjection() +{ + m_projection[0] = 1.0f / static_cast( m_nWidth / 2 ); + m_projection[5] = 1.0f / static_cast( m_nHeight / 2 ); + m_projection[10] = 1.0f / (g_MaxWorldCoord * m_fScale); - m_projection[12] = 0.0f; - m_projection[13] = 0.0f; - m_projection[14] = -1.0f; + m_projection[12] = 0.0f; + m_projection[13] = 0.0f; + m_projection[14] = -1.0f; - m_projection[1] = - m_projection[2] = - m_projection[3] = + m_projection[1] = + m_projection[2] = + m_projection[3] = - m_projection[4] = - m_projection[6] = - m_projection[7] = + m_projection[4] = + m_projection[6] = + m_projection[7] = - m_projection[8] = - m_projection[9] = - m_projection[11] = 0.0f; + m_projection[8] = + m_projection[9] = + m_projection[11] = 0.0f; - m_projection[15] = 1.0f; + m_projection[15] = 1.0f; - m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight ); + m_view.Construct(m_projection, m_modelview, m_nWidth, m_nHeight); } // note: modelview matrix must have a uniform scale, otherwise strange things happen when rendering the rotation manipulator. -void XYWnd::updateModelview(){ - int nDim1 = ( m_viewType == YZ ) ? 1 : 0; - int nDim2 = ( m_viewType == XY ) ? 1 : 2; - - // translation - m_modelview[12] = -m_vOrigin[nDim1] * m_fScale; - m_modelview[13] = -m_vOrigin[nDim2] * m_fScale; - m_modelview[14] = g_MaxWorldCoord * m_fScale; - - // axis base - switch ( m_viewType ) - { - case XY: - m_modelview[0] = m_fScale; - m_modelview[1] = 0; - m_modelview[2] = 0; - - m_modelview[4] = 0; - m_modelview[5] = m_fScale; - m_modelview[6] = 0; - - m_modelview[8] = 0; - m_modelview[9] = 0; - m_modelview[10] = -m_fScale; - break; - case XZ: - m_modelview[0] = m_fScale; - m_modelview[1] = 0; - m_modelview[2] = 0; - - m_modelview[4] = 0; - m_modelview[5] = 0; - m_modelview[6] = m_fScale; - - m_modelview[8] = 0; - m_modelview[9] = m_fScale; - m_modelview[10] = 0; - break; - case YZ: - m_modelview[0] = 0; - m_modelview[1] = 0; - m_modelview[2] = -m_fScale; - - m_modelview[4] = m_fScale; - m_modelview[5] = 0; - m_modelview[6] = 0; - - m_modelview[8] = 0; - m_modelview[9] = m_fScale; - m_modelview[10] = 0; - break; - } - - m_modelview[3] = m_modelview[7] = m_modelview[11] = 0; - m_modelview[15] = 1; - - m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight ); +void XYWnd::updateModelview() +{ + int nDim1 = (m_viewType == YZ) ? 1 : 0; + int nDim2 = (m_viewType == XY) ? 1 : 2; + + // translation + m_modelview[12] = -m_vOrigin[nDim1] * m_fScale; + m_modelview[13] = -m_vOrigin[nDim2] * m_fScale; + m_modelview[14] = g_MaxWorldCoord * m_fScale; + + // axis base + switch (m_viewType) { + case XY: + m_modelview[0] = m_fScale; + m_modelview[1] = 0; + m_modelview[2] = 0; + + m_modelview[4] = 0; + m_modelview[5] = m_fScale; + m_modelview[6] = 0; + + m_modelview[8] = 0; + m_modelview[9] = 0; + m_modelview[10] = -m_fScale; + break; + case XZ: + m_modelview[0] = m_fScale; + m_modelview[1] = 0; + m_modelview[2] = 0; + + m_modelview[4] = 0; + m_modelview[5] = 0; + m_modelview[6] = m_fScale; + + m_modelview[8] = 0; + m_modelview[9] = m_fScale; + m_modelview[10] = 0; + break; + case YZ: + m_modelview[0] = 0; + m_modelview[1] = 0; + m_modelview[2] = -m_fScale; + + m_modelview[4] = m_fScale; + m_modelview[5] = 0; + m_modelview[6] = 0; + + m_modelview[8] = 0; + m_modelview[9] = m_fScale; + m_modelview[10] = 0; + break; + } + + m_modelview[3] = m_modelview[7] = m_modelview[11] = 0; + m_modelview[15] = 1; + + m_view.Construct(m_projection, m_modelview, m_nWidth, m_nHeight); } /* @@ -2195,531 +2299,588 @@ void XYWnd::updateModelview(){ //#define DBG_SCENEDUMP -void XYWnd::XY_Draw(){ - // - // clear - // - glViewport( 0, 0, m_nWidth, m_nHeight ); - glClearColor( g_xywindow_globals.color_gridback[0], - g_xywindow_globals.color_gridback[1], - g_xywindow_globals.color_gridback[2],0 ); - - glClear( GL_COLOR_BUFFER_BIT ); - - // - // set up viewpoint - // - - glMatrixMode( GL_PROJECTION ); - glLoadMatrixf( reinterpret_cast( &m_projection ) ); - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - glScalef( m_fScale, m_fScale, 1 ); - int nDim1 = ( m_viewType == YZ ) ? 1 : 0; - int nDim2 = ( m_viewType == XY ) ? 1 : 2; - glTranslatef( -m_vOrigin[nDim1], -m_vOrigin[nDim2], 0 ); - - glDisable( GL_LINE_STIPPLE ); - glLineWidth( 1 ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - glDisableClientState( GL_NORMAL_ARRAY ); - glDisableClientState( GL_COLOR_ARRAY ); - glDisable( GL_TEXTURE_2D ); - glDisable( GL_LIGHTING ); - glDisable( GL_COLOR_MATERIAL ); - glDisable( GL_DEPTH_TEST ); - - if ( m_backgroundActivated ) { - XY_DrawBackground(); - } - XY_DrawGrid(); - - if ( g_xywindow_globals_private.show_blocks ) { - XY_DrawBlockGrid(); - } - - glLoadMatrixf( reinterpret_cast( &m_modelview ) ); - - unsigned int globalstate = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_POLYGONSMOOTH | RENDER_LINESMOOTH; - if ( !g_xywindow_globals.m_bNoStipple ) { - globalstate |= RENDER_LINESTIPPLE; - } - - { - XYRenderer renderer( globalstate, m_state_selected ); - - Scene_Render( renderer, m_view ); - - GlobalOpenGL_debugAssertNoErrors(); - renderer.render( m_modelview, m_projection ); - GlobalOpenGL_debugAssertNoErrors(); - } - - glDepthMask( GL_FALSE ); - - GlobalOpenGL_debugAssertNoErrors(); - - glLoadMatrixf( reinterpret_cast( &m_modelview ) ); - - GlobalOpenGL_debugAssertNoErrors(); - glDisable( GL_LINE_STIPPLE ); - GlobalOpenGL_debugAssertNoErrors(); - glLineWidth( 1 ); - GlobalOpenGL_debugAssertNoErrors(); - if ( GlobalOpenGL().GL_1_3() ) { - glActiveTexture( GL_TEXTURE0 ); - glClientActiveTexture( GL_TEXTURE0 ); - } - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - glDisableClientState( GL_NORMAL_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - glDisableClientState( GL_COLOR_ARRAY ); - GlobalOpenGL_debugAssertNoErrors(); - glDisable( GL_TEXTURE_2D ); - GlobalOpenGL_debugAssertNoErrors(); - glDisable( GL_LIGHTING ); - GlobalOpenGL_debugAssertNoErrors(); - glDisable( GL_COLOR_MATERIAL ); - GlobalOpenGL_debugAssertNoErrors(); - - GlobalOpenGL_debugAssertNoErrors(); - - - // size info - if ( g_xywindow_globals_private.m_bSizePaint && GlobalSelectionSystem().countSelected() != 0 ) { - Vector3 min, max; - Select_GetBounds( min, max ); - PaintSizeInfo( nDim1, nDim2, min, max ); - } - - if ( g_bCrossHairs ) { - glColor4f( 0.2f, 0.9f, 0.2f, 0.8f ); - glBegin( GL_LINES ); - if ( m_viewType == XY ) { - glVertex2f( 2.0f * g_MinWorldCoord, m_mousePosition[1] ); - glVertex2f( 2.0f * g_MaxWorldCoord, m_mousePosition[1] ); - glVertex2f( m_mousePosition[0], 2.0f * g_MinWorldCoord ); - glVertex2f( m_mousePosition[0], 2.0f * g_MaxWorldCoord ); - } - else if ( m_viewType == YZ ) { - glVertex3f( m_mousePosition[0], 2.0f * g_MinWorldCoord, m_mousePosition[2] ); - glVertex3f( m_mousePosition[0], 2.0f * g_MaxWorldCoord, m_mousePosition[2] ); - glVertex3f( m_mousePosition[0], m_mousePosition[1], 2.0f * g_MinWorldCoord ); - glVertex3f( m_mousePosition[0], m_mousePosition[1], 2.0f * g_MaxWorldCoord ); - } - else - { - glVertex3f( 2.0f * g_MinWorldCoord, m_mousePosition[1], m_mousePosition[2] ); - glVertex3f( 2.0f * g_MaxWorldCoord, m_mousePosition[1], m_mousePosition[2] ); - glVertex3f( m_mousePosition[0], m_mousePosition[1], 2.0f * g_MinWorldCoord ); - glVertex3f( m_mousePosition[0], m_mousePosition[1], 2.0f * g_MaxWorldCoord ); - } - glEnd(); - } - - if ( ClipMode() ) { - GlobalClipPoints_Draw( m_fScale ); - } - - GlobalOpenGL_debugAssertNoErrors(); - - // reset modelview - glLoadIdentity(); - glScalef( m_fScale, m_fScale, 1 ); - glTranslatef( -m_vOrigin[nDim1], -m_vOrigin[nDim2], 0 ); - - DrawCameraIcon( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ), Camera_getAngles( *g_pParentWnd->GetCamWnd() ) ); - - Feedback_draw2D( m_viewType ); - - if ( g_xywindow_globals_private.show_outline ) { - if ( Active() ) { - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( 0, m_nWidth, 0, m_nHeight, 0, 1 ); - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - // four view mode doesn't colorize - if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit ) { - glColor3fv( vector3_to_array( g_xywindow_globals.color_viewname ) ); - } - else - { - switch ( m_viewType ) - { - case YZ: - glColor3fv( vector3_to_array( g_xywindow_globals.AxisColorX ) ); - break; - case XZ: - glColor3fv( vector3_to_array( g_xywindow_globals.AxisColorY ) ); - break; - case XY: - glColor3fv( vector3_to_array( g_xywindow_globals.AxisColorZ ) ); - break; - } - } - glBegin( GL_LINE_LOOP ); - glVertex2f( 0.5, 0.5 ); - glVertex2f( m_nWidth - 0.5, 1 ); - glVertex2f( m_nWidth - 0.5, m_nHeight - 0.5 ); - glVertex2f( 0.5, m_nHeight - 0.5 ); - glEnd(); - } - } - - GlobalOpenGL_debugAssertNoErrors(); - - glFinish(); -} - -void XYWnd_MouseToPoint( XYWnd* xywnd, int x, int y, Vector3& point ){ - xywnd->XY_ToPoint( x, y, point ); - xywnd->XY_SnapToGrid( point ); - - int nDim = ( xywnd->GetViewType() == XY ) ? 2 : ( xywnd->GetViewType() == YZ ) ? 0 : 1; - float fWorkMid = float_mid( Select_getWorkZone().d_work_min[nDim], Select_getWorkZone().d_work_max[nDim] ); - point[nDim] = float_snapped( fWorkMid, GetGridSize() ); -} +void XYWnd::XY_Draw() +{ + // + // clear + // + glViewport(0, 0, m_nWidth, m_nHeight); + glClearColor(g_xywindow_globals.color_gridback[0], + g_xywindow_globals.color_gridback[1], + g_xywindow_globals.color_gridback[2], 0); + + glClear(GL_COLOR_BUFFER_BIT); + + // + // set up viewpoint + // + + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(reinterpret_cast( &m_projection )); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glScalef(m_fScale, m_fScale, 1); + int nDim1 = (m_viewType == YZ) ? 1 : 0; + int nDim2 = (m_viewType == XY) ? 1 : 2; + glTranslatef(-m_vOrigin[nDim1], -m_vOrigin[nDim2], 0); + + glDisable(GL_LINE_STIPPLE); + glLineWidth(1); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_DEPTH_TEST); + + if (m_backgroundActivated) { + XY_DrawBackground(); + } + XY_DrawGrid(); + + if (g_xywindow_globals_private.show_blocks) { + XY_DrawBlockGrid(); + } + + glLoadMatrixf(reinterpret_cast( &m_modelview )); + + unsigned int globalstate = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_POLYGONSMOOTH | RENDER_LINESMOOTH; + if (!g_xywindow_globals.m_bNoStipple) { + globalstate |= RENDER_LINESTIPPLE; + } + + { + XYRenderer renderer(globalstate, m_state_selected); + + Scene_Render(renderer, m_view); + + GlobalOpenGL_debugAssertNoErrors(); + renderer.render(m_modelview, m_projection); + GlobalOpenGL_debugAssertNoErrors(); + } + + glDepthMask(GL_FALSE); + + GlobalOpenGL_debugAssertNoErrors(); + + glLoadMatrixf(reinterpret_cast( &m_modelview )); + + GlobalOpenGL_debugAssertNoErrors(); + glDisable(GL_LINE_STIPPLE); + GlobalOpenGL_debugAssertNoErrors(); + glLineWidth(1); + GlobalOpenGL_debugAssertNoErrors(); + if (GlobalOpenGL().GL_1_3()) { + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + } + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + glDisableClientState(GL_NORMAL_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + glDisableClientState(GL_COLOR_ARRAY); + GlobalOpenGL_debugAssertNoErrors(); + glDisable(GL_TEXTURE_2D); + GlobalOpenGL_debugAssertNoErrors(); + glDisable(GL_LIGHTING); + GlobalOpenGL_debugAssertNoErrors(); + glDisable(GL_COLOR_MATERIAL); + GlobalOpenGL_debugAssertNoErrors(); + + GlobalOpenGL_debugAssertNoErrors(); + + + // size info + if (g_xywindow_globals_private.m_bSizePaint && GlobalSelectionSystem().countSelected() != 0) { + Vector3 min, max; + Select_GetBounds(min, max); + PaintSizeInfo(nDim1, nDim2, min, max); + } + + if (g_bCrossHairs) { + glColor4f(0.2f, 0.9f, 0.2f, 0.8f); + glBegin(GL_LINES); + if (m_viewType == XY) { + glVertex2f(2.0f * g_MinWorldCoord, m_mousePosition[1]); + glVertex2f(2.0f * g_MaxWorldCoord, m_mousePosition[1]); + glVertex2f(m_mousePosition[0], 2.0f * g_MinWorldCoord); + glVertex2f(m_mousePosition[0], 2.0f * g_MaxWorldCoord); + } else if (m_viewType == YZ) { + glVertex3f(m_mousePosition[0], 2.0f * g_MinWorldCoord, m_mousePosition[2]); + glVertex3f(m_mousePosition[0], 2.0f * g_MaxWorldCoord, m_mousePosition[2]); + glVertex3f(m_mousePosition[0], m_mousePosition[1], 2.0f * g_MinWorldCoord); + glVertex3f(m_mousePosition[0], m_mousePosition[1], 2.0f * g_MaxWorldCoord); + } else { + glVertex3f(2.0f * g_MinWorldCoord, m_mousePosition[1], m_mousePosition[2]); + glVertex3f(2.0f * g_MaxWorldCoord, m_mousePosition[1], m_mousePosition[2]); + glVertex3f(m_mousePosition[0], m_mousePosition[1], 2.0f * g_MinWorldCoord); + glVertex3f(m_mousePosition[0], m_mousePosition[1], 2.0f * g_MaxWorldCoord); + } + glEnd(); + } + + if (ClipMode()) { + GlobalClipPoints_Draw(m_fScale); + } + + GlobalOpenGL_debugAssertNoErrors(); + + // reset modelview + glLoadIdentity(); + glScalef(m_fScale, m_fScale, 1); + glTranslatef(-m_vOrigin[nDim1], -m_vOrigin[nDim2], 0); + + DrawCameraIcon(Camera_getOrigin(*g_pParentWnd->GetCamWnd()), Camera_getAngles(*g_pParentWnd->GetCamWnd())); + + Feedback_draw2D(m_viewType); + + if (g_xywindow_globals_private.show_outline) { + if (Active()) { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, m_nWidth, 0, m_nHeight, 0, 1); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // four view mode doesn't colorize + if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit) { + glColor3fv(vector3_to_array(g_xywindow_globals.color_viewname)); + } else { + switch (m_viewType) { + case YZ: + glColor3fv(vector3_to_array(g_xywindow_globals.AxisColorX)); + break; + case XZ: + glColor3fv(vector3_to_array(g_xywindow_globals.AxisColorY)); + break; + case XY: + glColor3fv(vector3_to_array(g_xywindow_globals.AxisColorZ)); + break; + } + } + glBegin(GL_LINE_LOOP); + glVertex2f(0.5, 0.5); + glVertex2f(m_nWidth - 0.5, 1); + glVertex2f(m_nWidth - 0.5, m_nHeight - 0.5); + glVertex2f(0.5, m_nHeight - 0.5); + glEnd(); + } + } + + GlobalOpenGL_debugAssertNoErrors(); + + glFinish(); +} + +void XYWnd_MouseToPoint(XYWnd *xywnd, int x, int y, Vector3 &point) +{ + xywnd->XY_ToPoint(x, y, point); + xywnd->XY_SnapToGrid(point); -void XYWnd::OnEntityCreate( const char* item ){ - StringOutputStream command; - command << "entityCreate -class " << item; - UndoableCommand undo( command.c_str() ); - Vector3 point; - XYWnd_MouseToPoint( this, m_entityCreate_x, m_entityCreate_y, point ); - Entity_createFromSelection( item, point ); + int nDim = (xywnd->GetViewType() == XY) ? 2 : (xywnd->GetViewType() == YZ) ? 0 : 1; + float fWorkMid = float_mid(Select_getWorkZone().d_work_min[nDim], Select_getWorkZone().d_work_max[nDim]); + point[nDim] = float_snapped(fWorkMid, GetGridSize()); } - - -void GetFocusPosition( Vector3& position ){ - if ( GlobalSelectionSystem().countSelected() != 0 ) { - Select_GetMid( position ); - } - else - { - position = Camera_getOrigin( *g_pParentWnd->GetCamWnd() ); - } +void XYWnd::OnEntityCreate(const char *item) +{ + StringOutputStream command; + command << "entityCreate -class " << item; + UndoableCommand undo(command.c_str()); + Vector3 point; + XYWnd_MouseToPoint(this, m_entityCreate_x, m_entityCreate_y, point); + Entity_createFromSelection(item, point); } -void XYWnd_Focus( XYWnd* xywnd ){ - Vector3 position; - GetFocusPosition( position ); - xywnd->PositionView( position ); -} -void XY_Split_Focus(){ - Vector3 position; - GetFocusPosition( position ); - if ( g_pParentWnd->GetXYWnd() ) { - g_pParentWnd->GetXYWnd()->PositionView( position ); - } - if ( g_pParentWnd->GetXZWnd() ) { - g_pParentWnd->GetXZWnd()->PositionView( position ); - } - if ( g_pParentWnd->GetYZWnd() ) { - g_pParentWnd->GetYZWnd()->PositionView( position ); - } +void GetFocusPosition(Vector3 &position) +{ + if (GlobalSelectionSystem().countSelected() != 0) { + Select_GetMid(position); + } else { + position = Camera_getOrigin(*g_pParentWnd->GetCamWnd()); + } } -void XY_Focus(){ - if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit ) { - // cannot do this in a split window - // do something else that the user may want here - XY_Split_Focus(); - return; - } - - XYWnd* xywnd = g_pParentWnd->GetXYWnd(); - XYWnd_Focus( xywnd ); +void XYWnd_Focus(XYWnd *xywnd) +{ + Vector3 position; + GetFocusPosition(position); + xywnd->PositionView(position); } -void XY_Top(){ - if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating ) { - // cannot do this in a split window - // do something else that the user may want here - XY_Split_Focus(); - return; - } +void XY_Split_Focus() +{ + Vector3 position; + GetFocusPosition(position); + if (g_pParentWnd->GetXYWnd()) { + g_pParentWnd->GetXYWnd()->PositionView(position); + } + if (g_pParentWnd->GetXZWnd()) { + g_pParentWnd->GetXZWnd()->PositionView(position); + } + if (g_pParentWnd->GetYZWnd()) { + g_pParentWnd->GetYZWnd()->PositionView(position); + } +} + +void XY_Focus() +{ + if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit) { + // cannot do this in a split window + // do something else that the user may want here + XY_Split_Focus(); + return; + } - XYWnd* xywnd = g_pParentWnd->GetXYWnd(); - xywnd->SetViewType( XY ); - XYWnd_Focus( xywnd ); + XYWnd *xywnd = g_pParentWnd->GetXYWnd(); + XYWnd_Focus(xywnd); } -void XY_Side(){ - if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating ) { - // cannot do this in a split window - // do something else that the user may want here - XY_Split_Focus(); - return; - } +void XY_Top() +{ + if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating) { + // cannot do this in a split window + // do something else that the user may want here + XY_Split_Focus(); + return; + } - XYWnd* xywnd = g_pParentWnd->GetXYWnd(); - xywnd->SetViewType( XZ ); - XYWnd_Focus( xywnd ); + XYWnd *xywnd = g_pParentWnd->GetXYWnd(); + xywnd->SetViewType(XY); + XYWnd_Focus(xywnd); } -void XY_Front(){ - if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating ) { - // cannot do this in a split window - // do something else that the user may want here - XY_Split_Focus(); - return; - } +void XY_Side() +{ + if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating) { + // cannot do this in a split window + // do something else that the user may want here + XY_Split_Focus(); + return; + } - XYWnd* xywnd = g_pParentWnd->GetXYWnd(); - xywnd->SetViewType( YZ ); - XYWnd_Focus( xywnd ); + XYWnd *xywnd = g_pParentWnd->GetXYWnd(); + xywnd->SetViewType(XZ); + XYWnd_Focus(xywnd); } -void XY_Next(){ - if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating ) { - // cannot do this in a split window - // do something else that the user may want here - XY_Split_Focus(); - return; - } - - XYWnd* xywnd = g_pParentWnd->GetXYWnd(); - if ( xywnd->GetViewType() == XY ) { - xywnd->SetViewType( XZ ); - } - else if ( xywnd->GetViewType() == XZ ) { - xywnd->SetViewType( YZ ); - } - else{ - xywnd->SetViewType( XY ); - } - XYWnd_Focus( xywnd ); -} +void XY_Front() +{ + if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating) { + // cannot do this in a split window + // do something else that the user may want here + XY_Split_Focus(); + return; + } -void XY_Zoom100(){ - if ( g_pParentWnd->GetXYWnd() ) { - g_pParentWnd->GetXYWnd()->SetScale( 1 ); - } - if ( g_pParentWnd->GetXZWnd() ) { - g_pParentWnd->GetXZWnd()->SetScale( 1 ); - } - if ( g_pParentWnd->GetYZWnd() ) { - g_pParentWnd->GetYZWnd()->SetScale( 1 ); - } + XYWnd *xywnd = g_pParentWnd->GetXYWnd(); + xywnd->SetViewType(YZ); + XYWnd_Focus(xywnd); } -void XY_ZoomIn(){ - XYWnd_ZoomIn( g_pParentWnd->ActiveXY() ); +void XY_Next() +{ + if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating) { + // cannot do this in a split window + // do something else that the user may want here + XY_Split_Focus(); + return; + } + + XYWnd *xywnd = g_pParentWnd->GetXYWnd(); + if (xywnd->GetViewType() == XY) { + xywnd->SetViewType(XZ); + } else if (xywnd->GetViewType() == XZ) { + xywnd->SetViewType(YZ); + } else { + xywnd->SetViewType(XY); + } + XYWnd_Focus(xywnd); +} + +void XY_Zoom100() +{ + if (g_pParentWnd->GetXYWnd()) { + g_pParentWnd->GetXYWnd()->SetScale(1); + } + if (g_pParentWnd->GetXZWnd()) { + g_pParentWnd->GetXZWnd()->SetScale(1); + } + if (g_pParentWnd->GetYZWnd()) { + g_pParentWnd->GetYZWnd()->SetScale(1); + } +} + +void XY_ZoomIn() +{ + XYWnd_ZoomIn(g_pParentWnd->ActiveXY()); } // NOTE: the zoom out factor is 4/5, we could think about customizing it // we don't go below a zoom factor corresponding to 10% of the max world size // (this has to be computed against the window size) -void XY_ZoomOut(){ - XYWnd_ZoomOut( g_pParentWnd->ActiveXY() ); +void XY_ZoomOut() +{ + XYWnd_ZoomOut(g_pParentWnd->ActiveXY()); } - -void ToggleShowCrosshair(){ - g_bCrossHairs ^= 1; - XY_UpdateAllWindows(); +void ToggleShowCrosshair() +{ + g_bCrossHairs ^= 1; + XY_UpdateAllWindows(); } -void ToggleShowSizeInfo(){ - g_xywindow_globals_private.m_bSizePaint = !g_xywindow_globals_private.m_bSizePaint; - XY_UpdateAllWindows(); +void ToggleShowSizeInfo() +{ + g_xywindow_globals_private.m_bSizePaint = !g_xywindow_globals_private.m_bSizePaint; + XY_UpdateAllWindows(); } -void ToggleShowGrid(){ - g_xywindow_globals_private.d_showgrid = !g_xywindow_globals_private.d_showgrid; - XY_UpdateAllWindows(); +void ToggleShowGrid() +{ + g_xywindow_globals_private.d_showgrid = !g_xywindow_globals_private.d_showgrid; + XY_UpdateAllWindows(); } -ToggleShown g_xy_top_shown( true ); +ToggleShown g_xy_top_shown(true); -void XY_Top_Shown_Construct( ui::Window parent ){ - g_xy_top_shown.connect( parent ); +void XY_Top_Shown_Construct(ui::Window parent) +{ + g_xy_top_shown.connect(parent); } -ToggleShown g_yz_side_shown( false ); +ToggleShown g_yz_side_shown(false); -void YZ_Side_Shown_Construct( ui::Window parent ){ - g_yz_side_shown.connect( parent ); +void YZ_Side_Shown_Construct(ui::Window parent) +{ + g_yz_side_shown.connect(parent); } -ToggleShown g_xz_front_shown( false ); +ToggleShown g_xz_front_shown(false); -void XZ_Front_Shown_Construct( ui::Window parent ){ - g_xz_front_shown.connect( parent ); +void XZ_Front_Shown_Construct(ui::Window parent) +{ + g_xz_front_shown.connect(parent); } -class EntityClassMenu : public ModuleObserver -{ -std::size_t m_unrealised; +class EntityClassMenu : public ModuleObserver { + std::size_t m_unrealised; public: -EntityClassMenu() : m_unrealised( 1 ){ -} -void realise(){ - if ( --m_unrealised == 0 ) { - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - if ( XYWnd::m_mnuDrop ) { - XYWnd::m_mnuDrop.destroy(); - XYWnd::m_mnuDrop = ui::Menu(ui::null); - } - } -} + EntityClassMenu() : m_unrealised(1) + { + } + + void realise() + { + if (--m_unrealised == 0) { + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + if (XYWnd::m_mnuDrop) { + XYWnd::m_mnuDrop.destroy(); + XYWnd::m_mnuDrop = ui::Menu(ui::null); + } + } + } }; EntityClassMenu g_EntityClassMenu; - - -void ShowNamesToggle(){ - GlobalEntityCreator().setShowNames( !GlobalEntityCreator().getShowNames() ); - XY_UpdateAllWindows(); +void ShowNamesToggle() +{ + GlobalEntityCreator().setShowNames(!GlobalEntityCreator().getShowNames()); + XY_UpdateAllWindows(); } + typedef FreeCaller ShowNamesToggleCaller; -void ShowNamesExport( const Callback & importer ){ - importer( GlobalEntityCreator().getShowNames() ); + +void ShowNamesExport(const Callback &importer) +{ + importer(GlobalEntityCreator().getShowNames()); } + typedef FreeCaller &), ShowNamesExport> ShowNamesExportCaller; -void ShowAnglesToggle(){ - GlobalEntityCreator().setShowAngles( !GlobalEntityCreator().getShowAngles() ); - XY_UpdateAllWindows(); +void ShowAnglesToggle() +{ + GlobalEntityCreator().setShowAngles(!GlobalEntityCreator().getShowAngles()); + XY_UpdateAllWindows(); } + typedef FreeCaller ShowAnglesToggleCaller; -void ShowAnglesExport( const Callback & importer ){ - importer( GlobalEntityCreator().getShowAngles() ); + +void ShowAnglesExport(const Callback &importer) +{ + importer(GlobalEntityCreator().getShowAngles()); } + typedef FreeCaller &), ShowAnglesExport> ShowAnglesExportCaller; -void ShowBlocksToggle(){ - g_xywindow_globals_private.show_blocks ^= 1; - XY_UpdateAllWindows(); +void ShowBlocksToggle() +{ + g_xywindow_globals_private.show_blocks ^= 1; + XY_UpdateAllWindows(); } + typedef FreeCaller ShowBlocksToggleCaller; -void ShowBlocksExport( const Callback & importer ){ - importer( g_xywindow_globals_private.show_blocks ); + +void ShowBlocksExport(const Callback &importer) +{ + importer(g_xywindow_globals_private.show_blocks); } + typedef FreeCaller &), ShowBlocksExport> ShowBlocksExportCaller; -void ShowCoordinatesToggle(){ - g_xywindow_globals_private.show_coordinates ^= 1; - XY_UpdateAllWindows(); +void ShowCoordinatesToggle() +{ + g_xywindow_globals_private.show_coordinates ^= 1; + XY_UpdateAllWindows(); } + typedef FreeCaller ShowCoordinatesToggleCaller; -void ShowCoordinatesExport( const Callback & importer ){ - importer( g_xywindow_globals_private.show_coordinates ); + +void ShowCoordinatesExport(const Callback &importer) +{ + importer(g_xywindow_globals_private.show_coordinates); } + typedef FreeCaller &), ShowCoordinatesExport> ShowCoordinatesExportCaller; -void ShowOutlineToggle(){ - g_xywindow_globals_private.show_outline ^= 1; - XY_UpdateAllWindows(); +void ShowOutlineToggle() +{ + g_xywindow_globals_private.show_outline ^= 1; + XY_UpdateAllWindows(); } + typedef FreeCaller ShowOutlineToggleCaller; -void ShowOutlineExport( const Callback & importer ){ - importer( g_xywindow_globals_private.show_outline ); + +void ShowOutlineExport(const Callback &importer) +{ + importer(g_xywindow_globals_private.show_outline); } + typedef FreeCaller &), ShowOutlineExport> ShowOutlineExportCaller; -void ShowAxesToggle(){ - g_xywindow_globals_private.show_axis ^= 1; - XY_UpdateAllWindows(); +void ShowAxesToggle() +{ + g_xywindow_globals_private.show_axis ^= 1; + XY_UpdateAllWindows(); } + typedef FreeCaller ShowAxesToggleCaller; -void ShowAxesExport( const Callback & importer ){ - importer( g_xywindow_globals_private.show_axis ); + +void ShowAxesExport(const Callback &importer) +{ + importer(g_xywindow_globals_private.show_axis); } + typedef FreeCaller &), ShowAxesExport> ShowAxesExportCaller; -void ShowWorkzoneToggle(){ - g_xywindow_globals_private.d_show_work ^= 1; - XY_UpdateAllWindows(); +void ShowWorkzoneToggle() +{ + g_xywindow_globals_private.d_show_work ^= 1; + XY_UpdateAllWindows(); } + typedef FreeCaller ShowWorkzoneToggleCaller; -void ShowWorkzoneExport( const Callback & importer ){ - importer( g_xywindow_globals_private.d_show_work ); + +void ShowWorkzoneExport(const Callback &importer) +{ + importer(g_xywindow_globals_private.d_show_work); } + typedef FreeCaller &), ShowWorkzoneExport> ShowWorkzoneExportCaller; ShowNamesExportCaller g_show_names_caller; -Callback &)> g_show_names_callback( g_show_names_caller ); -ToggleItem g_show_names( g_show_names_callback ); +Callback &)> g_show_names_callback(g_show_names_caller); +ToggleItem g_show_names(g_show_names_callback); ShowAnglesExportCaller g_show_angles_caller; -Callback &)> g_show_angles_callback( g_show_angles_caller ); -ToggleItem g_show_angles( g_show_angles_callback ); +Callback &)> g_show_angles_callback(g_show_angles_caller); +ToggleItem g_show_angles(g_show_angles_callback); ShowBlocksExportCaller g_show_blocks_caller; -Callback &)> g_show_blocks_callback( g_show_blocks_caller ); -ToggleItem g_show_blocks( g_show_blocks_callback ); +Callback &)> g_show_blocks_callback(g_show_blocks_caller); +ToggleItem g_show_blocks(g_show_blocks_callback); ShowCoordinatesExportCaller g_show_coordinates_caller; -Callback &)> g_show_coordinates_callback( g_show_coordinates_caller ); -ToggleItem g_show_coordinates( g_show_coordinates_callback ); +Callback &)> g_show_coordinates_callback(g_show_coordinates_caller); +ToggleItem g_show_coordinates(g_show_coordinates_callback); ShowOutlineExportCaller g_show_outline_caller; -Callback &)> g_show_outline_callback( g_show_outline_caller ); -ToggleItem g_show_outline( g_show_outline_callback ); +Callback &)> g_show_outline_callback(g_show_outline_caller); +ToggleItem g_show_outline(g_show_outline_callback); ShowAxesExportCaller g_show_axes_caller; -Callback &)> g_show_axes_callback( g_show_axes_caller ); -ToggleItem g_show_axes( g_show_axes_callback ); +Callback &)> g_show_axes_callback(g_show_axes_caller); +ToggleItem g_show_axes(g_show_axes_callback); ShowWorkzoneExportCaller g_show_workzone_caller; -Callback &)> g_show_workzone_callback( g_show_workzone_caller ); -ToggleItem g_show_workzone( g_show_workzone_callback ); +Callback &)> g_show_workzone_callback(g_show_workzone_caller); +ToggleItem g_show_workzone(g_show_workzone_callback); -void XYShow_registerCommands(){ - GlobalToggles_insert( "ShowAngles", ShowAnglesToggleCaller(), ToggleItem::AddCallbackCaller( g_show_angles ) ); - GlobalToggles_insert( "ShowNames", ShowNamesToggleCaller(), ToggleItem::AddCallbackCaller( g_show_names ) ); - GlobalToggles_insert( "ShowBlocks", ShowBlocksToggleCaller(), ToggleItem::AddCallbackCaller( g_show_blocks ) ); - GlobalToggles_insert( "ShowCoordinates", ShowCoordinatesToggleCaller(), ToggleItem::AddCallbackCaller( g_show_coordinates ) ); - GlobalToggles_insert( "ShowWindowOutline", ShowOutlineToggleCaller(), ToggleItem::AddCallbackCaller( g_show_outline ) ); - GlobalToggles_insert( "ShowAxes", ShowAxesToggleCaller(), ToggleItem::AddCallbackCaller( g_show_axes ) ); - GlobalToggles_insert( "ShowWorkzone", ShowWorkzoneToggleCaller(), ToggleItem::AddCallbackCaller( g_show_workzone ) ); +void XYShow_registerCommands() +{ + GlobalToggles_insert("ShowAngles", ShowAnglesToggleCaller(), ToggleItem::AddCallbackCaller(g_show_angles)); + GlobalToggles_insert("ShowNames", ShowNamesToggleCaller(), ToggleItem::AddCallbackCaller(g_show_names)); + GlobalToggles_insert("ShowBlocks", ShowBlocksToggleCaller(), ToggleItem::AddCallbackCaller(g_show_blocks)); + GlobalToggles_insert("ShowCoordinates", ShowCoordinatesToggleCaller(), + ToggleItem::AddCallbackCaller(g_show_coordinates)); + GlobalToggles_insert("ShowWindowOutline", ShowOutlineToggleCaller(), ToggleItem::AddCallbackCaller(g_show_outline)); + GlobalToggles_insert("ShowAxes", ShowAxesToggleCaller(), ToggleItem::AddCallbackCaller(g_show_axes)); + GlobalToggles_insert("ShowWorkzone", ShowWorkzoneToggleCaller(), ToggleItem::AddCallbackCaller(g_show_workzone)); } -void XYWnd_registerShortcuts(){ - command_connect_accelerator( "ToggleCrosshairs" ); - command_connect_accelerator( "ToggleSizePaint" ); +void XYWnd_registerShortcuts() +{ + command_connect_accelerator("ToggleCrosshairs"); + command_connect_accelerator("ToggleSizePaint"); } - -void Orthographic_constructPreferences( PreferencesPage& page ){ - page.appendCheckBox( "", "Solid selection boxes", g_xywindow_globals.m_bNoStipple ); - page.appendCheckBox( "", "Display size info", g_xywindow_globals_private.m_bSizePaint ); - page.appendCheckBox( "", "Chase mouse during drags", g_xywindow_globals_private.m_bChaseMouse ); - page.appendCheckBox( "", "Update views on camera move", g_xywindow_globals_private.m_bCamXYUpdate ); +void Orthographic_constructPreferences(PreferencesPage &page) +{ + page.appendCheckBox("", "Solid selection boxes", g_xywindow_globals.m_bNoStipple); + page.appendCheckBox("", "Display size info", g_xywindow_globals_private.m_bSizePaint); + page.appendCheckBox("", "Chase mouse during drags", g_xywindow_globals_private.m_bChaseMouse); + page.appendCheckBox("", "Update views on camera move", g_xywindow_globals_private.m_bCamXYUpdate); } -void Orthographic_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Orthographic", "Orthographic View Preferences" ) ); - Orthographic_constructPreferences( page ); + +void Orthographic_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Orthographic", "Orthographic View Preferences")); + Orthographic_constructPreferences(page); } -void Orthographic_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage( makeCallbackF(Orthographic_constructPage) ); + +void Orthographic_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(Orthographic_constructPage)); } -void Clipper_constructPreferences( PreferencesPage& page ){ - page.appendCheckBox( "", "Clipper tool uses caulk", g_clip_useCaulk ); +void Clipper_constructPreferences(PreferencesPage &page) +{ + page.appendCheckBox("", "Clipper tool uses caulk", g_clip_useCaulk); } -void Clipper_constructPage( PreferenceGroup& group ){ - PreferencesPage page( group.createPage( "Clipper", "Clipper Tool Settings" ) ); - Clipper_constructPreferences( page ); + +void Clipper_constructPage(PreferenceGroup &group) +{ + PreferencesPage page(group.createPage("Clipper", "Clipper Tool Settings")); + Clipper_constructPreferences(page); } -void Clipper_registerPreferencesPage(){ - PreferencesDialog_addSettingsPage( makeCallbackF(Clipper_constructPage) ); + +void Clipper_registerPreferencesPage() +{ + PreferencesDialog_addSettingsPage(makeCallbackF(Clipper_constructPage)); } @@ -2728,68 +2889,88 @@ void Clipper_registerPreferencesPage(){ struct ToggleShown_Bool { - static void Export(const ToggleShown &self, const Callback &returnz) { - returnz(self.active()); - } - - static void Import(ToggleShown &self, bool value) { - self.set(value); - } + static void Export(const ToggleShown &self, const Callback &returnz) + { + returnz(self.active()); + } + + static void Import(ToggleShown &self, bool value) + { + self.set(value); + } }; -void XYWindow_Construct(){ - GlobalCommands_insert( "ToggleCrosshairs", makeCallbackF(ToggleShowCrosshair), Accelerator( 'X', (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalCommands_insert( "ToggleSizePaint", makeCallbackF(ToggleShowSizeInfo), Accelerator( 'J' ) ); - GlobalCommands_insert( "ToggleGrid", makeCallbackF(ToggleShowGrid), Accelerator( '0' ) ); - - GlobalToggles_insert( "ToggleView", ToggleShown::ToggleCaller( g_xy_top_shown ), ToggleItem::AddCallbackCaller( g_xy_top_shown.m_item ), Accelerator( 'V', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalToggles_insert( "ToggleSideView", ToggleShown::ToggleCaller( g_yz_side_shown ), ToggleItem::AddCallbackCaller( g_yz_side_shown.m_item ) ); - GlobalToggles_insert( "ToggleFrontView", ToggleShown::ToggleCaller( g_xz_front_shown ), ToggleItem::AddCallbackCaller( g_xz_front_shown.m_item ) ); - GlobalCommands_insert( "NextView", makeCallbackF(XY_Next), Accelerator( GDK_KEY_Tab, (GdkModifierType)GDK_CONTROL_MASK ) ); // fixme: doesn't show its shortcut - GlobalCommands_insert( "ZoomIn", makeCallbackF(XY_ZoomIn), Accelerator( GDK_KEY_Delete ) ); - GlobalCommands_insert( "ZoomOut", makeCallbackF(XY_ZoomOut), Accelerator( GDK_KEY_Insert ) ); - GlobalCommands_insert( "ViewTop", makeCallbackF(XY_Top), Accelerator( GDK_KEY_KP_Home ) ); - GlobalCommands_insert( "ViewSide", makeCallbackF(XY_Side), Accelerator( GDK_KEY_KP_Page_Down ) ); - GlobalCommands_insert( "ViewFront", makeCallbackF(XY_Front), Accelerator( GDK_KEY_KP_End ) ); - GlobalCommands_insert( "Zoom100", makeCallbackF(XY_Zoom100) ); - GlobalCommands_insert( "CenterXYView", makeCallbackF(XY_Focus), Accelerator( GDK_KEY_Tab, (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - - GlobalPreferenceSystem().registerPreference( "ClipCaulk", make_property_string( g_clip_useCaulk ) ); - - GlobalPreferenceSystem().registerPreference( "NewRightClick", make_property_string( g_xywindow_globals.m_bRightClick ) ); - GlobalPreferenceSystem().registerPreference( "ChaseMouse", make_property_string( g_xywindow_globals_private.m_bChaseMouse ) ); - GlobalPreferenceSystem().registerPreference( "SizePainting", make_property_string( g_xywindow_globals_private.m_bSizePaint ) ); - GlobalPreferenceSystem().registerPreference( "NoStipple", make_property_string( g_xywindow_globals.m_bNoStipple ) ); - GlobalPreferenceSystem().registerPreference( "SI_ShowCoords", make_property_string( g_xywindow_globals_private.show_coordinates ) ); - GlobalPreferenceSystem().registerPreference( "SI_ShowOutlines", make_property_string( g_xywindow_globals_private.show_outline ) ); - GlobalPreferenceSystem().registerPreference( "SI_ShowAxis", make_property_string( g_xywindow_globals_private.show_axis ) ); - GlobalPreferenceSystem().registerPreference( "CamXYUpdate", make_property_string( g_xywindow_globals_private.m_bCamXYUpdate ) ); - GlobalPreferenceSystem().registerPreference( "ShowWorkzone", make_property_string( g_xywindow_globals_private.d_show_work ) ); - - GlobalPreferenceSystem().registerPreference( "SI_AxisColors0", make_property_string( g_xywindow_globals.AxisColorX ) ); - GlobalPreferenceSystem().registerPreference( "SI_AxisColors1", make_property_string( g_xywindow_globals.AxisColorY ) ); - GlobalPreferenceSystem().registerPreference( "SI_AxisColors2", make_property_string( g_xywindow_globals.AxisColorZ ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors1", make_property_string( g_xywindow_globals.color_gridback ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors2", make_property_string( g_xywindow_globals.color_gridminor ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors3", make_property_string( g_xywindow_globals.color_gridmajor ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors6", make_property_string( g_xywindow_globals.color_gridblock ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors7", make_property_string( g_xywindow_globals.color_gridtext ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors8", make_property_string( g_xywindow_globals.color_brushes ) ); - GlobalPreferenceSystem().registerPreference( "SI_Colors14", make_property_string( g_xywindow_globals.color_gridmajor_alt ) ); - - - GlobalPreferenceSystem().registerPreference( "XZVIS", make_property_string( g_xz_front_shown ) ); - GlobalPreferenceSystem().registerPreference( "YZVIS", make_property_string( g_yz_side_shown ) ); - - Orthographic_registerPreferencesPage(); - Clipper_registerPreferencesPage(); - - XYWnd::captureStates(); - GlobalEntityClassManager().attach( g_EntityClassMenu ); -} - -void XYWindow_Destroy(){ - GlobalEntityClassManager().detach( g_EntityClassMenu ); - XYWnd::releaseStates(); +void XYWindow_Construct() +{ + GlobalCommands_insert("ToggleCrosshairs", makeCallbackF(ToggleShowCrosshair), + Accelerator('X', (GdkModifierType) GDK_SHIFT_MASK)); + GlobalCommands_insert("ToggleSizePaint", makeCallbackF(ToggleShowSizeInfo), Accelerator('J')); + GlobalCommands_insert("ToggleGrid", makeCallbackF(ToggleShowGrid), Accelerator('0')); + + GlobalToggles_insert("ToggleView", ToggleShown::ToggleCaller(g_xy_top_shown), + ToggleItem::AddCallbackCaller(g_xy_top_shown.m_item), + Accelerator('V', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + GlobalToggles_insert("ToggleSideView", ToggleShown::ToggleCaller(g_yz_side_shown), + ToggleItem::AddCallbackCaller(g_yz_side_shown.m_item)); + GlobalToggles_insert("ToggleFrontView", ToggleShown::ToggleCaller(g_xz_front_shown), + ToggleItem::AddCallbackCaller(g_xz_front_shown.m_item)); + GlobalCommands_insert("NextView", makeCallbackF(XY_Next), Accelerator(GDK_KEY_Tab, + (GdkModifierType) GDK_CONTROL_MASK)); // fixme: doesn't show its shortcut + GlobalCommands_insert("ZoomIn", makeCallbackF(XY_ZoomIn), Accelerator(GDK_KEY_Delete)); + GlobalCommands_insert("ZoomOut", makeCallbackF(XY_ZoomOut), Accelerator(GDK_KEY_Insert)); + GlobalCommands_insert("ViewTop", makeCallbackF(XY_Top), Accelerator(GDK_KEY_KP_Home)); + GlobalCommands_insert("ViewSide", makeCallbackF(XY_Side), Accelerator(GDK_KEY_KP_Page_Down)); + GlobalCommands_insert("ViewFront", makeCallbackF(XY_Front), Accelerator(GDK_KEY_KP_End)); + GlobalCommands_insert("Zoom100", makeCallbackF(XY_Zoom100)); + GlobalCommands_insert("CenterXYView", makeCallbackF(XY_Focus), + Accelerator(GDK_KEY_Tab, (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); + + GlobalPreferenceSystem().registerPreference("ClipCaulk", make_property_string(g_clip_useCaulk)); + + GlobalPreferenceSystem().registerPreference("NewRightClick", + make_property_string(g_xywindow_globals.m_bRightClick)); + GlobalPreferenceSystem().registerPreference("ChaseMouse", + make_property_string(g_xywindow_globals_private.m_bChaseMouse)); + GlobalPreferenceSystem().registerPreference("SizePainting", + make_property_string(g_xywindow_globals_private.m_bSizePaint)); + GlobalPreferenceSystem().registerPreference("NoStipple", make_property_string(g_xywindow_globals.m_bNoStipple)); + GlobalPreferenceSystem().registerPreference("SI_ShowCoords", + make_property_string(g_xywindow_globals_private.show_coordinates)); + GlobalPreferenceSystem().registerPreference("SI_ShowOutlines", + make_property_string(g_xywindow_globals_private.show_outline)); + GlobalPreferenceSystem().registerPreference("SI_ShowAxis", + make_property_string(g_xywindow_globals_private.show_axis)); + GlobalPreferenceSystem().registerPreference("CamXYUpdate", + make_property_string(g_xywindow_globals_private.m_bCamXYUpdate)); + GlobalPreferenceSystem().registerPreference("ShowWorkzone", + make_property_string(g_xywindow_globals_private.d_show_work)); + + GlobalPreferenceSystem().registerPreference("SI_AxisColors0", make_property_string(g_xywindow_globals.AxisColorX)); + GlobalPreferenceSystem().registerPreference("SI_AxisColors1", make_property_string(g_xywindow_globals.AxisColorY)); + GlobalPreferenceSystem().registerPreference("SI_AxisColors2", make_property_string(g_xywindow_globals.AxisColorZ)); + GlobalPreferenceSystem().registerPreference("SI_Colors1", make_property_string(g_xywindow_globals.color_gridback)); + GlobalPreferenceSystem().registerPreference("SI_Colors2", make_property_string(g_xywindow_globals.color_gridminor)); + GlobalPreferenceSystem().registerPreference("SI_Colors3", make_property_string(g_xywindow_globals.color_gridmajor)); + GlobalPreferenceSystem().registerPreference("SI_Colors6", make_property_string(g_xywindow_globals.color_gridblock)); + GlobalPreferenceSystem().registerPreference("SI_Colors7", make_property_string(g_xywindow_globals.color_gridtext)); + GlobalPreferenceSystem().registerPreference("SI_Colors8", make_property_string(g_xywindow_globals.color_brushes)); + GlobalPreferenceSystem().registerPreference("SI_Colors14", + make_property_string(g_xywindow_globals.color_gridmajor_alt)); + + + GlobalPreferenceSystem().registerPreference("XZVIS", make_property_string(g_xz_front_shown)); + GlobalPreferenceSystem().registerPreference("YZVIS", make_property_string(g_yz_side_shown)); + + Orthographic_registerPreferencesPage(); + Clipper_registerPreferencesPage(); + + XYWnd::captureStates(); + GlobalEntityClassManager().attach(g_EntityClassMenu); +} + +void XYWindow_Destroy() +{ + GlobalEntityClassManager().detach(g_EntityClassMenu); + XYWnd::releaseStates(); } diff --git a/radiant/xywindow.h b/radiant/xywindow.h index 0b762d45..aa6b5982 100644 --- a/radiant/xywindow.h +++ b/radiant/xywindow.h @@ -35,242 +35,306 @@ #include "qerplugin.h" class Shader; + class SelectionSystemWindowObserver; -namespace scene -{ -class Node; +namespace scene { + class Node; } void FlipClip(); + void SplitClip(); + void Clip(); -void OnClipMode( bool enabled ); + +void OnClipMode(bool enabled); + bool ClipMode(); -inline const char* ViewType_getTitle( VIEWTYPE viewtype ){ - if ( viewtype == XY ) { - return "XY Top"; - } - if ( viewtype == XZ ) { - return "XZ Front"; - } - if ( viewtype == YZ ) { - return "YZ Side"; - } - return ""; +inline const char *ViewType_getTitle(VIEWTYPE viewtype) +{ + if (viewtype == XY) { + return "XY Top"; + } + if (viewtype == XZ) { + return "XZ Front"; + } + if (viewtype == YZ) { + return "YZ Side"; + } + return ""; } -class XYWnd -{ -ui::GLArea m_gl_widget; -guint m_sizeHandler; -guint m_exposeHandler; +class XYWnd { + ui::GLArea m_gl_widget; + guint m_sizeHandler; + guint m_exposeHandler; -DeferredDraw m_deferredDraw; -DeferredMotion m_deferred_motion; + DeferredDraw m_deferredDraw; + DeferredMotion m_deferred_motion; public: -ui::Window m_parent; -XYWnd(); -~XYWnd(); + ui::Window m_parent; -void queueDraw(){ - m_deferredDraw.draw(); -} -ui::GLArea GetWidget(){ - return m_gl_widget; -} + XYWnd(); + + ~XYWnd(); + + void queueDraw() + { + m_deferredDraw.draw(); + } + + ui::GLArea GetWidget() + { + return m_gl_widget; + } public: -SelectionSystemWindowObserver* m_window_observer; -XORRectangle m_XORRectangle; -WindowPositionTracker m_positionTracker; - -static void captureStates(); -static void releaseStates(); - -void PositionView( const Vector3& position ); -const Vector3& GetOrigin(); -void SetOrigin( const Vector3& origin ); -void Scroll( int x, int y ); - -void XY_Draw(); -void DrawCameraIcon( const Vector3& origin, const Vector3& angles ); -void XY_DrawBlockGrid(); -void XY_DrawAxis(); -void XY_DrawGrid(); -void XY_DrawBackground(); -void XY_LoadBackgroundImage( const char *name ); -void XY_DisableBackground(); - -void XY_MouseUp( int x, int y, unsigned int buttons ); -void XY_MouseDown( int x, int y, unsigned int buttons ); -void XY_MouseMoved( int x, int y, unsigned int buttons ); - -void NewBrushDrag_Begin( int x, int y ); -void NewBrushDrag( int x, int y ); -void NewBrushDrag_End( int x, int y ); - -void XY_ToPoint( int x, int y, Vector3& point ); -void XY_SnapToGrid( Vector3& point ); - -void Move_Begin(); -void Move_End(); -bool m_move_started; -guint m_move_focusOut; - -void Zoom_Begin(); -void Zoom_End(); -bool m_zoom_started; -guint m_zoom_focusOut; - -void SetActive( bool b ){ - m_bActive = b; -}; -bool Active(){ - return m_bActive; -}; + SelectionSystemWindowObserver *m_window_observer; + XORRectangle m_XORRectangle; + WindowPositionTracker m_positionTracker; + + static void captureStates(); + + static void releaseStates(); + + void PositionView(const Vector3 &position); + + const Vector3 &GetOrigin(); + + void SetOrigin(const Vector3 &origin); + + void Scroll(int x, int y); + + void XY_Draw(); + + void DrawCameraIcon(const Vector3 &origin, const Vector3 &angles); + + void XY_DrawBlockGrid(); + + void XY_DrawAxis(); + + void XY_DrawGrid(); + + void XY_DrawBackground(); + + void XY_LoadBackgroundImage(const char *name); + + void XY_DisableBackground(); + + void XY_MouseUp(int x, int y, unsigned int buttons); + + void XY_MouseDown(int x, int y, unsigned int buttons); + + void XY_MouseMoved(int x, int y, unsigned int buttons); + + void NewBrushDrag_Begin(int x, int y); + + void NewBrushDrag(int x, int y); + + void NewBrushDrag_End(int x, int y); + + void XY_ToPoint(int x, int y, Vector3 &point); + + void XY_SnapToGrid(Vector3 &point); + + void Move_Begin(); + + void Move_End(); + + bool m_move_started; + guint m_move_focusOut; + + void Zoom_Begin(); -void Clipper_OnLButtonDown( int x, int y ); -void Clipper_OnLButtonUp( int x, int y ); -void Clipper_OnMouseMoved( int x, int y ); -void Clipper_Crosshair_OnMouseMoved( int x, int y ); -void DropClipPoint( int pointx, int pointy ); + void Zoom_End(); -void SetViewType( VIEWTYPE n ); -bool m_bActive; + bool m_zoom_started; + guint m_zoom_focusOut; -static ui::Menu m_mnuDrop; + void SetActive(bool b) + { + m_bActive = b; + }; -int m_chasemouse_current_x, m_chasemouse_current_y; -int m_chasemouse_delta_x, m_chasemouse_delta_y; + bool Active() + { + return m_bActive; + }; + void Clipper_OnLButtonDown(int x, int y); -guint m_chasemouse_handler; -void ChaseMouse(); -bool chaseMouseMotion( int pointx, int pointy ); + void Clipper_OnLButtonUp(int x, int y); -void updateModelview(); -void updateProjection(); -Matrix4 m_projection; -Matrix4 m_modelview; + void Clipper_OnMouseMoved(int x, int y); -int m_nWidth; -int m_nHeight; + void Clipper_Crosshair_OnMouseMoved(int x, int y); + + void DropClipPoint(int pointx, int pointy); + + void SetViewType(VIEWTYPE n); + + bool m_bActive; + + static ui::Menu m_mnuDrop; + + int m_chasemouse_current_x, m_chasemouse_current_y; + int m_chasemouse_delta_x, m_chasemouse_delta_y; + + + guint m_chasemouse_handler; + + void ChaseMouse(); + + bool chaseMouseMotion(int pointx, int pointy); + + void updateModelview(); + + void updateProjection(); + + Matrix4 m_projection; + Matrix4 m_modelview; + + int m_nWidth; + int m_nHeight; // background image stuff -qtexture_t *m_tex; -bool m_backgroundActivated; -float m_alpha; // vertex alpha -float m_xmin, m_ymin, m_xmax, m_ymax; + qtexture_t *m_tex; + bool m_backgroundActivated; + float m_alpha; // vertex alpha + float m_xmin, m_ymin, m_xmax, m_ymax; private: -float m_fScale; -Vector3 m_vOrigin; + float m_fScale; + Vector3 m_vOrigin; + + View m_view; + static Shader *m_state_selected; -View m_view; -static Shader* m_state_selected; + int m_ptCursorX, m_ptCursorY; -int m_ptCursorX, m_ptCursorY; + unsigned int m_buttonstate; -unsigned int m_buttonstate; + int m_nNewBrushPressx; + int m_nNewBrushPressy; + scene::Node *m_NewBrushDrag; + bool m_bNewBrushDrag; -int m_nNewBrushPressx; -int m_nNewBrushPressy; -scene::Node* m_NewBrushDrag; -bool m_bNewBrushDrag; + Vector3 m_mousePosition; -Vector3 m_mousePosition; + VIEWTYPE m_viewType; -VIEWTYPE m_viewType; + void OriginalButtonUp(guint32 nFlags, int point, int pointy); -void OriginalButtonUp( guint32 nFlags, int point, int pointy ); -void OriginalButtonDown( guint32 nFlags, int point, int pointy ); + void OriginalButtonDown(guint32 nFlags, int point, int pointy); -void OnContextMenu(); -void PaintSizeInfo( int nDim1, int nDim2, Vector3& vMinBounds, Vector3& vMaxBounds ); + void OnContextMenu(); -int m_entityCreate_x, m_entityCreate_y; -bool m_entityCreate; + void PaintSizeInfo(int nDim1, int nDim2, Vector3 &vMinBounds, Vector3 &vMaxBounds); + + int m_entityCreate_x, m_entityCreate_y; + bool m_entityCreate; public: -void ButtonState_onMouseDown( unsigned int buttons ){ - m_buttonstate |= buttons; -} -void ButtonState_onMouseUp( unsigned int buttons ){ - m_buttonstate &= ~buttons; -} -unsigned int getButtonState() const { - return m_buttonstate; -} -void EntityCreate_MouseDown( int x, int y ); -void EntityCreate_MouseMove( int x, int y ); -void EntityCreate_MouseUp( int x, int y ); + void ButtonState_onMouseDown(unsigned int buttons) + { + m_buttonstate |= buttons; + } -void OnEntityCreate( const char* item ); -VIEWTYPE GetViewType(){ - return m_viewType; -} -void SetScale( float f ); -float Scale(){ - return m_fScale; -} -int Width(){ - return m_nWidth; -} -int Height(){ - return m_nHeight; -} + void ButtonState_onMouseUp(unsigned int buttons) + { + m_buttonstate &= ~buttons; + } + + unsigned int getButtonState() const + { + return m_buttonstate; + } + + void EntityCreate_MouseDown(int x, int y); + + void EntityCreate_MouseMove(int x, int y); + + void EntityCreate_MouseUp(int x, int y); + + void OnEntityCreate(const char *item); + + VIEWTYPE GetViewType() + { + return m_viewType; + } + + void SetScale(float f); + + float Scale() + { + return m_fScale; + } + + int Width() + { + return m_nWidth; + } -Signal0 onDestroyed; -Signal3 onMouseDown; -void mouseDown( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ); -typedef Member MouseDownCaller; + int Height() + { + return m_nHeight; + } + + Signal0 onDestroyed; + Signal3 onMouseDown; + + void mouseDown(const WindowVector &position, ButtonIdentifier button, ModifierFlags modifiers); + + typedef Member MouseDownCaller; }; -inline void XYWnd_Update( XYWnd& xywnd ){ - xywnd.queueDraw(); +inline void XYWnd_Update(XYWnd &xywnd) +{ + xywnd.queueDraw(); } -struct xywindow_globals_t -{ - Vector3 color_gridback; - Vector3 color_gridminor; - Vector3 color_gridmajor; - Vector3 color_gridblock; - Vector3 color_gridtext; - Vector3 color_brushes; - Vector3 color_selbrushes; - Vector3 color_clipper; - Vector3 color_viewname; - Vector3 color_gridminor_alt; - Vector3 color_gridmajor_alt; - Vector3 AxisColorX; - Vector3 AxisColorY; - Vector3 AxisColorZ; - - bool m_bRightClick; - bool m_bNoStipple; - - xywindow_globals_t() : - color_gridback( 1.f, 1.f, 1.f ), - color_gridminor( 0.75f, 0.75f, 0.75f ), - color_gridmajor( 0.5f, 0.5f, 0.5f ), - color_gridblock( 0.f, 0.f, 1.f ), - color_gridtext( 0.f, 0.f, 0.f ), - color_brushes( 0.f, 0.f, 0.f ), - color_selbrushes( 1.f, 0.f, 0.f ), - color_clipper( 0.f, 0.f, 1.f ), - color_viewname( 0.5f, 0.f, 0.75f ), - color_gridminor_alt( 0.f, 0.f, 0.f ), - color_gridmajor_alt( 0.f, 0.f, 0.f ), - - AxisColorX( 1.f, 0.f, 0.f ), - AxisColorY( 0.f, 1.f, 0.f ), - AxisColorZ( 0.f, 0.f, 1.f ), - m_bRightClick( true ), - m_bNoStipple( false ){ - } +struct xywindow_globals_t { + Vector3 color_gridback; + Vector3 color_gridminor; + Vector3 color_gridmajor; + Vector3 color_gridblock; + Vector3 color_gridtext; + Vector3 color_brushes; + Vector3 color_selbrushes; + Vector3 color_clipper; + Vector3 color_viewname; + Vector3 color_gridminor_alt; + Vector3 color_gridmajor_alt; + Vector3 AxisColorX; + Vector3 AxisColorY; + Vector3 AxisColorZ; + + bool m_bRightClick; + bool m_bNoStipple; + + xywindow_globals_t() : + color_gridback(1.f, 1.f, 1.f), + color_gridminor(0.75f, 0.75f, 0.75f), + color_gridmajor(0.5f, 0.5f, 0.5f), + color_gridblock(0.f, 0.f, 1.f), + color_gridtext(0.f, 0.f, 0.f), + color_brushes(0.f, 0.f, 0.f), + color_selbrushes(1.f, 0.f, 0.f), + color_clipper(0.f, 0.f, 1.f), + color_viewname(0.5f, 0.f, 0.75f), + color_gridminor_alt(0.f, 0.f, 0.f), + color_gridmajor_alt(0.f, 0.f, 0.f), + + AxisColorX(1.f, 0.f, 0.f), + AxisColorY(0.f, 1.f, 0.f), + AxisColorZ(0.f, 0.f, 1.f), + m_bRightClick(true), + m_bNoStipple(false) + { + } }; @@ -279,17 +343,22 @@ extern xywindow_globals_t g_xywindow_globals; VIEWTYPE GlobalXYWnd_getCurrentViewType(); -void XY_Top_Shown_Construct( ui::Window parent ); -void YZ_Side_Shown_Construct( ui::Window parent ); -void XZ_Front_Shown_Construct( ui::Window parent ); +void XY_Top_Shown_Construct(ui::Window parent); + +void YZ_Side_Shown_Construct(ui::Window parent); + +void XZ_Front_Shown_Construct(ui::Window parent); void XYWindow_Construct(); + void XYWindow_Destroy(); void WXY_Print(); + void WXY_BackgroundSelect(); void XYShow_registerCommands(); + void XYWnd_registerShortcuts(); #endif