* m3: copy texture name, alignment +new: color, light power, color
	* alt + m3/drag: paste texture name (to pointed and selected stuff)
	* shift + m3/drag: paste texture name, alignment +new: light power
	* ctrl + m3/drag: paste texture seamlessly between brush faces +new: light color
	* ctrl + shift + m3/drag: project texture from copied brush face +new: paste light power, color
	* alt + ctrl/shift/ctrl+shift + m3/drag: respective texture alignment paste w/o texture name
fix void NormalizeColor( Vector3& color )
fix: reset texture clipboard texdef on selection in texbro (was only resetting scales)
This commit is contained in:
Garux 2018-08-11 23:36:50 +03:00
parent 7908a2b593
commit 3706e1131a
9 changed files with 296 additions and 123 deletions

View File

@ -187,6 +187,33 @@ void* getEnvironment() const {
} }
}; };
template<typename Caller>
class BindFirstOpaque4
{
typedef typename Caller::first_argument_type FirstBound;
FirstBound firstBound;
public:
typedef typename Caller::second_argument_type first_argument_type;
typedef typename Caller::third_argument_type second_argument_type;
typedef typename Caller::fourth_argument_type third_argument_type;
typedef typename Caller::fifth_argument_type fourth_argument_type;
typedef typename Caller::result_type result_type;
explicit BindFirstOpaque4( FirstBound firstBound ) : firstBound( firstBound ){
}
result_type operator()( first_argument_type a1, second_argument_type a2, third_argument_type a3, fourth_argument_type a4 ) const {
return Caller::call( firstBound, a1, a2, a3, a4 );
}
FirstBound getBound() const {
return firstBound;
}
static result_type thunk( void* environment, first_argument_type a1, second_argument_type a2, third_argument_type a3, fourth_argument_type a4 ){
return Caller::call( ConvertFromOpaque<FirstBound>::apply( environment ), a1, a2, a3, a4 );
}
void* getEnvironment() const {
return convertToOpaque( firstBound );
}
};
template<typename Thunk_> template<typename Thunk_>
class CallbackBase class CallbackBase
{ {
@ -393,6 +420,62 @@ inline Callback3<
} }
/// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and four other arguments.
///
template<typename FirstArgument, typename SecondArgument, typename ThirdArgument, typename FourthArgument, typename Result>
class Callback4 : public CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument, ThirdArgument, FourthArgument )>
{
typedef CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument, ThirdArgument, FourthArgument )> Base;
static Result nullThunk( void*, FirstArgument, SecondArgument, ThirdArgument, FourthArgument ){
}
public:
typedef FirstArgument first_argument_type;
typedef SecondArgument second_argument_type;
typedef ThirdArgument third_argument_type;
typedef FourthArgument fourth_argument_type;
typedef Result result_type;
Callback4() : Base( 0, nullThunk ){
}
template<typename Caller>
Callback4( const BindFirstOpaque4<Caller>& caller ) : Base( caller.getEnvironment(), BindFirstOpaque4<Caller>::thunk ){
}
Callback4( void* environment, typename Base::Thunk function ) : Base( environment, function ){
}
result_type operator()( FirstArgument firstArgument, SecondArgument secondArgument, ThirdArgument thirdArgument, FourthArgument fourthArgument ) const {
return Base::getThunk() ( Base::getEnvironment(), firstArgument, secondArgument, thirdArgument, fourthArgument );
}
};
template<typename Caller>
inline Callback4<
typename Caller::second_argument_type,
typename Caller::third_argument_type,
typename Caller::fourth_argument_type,
typename Caller::fifth_argument_type,
typename Caller::result_type
> makeCallback4( const Caller& caller, typename Caller::first_argument_type callee ){
return Callback4<
typename Caller::second_argument_type,
typename Caller::third_argument_type,
typename Caller::fourth_argument_type,
typename Caller::fifth_argument_type,
typename Caller::result_type
>( BindFirstOpaque4<Caller>( callee ) );
}
template<typename Caller>
inline Callback4<
typename Caller::first_argument_type,
typename Caller::second_argument_type,
typename Caller::third_argument_type,
typename Caller::fourth_argument_type,
typename Caller::result_type
> makeStatelessCallback4( const Caller& caller ){
return makeCallback4( Caller4To5<Caller>(), 0 );
}
/// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function. /// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function.
/// ///
/// \dontinclude generic/callback.cpp /// \dontinclude generic/callback.cpp

