binds...
	* m2 drag in cam = sideways+updownways strafemode; do not enter/quit freelook, if long button press (>300ms)
	* m1 drag in freelook = sideways+updownways strafemode (mainly for visual editing)
	* ctrl + m3/drag = seamless brush face to face texture paste; works for any faces in BP mode, only axial ones in AP
	* ctrl + shift + a: select all visible brush faces and curves, textured by selected shader
		(more obvious way, than existing ones: components mode::faces->shift+a and find/replace to empty)
	* shift during creating brush = quadratic brush
	* drag clipper point + shift = constrain to axis with biggest move amount

misc...
	* -gamedetect command line option to enable game detection
	* don't disable aero by default; -aero command line option disables one
	* "Don't show" (during session) checkbox in Light Intensity dialog
	* fix: show-grid toggle hides grid, when snap-to-grid is off too
	* region mode: draw out of region part of grid in subtle style
	texbro tags button png icon
This commit is contained in:
Garux 2017-08-02 09:42:58 +03:00
parent 7e36f12449
commit 9613511560
18 changed files with 393 additions and 132 deletions

View File

@ -663,6 +663,7 @@ void TexMatToFakeTexCoords( const brushprimit_texdef_t& bp_texdef, texdef_t& tex
// compute back the texture matrix from fake shift scale rot
void FakeTexCoordsToTexMat( const texdef_t& texdef, brushprimit_texdef_t& bp_texdef ){
#if 1
double r = degrees_to_radians( -texdef.rotate );
double c = cos( r );
double s = sin( r );
@ -674,6 +675,20 @@ void FakeTexCoordsToTexMat( const texdef_t& texdef, brushprimit_texdef_t& bp_tex
bp_texdef.coords[1][1] = static_cast<float>( y * c );
bp_texdef.coords[0][2] = -texdef.shift[0];
bp_texdef.coords[1][2] = texdef.shift[1];
#else
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<float>( x * c );
bp_texdef.coords[1][0] = static_cast<float>( -y * s );
bp_texdef.coords[0][1] = static_cast<float>( x * s );
bp_texdef.coords[1][1] = static_cast<float>( y * c );
bp_texdef.coords[0][2] = -texdef.shift[0];
bp_texdef.coords[1][2] = texdef.shift[1];
#endif
// globalOutputStream() << "[ " << bp_texdef.coords[0][0] << " " << bp_texdef.coords[0][1] << " ][ " << bp_texdef.coords[1][0] << " " << bp_texdef.coords[1][1] << " ]\n";
}
#if 0 // texture locking (brush primit)
@ -1349,7 +1364,7 @@ void Texdef_transformLocked( TextureProjection& projection, std::size_t width, s
identity2stOriginal = matrix4_multiplied_by_matrix4( identity2stOriginal, identityCorrected );
}
else if( dot != dot ){ //catch QNAN: happens on scaling cuboid on Z and sometimes on rotating
else if( dot != dot ){ //catch QNAN: happens on scaling cuboid on Z and sometimes on rotating (in bp mode)
return;
}

View File

@ -579,7 +579,6 @@ void operator()( Face& face ) const {
class FaceFindShader
{
const char* m_find;
const char* m_replace;
public:
FaceFindShader( const char* find ) : m_find( find ){
}
@ -590,6 +589,10 @@ void operator()( FaceInstance& faceinst ) const {
}
};
void Scene_BrushFacesSelectByShader( scene::Graph& graph, const char* name ){
Scene_ForEachBrush_ForEachFaceInstance( graph, FaceFindShader( name ) );
}
bool DoingSearch( const char *repl ){
return ( repl == NULL || ( strcmp( "textures/", repl ) == 0 ) );
}

View File

@ -68,6 +68,7 @@ void Scene_BrushFindReplaceShader_Selected( scene::Graph& graph, const char* fin
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_BrushFacesSelectByShader( scene::Graph& graph, const char* name );
#include "itexdef.h"
template<typename Element> class BasicVector3;

View File

@ -320,6 +320,7 @@ void Camera_FreeMove( camera_t& camera, int dx, int dy ){
Camera_Freemove_updateAxes( camera );
}
#if 0
void Cam_MouseControl( camera_t& camera, int x, int y ){
// int xl, xh;
// int yl, yh;
@ -353,6 +354,7 @@ void Cam_MouseControl( camera_t& camera, int x, int y ){
Camera_updateModelview( camera );
}
#endif // 0
void Camera_mouseMove( camera_t& camera, int x, int y ){
//globalOutputStream() << "mousemove... ";
@ -655,17 +657,17 @@ void Camera_motionDelta( int x, int y, unsigned int state, void* data ){
cam->m_strafe = false;
break;
case 1:
cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0 && ( state & GDK_SHIFT_MASK ) == 0;
cam->m_strafe = ( ( state & GDK_CONTROL_MASK ) != 0 || ( state & GDK_BUTTON3_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 = ( ( state & GDK_CONTROL_MASK ) != 0 || ( state & GDK_BUTTON3_MASK ) != 0 ) && ( state & GDK_SHIFT_MASK ) == 0;
cam->m_strafe_forward = cam->m_strafe;
break;
case 4:
cam->m_strafe_forward_invert = true;
default:
cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0;
cam->m_strafe = ( state & GDK_CONTROL_MASK ) != 0 || ( state & GDK_BUTTON3_MASK ) != 0;
if ( cam->m_strafe ) {
cam->m_strafe_forward = ( state & GDK_SHIFT_MASK ) != 0;
}
@ -674,6 +676,11 @@ void Camera_motionDelta( int x, int y, unsigned int state, void* data ){
}
break;
}
if( ( state & GDK_BUTTON1_MASK ) != 0 ){
cam->m_strafe = true;
cam->m_strafe_forward = false;
}
}
@ -713,6 +720,7 @@ guint m_selection_button_release_handler;
guint m_selection_motion_handler;
guint m_freelook_button_press_handler;
guint m_freelook_button_release_handler;
guint m_sizeHandler;
guint m_exposeHandler;
@ -752,6 +760,7 @@ void Cam_ChangeFloor( bool up );
void DisableFreeMove();
void EnableFreeMove();
bool m_bFreeMove;
bool m_bFreeMove_entering;
CameraView& getCameraView(){
return m_cameraview;
@ -863,12 +872,13 @@ void context_menu(){
/* GDK_2BUTTON_PRESS doesn't always work in this case, so... */
bool context_menu_try( CamWnd* camwnd ){
//globalOutputStream() << camwnd->m_rightClickTimer.elapsed_msec() << "\n";
return camwnd->m_rightClickTimer.elapsed_msec() < 200;
return camwnd->m_rightClickTimer.elapsed_msec() < 250;
//doesn't work if cam redraw > 200msec (3x click works): gtk_widget_queue_draw proceeds after timer.start()
}
gboolean enable_freelook_button_press( GtkWidget* widget, GdkEventButton* event, CamWnd* camwnd ){
if ( event->type == GDK_BUTTON_PRESS && event->button == 3 && modifiers_for_state( event->state ) == c_modifierNone ) {
camwnd->m_bFreeMove_entering = true;
if( context_menu_try( camwnd ) ){
context_menu();
}
@ -883,9 +893,10 @@ gboolean enable_freelook_button_press( GtkWidget* widget, GdkEventButton* event,
gboolean disable_freelook_button_press( GtkWidget* widget, GdkEventButton* event, CamWnd* camwnd ){
if ( event->type == GDK_BUTTON_PRESS && event->button == 3 && modifiers_for_state( event->state ) == c_modifierNone ) {
camwnd->m_bFreeMove_entering = false;
bool doubleclicked = context_menu_try( camwnd );
camwnd->DisableFreeMove();
if( doubleclicked ){
camwnd->DisableFreeMove();
context_menu();
}
else{
@ -896,6 +907,17 @@ gboolean disable_freelook_button_press( GtkWidget* widget, GdkEventButton* event
return FALSE;
}
gboolean disable_freelook_button_release( GtkWidget* widget, GdkEventButton* event, CamWnd* camwnd ){
if ( event->type == GDK_BUTTON_RELEASE && event->button == 3 && modifiers_for_state( event->state ) == c_modifierNone ) {
if( ( camwnd->m_rightClickTimer.elapsed_msec() > 300 && camwnd->m_bFreeMove_entering ) ||
( camwnd->m_rightClickTimer.elapsed_msec() < 300 && !camwnd->m_bFreeMove_entering ) ){
camwnd->DisableFreeMove();
return TRUE;
}
}
return FALSE;
}
#if 0
gboolean mousecontrol_button_press( GtkWidget* widget, GdkEventButton* event, CamWnd* camwnd ){
if ( event->type == GDK_BUTTON_PRESS && event->button == 3 ) {
@ -1266,6 +1288,7 @@ void CamWnd_Add_Handlers_FreeMove( CamWnd& camwnd ){
camwnd.m_selection_motion_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "motion_notify_event", G_CALLBACK( DeferredMotion::gtk_motion ), &camwnd.m_deferred_motion_freemove );
camwnd.m_freelook_button_press_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "button_press_event", G_CALLBACK( disable_freelook_button_press ), &camwnd );
camwnd.m_freelook_button_release_handler = g_signal_connect( G_OBJECT( camwnd.m_gl_widget ), "button_release_event", G_CALLBACK( disable_freelook_button_release ), &camwnd );
KeyEvent_connect( "CameraFreeMoveForward" );
KeyEvent_connect( "CameraFreeMoveBack" );
@ -1304,6 +1327,7 @@ void CamWnd_Remove_Handlers_FreeMove( CamWnd& camwnd ){
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_release_handler );
}
CamWnd::CamWnd() :
@ -1320,6 +1344,7 @@ CamWnd::CamWnd() :
m_selection_button_release_handler( 0 ),
m_selection_motion_handler( 0 ),
m_freelook_button_press_handler( 0 ),
m_freelook_button_release_handler( 0 ),
m_drawing( false ){
m_bFreeMove = false;

View File

@ -104,17 +104,16 @@ bool gamedetect_check_game( const char *gamefile, const char *checkfile1, const
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;
bool nogamedetect = true;
bool gamedetect = 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;
for ( i = 1; i < g_argc; ++i ){
if ( !strcmp( g_argv[i], "-gamedetect" ) ) {
gamedetect = true;
//nogamedetect = !strcmp( g_argv[i + 1], "false" );
break;
}
if ( !nogamedetect ) {
}
if ( gamedetect ) {
static char buf[1024 + 64];
strncpy( buf, environment_get_app_path(), sizeof( buf ) );
buf[sizeof( buf ) - 1 - 64] = 0;

View File

@ -904,8 +904,18 @@ static void DoGtkTextEditor( const char* filename, guint cursorpos, int length )
// =============================================================================
// Light Intensity dialog
#include <gtk/gtkcheckbutton.h>
bool g_dontDoLightIntensityDlg = false;
void dontDoLightIntensityDlg_toggled( GtkToggleButton* togglebutton, gpointer user_data ){
g_dontDoLightIntensityDlg = gtk_toggle_button_get_active( togglebutton );
}
EMessageBoxReturn DoLightIntensityDlg( int *intensity ){
if( g_dontDoLightIntensityDlg ){
return eIDOK;
}
ModalDialog dialog;
GtkEntry* intensity_entry;
ModalDialogButton ok_button( dialog, eIDOK );
@ -936,6 +946,13 @@ EMessageBoxReturn DoLightIntensityDlg( int *intensity ){
intensity_entry = entry;
}
{
GtkWidget* check = gtk_check_button_new_with_label( "Don't Show" );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( check ), FALSE );
gtk_widget_show( check );
gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 );
g_signal_connect( G_OBJECT( check ), "toggled", G_CALLBACK( dontDoLightIntensityDlg_toggled ), 0 );
}
}
{
GtkVBox* vbox = create_dialog_vbox( 4 );

View File

@ -564,25 +564,26 @@ int main( int argc, char* argv[] ){
streams_init();
#ifdef WIN32
HMODULE lib;
lib = LoadLibrary( "dwmapi.dll" );
if ( lib != 0 ) {
void ( WINAPI *qDwmEnableComposition )( bool bEnable ) = ( void (WINAPI *) ( bool bEnable ) )GetProcAddress( lib, "DwmEnableComposition" );
if ( qDwmEnableComposition ) {
bool Aero = false;
for ( int i = 1; i < argc; ++i ){
if ( !stricmp( argv[i], "-aero" ) ){
Aero = true;
qDwmEnableComposition( TRUE );
break;
}
}
// disable Aero
if ( !Aero ){
qDwmEnableComposition( FALSE );
{
bool aero = true;
for ( int i = 1; i < argc; ++i ){
if ( !stricmp( argv[i], "-aero" ) ){
aero = false;
break;
}
}
if( !aero ){
HMODULE lib;
lib = LoadLibrary( "dwmapi.dll" );
if ( lib != 0 ) {
void ( WINAPI *qDwmEnableComposition )( bool bEnable ) = ( void (WINAPI *) ( bool bEnable ) )GetProcAddress( lib, "DwmEnableComposition" );
if ( qDwmEnableComposition ) {
// disable Aero
qDwmEnableComposition( FALSE );
}
FreeLibrary( lib );
}
}
FreeLibrary( lib );
}
_setmaxstdio(2048);
#endif

View File

@ -1987,6 +1987,7 @@ GtkMenuItem* create_edit_menu(){
// menu_tearoff( convert_menu );
// }
create_menu_item_with_mnemonic( menu, "Select All Of Type", "SelectAllOfType" );
create_menu_item_with_mnemonic( menu, "Select Textured", "SelectTextured" );
create_menu_item_with_mnemonic( menu, "_Expand Selection To Primitives", "ExpandSelectionToPrimitives" );
create_menu_item_with_mnemonic( menu, "_Expand Selection To Entities", "ExpandSelectionToEntities" );
create_menu_item_with_mnemonic( menu, "Select Connected Entities", "SelectConnectedEntities" );

View File

@ -1448,13 +1448,13 @@ void ConstructRegionStartpoint( scene::Node* startpoint, const Vector3& region_m
===========================================================
*/
bool region_active = false;
bool g_region_active = false;
BoolExportCaller g_region_caller( region_active );
BoolExportCaller g_region_caller( g_region_active );
ToggleItem g_region_item( g_region_caller );
Vector3 region_mins( g_MinWorldCoord, g_MinWorldCoord, g_MinWorldCoord );
Vector3 region_maxs( g_MaxWorldCoord, g_MaxWorldCoord, g_MaxWorldCoord );
Vector3 g_region_mins( g_MinWorldCoord, g_MinWorldCoord, g_MinWorldCoord );
Vector3 g_region_maxs( g_MaxWorldCoord, g_MaxWorldCoord, g_MaxWorldCoord );
scene::Node* region_sides[6];
scene::Node* region_startpoint = 0;
@ -1479,8 +1479,8 @@ void AddRegionBrushes( void ){
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, g_region_mins, g_region_maxs );
ConstructRegionStartpoint( region_startpoint, g_region_mins, g_region_maxs );
Node_getTraversable( GlobalSceneGraph().root() )->insert( NodeSmartReference( *region_startpoint ) );
}
@ -1553,7 +1553,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
(
aabb_intersects_aabb(
instance.worldAABB(),
aabb_for_minmax( region_mins, region_maxs )
aabb_for_minmax( g_region_mins, g_region_maxs )
) != 0
) ^ m_exclude
)
@ -1575,21 +1575,21 @@ void Scene_Exclude_Region( bool exclude ){
===========
*/
void Map_RegionOff(){
region_active = false;
g_region_active = false;
g_region_item.update();
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;
g_region_maxs[0] = g_MaxWorldCoord - 64;
g_region_mins[0] = g_MinWorldCoord + 64;
g_region_maxs[1] = g_MaxWorldCoord - 64;
g_region_mins[1] = g_MinWorldCoord + 64;
g_region_maxs[2] = g_MaxWorldCoord - 64;
g_region_mins[2] = g_MinWorldCoord + 64;
Scene_Exclude_All( false );
}
void Map_ApplyRegion( void ){
region_active = true;
g_region_active = true;
g_region_item.update();
Scene_Exclude_Region( false );
@ -1606,9 +1606,9 @@ void Map_RegionSelectedBrushes( void ){
if ( GlobalSelectionSystem().countSelected() != 0
&& GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) {
region_active = true;
g_region_active = true;
g_region_item.update();
Select_GetBounds( region_mins, region_maxs );
Select_GetBounds( g_region_mins, g_region_maxs );
Scene_Exclude_Selected( false );
@ -1625,12 +1625,12 @@ void Map_RegionSelectedBrushes( void ){
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;
g_region_mins[0] = x_min;
g_region_maxs[0] = x_max;
g_region_mins[1] = y_min;
g_region_maxs[1] = y_max;
g_region_mins[2] = g_MinWorldCoord + 64;
g_region_maxs[2] = g_MaxWorldCoord - 64;
Map_ApplyRegion();
}
@ -1638,8 +1638,8 @@ void Map_RegionXY( float x_min, float y_min, float x_max, float y_max ){
void Map_RegionBounds( const AABB& bounds ){
Map_RegionOff();
region_mins = vector3_subtracted( bounds.origin, bounds.extents );
region_maxs = vector3_added( bounds.origin, bounds.extents );
g_region_mins = vector3_subtracted( bounds.origin, bounds.extents );
g_region_maxs = vector3_added( bounds.origin, bounds.extents );
deleteSelection();

View File

@ -95,8 +95,8 @@ scene::Node& Map_FindOrInsertWorldspawn( Map& map );
template<typename Element> class BasicVector3;
typedef BasicVector3<float> Vector3;
extern Vector3 region_mins, region_maxs;
extern bool region_active;
extern Vector3 g_region_mins, g_region_maxs;
extern bool g_region_active;
// used to be #defines, multiple engine support suggests we should go towards dynamic
extern float g_MaxWorldCoord;

View File

@ -171,7 +171,7 @@ void bsp_init(){
build_set_variable( "BspFile", name.c_str() );
}
if( region_active ){
if( g_region_active ){
StringOutputStream name( 256 );
name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".reg";
build_set_variable( "MapFile", name.c_str() );
@ -240,7 +240,7 @@ bool Region_cameraValid(){
for ( int i = 0 ; i < 3 ; i++ )
{
if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) {
if ( vOrig[i] > g_region_maxs[i] || vOrig[i] < g_region_mins[i] ) {
return false;
}
}
@ -251,7 +251,7 @@ bool Region_cameraValid(){
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() ) {
if ( g_region_active && !Region_cameraValid() ) {
globalErrorStream() << "The camera must be in the region to start a region compile.\n";
return;
}
@ -267,7 +267,7 @@ void RunBSP( const char* name ){
Map_Snapshot();
}
if ( region_active ) {
if ( g_region_active ) {
const char* mapname = Map_Name( g_map );
StringOutputStream name( 256 );
name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".reg";

View File

@ -868,6 +868,11 @@ void Select_AllOfType(){
}
}
void Select_FacesAndPatchesByShader(){
Scene_BrushFacesSelectByShader( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) );
Scene_PatchSelectByShader( GlobalSceneGraph(), TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) );
}
void Select_Inside( void ){
SelectByBounds<SelectionPolicy_Inside>::DoSelection();
}
@ -1079,6 +1084,8 @@ void Select_registerCommands(){
GlobalCommands_insert( "RotateSelectionClockwise", FreeCaller<Selection_RotateClockwise>() );
GlobalCommands_insert( "RotateSelectionAnticlockwise", FreeCaller<Selection_RotateAnticlockwise>() );
GlobalCommands_insert( "SelectTextured", FreeCaller<Select_FacesAndPatchesByShader>(), Accelerator( 'A', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
}

View File

@ -4080,14 +4080,14 @@ 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_texture2_seamless = c_modifierControl;
const ModifierFlags c_modifier_apply_texture3 = c_modifierShift;
const ModifierFlags c_modifier_copy_texture = c_modifierNone;
void Scene_copyClosestTexture( SelectionTest& test );
void Scene_applyClosestTexture( SelectionTest& test );
void Scene_applyClosestTexture( SelectionTest& test, bool seamless );
class TexManipulator_
{
@ -4105,10 +4105,10 @@ void mouseDown( DeviceVector position ){
ConstructSelectionTest( scissored, SelectionBoxForPoint( &position[0], &m_epsilon[0] ) );
SelectionVolume volume( scissored );
if ( m_state == c_modifier_apply_texture1 || m_state == c_modifier_apply_texture2 || m_state == c_modifier_apply_texture3 ) {
if ( m_state == c_modifier_apply_texture1 || m_state == c_modifier_apply_texture2_seamless || m_state == c_modifier_apply_texture3 ) {
m_undo_begun = true;
GlobalUndoSystem().start();
Scene_applyClosestTexture( volume );
Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless );
}
else if ( m_state == c_modifier_copy_texture ) {
Scene_copyClosestTexture( volume );
@ -4121,7 +4121,7 @@ void mouseMoved( DeviceVector position ){
ConstructSelectionTest( scissored, SelectionBoxForPoint( &device_constrained( position )[0], &m_epsilon[0] ) );
SelectionVolume volume( scissored );
Scene_applyClosestTexture( volume );
Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless );
}
}
typedef MemberCaller1<TexManipulator_, DeviceVector, &TexManipulator_::mouseMoved> MouseMovedCaller;

View File

@ -1362,13 +1362,132 @@ void SurfaceInspector::ApplyFlags(){
}
class FaceTexture
{
public:
TextureProjection m_projection;
ContentsFlagsValue m_flags;
Plane3 m_plane;
std::size_t m_width;
std::size_t m_height;
FaceTexture() : m_plane( 0, 0, 1, 0 ), m_width( 64 ), m_height( 64 ) {
}
};
FaceTexture g_faceTextureClipboard;
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 Face_getTexture( Face& face, CopiedString& shader, TextureProjection& projection, ContentsFlagsValue& flags ){
shader = face.GetShader();
face.GetTexdef( projection );
flags = face.getShader().m_flags;
g_faceTextureClipboard.m_plane = face.getPlane().plane3();
g_faceTextureClipboard.m_width = face.getShader().width();
g_faceTextureClipboard.m_height = face.getShader().height();
}
typedef Function4<Face&, CopiedString&, TextureProjection&, ContentsFlagsValue&, void, Face_getTexture> FaceGetTexture;
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;
}
/// \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;
}
void Face_setTexture_Seamless( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
face.SetShader( shader );
DoubleLine line = plane3_intersect_plane3( g_faceTextureClipboard.m_plane, face.getPlane().plane3() );
Quaternion rotation = Quaternion( vector3_cross( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ), static_cast<float>( 1.0 + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ) ) );
//Quaternion rotation = quaternion_for_unit_vectors( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() );
//rotation.w() = sqrt( vector3_length_squared( g_faceTextureClipboard.m_plane.normal() ) * vector3_length_squared( face.getPlane().plane3().normal() ) ) + vector3_dot( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() );
//globalOutputStream() << "rotation: " << rotation.x() << " " << rotation.y() << " " << rotation.z() << " " << rotation.w() << " " << "\n";
//quaternion_normalise( rotation );
const double n = ( 1.0 / sqrt( rotation[0] * rotation[0] + rotation[1] * rotation[1] + rotation[2] * rotation[2] + rotation[3] * rotation[3] ) );
rotation = Quaternion(
static_cast<float>( rotation[0] * n ),
static_cast<float>( rotation[1] * n ),
static_cast<float>( rotation[2] * n ),
static_cast<float>( rotation[3] * n )
);
//globalOutputStream() << "rotation: " << rotation.x() << " " << rotation.y() << " " << rotation.z() << " " << rotation.w() << " " << "\n";
Matrix4 transform = g_matrix4_identity;
matrix4_pivoted_rotate_by_quaternion( transform, rotation, line.origin );
// Matrix4 transform = matrix4_rotation_for_quaternion_quantised( rotation );
// Vector3 translation;
// translation_for_pivoted_matrix_transform( translation, transform, line.origin );
// transform.tx() = translation.x();
// transform.ty() = translation.y();
// transform.tz() = translation.z();
//globalOutputStream() << "transform: " << transform << "\n";
TextureProjection proj = projection;
Texdef_transformLocked( proj, g_faceTextureClipboard.m_width, g_faceTextureClipboard.m_height, g_faceTextureClipboard.m_plane, transform );
//face.SetTexdef( projection );
face.SetTexdef( proj );
face.SetFlags( flags );
g_faceTextureClipboard.m_plane = face.getPlane().plane3();
g_faceTextureClipboard.m_projection = proj;
}
typedef Function4<Face&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Face_setTexture_Seamless> FaceSetTextureSeamless;
void Face_setTexture( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
face.SetShader( shader );
face.SetTexdef( projection );
@ -1400,7 +1519,7 @@ struct Texturable
};
void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable ){
void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable, bool seamless ){
if ( face.isFiltered() ) {
return;
}
@ -1409,7 +1528,10 @@ void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& be
if ( intersection.valid()
&& SelectionIntersection_closer( intersection, bestIntersection ) ) {
bestIntersection = intersection;
texturable.setTexture = makeCallback3( FaceSetTexture(), face );
if( seamless )
texturable.setTexture = makeCallback3( FaceSetTextureSeamless(), face );
else
texturable.setTexture = makeCallback3( FaceSetTexture(), face );
texturable.getTexture = makeCallback3( FaceGetTexture(), face );
}
}
@ -1439,9 +1561,10 @@ class BrushGetClosestFaceVisibleWalker : public scene::Graph::Walker
{
SelectionTest& m_test;
Texturable& m_texturable;
bool m_seamless;
mutable SelectionIntersection m_bestIntersection;
public:
BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable ) : m_test( test ), m_texturable( texturable ){
BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable, bool seamless ) : m_test( test ), m_texturable( texturable ), m_seamless( seamless ){
}
bool pre( const scene::Path& path, scene::Instance& instance ) const {
if ( path.top().get().visible() ) {
@ -1451,7 +1574,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
for ( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i )
{
Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable );
Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable, m_seamless );
}
}
else
@ -1482,9 +1605,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
}
};
Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test ){
Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test, bool seamless = false ){
Texturable texturable;
graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable ) );
graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable, seamless ) );
return texturable;
}
@ -1497,32 +1620,13 @@ bool Scene_getClosestTexture( scene::Graph& graph, SelectionTest& test, CopiedSt
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 );
void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags, bool seamless ){
Texturable texturable = Scene_getClosestTexturable( graph, test, seamless );
if ( texturable.setTexture != SetTextureCallback() ) {
texturable.setTexture( shader, projection, flags );
}
}
class FaceTexture
{
public:
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 TextureClipboard_textureSelected( const char* shader ){
FaceTextureClipboard_setDefault();
}
class TextureBrowser;
extern TextureBrowser g_TextureBrowser;
void TextureBrowser_SetSelectedShader( TextureBrowser& textureBrowser, const char* shader );
@ -1535,12 +1639,12 @@ void Scene_copyClosestTexture( SelectionTest& test ){
}
}
void Scene_applyClosestTexture( SelectionTest& test ){
void Scene_applyClosestTexture( SelectionTest& test, bool seamless ){
// UndoableCommand command( "facePaintTexture" );
Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags );
Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags, seamless );
//SceneChangeNotify();
SceneChangeNotify();
}

View File

@ -2288,10 +2288,10 @@ GtkWidget* TextureBrowser_constructWindow( GtkWindow* toplevel ){
//gtk_menu_bar_append( GTK_MENU_BAR( menu_bar ), tags_item );
GtkButton* button = GTK_BUTTON( gtk_button_new() );
//button_set_icon( button, "texbro_tags.png" );
GtkWidget *label = gtk_label_new (">t");
gtk_container_add (GTK_CONTAINER (button), label);
gtk_widget_show (label);
button_set_icon( button, "texbro_tags.png" );
// GtkWidget *label = gtk_label_new (">t");
// gtk_container_add (GTK_CONTAINER (button), label);
// gtk_widget_show (label);
gtk_widget_show( GTK_WIDGET( button ) );
gtk_button_set_relief( button, GTK_RELIEF_NONE );

View File

@ -83,6 +83,7 @@ class ClipPoint
{
public:
Vector3 m_ptClip; // the 3d point
Vector3 m_ptStart;
bool m_bSet;
ClipPoint(){
@ -308,15 +309,15 @@ bool ClipMode(){
void NewClipPoint( const Vector3& point ){
if ( g_Clip1.Set() == false ) {
g_Clip1.m_ptClip = point;
g_Clip1.m_ptClip = g_Clip1.m_ptStart = point;
g_Clip1.Set( true );
}
else if ( g_Clip2.Set() == false ) {
g_Clip2.m_ptClip = point;
g_Clip2.m_ptClip = g_Clip2.m_ptStart = point;
g_Clip2.Set( true );
}
else if ( g_Clip3.Set() == false ) {
g_Clip3.m_ptClip = point;
g_Clip3.m_ptClip = g_Clip3.m_ptStart = point;
g_Clip3.Set( true );
}
else
@ -324,7 +325,7 @@ void NewClipPoint( const Vector3& point ){
g_Clip1.Reset();
g_Clip2.Reset();
g_Clip3.Reset();
g_Clip1.m_ptClip = point;
g_Clip1.m_ptClip = g_Clip1.m_ptStart = point;
g_Clip1.Set( true );
}
@ -1000,14 +1001,27 @@ void XYWnd::Clipper_OnLButtonDown( int x, int y ){
void XYWnd::Clipper_OnLButtonUp( int x, int y ){
if ( g_pMovingClip ) {
g_pMovingClip->m_ptStart = g_pMovingClip->m_ptClip;
g_pMovingClip = 0;
}
}
void XYWnd::Clipper_OnMouseMoved( int x, int y ){
void XYWnd::Clipper_OnMouseMoved( int x, int y, bool snap ){
if ( g_pMovingClip ) {
XY_ToPoint( x, y, g_pMovingClip->m_ptClip );
XY_SnapToGrid( g_pMovingClip->m_ptClip );
if( snap ){
Vector3 diff = g_pMovingClip->m_ptClip - g_pMovingClip->m_ptStart;
int largest_index = ( fabs( diff[1] ) > fabs( diff[0] ) )
? ( fabs( diff[1] ) > fabs( diff[2] ) )
? 1
: 2
: ( fabs( diff[0] ) > fabs( diff[2] ) )
? 0
: 2;
g_pMovingClip->m_ptClip[( largest_index + 1 ) % 3] = g_pMovingClip->m_ptStart[( largest_index + 1 ) % 3];
g_pMovingClip->m_ptClip[( largest_index + 2 ) % 3] = g_pMovingClip->m_ptStart[( largest_index + 2 ) % 3];
}
Clip_Update();
}
}
@ -1143,7 +1157,7 @@ void XYWnd::NewBrushDrag_End( int x, int y ){
}
}
void XYWnd::NewBrushDrag( int x, int y ){
void XYWnd::NewBrushDrag( int x, int y, bool square ){
Vector3 mins, maxs;
XY_ToPoint( m_nNewBrushPressx, m_nNewBrushPressy, mins );
XY_SnapToGrid( mins );
@ -1159,6 +1173,12 @@ void XYWnd::NewBrushDrag( int x, int y ){
maxs[nDim] = mins[nDim] + GetGridSize();
}
if( square ){
float squaresize = std::max( fabs( maxs[(nDim + 1) % 3] - mins[(nDim + 1) % 3] ), fabs( maxs[(nDim + 2) % 3] - mins[(nDim + 2) % 3] ) );
maxs[(nDim + 1) % 3] = ( maxs[(nDim + 1) % 3] - mins[(nDim + 1) % 3] ) > 0.f ? ( mins[(nDim + 1) % 3] + squaresize ) : ( mins[(nDim + 1) % 3] - squaresize );
maxs[(nDim + 2) % 3] = ( maxs[(nDim + 2) % 3] - mins[(nDim + 2) % 3] ) > 0.f ? ( mins[(nDim + 2) % 3] + squaresize ) : ( mins[(nDim + 2) % 3] - squaresize );
}
for ( int i = 0 ; i < 3 ; i++ )
{
if ( mins[i] == maxs[i] ) {
@ -1520,8 +1540,8 @@ void XYWnd::XY_MouseUp( int x, int y, unsigned int buttons ){
else if ( m_zoom_started ) {
Zoom_End();
}
else if ( ( ClipMode() && ( buttons == Clipper_buttons() || buttons == Clipper_quick_buttons() ) ) ||
g_clipper_doubleclicked ){
else if ( ( ClipMode() && ( buttons == Clipper_buttons() || buttons == Clipper_quick_buttons() || g_pMovingClip ) ) ||
g_clipper_doubleclicked ){ // handle mouse release, if quit quick clipper mode via doubleclick
Clipper_OnLButtonUp( x, y );
g_clipper_doubleclicked = false;
}
@ -1548,11 +1568,11 @@ void XYWnd::XY_MouseMoved( int x, int y, unsigned int buttons ){
}
else if ( ClipMode() && g_pMovingClip != 0 ) {
Clipper_OnMouseMoved( x, y );
Clipper_OnMouseMoved( x, y, buttons & RAD_SHIFT );
}
// lbutton without selection = drag new brush
else if ( m_bNewBrushDrag ) {
NewBrushDrag( x, y );
NewBrushDrag( x, y, buttons == ( RAD_LBUTTON | RAD_SHIFT ) );
}
// control mbutton = move camera
@ -1961,26 +1981,26 @@ void XYWnd::XY_DrawGrid( void ) {
const int nDim2 = ( m_viewType == XY ) ? 1 : 2;
xb = m_vOrigin[nDim1] - w;
if ( xb < region_mins[nDim1] ) {
xb = region_mins[nDim1];
if ( xb < g_region_mins[nDim1] ) {
xb = g_region_mins[nDim1];
}
xb = step * floor( xb / step );
xe = m_vOrigin[nDim1] + w;
if ( xe > region_maxs[nDim1] ) {
xe = region_maxs[nDim1];
if ( xe > g_region_maxs[nDim1] ) {
xe = g_region_maxs[nDim1];
}
xe = step * ceil( xe / step );
yb = m_vOrigin[nDim2] - h;
if ( yb < region_mins[nDim2] ) {
yb = region_mins[nDim2];
if ( yb < g_region_mins[nDim2] ) {
yb = g_region_mins[nDim2];
}
yb = step * floor( yb / step );
ye = m_vOrigin[nDim2] + h;
if ( ye > region_maxs[nDim2] ) {
ye = region_maxs[nDim2];
if ( ye > g_region_maxs[nDim2] ) {
ye = g_region_maxs[nDim2];
}
ye = step * ceil( ye / step );
@ -1991,7 +2011,7 @@ void XYWnd::XY_DrawGrid( void ) {
// djbob
// draw minor blocks
if ( g_xywindow_globals_private.d_showgrid || a < 1.0f ) {
if ( g_xywindow_globals_private.d_showgrid /*|| a < 1.0f*/ ) {
if ( a < 1.0f ) {
glEnable( GL_BLEND );
}
@ -2036,6 +2056,74 @@ void XYWnd::XY_DrawGrid( void ) {
if ( a < 1.0f ) {
glDisable( GL_BLEND );
}
if( g_region_active ){
float xb_, xe_, yb_, ye_;
xb_ = m_vOrigin[nDim1] - w;
if ( xb_ < g_MinWorldCoord ) {
xb_ = g_MinWorldCoord;
}
xb_ = step * floor( xb_ / step );
xe_ = m_vOrigin[nDim1] + w;
if ( xe_ > g_MaxWorldCoord ) {
xe_ = g_MaxWorldCoord;
}
xe_ = step * ceil( xe_ / step );
yb_ = m_vOrigin[nDim2] - h;
if ( yb_ < g_MinWorldCoord ) {
yb_ = g_MinWorldCoord;
}
yb_ = step * floor( yb_ / step );
ye_ = m_vOrigin[nDim2] + h;
if ( ye_ > g_MaxWorldCoord ) {
ye_ = g_MaxWorldCoord;
}
ye_ = step * ceil( ye_ / step );
glEnable( GL_BLEND );
// draw minor blocks
if ( COLORS_DIFFER( g_xywindow_globals.color_gridminor, g_xywindow_globals.color_gridback ) ) {
glColor4fv( vector4_to_array( Vector4( g_xywindow_globals.color_gridminor, .5f ) ) );
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, .5f ) ) );
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();
}
glDisable( GL_BLEND );
}
}
// draw coordinate text if needed
@ -2123,26 +2211,26 @@ void XYWnd::XY_DrawBlockGrid(){
int nDim2 = ( m_viewType == XY ) ? 1 : 2;
xb = m_vOrigin[nDim1] - w;
if ( xb < region_mins[nDim1] ) {
xb = region_mins[nDim1];
if ( xb < g_region_mins[nDim1] ) {
xb = g_region_mins[nDim1];
}
xb = static_cast<float>( 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];
if ( xe > g_region_maxs[nDim1] ) {
xe = g_region_maxs[nDim1];
}
xe = static_cast<float>( 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];
if ( yb < g_region_mins[nDim2] ) {
yb = g_region_mins[nDim2];
}
yb = static_cast<float>( 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];
if ( ye > g_region_maxs[nDim2] ) {
ye = g_region_maxs[nDim2];
}
ye = static_cast<float>( g_xywindow_globals_private.blockSize * ceil( ye / g_xywindow_globals_private.blockSize ) );

View File

@ -118,7 +118,7 @@ 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( int x, int y, bool square );
void NewBrushDrag_End( int x, int y );
void XY_ToPoint( int x, int y, Vector3& point );
@ -158,7 +158,7 @@ void UpdateCameraIcon();
void Clipper_OnLButtonDown( int x, int y );
void Clipper_OnLButtonUp( int x, int y );
void Clipper_OnMouseMoved( int x, int y );
void Clipper_OnMouseMoved( int x, int y, bool snap );
void Clipper_Crosshair_OnMouseMoved( int x, int y );
void DropClipPoint( int pointx, int pointy );

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B