Skip to content

Commit 9b21e5d

Browse files
committed
Editor: Resize Tool for the sprites thunder-engine#338
1 parent ce69c9f commit 9b21e5d

20 files changed

+515
-178
lines changed

engine/includes/editor/editortool.h

+12-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@
88
#include <QCursor>
99

1010
class Actor;
11+
class Renderable;
1112

1213
class NEXT_LIBRARY_EXPORT EditorTool {
1314
public:
14-
struct Select {
15+
struct NEXT_LIBRARY_EXPORT Select {
16+
Select();
17+
1518
Actor *object;
19+
Renderable *renderable;
1620
Vector3 position;
1721
Vector3 scale;
1822
Vector3 euler;
23+
Vector3 pivot;
24+
AABBox box;
1925
};
2026

2127
typedef QMap<uint32_t, Select> SelectMap;
@@ -27,6 +33,7 @@ class NEXT_LIBRARY_EXPORT EditorTool {
2733

2834
virtual void beginControl();
2935
virtual void endControl();
36+
virtual void cancelControl();
3037

3138
virtual QString icon() const = 0;
3239
virtual QString name() const = 0;
@@ -36,9 +43,13 @@ class NEXT_LIBRARY_EXPORT EditorTool {
3643
Vector3 objectPosition();
3744
AABBox objectBound();
3845

46+
const VariantList &cache() const;
47+
3948
protected:
4049
SelectMap &m_Selected;
4150

51+
VariantList m_PropertiesCache;
52+
4253
QCursor m_Cursor;
4354

4455
};

engine/includes/editor/handles.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class NEXT_LIBRARY_EXPORT Handles {
4949
static Vector3 moveTool(const Vector3 &position, const Quaternion &rotation, bool locked);
5050
static float rotationTool(const Vector3 &position, const Quaternion &rotation, bool locked);
5151
static Vector3 scaleTool(const Vector3 &position, const Quaternion &rotation, bool locked);
52-
static void rectTool(const Vector3 &position, const Vector2 &size, const Quaternion &rotation, bool locked);
52+
static Vector3 rectTool(const Vector3 &position, const Vector3 &box, int &axis, bool locked);
5353

5454
public:
5555
static Vector4 s_Color;
@@ -96,6 +96,8 @@ class NEXT_LIBRARY_EXPORT Handles {
9696
static MaterialInstance *s_Solid;
9797
static MaterialInstance *s_Sprite;
9898

99+
static Texture *s_Corner;
100+
99101
};
100102

101103
#endif // HANDLES_H

engine/src/components/actor.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,6 @@ VariantMap Actor::saveUserData() const {
563563
}
564564
}
565565

566-
567566
VariantList fixed;
568567

569568
for(auto it : objects) {

engine/src/editor/editortool.cpp

+59-12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
#include "components/transform.h"
55
#include "components/renderable.h"
66

7+
EditorTool::Select::Select() :
8+
object(nullptr),
9+
renderable(nullptr) {
10+
11+
}
12+
713
EditorTool::EditorTool(EditorTool::SelectMap &selection) :
814
m_Selected(selection) {
915

@@ -14,43 +20,84 @@ void EditorTool::update() {
1420
}
1521

1622
void EditorTool::beginControl() {
23+
m_PropertiesCache.clear();
1724

25+
for(auto &it : m_Selected) {
26+
Transform *t = it.object->transform();
27+
it.position = t->position();
28+
it.scale = t->scale();
29+
it.euler = t->rotation();
30+
31+
VariantMap components;
32+
for(auto &child : it.object->getChildren()) {
33+
Component *component = dynamic_cast<Component *>(child);
34+
if(component) {
35+
VariantMap properies;
36+
const MetaObject *meta = component->metaObject();
37+
for(int i = 0; i < meta->propertyCount(); i++) {
38+
MetaProperty property = meta->property(i);
39+
properies[property.name()] = property.read(component);
40+
}
41+
components[to_string(component->uuid())] = properies;
42+
}
43+
}
44+
m_PropertiesCache.push_back(components);
45+
}
1846
}
1947

2048
void EditorTool::endControl() {
2149

2250
}
2351

52+
void EditorTool::cancelControl() {
53+
auto cache = m_PropertiesCache.begin();
54+
for(auto &it : m_Selected) {
55+
VariantMap components = (*cache).toMap();
56+
for(auto &child : it.object->getChildren()) {
57+
Component *component = dynamic_cast<Component *>(child);
58+
if(component) {
59+
VariantMap properties = components[to_string(component->uuid())].toMap();
60+
const MetaObject *meta = component->metaObject();
61+
for(int i = 0; i < meta->propertyCount(); i++) {
62+
MetaProperty property = meta->property(i);
63+
property.write(component, properties[property.name()]);
64+
}
65+
}
66+
}
67+
68+
++cache;
69+
}
70+
}
71+
2472
QCursor EditorTool::cursor() const {
2573
return m_Cursor;
2674
}
2775

2876
Vector3 EditorTool::objectPosition() {
29-
Vector3 result;
30-
if(!m_Selected.empty()) {
31-
for(auto &it : m_Selected) {
32-
result += it.object->transform()->worldPosition();
33-
}
34-
result = result / m_Selected.size();
35-
}
36-
return result;
77+
return objectBound().center;
3778
}
3879

3980
AABBox EditorTool::objectBound() {
4081
AABBox result;
4182
bool first = true;
4283
if(!m_Selected.empty()) {
4384
for(auto &it : m_Selected) {
44-
Renderable *renderable = dynamic_cast<Renderable *>(it.object->component("Renderable"));
45-
if(renderable) {
85+
if(it.renderable == nullptr) {
86+
it.renderable = dynamic_cast<Renderable *>(it.object->component("Renderable"));
87+
}
88+
if(it.renderable) {
4689
if(first) {
47-
result = renderable->bound();
90+
result = it.renderable->bound();
4891
first = false;
4992
} else {
50-
result.encapsulate(renderable->bound());
93+
result.encapsulate(it.renderable->bound());
5194
}
5295
}
5396
}
5497
}
5598
return result;
5699
}
100+
101+
const VariantList &EditorTool::cache() const {
102+
return m_PropertiesCache;
103+
}

engine/src/editor/handles.cpp

+139-33
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ Mesh *Handles::s_Rectangle = nullptr;
6363
Mesh *Handles::s_Box = nullptr;
6464
Mesh *Handles::s_Bone = nullptr;
6565

66+
Texture *Handles::s_Corner = nullptr;
67+
6668
enum {
6769
AXIS,
6870
SCALE,
@@ -107,6 +109,10 @@ void Handles::init() {
107109
}
108110
}
109111

112+
if(s_Corner == nullptr) {
113+
s_Corner = Engine::loadResource<Texture>(".embedded/corner.png");
114+
}
115+
110116
if(s_Lines == nullptr) {
111117
s_Lines = Engine::objectCreate<Mesh>("Lines");
112118
s_Lines->makeDynamic();
@@ -667,6 +673,7 @@ float Handles::rotationTool(const Vector3 &position, const Quaternion &rotation,
667673
}
668674

669675
Vector3 Handles::scaleTool(const Vector3 &position, const Quaternion &rotation, bool locked) {
676+
Vector3 result;
670677
if(ICommandBuffer::isInited()) {
671678
Camera *camera = Camera::current();
672679
if(camera) {
@@ -787,51 +794,150 @@ Vector3 Handles::scaleTool(const Vector3 &position, const Quaternion &rotation,
787794
}
788795
s_Color = s_Normal;
789796
}
797+
798+
Plane plane;
799+
plane.point = position;
800+
plane.normal = camera->actor()->transform()->quaternion() * Vector3(0.0f, 0.0f, 1.0f);
801+
if(s_Axes == AXIS_X) {
802+
plane.normal = Vector3(0.0f, plane.normal.y, plane.normal.z);
803+
} else if(s_Axes == AXIS_Z) {
804+
plane.normal = Vector3(plane.normal.x, plane.normal.y, 0.0f);
805+
} else if(s_Axes == (AXIS_X | AXIS_Z)) {
806+
plane.normal = Vector3(0.0f, 1.0f, 0.0f);
807+
} else if(s_Axes == (AXIS_X | AXIS_Y)) {
808+
plane.normal = Vector3(0.0f, 0.0f, 1.0f);
809+
} else if(s_Axes == (AXIS_Z | AXIS_Y)) {
810+
plane.normal = Vector3(1.0f, 0.0f, 0.0f);
811+
} else if(s_Axes == AXIS_Y || s_Axes == (AXIS_X | AXIS_Y | AXIS_Z)) {
812+
plane.normal = Vector3(plane.normal.x, 0.0f, plane.normal.z);
813+
}
814+
plane.normal.normalize();
815+
plane.d = plane.normal.dot(plane.point);
816+
817+
Ray ray = camera->castRay(s_Mouse.x, s_Mouse.y);
818+
Vector3 point;
819+
ray.intersect(plane, &point, true);
820+
if(s_Axes & AXIS_X) {
821+
result.x = point.x;
822+
}
823+
if(s_Axes & AXIS_Y) {
824+
result.y = point.y;
825+
}
826+
if(s_Axes & AXIS_Z) {
827+
result.z = point.z;
828+
}
790829
}
791-
return Vector3(s_Mouse, 1.0) * 500;
830+
return result;
792831
}
793832

794-
void Handles::rectTool(const Vector3 &position, const Vector2 &size, const Quaternion &rotation, bool locked) {
833+
Vector3 Handles::rectTool(const Vector3 &position, const Vector3 &box, int &axis, bool locked) {
834+
Vector3 result;
795835
if(ICommandBuffer::isInited()) {
796-
Matrix4 model(position, rotation, Vector3(1.0f));
797-
798-
Vector3 tr(size.x * 0.5f, size.y * 0.5f, 0.0f);
799-
Vector3 tl(size.x *-0.5f, size.y * 0.5f, 0.0f);
800-
Vector3 br(size.x * 0.5f, size.y *-0.5f, 0.0f);
801-
Vector3 bl(size.x *-0.5f, size.y *-0.5f, 0.0f);
802-
803-
drawRectangle(position, rotation, size.x, size.y);
804-
805-
if(!locked) {
806-
float sence = Handles::s_Sense * 0.25f;
807-
808-
Handles::s_Axes = 0;
809-
if(HandleTools::distanceToPoint(model, tr) <= sence) {
810-
Handles::s_Axes = Handles::POINT_T | Handles::POINT_R;
811-
} else if(HandleTools::distanceToPoint(model, tl) <= sence) {
812-
Handles::s_Axes = Handles::POINT_T | Handles::POINT_L;
813-
} else if(HandleTools::distanceToPoint(model, br) <= sence) {
814-
Handles::s_Axes = Handles::POINT_B | Handles::POINT_R;
815-
} else if(HandleTools::distanceToPoint(model, bl) <= sence) {
816-
Handles::s_Axes = Handles::POINT_B | Handles::POINT_L;
817-
} else if(HandleTools::distanceToPath(model, {tr, tl}) <= sence) {
818-
Handles::s_Axes = Handles::POINT_T;
819-
} else if(HandleTools::distanceToPath(model, {br, bl}) <= sence) {
820-
Handles::s_Axes = Handles::POINT_B;
821-
} else if(HandleTools::distanceToPath(model, {tr, br}) <= sence) {
822-
Handles::s_Axes = Handles::POINT_R;
823-
} else if(HandleTools::distanceToPath(model, {tl, bl}) <= sence) {
824-
Handles::s_Axes = Handles::POINT_L;
836+
Camera *camera = Camera::current();
837+
838+
if(camera) {
839+
axis = Handles::AXIS_Z;
840+
841+
Plane plane;
842+
plane.normal = Vector3(0.0f, 0.0f, 1.0f);
843+
844+
Vector2 size(box.x, box.y);
845+
846+
Quaternion q;
847+
848+
Vector3 normal = camera->actor()->transform()->quaternion() * plane.normal;
849+
normal.normalize();
850+
if(abs(normal.x) > abs(normal.z)) {
851+
axis = Handles::AXIS_X;
852+
plane.normal = Vector3(1.0f, 0.0f, 0.0f);
853+
size = Vector2(box.z, box.y);
854+
q = Quaternion(Vector3(0.0f, 90.0f, 0.0f));
855+
}
856+
if(abs(normal.y) > abs(normal.x) && abs(normal.y) > abs(normal.x)) {
857+
axis = Handles::AXIS_Y;
858+
plane.normal = Vector3(0.0f, 1.0f, 0.0f);
859+
size = Vector2(box.x, box.z);
860+
q = Quaternion(Vector3(90.0f, 0.0f, 0.0f));
861+
}
862+
863+
plane.point = position;
864+
plane.d = plane.normal.dot(plane.point);
865+
866+
867+
Matrix4 model(position, q, Vector3(1.0f));
868+
869+
Vector3 tr(size.x * 0.5f, size.y * 0.5f, 0.0f);
870+
Vector3 tl(size.x *-0.5f, size.y * 0.5f, 0.0f);
871+
Vector3 br(size.x * 0.5f, size.y *-0.5f, 0.0f);
872+
Vector3 bl(size.x *-0.5f, size.y *-0.5f, 0.0f);
873+
874+
drawRectangle(position, q, size.x, size.y);
875+
876+
Transform *t = camera->actor()->transform();
877+
normal = position - t->position();
878+
float scale = 1.0f;
879+
if(!camera->orthographic()) {
880+
scale = normal.length();
825881
} else {
826-
Camera *camera = Camera::current();
827-
if(camera) {
882+
scale = camera->orthoSize();
883+
}
884+
scale *= (CONTROL_SIZE / s_Screen.y);
885+
886+
drawBillboard(model * tr, Vector2(scale * 0.05f), s_Corner);
887+
drawBillboard(model * tl, Vector2(scale * 0.05f), s_Corner);
888+
drawBillboard(model * br, Vector2(scale * 0.05f), s_Corner);
889+
drawBillboard(model * bl, Vector2(scale * 0.05f), s_Corner);
890+
891+
if(!locked) {
892+
float sence = Handles::s_Sense * 0.25f;
893+
894+
Handles::s_Axes = 0;
895+
if(HandleTools::distanceToPoint(model, tr) <= sence) {
896+
Handles::s_Axes = Handles::POINT_T | Handles::POINT_R;
897+
} else if(HandleTools::distanceToPoint(model, tl) <= sence) {
898+
Handles::s_Axes = Handles::POINT_T | Handles::POINT_L;
899+
} else if(HandleTools::distanceToPoint(model, br) <= sence) {
900+
Handles::s_Axes = Handles::POINT_B | Handles::POINT_R;
901+
} else if(HandleTools::distanceToPoint(model, bl) <= sence) {
902+
Handles::s_Axes = Handles::POINT_B | Handles::POINT_L;
903+
} else if(HandleTools::distanceToPath(model, {tr, tl}) <= sence) {
904+
Handles::s_Axes = Handles::POINT_T;
905+
} else if(HandleTools::distanceToPath(model, {br, bl}) <= sence) {
906+
Handles::s_Axes = Handles::POINT_B;
907+
} else if(HandleTools::distanceToPath(model, {tr, br}) <= sence) {
908+
Handles::s_Axes = Handles::POINT_R;
909+
} else if(HandleTools::distanceToPath(model, {tl, bl}) <= sence) {
910+
Handles::s_Axes = Handles::POINT_L;
911+
} else {
828912
Ray ray = camera->castRay(Handles::s_Mouse.x, Handles::s_Mouse.y);
829913
if(ray.intersect(model * tr, model * tl, model * bl, nullptr, true) ||
830914
ray.intersect(model * bl, model * br, model * tr, nullptr, true)) {
831915
Handles::s_Axes = Handles::POINT_B | Handles::POINT_T | Handles::POINT_L | Handles::POINT_R;
832916
}
833917
}
834918
}
919+
920+
Ray ray = camera->castRay(Handles::s_Mouse.x, Handles::s_Mouse.y);
921+
Vector3 point;
922+
923+
ray.intersect(plane, &point, true);
924+
if(Handles::s_Axes & Handles::POINT_L || Handles::s_Axes & Handles::POINT_R) {
925+
switch(axis) {
926+
case Handles::AXIS_X: result.z = point.z; break;
927+
case Handles::AXIS_Y: result.x = point.x; break;
928+
case Handles::AXIS_Z: result.x = point.x; break;
929+
default: break;
930+
}
931+
}
932+
if(Handles::s_Axes & Handles::POINT_T || Handles::s_Axes & Handles::POINT_B) {
933+
switch(axis) {
934+
case Handles::AXIS_X: result.y = point.y; break;
935+
case Handles::AXIS_Y: result.z = point.z; break;
936+
case Handles::AXIS_Z: result.y = point.y; break;
937+
default: break;
938+
}
939+
}
835940
}
836941
}
942+
return result;
837943
}
173 Bytes
Loading

0 commit comments

Comments
 (0)