mirror of
https://github.com/Garux/netradiant-custom.git
synced 2026-09-28 00:00:03 +02:00
179 lines
7.1 KiB
C++
179 lines
7.1 KiB
C++
/*
|
|
Copyright (C) 2001-2006, William Joseph.
|
|
All Rights Reserved.
|
|
|
|
This file is part of GtkRadiant.
|
|
|
|
GtkRadiant is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
GtkRadiant is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GtkRadiant; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "selection_.h"
|
|
#include "grid.h"
|
|
|
|
class ScaleAxis : public Manipulatable
|
|
{
|
|
Vector3 m_start;
|
|
Vector3 m_axis;
|
|
Scalable& m_scalable;
|
|
|
|
Vector3 m_chosen_extent;
|
|
AABB m_bounds;
|
|
public:
|
|
ScaleAxis( Scalable& scalable )
|
|
: m_scalable( scalable ){
|
|
}
|
|
void Construct( const Matrix4& device2manip, const DeviceVector device_point, const AABB& bounds, const Vector3& transform_origin ) override {
|
|
m_start = point_on_axis( m_axis, device2manip, device_point );
|
|
|
|
m_chosen_extent = Vector3(
|
|
std::max( bounds.origin[0] + bounds.extents[0] - transform_origin[0], - bounds.origin[0] + bounds.extents[0] + transform_origin[0] ),
|
|
std::max( bounds.origin[1] + bounds.extents[1] - transform_origin[1], - bounds.origin[1] + bounds.extents[1] + transform_origin[1] ),
|
|
std::max( bounds.origin[2] + bounds.extents[2] - transform_origin[2], - bounds.origin[2] + bounds.extents[2] + transform_origin[2] )
|
|
);
|
|
m_bounds = bounds;
|
|
}
|
|
void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const DeviceVector device_point ) override {
|
|
//globalOutputStream() << "manip2object: " << manip2object << " device2manip: " << device2manip << " x: " << x << " y:" << y << '\n';
|
|
Vector3 current = point_on_axis( m_axis, device2manip, device_point );
|
|
Vector3 delta = vector3_subtracted( current, m_start );
|
|
|
|
delta = translation_local2object( delta, manip2object );
|
|
vector3_snap( delta, GetSnapGridSize() );
|
|
vector3_scale( delta, m_axis );
|
|
|
|
Vector3 start( vector3_snapped( m_start, GetSnapGridSize() != 0 ? GetSnapGridSize() : 1e-3f ) );
|
|
for ( std::size_t i = 0; i < 3; ++i ){ //prevent snapping to 0 with big gridsize
|
|
if( float_snapped( m_start[i], 1e-3f ) != 0 && start[i] == 0 ){
|
|
start[i] = GetSnapGridSize();
|
|
}
|
|
}
|
|
//globalOutputStream() << "m_start: " << m_start << " start: " << start << " delta: " << delta << '\n';
|
|
/* boundless way */
|
|
Vector3 scale(
|
|
start[0] == 0 ? 1 : 1 + delta[0] / start[0],
|
|
start[1] == 0 ? 1 : 1 + delta[1] / start[1],
|
|
start[2] == 0 ? 1 : 1 + delta[2] / start[2]
|
|
);
|
|
/* try bbox way */
|
|
for( std::size_t i = 0; i < 3; ++i ){
|
|
if( m_chosen_extent[i] > 0.0625f && m_axis[i] != 0 ){ //epsilon to prevent super high scale for set of models, having really small extent, formed by origins
|
|
scale[i] = ( m_chosen_extent[i] + delta[i] ) / m_chosen_extent[i];
|
|
if( g_modifiers.ctrl() ){ // snap bbox dimension size to grid
|
|
const float snappdwidth = float_snapped( scale[i] * m_bounds.extents[i] * 2.f, GetSnapGridSize() );
|
|
scale[i] = snappdwidth / ( m_bounds.extents[i] * 2.f );
|
|
}
|
|
}
|
|
}
|
|
if( g_modifiers.shift() ){ // scale all axes equally
|
|
for( std::size_t i = 0; i < 3; ++i ){
|
|
if( m_axis[i] == 0 ){
|
|
scale[i] = vector3_dot( scale, vector3_scaled( m_axis, m_axis ) );
|
|
}
|
|
}
|
|
}
|
|
//globalOutputStream() << "scale: " << scale << '\n';
|
|
m_scalable.scale( scale );
|
|
}
|
|
|
|
void SetAxis( const Vector3& axis ){
|
|
m_axis = axis;
|
|
}
|
|
};
|
|
|
|
class ScaleFree : public Manipulatable
|
|
{
|
|
Vector3 m_start;
|
|
Vector3 m_axis;
|
|
Vector3 m_axis2;
|
|
Scalable& m_scalable;
|
|
|
|
Vector3 m_chosen_extent;
|
|
AABB m_bounds;
|
|
public:
|
|
ScaleFree( Scalable& scalable )
|
|
: m_scalable( scalable ){
|
|
}
|
|
void Construct( const Matrix4& device2manip, const DeviceVector device_point, const AABB& bounds, const Vector3& transform_origin ) override {
|
|
m_start = point_on_plane( device2manip, device_point );
|
|
|
|
m_chosen_extent = Vector3(
|
|
std::max( bounds.origin[0] + bounds.extents[0] - transform_origin[0], -( bounds.origin[0] - bounds.extents[0] - transform_origin[0] ) ),
|
|
std::max( bounds.origin[1] + bounds.extents[1] - transform_origin[1], -( bounds.origin[1] - bounds.extents[1] - transform_origin[1] ) ),
|
|
std::max( bounds.origin[2] + bounds.extents[2] - transform_origin[2], -( bounds.origin[2] - bounds.extents[2] - transform_origin[2] ) )
|
|
);
|
|
m_bounds = bounds;
|
|
}
|
|
void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const DeviceVector device_point ) override {
|
|
Vector3 current = point_on_plane( device2manip, device_point );
|
|
Vector3 delta = vector3_subtracted( current, m_start );
|
|
|
|
delta = translation_local2object( delta, manip2object );
|
|
vector3_snap( delta, GetSnapGridSize() );
|
|
if( m_axis != g_vector3_identity )
|
|
delta = vector3_scaled( delta, m_axis ) + vector3_scaled( delta, m_axis2 );
|
|
|
|
Vector3 start( vector3_snapped( m_start, GetSnapGridSize() != 0 ? GetSnapGridSize() : 1e-3f ) );
|
|
for ( std::size_t i = 0; i < 3; ++i ){ //prevent snapping to 0 with big gridsize
|
|
if( float_snapped( m_start[i], 1e-3f ) != 0 && start[i] == 0 ){
|
|
start[i] = GetSnapGridSize();
|
|
}
|
|
}
|
|
|
|
const std::size_t ignore_axis = vector3_min_abs_component_index( m_start );
|
|
if( g_modifiers.shift() )
|
|
start[ignore_axis] = 0;
|
|
|
|
Vector3 scale(
|
|
start[0] == 0 ? 1 : 1 + delta[0] / start[0],
|
|
start[1] == 0 ? 1 : 1 + delta[1] / start[1],
|
|
start[2] == 0 ? 1 : 1 + delta[2] / start[2]
|
|
);
|
|
|
|
//globalOutputStream() << "m_start: " << m_start << " start: " << start << " delta: " << delta << '\n';
|
|
for( std::size_t i = 0; i < 3; ++i ){
|
|
if( m_chosen_extent[i] > 0.0625f && start[i] != 0 ){
|
|
scale[i] = ( m_chosen_extent[i] + delta[i] ) / m_chosen_extent[i];
|
|
if( g_modifiers.ctrl() ){ // snap bbox dimension size to grid
|
|
const float snappdwidth = float_snapped( scale[i] * m_bounds.extents[i] * 2.f, GetSnapGridSize() );
|
|
scale[i] = snappdwidth / ( m_bounds.extents[i] * 2.f );
|
|
}
|
|
}
|
|
}
|
|
//globalOutputStream() << "pre snap scale: " << scale << '\n';
|
|
if( g_modifiers.shift() ){ // snap 2 axes equally
|
|
float bestscale = ignore_axis != 0 ? scale[0] : scale[1];
|
|
for( std::size_t i = ignore_axis != 0 ? 1 : 2; i < 3; ++i ){
|
|
if( ignore_axis != i && std::fabs( scale[i] ) < std::fabs( bestscale ) ){
|
|
bestscale = scale[i];
|
|
}
|
|
//globalOutputStream() << "bestscale: " << bestscale << '\n';
|
|
}
|
|
for( std::size_t i = 0; i < 3; ++i ){
|
|
if( ignore_axis != i ){
|
|
scale[i] = ( scale[i] < 0 ) ? -std::fabs( bestscale ) : fabs( bestscale );
|
|
}
|
|
}
|
|
}
|
|
//globalOutputStream() << "scale: " << scale << '\n';
|
|
m_scalable.scale( scale );
|
|
}
|
|
void SetAxes( const Vector3& axis, const Vector3& axis2 ){
|
|
m_axis = axis;
|
|
m_axis2 = axis2;
|
|
}
|
|
};
|