View File

@ -162,6 +162,21 @@ static result_type call( first_argument_type a1, second_argument_type a2, third_
} }
}; };
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename R, R( *func ) ( A1, A2, A3, A4, A5 )>
class Function5
{
public:
typedef A1 first_argument_type;
typedef A2 second_argument_type;
typedef A3 third_argument_type;
typedef A4 fourth_argument_type;
typedef A5 fifth_argument_type;
typedef R result_type;
static result_type call( first_argument_type a1, second_argument_type a2, third_argument_type a3, fourth_argument_type a4, fifth_argument_type a5 ){
return (func)( a1, a2, a3, a4, a5 );
}
};
template<typename Caller, typename FirstArgument = void*> template<typename Caller, typename FirstArgument = void*>
class Caller0To1 class Caller0To1
{ {
@ -212,6 +227,21 @@ static result_type call( first_argument_type, second_argument_type a2, third_arg
} }
}; };
template<typename Caller, typename FirstArgument = void*>
class Caller4To5
{
public:
typedef FirstArgument first_argument_type;
typedef typename Caller::first_argument_type second_argument_type;
typedef typename Caller::second_argument_type third_argument_type;
typedef typename Caller::third_argument_type fourth_argument_type;
typedef typename Caller::fourth_argument_type fifth_argument_type;
typedef typename Caller::result_type result_type;
static result_type call( first_argument_type, second_argument_type a2, third_argument_type a3, fourth_argument_type a4, fifth_argument_type a5 ){
return Caller::call( a2, a3, a4, a5 );
}
};
template<typename Functor> template<typename Functor>
class FunctorInvoke class FunctorInvoke
{ {

View File

@ -41,7 +41,7 @@ inline void read_colour( Vector3& colour, const char* value ){
inline void write_colour( const Vector3& colour, Entity* entity ){ inline void write_colour( const Vector3& colour, Entity* entity ){
char value[64]; char value[64];
sprintf( value, "%f %f %f", colour[0], colour[1], colour[2] ); sprintf( value, "%g %g %g", colour[0], colour[1], colour[2] );
entity->setKeyValue( "_color", value ); entity->setKeyValue( "_color", value );
} }

View File

@ -689,14 +689,10 @@ void light_draw( const AABB& aabb_light, RenderStateFlags state ){
inline void write_intensity( const float intensity, Entity* entity ){ inline void write_intensity( const float intensity, Entity* entity ){
char value[64]; char value[64];
sprintf( value, "%g", intensity ); sprintf( value, "%g", intensity );
if( !string_empty( entity->getKeyValue( "_light" ) ) ) //primaryIntensity //if set or default is set in .ent
//primaryIntensity
if( !string_empty( entity->getKeyValue( "_light" ) ) ){
entity->setKeyValue( "_light", value ); entity->setKeyValue( "_light", value );
} else //secondaryIntensity
else{ //secondaryIntensity entity->setKeyValue( "light", value ); //otherwise default to "light", which is understood by both q3 and q1
entity->setKeyValue( "light", value );
}
} }
// These variables are tweakable on the q3map2 console, setting to q3map2 // These variables are tweakable on the q3map2 console, setting to q3map2

View File

@ -37,7 +37,7 @@ struct brushprimit_texdef_t
coords[1][1] = 2.0f; coords[1][1] = 2.0f;
coords[1][2] = 0.f; coords[1][2] = 0.f;
} }
void removeScale( std::size_t width, std::size_t height ){ void removeScale( std::size_t width, std::size_t height ){ /* values in texture size scale for certain operations */
#if 1 #if 1
coords[0][0] *= width; coords[0][0] *= width;
coords[0][1] *= width; coords[0][1] *= width;
@ -47,7 +47,7 @@ struct brushprimit_texdef_t
coords[1][2] *= height; coords[1][2] *= height;
#endif #endif
} }
void addScale( std::size_t width, std::size_t height ){ void addScale( std::size_t width, std::size_t height ){ /* addScaled in .map; offsets in range -1..1; texture size irrelevant */
#if 1 #if 1
ASSERT_MESSAGE( width > 0, "shader-width is 0" ); ASSERT_MESSAGE( width > 0, "shader-width is 0" );
ASSERT_MESSAGE( height > 0, "shader-height is 0" ); ASSERT_MESSAGE( height > 0, "shader-height is 0" );

View File

@ -515,8 +515,10 @@ void NormalizeColor( Vector3& color ){
const std::size_t maxi = vector3_max_abs_component_index( color ); const std::size_t maxi = vector3_max_abs_component_index( color );
if ( color[maxi] == 0.f ) if ( color[maxi] == 0.f )
color = Vector3( 1, 1, 1 ); color = Vector3( 1, 1, 1 );
else else{
color /= color[maxi]; const float max = color[maxi];
color /= max;
}
} }
void Entity_normalizeColor(){ void Entity_normalizeColor(){

View File

@ -865,6 +865,10 @@ int getShaderFlags() const {
} }
return 0; return 0;
} }
const Shader* getShader(){
ASSERT_MESSAGE( m_state != 0, "patch shader is not realised" );
return m_state;
}
typedef PatchControl* iterator; typedef PatchControl* iterator;
typedef const PatchControl* const_iterator; typedef const PatchControl* const_iterator;

View File

@ -5570,7 +5570,8 @@ const ModifierFlags c_modifier_copy_texture = c_modifierNone;
void Scene_copyClosestTexture( SelectionTest& test ); void Scene_copyClosestTexture( SelectionTest& test );
void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project, bool texturize_selected = false ); void Scene_applyClosestTexture( SelectionTest& test, bool shift, bool ctrl, bool alt, bool texturize_selected = false );
const char* Scene_applyClosestTexture_getUndoName( bool shift, bool ctrl, bool alt );
class TexManipulator_ class TexManipulator_
{ {
@ -5591,13 +5592,15 @@ void mouseDown( DeviceVector position ){
ConstructSelectionTest( scissored, SelectionBoxForPoint( &position[0], &m_epsilon[0] ) ); ConstructSelectionTest( scissored, SelectionBoxForPoint( &position[0], &m_epsilon[0] ) );
SelectionVolume volume( scissored ); SelectionVolume volume( scissored );
if ( m_state == c_modifier_apply_texture1_project || m_state == c_modifier_apply_texture2_seamless || m_state == c_modifier_apply_texture3 ) { if( m_state == c_modifier_copy_texture ) {
Scene_copyClosestTexture( volume );
}
else{
m_undo_begun = true; m_undo_begun = true;
GlobalUndoSystem().start(); GlobalUndoSystem().start();
Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless, m_state == c_modifier_apply_texture1_project, true ); Scene_applyClosestTexture( volume, bitfield_enabled( m_state, c_modifierShift ),
} bitfield_enabled( m_state, c_modifierControl ),
else if ( m_state == c_modifier_copy_texture ) { bitfield_enabled( m_state, c_modifierAlt ), true );
Scene_copyClosestTexture( volume );
} }
} }
@ -5607,14 +5610,18 @@ void mouseMoved( DeviceVector position ){
ConstructSelectionTest( scissored, SelectionBoxForPoint( &device_constrained( position )[0], &m_epsilon[0] ) ); ConstructSelectionTest( scissored, SelectionBoxForPoint( &device_constrained( position )[0], &m_epsilon[0] ) );
SelectionVolume volume( scissored ); SelectionVolume volume( scissored );
Scene_applyClosestTexture( volume, m_state == c_modifier_apply_texture2_seamless, m_state == c_modifier_apply_texture1_project ); Scene_applyClosestTexture( volume, bitfield_enabled( m_state, c_modifierShift ),
bitfield_enabled( m_state, c_modifierControl ),
bitfield_enabled( m_state, c_modifierAlt ) );
} }
} }
typedef MemberCaller1<TexManipulator_, DeviceVector, &TexManipulator_::mouseMoved> MouseMovedCaller; typedef MemberCaller1<TexManipulator_, DeviceVector, &TexManipulator_::mouseMoved> MouseMovedCaller;
void mouseUp( DeviceVector position ){ void mouseUp( DeviceVector position ){
if( m_undo_begun ){ if( m_undo_begun ){
GlobalUndoSystem().finish( ( m_state == c_modifier_apply_texture1_project )? "projectTexture" : ( m_state == c_modifier_apply_texture2_seamless )? "paintTextureSeamless" : "paintTexture&Projection" ); GlobalUndoSystem().finish( Scene_applyClosestTexture_getUndoName( bitfield_enabled( m_state, c_modifierShift ),
bitfield_enabled( m_state, c_modifierControl ),
bitfield_enabled( m_state, c_modifierAlt ) ) );
m_undo_begun = false; m_undo_begun = false;
} }
g_mouseMovedCallback.clear(); g_mouseMovedCallback.clear();

View File

@ -1460,17 +1460,40 @@ void SurfaceInspector::ApplyFlags(){
} }
enum EPasteMode{
ePasteNone,
ePasteValues,
ePasteSeamless,
ePasteProject,
};
EPasteMode pastemode_for_modifiers( bool shift, bool ctrl ){
if( shift )
return ctrl? ePasteProject : ePasteValues;
else if( ctrl )
return ePasteSeamless;
return ePasteNone;
}
bool pastemode_if_setShader( EPasteMode mode, bool alt ){
return ( mode == ePasteNone ) || !alt;
}
class FaceTexture class FaceTexture
{ {
public: public:
TextureProjection m_projection; TextureProjection m_projection; //BP part is removeScale()'d
ContentsFlagsValue m_flags; ContentsFlagsValue m_flags;
Plane3 m_plane; Plane3 m_plane;
std::size_t m_width; std::size_t m_width;
std::size_t m_height; std::size_t m_height;
FaceTexture() : m_plane( 0, 0, 1, 0 ), m_width( 64 ), m_height( 64 ) { float m_light;
Vector3 m_colour;
FaceTexture() : m_plane( 0, 0, 1, 0 ), m_width( 64 ), m_height( 64 ), m_light( 300 ), m_colour( 1, 1, 1 ) {
m_projection.m_basis_s = Vector3( 0.7071067811865, 0.7071067811865, 0 ); m_projection.m_basis_s = Vector3( 0.7071067811865, 0.7071067811865, 0 );
m_projection.m_basis_t = Vector3( -0.4082482904639, 0.4082482904639, -0.4082482904639 * 2.0 ); m_projection.m_basis_t = Vector3( -0.4082482904639, 0.4082482904639, -0.4082482904639 * 2.0 );
} }
@ -1480,6 +1503,8 @@ FaceTexture g_faceTextureClipboard;
void FaceTextureClipboard_setDefault(){ void FaceTextureClipboard_setDefault(){
g_faceTextureClipboard.m_flags = ContentsFlagsValue( 0, 0, 0, false ); g_faceTextureClipboard.m_flags = ContentsFlagsValue( 0, 0, 0, false );
g_faceTextureClipboard.m_projection.m_texdef = texdef_t();
g_faceTextureClipboard.m_projection.m_brushprimit_texdef = brushprimit_texdef_t();
TexDef_Construct_Default( g_faceTextureClipboard.m_projection ); TexDef_Construct_Default( g_faceTextureClipboard.m_projection );
} }
@ -1489,88 +1514,105 @@ void TextureClipboard_textureSelected( const char* shader ){
void Face_getTexture( Face& face, CopiedString& shader, TextureProjection& projection, ContentsFlagsValue& flags ){ void Face_getTexture( Face& face, CopiedString& shader, FaceTexture& clipboard ){
shader = face.GetShader(); shader = face.GetShader();
face.GetTexdef( projection );
flags = face.getShader().m_flags;
g_faceTextureClipboard.m_plane = face.getPlane().plane3(); face.GetTexdef( clipboard.m_projection );
g_faceTextureClipboard.m_width = face.getShader().width(); clipboard.m_flags = face.getShader().m_flags;
g_faceTextureClipboard.m_height = face.getShader().height();
clipboard.m_plane = face.getPlane().plane3();
clipboard.m_width = face.getShader().width();
clipboard.m_height = face.getShader().height();
clipboard.m_colour = face.getShader().state()->getTexture().color;
} }
typedef Function4<Face&, CopiedString&, TextureProjection&, ContentsFlagsValue&, void, Face_getTexture> FaceGetTexture; typedef Function3<Face&, CopiedString&, FaceTexture&, void, Face_getTexture> FaceGetTexture;
void Face_setTexture( Face& face, const char* shader, const FaceTexture& clipboard, EPasteMode mode, bool setShader ){
void Face_setTexture_Seamless( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ if( setShader ){
face.SetShader( shader ); face.SetShader( shader );
face.SetFlags( clipboard.m_flags );
DoubleLine line = plane3_intersect_plane3( g_faceTextureClipboard.m_plane, face.getPlane().plane3() ); }
if( mode == ePasteValues ){
face.SetTexdef( clipboard.m_projection, false );
}
else if( mode == ePasteProject ){
face.ProjectTexture( clipboard.m_projection, clipboard.m_plane.normal() );
}
else if( mode == ePasteSeamless ){
DoubleLine line = plane3_intersect_plane3( clipboard.m_plane, face.getPlane().plane3() );
if( vector3_length_squared( line.direction ) == 0 ){ if( vector3_length_squared( line.direction ) == 0 ){
face.ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() ); face.ProjectTexture( clipboard.m_projection, clipboard.m_plane.normal() );
face.SetFlags( flags );
return; return;
} }
const Quaternion rotation = quaternion_for_unit_vectors( g_faceTextureClipboard.m_plane.normal(), face.getPlane().plane3().normal() ); const Quaternion rotation = quaternion_for_unit_vectors( clipboard.m_plane.normal(), face.getPlane().plane3().normal() );
// globalOutputStream() << "rotation: " << rotation.x() << " " << rotation.y() << " " << rotation.z() << " " << rotation.w() << " " << "\n"; // globalOutputStream() << "rotation: " << rotation.x() << " " << rotation.y() << " " << rotation.z() << " " << rotation.w() << " " << "\n";
Matrix4 transform = g_matrix4_identity; Matrix4 transform = g_matrix4_identity;
matrix4_pivoted_rotate_by_quaternion( transform, rotation, line.origin ); matrix4_pivoted_rotate_by_quaternion( transform, rotation, line.origin );
TextureProjection proj = projection; TextureProjection proj = clipboard.m_projection;
proj.m_brushprimit_texdef.addScale( g_faceTextureClipboard.m_width, g_faceTextureClipboard.m_height ); proj.m_brushprimit_texdef.addScale( clipboard.m_width, clipboard.m_height );
Texdef_transformLocked( proj, g_faceTextureClipboard.m_width, g_faceTextureClipboard.m_height, g_faceTextureClipboard.m_plane, transform, line.origin ); Texdef_transformLocked( proj, clipboard.m_width, clipboard.m_height, clipboard.m_plane, transform, line.origin );
proj.m_brushprimit_texdef.removeScale( g_faceTextureClipboard.m_width, g_faceTextureClipboard.m_height ); proj.m_brushprimit_texdef.removeScale( clipboard.m_width, clipboard.m_height );
//face.SetTexdef( projection );
face.SetTexdef( proj ); face.SetTexdef( proj );
face.SetFlags( flags );
g_faceTextureClipboard.m_plane = face.getPlane().plane3(); g_faceTextureClipboard.m_plane = face.getPlane().plane3();
g_faceTextureClipboard.m_projection = proj; g_faceTextureClipboard.m_projection = proj;
} }
typedef Function4<Face&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Face_setTexture_Seamless> FaceSetTextureSeamless;
void Face_setTexture_Project( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
face.SetShader( shader );
//face.SetTexdef( projection );
face.SetFlags( flags );
face.ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() );
} }
typedef Function4<Face&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Face_setTexture_Project> FaceSetTextureProject; typedef Function5<Face&, const char*, const FaceTexture&, EPasteMode, bool, void, Face_setTexture> FaceSetTexture;
void Face_setTexture( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ void Patch_getTexture( Patch& patch, CopiedString& shader, FaceTexture& clipboard ){
face.SetShader( shader );
face.SetTexdef( projection, false );
face.SetFlags( flags );
}
typedef Function4<Face&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Face_setTexture> FaceSetTexture;
void Patch_getTexture( Patch& patch, CopiedString& shader, TextureProjection& projection, ContentsFlagsValue& flags ){
shader = patch.GetShader(); shader = patch.GetShader();
projection = TextureProjection( texdef_t(), brushprimit_texdef_t(), Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ) ); FaceTextureClipboard_setDefault();
flags = ContentsFlagsValue( 0, 0, 0, false );
}
typedef Function4<Patch&, CopiedString&, TextureProjection&, ContentsFlagsValue&, void, Patch_getTexture> PatchGetTexture;
void Patch_setTexture_Project( Patch& patch, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ clipboard.m_width = patch.getShader()->getTexture().width;
clipboard.m_height = patch.getShader()->getTexture().height;
clipboard.m_colour = patch.getShader()->getTexture().color;
}
typedef Function3<Patch&, CopiedString&, FaceTexture&, void, Patch_getTexture> PatchGetTexture;
void Patch_setTexture( Patch& patch, const char* shader, const FaceTexture& clipboard, EPasteMode mode, bool setShader ){
if( setShader )
patch.SetShader( shader ); patch.SetShader( shader );
patch.ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() ); if( mode == ePasteProject )
patch.ProjectTexture( clipboard.m_projection, clipboard.m_plane.normal() );
} }
typedef Function4<Patch&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Patch_setTexture_Project> PatchSetTextureProject; typedef Function5<Patch&, const char*, const FaceTexture&, EPasteMode, bool, void, Patch_setTexture> PatchSetTexture;
void Patch_setTexture( Patch& patch, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){ #include "ientity.h"
patch.SetShader( shader ); void Light_getTexture( Entity& entity, CopiedString& shader, FaceTexture& clipboard ){
string_parse_vector3( entity.getKeyValue( "_color" ), clipboard.m_colour );
if( !string_parse_float( entity.getKeyValue( "_light" ), clipboard.m_light ) )
string_parse_float( entity.getKeyValue( "light" ), clipboard.m_light );
} }
typedef Function4<Patch&, const char*, const TextureProjection&, const ContentsFlagsValue&, void, Patch_setTexture> PatchSetTexture; typedef Function3<Entity&, CopiedString&, FaceTexture&, void, Light_getTexture> LightGetTexture;
void Light_setTexture( Entity& entity, const char* shader, const FaceTexture& clipboard, EPasteMode mode, bool setShader ){
if( mode == ePasteSeamless || mode == ePasteProject ){
char value[64];
sprintf( value, "%g %g %g", clipboard.m_colour[0], clipboard.m_colour[1], clipboard.m_colour[2] );
entity.setKeyValue( "_color", value );
}
if( mode == ePasteValues || mode == ePasteProject ){
/* copypaste of write_intensity() from entity plugin */
char value[64];
sprintf( value, "%g", clipboard.m_light );
if( !string_empty( entity.getKeyValue( "_light" ) ) ) //primaryIntensity //if set or default is set in .ent
entity.setKeyValue( "_light", value );
else //secondaryIntensity
entity.setKeyValue( "light", value ); //otherwise default to "light", which is understood by both q3 and q1
}
}
typedef Function5<Entity&, const char*, const FaceTexture&, EPasteMode, bool, void, Light_setTexture> LightSetTexture;
typedef Callback3<CopiedString&, TextureProjection&, ContentsFlagsValue&> GetTextureCallback; typedef Callback2<CopiedString&, FaceTexture&> GetTextureCallback;
typedef Callback3<const char*, const TextureProjection&, const ContentsFlagsValue&> SetTextureCallback; typedef Callback4<const char*, const FaceTexture&, EPasteMode, bool, void> SetTextureCallback;
struct Texturable struct Texturable
{ {
@ -1579,7 +1621,7 @@ struct Texturable
}; };
void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable, bool seamless, bool project ){ void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& bestIntersection, Texturable& texturable ){
if ( face.isFiltered() ) { if ( face.isFiltered() ) {
return; return;
} }
@ -1588,13 +1630,8 @@ void Face_getClosest( Face& face, SelectionTest& test, SelectionIntersection& be
if ( intersection.valid() if ( intersection.valid()
&& SelectionIntersection_closer( intersection, bestIntersection ) ) { && SelectionIntersection_closer( intersection, bestIntersection ) ) {
bestIntersection = intersection; bestIntersection = intersection;
if( project ) texturable.setTexture = makeCallback4( FaceSetTexture(), face );
texturable.setTexture = makeCallback3( FaceSetTextureProject(), face ); texturable.getTexture = makeCallback2( FaceGetTexture(), face );
else if( seamless )
texturable.setTexture = makeCallback3( FaceSetTextureSeamless(), face );
else
texturable.setTexture = makeCallback3( FaceSetTexture(), face );
texturable.getTexture = makeCallback3( FaceGetTexture(), face );
} }
} }
@ -1618,16 +1655,14 @@ void addIntersection( const SelectionIntersection& intersection ){
} }
} }
}; };
#include "eclasslib.h"
class BrushGetClosestFaceVisibleWalker : public scene::Graph::Walker class BrushGetClosestFaceVisibleWalker : public scene::Graph::Walker
{ {
SelectionTest& m_test; SelectionTest& m_test;
Texturable& m_texturable; Texturable& m_texturable;
const bool m_seamless;
const bool m_project;
mutable SelectionIntersection m_bestIntersection; mutable SelectionIntersection m_bestIntersection;
public: public:
BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable, bool seamless, bool project ) : m_test( test ), m_texturable( texturable ), m_seamless( seamless ), m_project( project ){ BrushGetClosestFaceVisibleWalker( SelectionTest& test, Texturable& texturable ) : m_test( test ), m_texturable( texturable ){
} }
bool pre( const scene::Path& path, scene::Instance& instance ) const { bool pre( const scene::Path& path, scene::Instance& instance ) const {
if ( !path.top().get().visible() ) if ( !path.top().get().visible() )
@ -1638,7 +1673,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
for ( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i ) for ( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i )
{ {
Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable, m_seamless, m_project ); Face_getClosest( *( *i ), m_test, m_bestIntersection, m_texturable );
} }
} }
else else
@ -1651,14 +1686,16 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
if ( occluded ) { if ( occluded ) {
Patch* patch = Node_getPatch( path.top() ); Patch* patch = Node_getPatch( path.top() );
if ( patch != 0 ) { if ( patch != 0 ) {
if( m_project ) m_texturable.setTexture = makeCallback4( PatchSetTexture(), *patch );
m_texturable.setTexture = makeCallback3( PatchSetTextureProject(), *patch ); m_texturable.getTexture = makeCallback2( PatchGetTexture(), *patch );
else return true;
m_texturable.setTexture = makeCallback3( PatchSetTexture(), *patch );
m_texturable.getTexture = makeCallback3( PatchGetTexture(), *patch );
} }
else Entity* entity = Node_getEntity( path.top() );
{ if( entity != 0 && string_equal_n( entity->getEntityClass().name(), "light", 5 ) ){
m_texturable.setTexture = makeCallback4( LightSetTexture(), *entity );
m_texturable.getTexture = makeCallback2( LightGetTexture(), *entity );
}
else{
m_texturable = Texturable(); m_texturable = Texturable();
} }
} }
@ -1668,25 +1705,25 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
} }
}; };
Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test, bool seamless = false, bool project = false ){ Texturable Scene_getClosestTexturable( scene::Graph& graph, SelectionTest& test ){
Texturable texturable; Texturable texturable;
graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable, seamless, project ) ); graph.traverse( BrushGetClosestFaceVisibleWalker( test, texturable ) );
return texturable; return texturable;
} }
bool Scene_getClosestTexture( scene::Graph& graph, SelectionTest& test, CopiedString& shader, TextureProjection& projection, ContentsFlagsValue& flags ){ bool Scene_getClosestTexture( scene::Graph& graph, SelectionTest& test, CopiedString& shader, FaceTexture& clipboard ){
Texturable texturable = Scene_getClosestTexturable( graph, test ); Texturable texturable = Scene_getClosestTexturable( graph, test );
if ( texturable.getTexture != GetTextureCallback() ) { if ( texturable.getTexture != GetTextureCallback() ) {
texturable.getTexture( shader, projection, flags ); texturable.getTexture( shader, clipboard );
return true; return true;
} }
return false; return false;
} }
void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags, bool seamless, bool project ){ void Scene_setClosestTexture( scene::Graph& graph, SelectionTest& test, const char* shader, const FaceTexture& clipboard, EPasteMode mode, bool setShader ){
Texturable texturable = Scene_getClosestTexturable( graph, test, seamless, project ); Texturable texturable = Scene_getClosestTexturable( graph, test );
if ( texturable.setTexture != SetTextureCallback() ) { if ( texturable.setTexture != SetTextureCallback() ) {
texturable.setTexture( shader, projection, flags ); texturable.setTexture( shader, clipboard, mode, setShader );
} }
} }
@ -1695,29 +1732,43 @@ const char* TextureBrowser_GetSelectedShader();
void Scene_copyClosestTexture( SelectionTest& test ){ void Scene_copyClosestTexture( SelectionTest& test ){
CopiedString shader; CopiedString shader;
if ( Scene_getClosestTexture( GlobalSceneGraph(), test, shader, g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags ) ) { if ( Scene_getClosestTexture( GlobalSceneGraph(), test, shader, g_faceTextureClipboard ) ) {
TextureBrowser_SetSelectedShader( shader.c_str() ); TextureBrowser_SetSelectedShader( shader.c_str() );
// UndoableCommand undo( "textureNameAndProjectionSetSelected" );
// Select_SetShader( shader.c_str() );
// Select_SetTexdef( g_faceTextureClipboard.m_projection );
} }
} }
void Scene_applyClosestTexture( SelectionTest& test, bool seamless, bool project, bool texturize_selected = false ){ const char* Scene_applyClosestTexture_getUndoName( bool shift, bool ctrl, bool alt ){
const EPasteMode mode = pastemode_for_modifiers( shift, ctrl );
const bool setShader = pastemode_if_setShader( mode, alt );
switch ( mode )
{
default: //case ePasteNone:
return "paintTexture";
case ePasteValues:
return setShader? "paintTexture,Values,LightPower" : "paintTexDefValues";
case ePasteSeamless:
return setShader? "paintTextureSeamless,LightColor" : "paintTexDefValuesSeamless";
case ePasteProject:
return setShader? "projectTexture,LightColor&Power" : "projectTexDefValues";
}
}
void Scene_applyClosestTexture( SelectionTest& test, bool shift, bool ctrl, bool alt, bool texturize_selected = false ){
// UndoableCommand command( "facePaintTexture" ); // UndoableCommand command( "facePaintTexture" );
const EPasteMode mode = pastemode_for_modifiers( shift, ctrl );
const bool setShader = pastemode_if_setShader( mode, alt );
if( texturize_selected ){ if( texturize_selected ){
if( project ){ if( setShader && mode != ePasteSeamless )
Select_SetShader( TextureBrowser_GetSelectedShader() ); Select_SetShader( TextureBrowser_GetSelectedShader() );
if( mode == ePasteValues )
Select_SetTexdef( g_faceTextureClipboard.m_projection, false, false );
else if( mode == ePasteProject )
Select_ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() ); Select_ProjectTexture( g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_plane.normal() );
} }
else if( !seamless ){
Select_SetShader( TextureBrowser_GetSelectedShader() );
Select_SetTexdef( g_faceTextureClipboard.m_projection, false, false );
}
}
Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader(), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags, seamless, project ); Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader(), g_faceTextureClipboard, mode, setShader );
SceneChangeNotify(); SceneChangeNotify();
} }