binds...
* 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:
parent
7908a2b593
commit
3706e1131a
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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" );
|
||||||
|
|
|
||||||
|
|
@ -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(){
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
typedef Function5<Face&, const char*, const FaceTexture&, EPasteMode, bool, void, Face_setTexture> FaceSetTexture;
|
||||||
|
|
||||||
|
|
||||||
void Face_setTexture_Project( 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 );
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
void Face_setTexture( Face& face, const char* shader, const TextureProjection& projection, const ContentsFlagsValue& flags ){
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user