mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-04 20:57:49 +00:00
197 lines
5.6 KiB
C++
197 lines
5.6 KiB
C++
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
|
|
|
|
#include "AppDraw/Draw.h"
|
|
#include "AppDraw/DrawPrimitives.h"
|
|
#include "AppDraw/DrawAdorn.h"
|
|
#include "GfxBase/Part.h"
|
|
#include "GfxBase/Adorn.h"
|
|
#include "Util/Math.h"
|
|
#include "V8DataModel/PartInstance.h"
|
|
|
|
namespace RBX {
|
|
|
|
static const int SelectionBoxLineThreshold = 1500; //!< tweakable threshold before boxes switch to lines
|
|
|
|
bool Draw::m_showHoverOver = true;
|
|
G3D::Color4 Draw::m_hoverOverColor(0.7f,0.9f,1.0f,1.0f); // 178, 229, 255
|
|
G3D::Color4 Draw::m_selectColor(0.1f,0.6f,1.0f,1.0f); // 25, 153, 256
|
|
|
|
void Draw::partAdorn(
|
|
const Part& part,
|
|
Adorn* adorn,
|
|
const G3D::Color3& controllerColor)
|
|
{
|
|
adornSurfaces(part, adorn, controllerColor);
|
|
}
|
|
|
|
/**
|
|
* Set color used for the selection box when a part is selected.
|
|
*/
|
|
void Draw::setSelectColor(const G3D::Color4& Color)
|
|
{
|
|
m_selectColor = Color;
|
|
}
|
|
|
|
/**
|
|
* Set the color used for the selection box when a part is mouse hover over.
|
|
*/
|
|
void Draw::setHoverOverColor(const G3D::Color4& color)
|
|
{
|
|
m_hoverOverColor = color;
|
|
}
|
|
|
|
void Draw::selectionBox(
|
|
const Part& part,
|
|
Adorn* adorn,
|
|
SelectState selectState,
|
|
float lineThickness)
|
|
{
|
|
if ( selectState == SELECT_HOVER && m_showHoverOver )
|
|
{
|
|
adorn->setObjectToWorldMatrix(part.coordinateFrame);
|
|
selectionBox(
|
|
part,
|
|
adorn,
|
|
m_hoverOverColor,
|
|
lineThickness * 2 );
|
|
}
|
|
else if ( selectState != SELECT_HOVER )
|
|
{
|
|
selectionBox(
|
|
part,
|
|
adorn,
|
|
(selectState == SELECT_NORMAL) ? selectColor() : Color3::orange(),
|
|
lineThickness );
|
|
}
|
|
}
|
|
|
|
void Draw::selectionBox(
|
|
ModelInstance& model,
|
|
Adorn* adorn,
|
|
const G3D::Color4& selectColor,
|
|
float lineThickness)
|
|
{
|
|
selectionBox(model.computePart(), adorn, selectColor, lineThickness);
|
|
}
|
|
|
|
void Draw::adornSurfaces(const Part& part,
|
|
Adorn* adorn,
|
|
const G3D::Color3& controllerColor)
|
|
{
|
|
for (int face = 0; face < 6; ++face) {
|
|
switch (part.surfaceType[face])
|
|
{
|
|
default: break;
|
|
case ROTATE:
|
|
case ROTATE_P:
|
|
case ROTATE_V: Draw::constraint(part, adorn, face, controllerColor); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Draw::constraint(const Part& part,
|
|
Adorn* adorn,
|
|
int face,
|
|
const G3D::Color3& controllerColor)
|
|
{
|
|
SurfaceType surfaceType = part.surfaceType[face];
|
|
|
|
debugAssert( (surfaceType == ROTATE)
|
|
|| (surfaceType == ROTATE_P)
|
|
|| (surfaceType == ROTATE_V));
|
|
|
|
Vector3 halfSize = part.gridSize * 0.5;
|
|
|
|
const Matrix3& relativeRotation = Math::getAxisRotationMatrix(face);
|
|
Vector3 relativeTranslation;
|
|
|
|
int normal = face % 3;
|
|
float posNeg = face > 2 ? -1.0f : 1.0f;
|
|
relativeTranslation[normal] = halfSize[normal] * posNeg;
|
|
|
|
CoordinateFrame translation(relativeRotation, relativeTranslation);
|
|
CoordinateFrame newObject = part.coordinateFrame * translation;
|
|
|
|
adorn->setObjectToWorldMatrix(newObject);
|
|
|
|
float axis = 1.0f;
|
|
float radius = 0.2f;
|
|
adorn->cylinderAlongX(radius, axis, Color3::yellow());
|
|
|
|
if ((surfaceType == ROTATE_V) || (surfaceType == ROTATE_P))
|
|
{
|
|
float axis = 0.25f;
|
|
float radius = 0.4f;
|
|
adorn->cylinderAlongX(radius, axis, controllerColor);
|
|
}
|
|
}
|
|
|
|
void Draw::selectionBox(
|
|
const Part& part,
|
|
Adorn* adorn,
|
|
const G3D::Color4& selectColor,
|
|
float lineThickness)
|
|
{
|
|
if ( adorn->getCamera() != NULL )
|
|
{
|
|
// determine distance from camera to object
|
|
const Vector3 camera_pos = adorn->getCamera()->getCameraCoordinateFrame().translation;
|
|
const Vector3 delta = part.coordinateFrame.translation - camera_pos;
|
|
const float delta_squared = delta.squaredLength();
|
|
|
|
// determine size of object by using longest axis
|
|
const float grid_size = part.gridSize[part.gridSize.primaryAxis()];
|
|
const float grid_size_squared = grid_size * grid_size;
|
|
|
|
// make sure the distance is greater than the size
|
|
if ( delta_squared > grid_size_squared )
|
|
{
|
|
// adjust distance based on thickness of lines
|
|
const float threshold_dist = SelectionBoxLineThreshold * lineThickness;
|
|
const float threshold_dist_squared = threshold_dist * threshold_dist;
|
|
|
|
// subtract the size from the distance and compare to the threshold
|
|
if ( delta_squared - grid_size_squared > threshold_dist_squared )
|
|
{
|
|
// switch to drawing lines
|
|
const Vector3 half_size = part.gridSize / 2;
|
|
adorn->setObjectToWorldMatrix(part.coordinateFrame);
|
|
DrawAdorn::outlineBox(adorn,Extents(-half_size,half_size),selectColor);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
adorn->setObjectToWorldMatrix( part.coordinateFrame );
|
|
|
|
Vector3 halfSize = 0.5f * part.gridSize;
|
|
|
|
float highlight = lineThickness;
|
|
|
|
for (int c1 = 0; c1 < 3; ++c1) { // x, y, z
|
|
int c2 = (c1 + 1) % 3; // y
|
|
int c3 = (c1 + 2) % 3; // z
|
|
for (int d2 = -1; d2 < 2; d2+=2) {
|
|
for (int d3 = -1; d3 < 2; d3+=2) {
|
|
|
|
// for c1, shorten the length of the edge segment by highlight size
|
|
// on both ends so that the edge segments do not overlap on the
|
|
// corners
|
|
Vector3 p0, p1;
|
|
p0[c1] = -halfSize[c1] - (c1 == 0 ? highlight : -highlight);
|
|
p0[c2] = d2 * halfSize[c2] - highlight;
|
|
p0[c3] = d3 * halfSize[c3] - highlight;
|
|
p1[c1] = halfSize[c1] + (c1 == 0 ? highlight : -highlight);
|
|
p1[c2] = d2 * halfSize[c2] + highlight;
|
|
p1[c3] = d3 * halfSize[c3] + highlight;
|
|
|
|
if (p0.x <= p1.x && p0.y <= p1.y && p0.z <= p1.z)
|
|
adorn->box( AABox(p0, p1),
|
|
selectColor );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace
|