1 // Copyright (c) 2011, Thomas Goyne <plorkyeran@aegisub.org>
2 //
3 // Permission to use, copy, modify, and distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 //
15 // Aegisub Project http://www.aegisub.org/
16
17 /// @file visual_tool_rotatez.cpp
18 /// @brief 2D rotation in Z axis visual typesetting tool
19 /// @ingroup visual_ts
20
21 #include "visual_tool_rotatez.h"
22
23 #include "include/aegisub/context.h"
24 #include "selection_controller.h"
25
26 #include <libaegisub/format.h>
27
28 #include <cmath>
29 #include <wx/colour.h>
30
31 static const float deg2rad = 3.1415926536f / 180.f;
32 static const float rad2deg = 180.f / 3.1415926536f;
33
VisualToolRotateZ(VideoDisplay * parent,agi::Context * context)34 VisualToolRotateZ::VisualToolRotateZ(VideoDisplay *parent, agi::Context *context)
35 : VisualTool<VisualDraggableFeature>(parent, context)
36 , org(new Feature)
37 {
38 features.push_back(*org);
39 org->type = DRAG_BIG_TRIANGLE;
40 }
41
Draw()42 void VisualToolRotateZ::Draw() {
43 if (!active_line) return;
44
45 DrawAllFeatures();
46
47 float radius = (pos - org->pos).Len();
48 float oRadius = radius;
49 if (radius < 50)
50 radius = 50;
51
52 // Set up the projection
53 gl.SetOrigin(org->pos);
54 gl.SetRotation(rotation_x, rotation_y, 0);
55 gl.SetScale(scale);
56
57 // Draw the circle
58 gl.SetLineColour(colour[0]);
59 gl.SetFillColour(colour[1], 0.3f);
60 gl.DrawRing(Vector2D(0, 0), radius + 4, radius - 4);
61
62 // Draw markers around circle
63 int markers = 6;
64 float markStart = -90.f / markers;
65 float markEnd = markStart + (180.f / markers);
66 for (int i = 0; i < markers; ++i) {
67 float angle = i * (360.f / markers);
68 gl.DrawRing(Vector2D(0, 0), radius+30, radius+12, 1.0, angle+markStart, angle+markEnd);
69 }
70
71 // Draw the baseline through the origin showing current rotation
72 Vector2D angle_vec(Vector2D::FromAngle(angle * deg2rad));
73 gl.SetLineColour(colour[3], 1, 2);
74 gl.DrawLine(angle_vec * -radius, angle_vec * radius);
75
76 if (org->pos != pos) {
77 Vector2D rotated_pos = Vector2D::FromAngle(angle * deg2rad - (pos - org->pos).Angle()) * oRadius;
78
79 // Draw the line from origin to rotated position
80 gl.DrawLine(Vector2D(), rotated_pos);
81
82 // Draw the line under the text
83 gl.DrawLine(rotated_pos - angle_vec * 20, rotated_pos + angle_vec * 20);
84 }
85
86 // Draw the fake features on the ring
87 gl.SetLineColour(colour[0], 1.f, 1);
88 gl.SetFillColour(colour[1], 0.3f);
89 gl.DrawCircle(angle_vec * radius, 4);
90 gl.DrawCircle(angle_vec * -radius, 4);
91
92 // Clear the projection
93 gl.ResetTransform();
94
95 // Draw line to mouse if it isn't over the origin feature
96 if (mouse_pos && (mouse_pos - org->pos).SquareLen() > 100) {
97 gl.SetLineColour(colour[0]);
98 gl.DrawLine(org->pos, mouse_pos);
99 }
100 }
101
InitializeHold()102 bool VisualToolRotateZ::InitializeHold() {
103 orig_angle = angle + (org->pos - mouse_pos).Angle() * rad2deg;
104 return true;
105 }
106
UpdateHold()107 void VisualToolRotateZ::UpdateHold() {
108 angle = orig_angle - (org->pos - mouse_pos).Angle() * rad2deg;
109
110 if (ctrl_down)
111 angle = floorf(angle / 30.f + .5f) * 30.f;
112
113 angle = fmodf(angle + 360.f, 360.f);
114
115 SetSelectedOverride("\\frz", agi::format("%.4g", angle));
116 }
117
UpdateDrag(Feature * feature)118 void VisualToolRotateZ::UpdateDrag(Feature *feature) {
119 auto org = GetLineOrigin(active_line);
120 if (!org) org = GetLinePosition(active_line);
121 auto d = ToScriptCoords(feature->pos) - org;
122
123 for (auto line : c->selectionController->GetSelectedSet()) {
124 org = GetLineOrigin(line);
125 if (!org) org = GetLinePosition(line);
126 SetOverride(line, "\\org", (d + org).PStr());
127 }
128 }
129
DoRefresh()130 void VisualToolRotateZ::DoRefresh() {
131 if (!active_line) return;
132
133 pos = FromScriptCoords(GetLinePosition(active_line));
134 if (!(org->pos = GetLineOrigin(active_line)))
135 org->pos = pos;
136 else
137 org->pos = FromScriptCoords(org->pos);
138
139 GetLineRotation(active_line, rotation_x, rotation_y, angle);
140 GetLineScale(active_line, scale);
141 }
142