home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
MEDIT.LZH
/
DISPLAY.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-12
|
56KB
|
1,926 lines
/* Project medit
Project Team DoGA
Copyright (c) 1995. All Rights Reserved.
サブシステム: medit.apx Application
ファイル: display.cpp
作成者: Taka2
概要
====
TWinDisplay (TWindow) のインプリメンテーション用のソースファイル
*/
#include <owl\owlpch.h>
#pragma hdrstop
#include <owl\statusba.h>
#include <owl\textgadg.h>
#include "display.h"
#include "anim.h"
#include "motion.h"
#include "bezier.h"
#include "status.h"
#include "syscolor.h"
#include "mecha.h"
#include "log.h"
static const int minimumcube = 1, minimummarker = 4;
double bezierrate[17][4] = {
{4096.0 / 4096.0, 0.0 / 4096.0, 0.0 / 4096.0, 0.0 / 4096.0},
{3375.0 / 4096.0, 675.0 / 4096.0, 45.0 / 4096.0, 1.0 / 4096.0},
{2744.0 / 4096.0, 1176.0 / 4096.0, 168.0 / 4096.0, 8.0 / 4096.0},
{2197.0 / 4096.0, 1521.0 / 4096.0, 351.0 / 4096.0, 27.0 / 4096.0},
{1728.0 / 4096.0, 1728.0 / 4096.0, 576.0 / 4096.0, 64.0 / 4096.0},
{1331.0 / 4096.0, 1815.0 / 4096.0, 825.0 / 4096.0, 125.0 / 4096.0},
{1000.0 / 4096.0, 1800.0 / 4096.0, 1080.0 / 4096.0, 216.0 / 4096.0},
{ 729.0 / 4096.0, 1701.0 / 4096.0, 1323.0 / 4096.0, 343.0 / 4096.0},
{ 512.0 / 4096.0, 1536.0 / 4096.0, 1536.0 / 4096.0, 512.0 / 4096.0},
{ 343.0 / 4096.0, 1323.0 / 4096.0, 1701.0 / 4096.0, 729.0 / 4096.0},
{ 216.0 / 4096.0, 1080.0 / 4096.0, 1800.0 / 4096.0, 1000.0 / 4096.0},
{ 125.0 / 4096.0, 825.0 / 4096.0, 1815.0 / 4096.0, 1331.0 / 4096.0},
{ 64.0 / 4096.0, 576.0 / 4096.0, 1728.0 / 4096.0, 1728.0 / 4096.0},
{ 27.0 / 4096.0, 351.0 / 4096.0, 1521.0 / 4096.0, 2197.0 / 4096.0},
{ 8.0 / 4096.0, 168.0 / 4096.0, 1176.0 / 4096.0, 2744.0 / 4096.0},
{ 1.0 / 4096.0, 45.0 / 4096.0, 675.0 / 4096.0, 3375.0 / 4096.0},
{ 0.0 / 4096.0, 0.0 / 4096.0, 0.0 / 4096.0, 4096.0 / 4096.0},
};
//
// このアプリケーションで処理するすべてのメッセージ/コマンドの
// 応答テーブルを作成する
//
DEFINE_RESPONSE_TABLE1(TWinDisplay, TWindow)
//{{TWinDisplayRSP_TBL_BEGIN}}
EV_WM_LBUTTONDOWN,
EV_WM_MOUSEMOVE,
EV_WM_LBUTTONUP,
EV_WM_RBUTTONDOWN,
//{{TWinDisplayRSP_TBL_END}}
END_RESPONSE_TABLE;
//{{TWinDisplay Implementation}}
TWinDisplay::TWinDisplay(TWindow* parent, AnimationData *d, SelectType sel, int x, int y, int w, int h):
TWindow(parent, 0, 0)
{
SetBkgndColor(TColor::LtGray);
anim = d;
type = sel;
convmatrix = Matrix(1);
markers = 0;
if (sel == SelXY) {
} else if (sel == SelZX) {
convmatrix.v[1] = Vector(0.0, 0.0, -1.0);
convmatrix.v[2] = Vector(0.0, 1.0, 0.0);
} else if (sel == SelYZ) {
convmatrix.v[0] = Vector(0.0, 0.0, 1.0);
convmatrix.v[1] = Vector(1.0, 0.0, 0.0);
convmatrix.v[2] = Vector(0.0, 1.0, 0.0);
} else {
}
Attr.X = x;
Attr.Y = y;
Attr.W = w;
Attr.H = h;
}
TWinDisplay::~TWinDisplay ()
{
Destroy();
// INSERT>> デストラクタ用のコードはここに
}
static void getpoint(Matrix& mat, TPoint& pc, TPoint& vx, TPoint& vy, TPoint& vz, int& zx, int& zy, int& zz)
{
vx = TPoint(int(mat.v[0].x),-int(mat.v[0].y));
vy = TPoint(int(mat.v[1].x),-int(mat.v[1].y));
vz = TPoint(int(mat.v[2].x),-int(mat.v[2].y));
pc = TPoint(int(mat.v[3].x),-int(mat.v[3].y));
zx = int(mat.v[0].z);
zy = int(mat.v[1].z);
zz = int(mat.v[2].z);
}
static void draw5line(TDC& dc, TPoint& center, TPoint& offset, TPoint& p1, TPoint& p2)
{
dc.MoveTo(center+offset+p1-p2);
dc.LineTo(center-offset+p1-p2);
dc.LineTo(center-offset-p1+p2);
dc.LineTo(center+offset-p1+p2);
dc.LineTo(center+offset+p1-p2);
dc.MoveTo(center+offset+p1+p2);
dc.LineTo(center-offset+p1+p2);
// dc.SelectObject(TPen(cBackGround,1,PS_DOT));
// dc.MoveTo(center+offset+p1); dc.LineTo(center-offset+p1);
// dc.MoveTo(center+offset+p2); dc.LineTo(center-offset+p2);
// dc.MoveTo(center+p1-p2); dc.LineTo(center-p1+p2);
}
static void draw4line(TDC& dc, TPoint& center, TPoint& p1, TPoint& p2)
{
dc.MoveTo(center+p1+p2);
dc.LineTo(center+p1-p2);
dc.LineTo(center-p1-p2);
dc.LineTo(center-p1+p2);
dc.LineTo(center+p1+p2);
// dc.SelectObject(TPen(cBackGround,1,PS_DOT));
// dc.MoveTo(center+p1); dc.LineTo(center-p1);
// dc.MoveTo(center+p2); dc.LineTo(center-p2);
}
static void draw9line(TDC& dc, TPoint& pc, TPoint& p1, TPoint& p2, TPoint& p3)
{
dc.MoveTo(pc+p1+p2+p3);
dc.LineTo(pc+p1+p2-p3);
dc.LineTo(pc+p1-p2-p3);
dc.LineTo(pc+p1-p2+p3);
dc.LineTo(pc-p1-p2+p3);
dc.LineTo(pc-p1+p2+p3);
dc.LineTo(pc-p1+p2-p3);
dc.LineTo(pc+p1+p2-p3);
dc.MoveTo(pc-p1+p2+p3);
dc.LineTo(pc+p1+p2+p3);
dc.LineTo(pc+p1-p2+p3);
// dc.SelectObject(TPen(cBackGround,1,PS_DOT));
// dc.MoveTo(pc+p1-p2); dc.LineTo(pc+p1+p2); dc.LineTo(pc-p1+p2);
// dc.MoveTo(pc+p2-p3); dc.LineTo(pc+p2+p3); dc.LineTo(pc-p2+p3);
// dc.MoveTo(pc+p3-p1); dc.LineTo(pc+p3+p1); dc.LineTo(pc-p3+p1);
}
void TWinDisplay::Set4Marker(SelectType type, TPoint& pc, TPoint& p1, TPoint& p2)
{
SelectType t1, t2;
if (type == SelXY) {
t1 = SelX;
t2 = SelY;
} else if (type == SelYZ) {
t1 = SelY;
t2 = SelZ;
} else {
t1 = SelZ;
t2 = SelX;
}
markerpoint[markers] = pc + p1; markertype[markers++] = SelScale | t1;
markerpoint[markers] = pc - p1; markertype[markers++] = SelScale | t1;
markerpoint[markers] = pc + p2; markertype[markers++] = SelScale | t2;
markerpoint[markers] = pc - p2; markertype[markers++] = SelScale | t2;
markerpoint[markers] = pc + p1 + p2; markertype[markers++] = SelRot | type;
markerpoint[markers] = pc + p1 - p2; markertype[markers++] = SelRot | type;
markerpoint[markers] = pc - p1 + p2; markertype[markers++] = SelRot | type;
markerpoint[markers] = pc - p1 - p2; markertype[markers++] = SelRot | type;
}
void TWinDisplay::Set5Marker(SelectType t3, SelectType /*t1*/, SelectType t2, TPoint& pc, TPoint& p3, TPoint& /*p1*/, TPoint& p2)
{
markerpoint[markers] = pc + p2; markertype[markers++] = SelScale | t2;
markerpoint[markers] = pc + p3; markertype[markers++] = SelScale | t3;
markerpoint[markers] = pc - p3; markertype[markers++] = SelScale | t3;
markerpoint[markers] = pc + p2 + p3; markertype[markers++] = SelRot | t2 | t3;
markerpoint[markers] = pc + p2 - p3; markertype[markers++] = SelRot | t2 | t3;
}
void TWinDisplay::Set9Marker(SelectType t, TPoint& pc, TPoint& /*p1*/, TPoint& p2, TPoint& p3)
{
SelectType /*t1, */t2, t3;
if (t == SelX) {
// t1 = SelX;
t2 = SelY;
t3 = SelZ;
} else if (t == SelY) {
// t1 = SelY;
t2 = SelZ;
t3 = SelX;
} else {
// t1 = SelZ;
t2 = SelX;
t3 = SelY;
}
markerpoint[markers] = pc + p2; markertype[markers++] = SelScale | t2;
markerpoint[markers] = pc + p3; markertype[markers++] = SelScale | t3;
markerpoint[markers] = pc + p2 + p3; markertype[markers++] = SelRot | t2 | t3;
markerpoint[markers] = pc + p2 - p3; markertype[markers++] = SelRot | t2 | t3;
markerpoint[markers] = pc - p2 + p3; markertype[markers++] = SelRot | t2 | t3;
}
void TWinDisplay::DrawMarker(TDC& dc)
{
for (int i = markers-1; i > 0; --i) {
switch (markertype[i] & SelMode) {
case SelMove: case SelTarget:
dc.SelectObject(TPen(cMarkerMove));
dc.SelectObject(TBrush(cMarkerMove));
break;
case SelRot:
dc.SelectObject(TPen(cMarkerRot));
dc.SelectObject(TBrush(cMarkerRot));
break;
case SelScale:
dc.SelectObject(TPen(cMarkerScale));
dc.SelectObject(TBrush(cMarkerScale));
break;
}
dc.Rectangle( markerpoint[i].x - markersize,
markerpoint[i].y - markersize,
markerpoint[i].x + markersize,
markerpoint[i].y + markersize);
}
}
void TWinDisplay::ShowCube(Matrix& m, int flag, SelectType t)
{
Matrix mat;
mat = convmatrix * m;
TClientDC dc(*this);
dc.SetROP2(R2_NOTXORPEN);
dc.SelectObject(TPen(cBackGround));
dc.SetBkMode(TRANSPARENT);
TPoint pc, vx, vy, vz;
int zx, zy, zz;
getpoint(mat, pc, vx, vy, vz, zx, zy, zz);
pc.x += Attr.W/2;
pc.y += Attr.H/2;
if (zx < 0) vx = -vx;
if (zy < 0) vy = -vy;
if (zz < 0) vz = -vz;
if (-minimumcube <= zx && zx <= minimumcube) {
if (-minimumcube <= zy && zy <= minimumcube) {
draw4line(dc, pc, vx, vy);
} else if (-minimumcube <= zz && zz <= minimumcube) {
draw4line(dc, pc, vz, vx);
} else {
draw5line(dc, pc, vx, vy, vz);
}
} else if (-minimumcube <= zy && zy <= minimumcube) {
if (-minimumcube <= zz && zz <= minimumcube) {
draw4line(dc, pc, vy, vz);
} else {
draw5line(dc, pc, vy, vz, vx);
}
} else if (-minimumcube <= zz && zz <= minimumcube) {
draw5line(dc, pc, vz, vx, vy);
} else {
draw9line(dc, pc, vx, vy, vz);
}
if (flag) {
markers = 0;
markerpoint[markers] = pc;
markertype[markers++] = SelMove;
if (anim->select->motiondata == NULL) {
markerpoint[markers] = pc;
markertype[markers++] = SelMove;
}
if (-minimummarker <= zx && zx <= minimummarker) {
if (-minimummarker <= zy && zy <= minimummarker) {
Set4Marker(SelXY, pc, vx, vy);
} else if (-minimummarker <= zz && zz <= minimummarker) {
Set4Marker(SelZX, pc, vz, vx);
} else {
if (t & SelZ) {
Set5Marker(SelX, SelZ, SelY, pc, vx, vz, vy);
} else {
Set5Marker(SelX, SelY, SelZ, pc, vx, vy, vz);
}
}
} else if (-minimummarker <= zy && zy <= minimummarker) {
if (-minimummarker <= zz && zz <= minimummarker) {
Set4Marker(SelYZ, pc, vy, vz);
} else {
if (t & SelZ) {
Set5Marker(SelY, SelZ, SelX, pc, vy, vz, vx);
} else {
Set5Marker(SelY, SelX, SelZ, pc, vy, vx, vz);
}
}
} else if (-minimummarker <= zz && zz <= minimummarker) {
if (t & SelY) {
Set5Marker(SelZ, SelY, SelX, pc, vz, vy, vx);
} else {
Set5Marker(SelZ, SelX, SelY, pc, vz, vx, vy);
}
} else {
if (t & SelX) {
Set9Marker(SelX, pc, vx, vy, vz);
} else if (t & SelY) {
Set9Marker(SelY, pc, vy, vz, vx);
} else {
Set9Marker(SelZ, pc, vz, vx, vy);
}
}
dc.SetROP2(R2_COPYPEN);
DrawMarker(dc);
}
}
void TWinDisplay::ShowCamera(Matrix& m, int flag)
{
Matrix mat;
mat = convmatrix * m;
TClientDC dc(*this);
dc.SetROP2(R2_XORPEN);
dc.SetBkMode(TRANSPARENT);
TPoint pc, vx, vy, vz;
int zx, zy, zz;
getpoint(mat, pc, vx, vy, vz, zx, zy, zz);
pc.x += Attr.W/2;
pc.y += Attr.H/2;
dc.SelectObject(TPen(cWireCameraSelect, 1, PS_DOT));
dc.MoveTo(pc); dc.LineTo(pc+vx);
dc.SelectObject(TPen(cWireCameraSelect));
if (vy.x == 0 && vy.y == 0) {
dc.MoveTo(pc); dc.LineTo(pc+vx+vz);
dc.MoveTo(pc); dc.LineTo(pc+vx-vz);
} else if (vz.x == 0 && vz.y == 0) {
dc.MoveTo(pc); dc.LineTo(pc+vx+vy);
dc.MoveTo(pc); dc.LineTo(pc+vx-vy);
} else {
dc.MoveTo(pc); dc.LineTo(pc+vx+vy+vz);
dc.MoveTo(pc); dc.LineTo(pc+vx+vy-vz);
dc.MoveTo(pc); dc.LineTo(pc+vx-vy+vz);
dc.MoveTo(pc); dc.LineTo(pc+vx-vy-vz);
}
if (flag) {
dc.SetROP2(R2_COPYPEN);
markers = 0;
markerpoint[markers] = pc;
markertype[markers++] = SelMove;
if (anim->camera->motiondata == NULL) {
markerpoint[markers] = pc;
markertype[markers++] = SelMove;
markerpoint[markers] = pc+vx;
markertype[markers++] = SelTarget;
}
DrawMarker(dc);
}
}
void TWinDisplay::ShowLight(Vector& vec, int /*flag*/)
{
TClientDC dc(*this);
dc.SetROP2(R2_NOTXORPEN);
dc.SelectObject(TPen(cBackGround));
Vector v = convmatrix * vec;
TPoint pc(Attr.W/2 , Attr.H/2);
TPoint vl(Attr.W/2 - v.x, Attr.H/2 + v.y);
dc.MoveTo(pc);
dc.LineTo(vl);
double l = v.length();
if (l > 1.0) {
v *= ((double)(markersize*8) /l);
TPoint v1(-v.x + 0.5 * v.y, v.y + 0.5 * v.x);
TPoint v2(-v.x - 0.5 * v.y, v.y - 0.5 * v.x);
dc.MoveTo(pc+v1);
dc.LineTo(pc);
dc.LineTo(pc+v2);
dc.SelectObject(TPen(cMarkerLight));
dc.SelectObject(TBrush(cMarkerLight));
dc.SetROP2(R2_XORPEN);
}
markers = 0;
markerpoint[markers] = vl;
markertype[markers++] = SelTarget;
dc.Rectangle( markerpoint[0].x - markersize,
markerpoint[0].y - markersize,
markerpoint[0].x + markersize,
markerpoint[0].y + markersize);
}
int TWinDisplay::GetPositionDistance(Motion *motion, TPoint &point)
{
int cx, cy;
cx = Attr.W / 2;
cy = Attr.H / 2;
Matrix m = anim->GetMatrix(motion);
TPoint p;
if (type == SelXY) {
p.x = cx + m.v[3].x;
p.y = cy - m.v[3].y;
} else if (type == SelYZ) {
p.x = cx + m.v[3].y;
p.y = cy - m.v[3].z;
} else if (type == SelZX) {
p.x = cx + m.v[3].x;
p.y = cy - m.v[3].z;
}
int distance;
if (p.x < point.x) {
distance = point.x - p.x;
} else {
distance = p.x - point.x;
}
if (p.y < point.y) {
distance += point.y - p.y;
} else {
distance += p.y - point.y;
}
return distance;
}
void TWinDisplay::DisplayCursorObject(UINT /*modKeys*/, TPoint& point)
{
Motion *m;
for (m = anim->motion; m != NULL; m = m->next) {
if (GetPositionDistance(m, point) < markersize*2) {
break;
}
}
if (m == NULL && GetPositionDistance(anim->camera, point) < markersize*2) {
m = anim->camera;
}
if (m == NULL && GetPositionDistance(anim->camera->target, point) < markersize*2) {
m = anim->camera->target;
}
anim->Status->DisplayStatusTemp(m);
}
void TWinDisplay::DrawBezier(Bezier *bezier)
{
Matrix m = GetMatrix();
TClientDC dc(*this);
// dc.SetROP2(R2_NOTXORPEN);
// dc.SelectObject(TPen(cBackGround));
dc.SetROP2(R2_XORPEN);
dc.SelectObject(TPen(cWireLocusSelect));
dc.SetBkMode(TRANSPARENT);
Vector v0 = m * bezier->point[0];
Vector v1 = m * bezier->point[1];
Vector v2 = m * bezier->point[2];
Vector v3 = m * bezier->point[3];
dc.MoveTo(v0.x, v0.y);
for (int i = 1; i < 16; ++i) {
double vx = v0.x * bezierrate[i][0] + v1.x * bezierrate[i][1] + v2.x * bezierrate[i][2] + v3.x * bezierrate[i][3];
double vy = v0.y * bezierrate[i][0] + v1.y * bezierrate[i][1] + v2.y * bezierrate[i][2] + v3.y * bezierrate[i][3];
dc.LineTo(vx, vy);
}
dc.LineTo(v3.x, v3.y);
Vector v01 = m * ((3.0 / 2.0) * bezier->point[0] - (1.0/2.0) * bezier->point[1]);
Vector v32 = m * ((3.0 / 2.0) * bezier->point[3] - (1.0/2.0) * bezier->point[2]);
dc.SelectObject(TPen(cWireBezierSelect,1,PS_DOT));
dc.MoveTo(v0.x, v0.y);
dc.LineTo(v01.x, v01.y);
dc.MoveTo(v3.x, v3.y);
dc.LineTo(v32.x, v32.y);
}
static int distance(TPoint& p1, TPoint& p2)
{
int dist;
TPoint p = p1 - p2;
if (p.x < 0) {
dist = -p.x;
} else {
dist = p.x;
}
if (p.y < 0) {
dist += -p.y;
} else {
dist += p.y;
}
return dist;
}
void TWinDisplay::OpCubeBegin(UINT /*modKeys*/, TPoint& point)
{
if (anim->select == NULL
|| (anim->select->motiondata == NULL
&& (anim->selectframe < anim->select->beginframe || anim->select->endframe < anim->selectframe))
|| (anim->select->motiondata != NULL
&& (anim->selectframe != anim->select->beginframe && anim->selectframe != anim->select->endframe))) {
return;
}
for (int i = 1; i < markers; ++i) {
if (distance(anim->drag_point, markerpoint[i]) < markersize * 2) {
break;
}
}
if (i == markers) {
return;
}
double rx, ry, len;
Matrix m;
Vector v;
anim->selectstatus = markertype[i];
anim->GetCubeMatrix(anim->select, anim->drag_move, anim->drag_rot, anim->drag_scale);
anim->drag_mat = anim->drag_move * anim->drag_rot * anim->drag_scale;
switch (markertype[i] & SelMode) {
case SelRot:
// anim->statusbar->SetText("向き設定中");
m = convmatrix * anim->drag_rot;
rx = anim->drag_px[0] = (double)(point.x - markerpoint[0].x);
ry = anim->drag_px[1] = (double)(point.y - markerpoint[0].y);
switch (markertype[i] & SelXYZ) {
case SelYZ: v = m.v[0]; break;
case SelZX: v = m.v[1]; break;
case SelXY: v = m.v[2]; break;
}
if (v.z > 0.0) {
anim->drag_py[0] = anim->drag_px[1];
anim->drag_py[1] = -anim->drag_px[0];
} else {
anim->drag_py[0] = -anim->drag_px[1];
anim->drag_py[1] = anim->drag_px[0];
}
anim->drag_point = markerpoint[0];
len = rx*rx+ry*ry;
if (len > 0.0) {
anim->drag_rx = rx / len * deg(90.0);
anim->drag_ry = ry / len * deg(90.0);
} else {
anim->drag_rx = anim->drag_ry = 0;
}
break;
case SelScale:
// anim->statusbar->SetText("大きさ設定中");
anim->drag_point = markerpoint[0];
rx = double(point.x - markerpoint[0].x);
ry = double(point.y - markerpoint[0].y);
len = rx * rx + ry * ry;
if (len > minimumdouble) {
anim->drag_rx = rx / len;
anim->drag_ry = ry / len;
} else {
anim->drag_rx = anim->drag_ry = 0;
}
break;
}
if (type == SelXY) {
v.x = double(point.x - anim->drag_point.x);
v.y = -double(point.y - anim->drag_point.y);
v.z = 0.0;
} else if (type == SelYZ) {
v.x = 0.0;
v.y= double(point.x - anim->drag_point.x);
v.z = -double(point.y - anim->drag_point.y);
} else {
v.x = double(point.x - anim->drag_point.x);
v.y = 0.0;
v.z = -double(point.y - anim->drag_point.y);
}
}
static void SelectOne(Vector& v)
{
double px, py, pz;
if ((px = v.x) < 0.0) px = -px;
if ((py = v.y) < 0.0) py = -py;
if ((pz = v.z) < 0.0) pz = -pz;
if (px > py && px > pz) {
v.y = v.z = 0.0;
} else if (py > pz) {
v.x = v.z = 0.0;
} else {
v.x = v.y = 0.0;
}
}
static void engrid(Vector& v, int grid)
{
if (v.x > 0) {
v.x = (double)( ((long)( v.x) + grid/2) / grid) * (double) grid;
} else {
v.x = -(double)( ((long)(-v.x) + grid/2) / grid) * (double) grid;
}
if (v.y > 0) {
v.y = (double)( ((long)( v.y) + grid/2) / grid) * (double) grid;
} else {
v.y = -(double)( ((long)(-v.y) + grid/2) / grid) * (double) grid;
}
if (v.z > 0) {
v.z = (double)( ((long)( v.z) + grid/2) / grid) * (double) grid;
} else {
v.z = -(double)( ((long)(-v.z) + grid/2) / grid) * (double) grid;
}
}
static void limit(Vector& v)
{
if (v.x > limitdim) v.x = limitdim;
if (v.x < -limitdim) v.x = -limitdim;
if (v.y > limitdim) v.y = limitdim;
if (v.y < -limitdim) v.y = -limitdim;
if (v.z > limitdim) v.z = limitdim;
if (v.z < -limitdim) v.z = -limitdim;
}
void TWinDisplay::OpCubeDrag(UINT modKeys, TPoint& point, Vector& v)
{
Matrix nmat;
Vector tmpvec;
Vector l;
double r;
double px, py;
switch (anim->selectstatus & SelMode) {
case SelMove:
if (modKeys & MK_SHIFT) {
SelectOne(v);
}
tmpvec = anim->select->position + (1.0/anim->displayscale)*v;
limit(tmpvec);
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
engrid(tmpvec, anim->gridspacing);
}
if (anim->select == anim->camera) {
Vector v0 = anim->camera->target->position - anim->camera->position;
double l0 = v0.length(), s;
if (l0 > minimumdouble) {
s = (anim->camera->target->position - tmpvec).length() / l0;
} else {
s = 0.0;
}
nmat = (anim->camera->target->position - tmpvec) ^ Vector(0,0,1);
nmat = anim->drag_move.move(tmpvec-anim->select->position)
* nmat * anim->drag_scale.scale(s);
} else {
nmat = anim->drag_move.move(tmpvec-anim->select->position)
* anim->drag_rot * anim->drag_scale;
}
anim->Status->DisplayPosition(tmpvec);
anim->ShowCube(anim->drag_mat, nmat);
anim->drag_mat = nmat;
break;
case SelTarget: {
if (modKeys & MK_SHIFT) {
SelectOne(v);
}
tmpvec = anim->camera->target->position + (1.0/anim->displayscale) * v;
limit(tmpvec);
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
engrid(tmpvec, anim->gridspacing);
}
Vector v0 = anim->camera->target->position - anim->camera->position;
double l0 = v0.length(), s;
if (l0 > minimumdouble) {
s = (tmpvec - anim->camera->position).length() / l0;
} else {
s = 0.0;
}
nmat = (tmpvec - anim->camera->position) ^ Vector(0.0, 0.0, 1.0);
nmat = anim->drag_move * nmat * anim->drag_scale.scale(s);
anim->Status->DisplayTarget(tmpvec);
anim->ShowCube(anim->drag_mat, nmat);
anim->drag_mat = nmat;
break;
}
case SelRot:
r = anim->drag_rx * (point.x - anim->drag_point.x)
+ anim->drag_ry * (point.y - anim->drag_point.y);
px = anim->drag_px[0] * (point.x - anim->drag_point.x)
+ anim->drag_px[1] * (point.y - anim->drag_point.y);
py = anim->drag_py[0] * (point.x - anim->drag_point.x)
+ anim->drag_py[1] * (point.y - anim->drag_point.y);
if (-minimumdouble < px && px < minimumdouble
&& -minimumdouble < py && py < minimumdouble) {
nmat = anim->drag_rot;
} else {
switch (anim->selectstatus & SelXYZ) {
case SelXY:
nmat = anim->drag_rot.rotz(atan2(py, px));
break;
case SelYZ:
nmat = anim->drag_rot.rotx(atan2(py, px));
break;
case SelZX:
nmat = anim->drag_rot.roty(atan2(py, px));
break;
}
}
tmpvec = nmat.GetRotation();
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
tmpvec *= rad(1.0);
engrid(tmpvec, anim->rotspacing);
tmpvec *= deg(1.0);
nmat = Matrix::m_rot(tmpvec);
}
nmat = anim->drag_move * nmat * anim->drag_scale;
anim->Status->DisplayRotation(tmpvec);
anim->ShowCube(anim->drag_mat, nmat);
anim->drag_mat = nmat;
break;
case SelScale:
r = anim->drag_rx * (double)(point.x - anim->drag_point.x)
+ anim->drag_ry * (double)(point.y - anim->drag_point.y);
tmpvec = anim->select->scale;
nmat = Matrix(1);
if (modKeys & MK_SHIFT) {
nmat.v[0].x = nmat.v[1].y = nmat.v[2].z = r;
tmpvec *= r;
} else {
if (anim->selectstatus & SelX) { nmat.v[0].x = r; tmpvec.x *= r;}
if (anim->selectstatus & SelY) { nmat.v[1].y = r; tmpvec.y *= r;}
if (anim->selectstatus & SelZ) { nmat.v[2].z = r; tmpvec.z *= r;}
}
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
Vector org = tmpvec;
tmpvec *= scalespacingfactor;
engrid(tmpvec, anim->scalespacing);
tmpvec *= (1.0/scalespacingfactor);
if (org.x < -minimumdouble || minimumdouble < org.x) nmat.v[0].x *= tmpvec.x / org.x;
if (org.y , -minimumdouble || minimumdouble < org.y) nmat.v[1].y *= tmpvec.y / org.y;
if (org.z < -minimumdouble || minimumdouble < org.z) nmat.v[2].z *= tmpvec.z / org.z;
}
nmat = anim->drag_move * anim->drag_rot * anim->drag_scale * nmat;
anim->ShowCube(anim->drag_mat, nmat);
anim->drag_mat = nmat;
anim->Status->DisplayScale(tmpvec);
break;
}
}
void TWinDisplay::OpCubeEnd(UINT modKeys, TPoint& point, Vector& v)
{
Vector tmpvec;
Motion *s = anim->select;
switch (anim->selectstatus & SelMode) {
case SelMode:
break;
case SelMove:
if (modKeys & MK_SHIFT) {
SelectOne(v);
}
tmpvec = anim->select->position;
anim->select->position += (1.0/anim->displayscale) * v;
limit(anim->select->position);
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
engrid(anim->select->position, anim->gridspacing);
}
if (tmpvec != anim->select->position) {
if (anim->select == anim->camera) {
anim->camera->GetPosition(anim->selectframe);
anim->CalcPoints(anim->select);
anim->CalcViewAll();
} else {
anim->CalcPoints(anim->select);
}
anim->editflag++;
anim->Redraw();
}
break;
case SelTarget:
if (modKeys & MK_SHIFT) {
SelectOne(v);
}
tmpvec = anim->camera->target->position + (1.0 / anim->displayscale) * v;
limit(tmpvec);
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
engrid(tmpvec, anim->gridspacing);
}
if (tmpvec != anim->camera->target->position) {
anim->camera->target->position = tmpvec;
anim->camera->GetPosition(anim->selectframe);
anim->CalcPoints(anim->camera);
anim->CalcViewAll();
anim->editflag++;
anim->Redraw();
}
break;
case SelRot: {
double px, py;
Matrix nmat;
px = anim->drag_px[0] * (point.x - anim->drag_point.x)
+ anim->drag_px[1] * (point.y - anim->drag_point.y);
py = anim->drag_py[0] * (point.x - anim->drag_point.x)
+ anim->drag_py[1] * (point.y - anim->drag_point.y);
if (-minimumdouble < px && px < minimumdouble
&& -minimumdouble < py && py < minimumdouble) {
nmat = anim->drag_rot;
} else {
switch (anim->selectstatus & SelXYZ) {
case SelXY:
nmat = anim->drag_rot.rotz(atan2(py, px));
break;
case SelYZ:
nmat = anim->drag_rot.rotx(atan2(py, px));
break;
case SelZX:
nmat = anim->drag_rot.roty(atan2(py, px));
break;
}
}
Vector tmprot = s->rotation;
s->rotation = nmat.GetRotation();
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
Vector tmpvec = rad(1.0) * s->rotation;
engrid(tmpvec, anim->rotspacing);
s->rotation = deg(1.0) * tmpvec;
}
if (tmprot != s->rotation) {
if (s->motiondata != NULL) {
if (anim->selectframe == anim->select->beginframe) {
s->motiondata->rotation[0] = s->rotation;
} else {
s->motiondata->rotation[1] = s->rotation;
if (s->motiondata->dirtype == DirForward) {
s->motiondata->dirtype = DirLinear;
}
}
}
anim->CalcPoints(anim->select);
anim->editflag++;
anim->Redraw();
} else {
anim->Status->DisplayStatus(FALSE);
}
}
break;
case SelScale: {
double r;
r = anim->drag_rx * (point.x - anim->drag_point.x)
+ anim->drag_ry * (point.y - anim->drag_point.y);
Vector tmpvec = s->scale;
if (modKeys & MK_SHIFT) {
tmpvec *= r;
} else {
if (anim->selectstatus & SelX) tmpvec.x *= r;
if (anim->selectstatus & SelY) tmpvec.y *= r;
if (anim->selectstatus & SelZ) tmpvec.z *= r;
}
int redrawflag;
redrawflag = s->scale != tmpvec;
if (tmpvec.x > 10000.0) { tmpvec.x = 10000.0; redrawflag = TRUE; }
if (tmpvec.y > 10000.0) { tmpvec.y = 10000.0; redrawflag = TRUE; }
if (tmpvec.z > 10000.0) { tmpvec.z = 10000.0; redrawflag = TRUE; }
if (tmpvec.x < -10000.0) { tmpvec.x = -10000.0; redrawflag = TRUE; }
if (tmpvec.y < -10000.0) { tmpvec.y = -10000.0; redrawflag = TRUE; }
if (tmpvec.z < -10000.0) { tmpvec.z = -10000.0; redrawflag = TRUE; }
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
tmpvec *= scalespacingfactor;
engrid(tmpvec, anim->scalespacing);
tmpvec *= (1.0/scalespacingfactor);
}
if ((-minimumdouble < tmpvec.x && tmpvec.x < minimumdouble)
|| (-minimumdouble < tmpvec.y && tmpvec.y < minimumdouble)
|| (-minimumdouble < tmpvec.z && tmpvec.z < minimumdouble)) {
Matrix nmat = anim->drag_move * anim->drag_rot * anim->drag_scale;
anim->ShowCube(anim->drag_mat, nmat);
anim->Status->DisplayScale(s->scale);
} else if (redrawflag) {
s->scale = tmpvec;
if (s->motiondata != NULL) {
if (anim->selectframe == anim->select->beginframe) {
s->motiondata->scale[0] = s->scale;
} else {
s->motiondata->scale[1] = s->scale;
// if (s->motiondata->dirtype == DirForward) {
// s->motiondata->dirtype = DirLinear;
// }
}
}
anim->CalcPoints(anim->select);
anim->Redraw();
anim->editflag++;
} else {
anim->Status->DisplayStatus(FALSE);
}
}
break;
}
}
void TWinDisplay::OpBezierBegin(UINT modKeys, TPoint& point)
{
int i;
if (anim->select == NULL || anim->select->motiondata == NULL) {
return;
}
Matrix m = GetMatrix();
Bezier *bezier = anim->select->motiondata->bezier;
Vector v;
// 選択フレームが制御点の場合には、その点を優先的に選択可能
if (anim->selectframe == anim->select->beginframe) {
v = m * bezier->point[0];
if (distance(TPoint(v.x, v.y), point) < markersize*2) {
anim->drag_count = 0;
anim->org_point = bezier->point[0];
anim->selectstatus = SelCube;
if ((modKeys & MK_SHIFT) != 0) {
anim->drag_count = 1;
anim->selectstatus = SelBezier;
}
}
} else if (anim->selectframe == anim->select->endframe) {
v = m * bezier->point[3];
if (distance(TPoint(v.x, v.y), point) < markersize*2) {
anim->drag_count = 3;
anim->org_point = bezier->point[3];
anim->selectstatus = SelCube;
if ((modKeys & MK_SHIFT) != 0) {
anim->drag_count = 2;
anim->selectstatus = SelBezier;
}
}
}
// 残りの制御点の中から探す
if (anim->selectstatus == SelMode) {
int selno[4];
Vector ov[4];
ov[0] = bezier->point[0];
ov[1] = ((3.0 / 2.0) * bezier->point[0] - (1.0/2.0) * bezier->point[1]);
ov[2] = ((3.0 / 2.0) * bezier->point[3] - (1.0/2.0) * bezier->point[2]);
ov[3] = bezier->point[3];
if ((modKeys & MK_SHIFT) != 0) {
selno[0] = 1; selno[1] = 2; selno[2] = 0; selno[3] = 3;
} else {
selno[0] = 0; selno[1] = 3; selno[2] = 1; selno[3] = 2;
}
for (i = 0; i < 4; ++i) {
Vector v = m * ov[selno[i]];
if (distance(TPoint(v.x, v.y), point) < markersize*2) {
anim->selectstatus = SelBezier;
anim->drag_count = selno[i];
anim->org_point = ov[selno[i]];
break;
}
}
}
if (anim->selectstatus == SelCube) {
if (anim->select == anim->camera->target) {
anim->GetCubeMatrix(anim->camera, anim->drag_move, anim->drag_rot, anim->drag_scale);
} else {
anim->GetCubeMatrix(anim->select, anim->drag_move, anim->drag_rot, anim->drag_scale);
}
anim->drag_mat = anim->drag_move * anim->drag_rot * anim->drag_scale;
}
if (anim->selectstatus != SelMode) {
if (anim->select->motiondata != NULL && anim->select->motiondata->dirtype == DirForward) {
anim->org_vector = anim->select->motiondata->bezier->GetVector(0.0);
}
if (anim->drag_count % 3 == 0) {
// anim->statusbar->SetText("位置設定中");
} else {
// anim->statusbar->SetText("進行方向設定中");
}
} else if (anim->select == anim->camera) {
anim->select = anim->camera->target;
OpBezierBegin(modKeys, point);
if (anim->selectstatus == SelMode) {
anim->select = anim->camera;
}
}
}
void TWinDisplay::OpBezierDrag(UINT modKeys, TPoint& /*point*/, Vector& v)
{
Bezier *bezier = anim->select->motiondata->bezier;
double diff = (1.0 / anim->displayscale) * markersize * 3;
anim->DrawBezier(bezier);
if (modKeys & MK_SHIFT) {
SelectOne(v);
}
Vector tmpvec = anim->org_point + (1.0 / anim->displayscale) * v;
if (anim->drag_count== 1
&& bezier->point[0].x-diff < tmpvec.x && tmpvec.x < bezier->point[0].x+diff
&& bezier->point[0].y-diff < tmpvec.y && tmpvec.y < bezier->point[0].y+diff
&& bezier->point[0].z-diff < tmpvec.z && tmpvec.z < bezier->point[0].z+diff) {
tmpvec = bezier->point[0];
} else if (anim->drag_count== 2
&& bezier->point[3].x-diff < tmpvec.x && tmpvec.x < bezier->point[3].x+diff
&& bezier->point[3].y-diff < tmpvec.y && tmpvec.y < bezier->point[3].y+diff
&& bezier->point[3].z-diff < tmpvec.z && tmpvec.z < bezier->point[3].z+diff) {
tmpvec = bezier->point[3];
} else {
limit(tmpvec);
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
Vector ovec = tmpvec;
engrid(tmpvec, anim->gridspacing);
if (type == SelXY) {
tmpvec.z = ovec.z;
} else if (type == SelYZ) {
tmpvec.x = ovec.x;
} else {
tmpvec.y = ovec.y;
}
}
}
if (anim->drag_count == 1) {
Vector mvec = 3.0 * bezier->point[0] - 2.0 * tmpvec;
bezier->MovePoint(1, mvec, BCsame);
} else if (anim->drag_count == 2) {
Vector mvec = 3.0 * bezier->point[3] - 2.0 * tmpvec;
bezier->MovePoint(2, mvec, BCsame);
} else {
bezier->MovePoint(anim->drag_count, tmpvec, BCsame);
}
if (anim->selectstatus == SelCube && anim->select == anim->camera) {
Matrix nmat;
Vector v0 = anim->camera->target->position - anim->camera->position;
double l0 = v0.length(), s;
if (l0 > minimumdouble) {
s = (anim->camera->target->position - tmpvec).length() / l0;
} else {
s = 0.0;
}
nmat = (anim->camera->target->position - tmpvec) ^ Vector(0,0,1);
nmat = anim->drag_move.move(tmpvec-anim->camera->position)
* nmat * anim->drag_scale.scale(s);
anim->ShowCube(anim->drag_mat, nmat);
anim->drag_mat = nmat;
} else if (anim->selectstatus == SelCube && anim->select == anim->camera->target) {
Matrix nmat;
Vector v0 = anim->camera->target->position - anim->camera->position;
double l0 = v0.length(), s;
if (l0 > minimumdouble) {
s = (tmpvec - anim->camera->position).length() / l0;
} else {
s = 0.0;
}
nmat = (tmpvec - anim->camera->position) ^ Vector(0.0, 0.0, 1.0);
nmat = anim->drag_move * nmat * anim->drag_scale.scale(s);
anim->ShowCube(anim->drag_mat, nmat);
anim->drag_mat = nmat;
} else if (anim->selectstatus == SelCube) {
Matrix nmat = Matrix::m_move(anim->displayoffset).scale(anim->displayscale).move(tmpvec)
* anim->drag_rot * anim->drag_scale;
anim->ShowCube(anim->drag_mat, nmat);
anim->drag_mat = nmat;
}
if (anim->select == anim->camera->target) {
anim->Status->DisplayTarget(tmpvec);
} else {
anim->Status->DisplayPosition(tmpvec);
}
anim->DrawBezier(bezier);
}
void TWinDisplay::OpBezierEnd(UINT modKeys, TPoint& /*point*/, Vector& v)
{
Bezier *bezier = anim->select->motiondata->bezier;
Vector tmpvec = anim->org_point + (1.0 / anim->displayscale) * v;
limit(tmpvec);
if (((modKeys & MK_CONTROL) != 0) ^ (anim->gridflag != FALSE)) {
Vector ovec = tmpvec;
engrid(tmpvec, anim->gridspacing);
if (type == SelXY) {
tmpvec.z = ovec.z;
} else if (type == SelYZ) {
tmpvec.x = ovec.x;
} else {
tmpvec.y = ovec.y;
}
}
if (anim->org_point != tmpvec) {
if (anim->select->motiondata->dirtype == DirForward) {
Vector& v1 = anim->org_vector;
Vector v2 = bezier->GetVector(0.0);
if (v1 != v2) {
anim->select->motiondata->SetAnyAxis(v1, v2);
}
#if 0
if (anim->drag_count == 1
|| (anim->drag_count > 1 && bezier->point[0] == bezier->point[1])) {
// Vector v1 = bezier->point[0] - anim->org_point;
// Vector v2 = bezier->point[0] - tmpvec;
anim->select->motiondata->SetAnyAxis(v1, v2);
}
#endif
}
if (anim->select == anim->camera || anim->select == anim->camera->target) {
anim->camera->GetPosition(anim->selectframe);
anim->CalcPoints(anim->camera);
anim->CalcViewAll();
} else {
anim->select->GetPosition(anim->selectframe);
anim->CalcPoints(anim->select);
}
anim->editflag++;
anim->Redraw();
} else {
anim->Status->DisplayStatus(FALSE);
}
if (anim->select == anim->camera->target) {
anim->select = anim->camera;
}
}
void TWinDisplay::OpZoomBegin(UINT /*modKeys*/, TPoint& point)
{
Vector v;
if (type == SelXY) {
v.x = double(point.x - Attr.W/2);
v.y = -double(point.y - Attr.H/2);
v.z = 0.0;
} else if (type == SelYZ) {
v.x = 0.0;
v.y= double(point.x - Attr.W/2);
v.z = -double(point.y - Attr.H/2);
} else {
v.x = double(point.x - Attr.W/2);
v.y = 0.0;
v.z = -double(point.y - Attr.H/2);
}
anim->displayoffset -= v;
anim->displayscale *= 4;
anim->displayoffset *= 4;
anim->SetScrollLimit(TRUE);
anim->zoomflag = TRUE;
anim->opstat = OpDefault;
anim->CalcPointsAll();
anim->Redraw(SelXYZ);
anim->Status->Redraw();
}
void TWinDisplay::OpLightBegin(UINT /*modKeys*/, TPoint& point)
{
if (distance(markerpoint[0], point) < markersize*2) {
anim->drag_point = point;
anim->selectstatus = SelTarget;
anim->org_vector = anim->org_point;
SetCapture();
}
}
void TWinDisplay::OpLightDrag(UINT /*modKeys*/, TPoint& /*point*/, Vector& v)
{
Vector tmpvec = anim->org_point - v;
anim->ShowLight(anim->org_vector, tmpvec);
anim->org_vector = tmpvec;
double l = tmpvec.length();
if (l > minimumdouble) {
tmpvec *= (100.0/l);
}
anim->Status->DisplayPosition(tmpvec);
}
void TWinDisplay::OpLightEnd(UINT /*modKeys*/, TPoint& /*point*/, Vector& /*v*/)
{
anim->org_point = anim->org_vector;
anim->editflag++;
ReleaseCapture();
}
void TWinDisplay::OpSelectMotion(UINT /*modKeys*/, TPoint& point, Vector& /*v*/)
{
Matrix mat = GetMatrix();
const int maxSelObj=128;
const int maxSelDist=markersize*10;
Motion *sel[maxSelObj];
int pnt[maxSelObj];
int dis[maxSelObj];
int d, i, count = 0;
Motion *m;
if ((m = anim->motion) == NULL) {
m = anim->camera;
}
for (;;) {
if (m->motiondata == NULL
|| (m->beginframe < anim->selectframe && anim->selectframe < m->endframe)) {
Vector v = mat * m->position;
if ((d = distance(TPoint(v.x, v.y), point)) < maxSelDist) {
if (count < maxSelObj || dis[count-1] > d) {
if (count < maxSelObj) {
count++;
}
for (i = count-1; i > 0; --i) {
if (dis[i-1] < d) {
break;
}
dis[i] = dis[i-1];
sel[i] = sel[i-1];
pnt[i] = pnt[i-1];
}
dis[i] = d;
if (m == anim->camera->target && anim->camera->motiondata == NULL) {
sel[i] = anim->camera;
} else {
sel[i] = m;
}
pnt[i] = -1;
}
}
}
if (m->motiondata != NULL) {
for (int n = 0; n <2; ++n) {
Vector v = mat * m->motiondata->bezier->point[n*3];
if ((d = distance(TPoint(v.x, v.y), point)) < maxSelDist) {
if (count < maxSelObj || dis[count-1] > d) {
if (count < maxSelObj) {
count++;
}
for (i = count-1; i > 0; --i) {
if (dis[i-1] < d) {
break;
}
dis[i] = dis[i-1];
sel[i] = sel[i-1];
pnt[i] = pnt[i-1];
}
dis[i] = d;
sel[i] = m;
pnt[i] = n;
}
}
}
}
if (m == anim->camera->target) {
break;
} else if (m == anim->camera) {
m = anim->camera->target;
} else if (m->next == NULL) {
m = anim->camera;
} else {
m = m->next;
}
}
Motion *selm = NULL;
int selp = -1;
if (count > 0) {
if (anim->select == NULL) {
selm = sel[0];
selp = pnt[0];
} else {
for (i = 0; i < count-1; ++i) {
if (sel[i] == anim->select
&& (pnt[i] < 0
|| (pnt[i] == 0 && anim->selectframe == sel[i]->beginframe)
|| (pnt[i] == 1 && anim->selectframe == sel[i]->endframe))) {
selm = sel[i+1];
selp = pnt[i+1];
break;
}
}
if (i == count-1) {
selm = sel[0];
selp = pnt[0];
}
}
}
if (selm == anim->camera->target && anim->camera->motiondata == NULL) {
selm = anim->camera;
}
if (selm != NULL) {
anim->SelectMotion(selm);
if (selm->motiondata == NULL) {
if (anim->selectframe < selm->beginframe) {
anim->SelectFrame(selm->beginframe);
} else if (anim->selectframe > selm->endframe) {
anim->SelectFrame(selm->endframe);
}
} else {
if (selp == 0) {
anim->SelectFrame(selm->beginframe);
} else if (selp == 1) {
anim->SelectFrame(selm->endframe);
}
}
anim->Redraw();
}
}
void TWinDisplay::OpSelectMotionAndDrag(UINT /*modKeys*/, TPoint& point, Vector& /*v*/)
{
if (anim->select != NULL) {
return;
}
Matrix mat = GetMatrix();
int seld = markersize*2, d;
Motion *selm = NULL;
for (Motion *m = anim->motion; m != NULL;m = m->next) {
Vector v = mat * m->position;
if ((d = distance(TPoint(v.x, v.y), point)) < seld) {
seld = d;
selm = m;
}
}
m = anim->camera; {
Vector v = mat * m->position;
if ((d = distance(TPoint(v.x, v.y), point)) < seld) {
seld = d;
selm = m;
}
}
m = anim->camera->target; {
Vector v = mat * m->position;
if ((d = distance(TPoint(v.x, v.y), point)) < seld) {
seld = d;
selm = m;
}
}
if (selm != NULL) {
if (selm->motiondata == NULL) {
if (selm == anim->camera->target) {
anim->SelectMotion(anim->camera);
anim->selectstatus = SelTarget;
} else {
anim->SelectMotion(selm);
anim->selectstatus = SelMove;
}
anim->GetCubeMatrix(anim->select, anim->drag_move, anim->drag_rot, anim->drag_scale);
anim->Redraw();
anim->drag_mat = anim->drag_move * anim->drag_rot * anim->drag_scale;
#if 0
anim->SelectMotion(selm);
anim->selectstatus = SelMove;
if (selm == anim->camera->target) {
anim->SelectMotion(anim->camera);
anim->selectstatus = SelTarget;
anim->GetCubeMatrix(anim->camera, anim->drag_move, anim->drag_rot, anim->drag_scale);
} else {
anim->GetCubeMatrix(anim->select, anim->drag_move, anim->drag_rot, anim->drag_scale);
}
anim->Redraw();
anim->drag_mat = anim->drag_move * anim->drag_rot * anim->drag_scale;
#endif
} else if (selm->beginframe == anim->selectframe || selm->endframe == anim->selectframe) {
anim->SelectMotion(selm);
anim->Redraw();
anim->selectstatus = SelCube;
anim->drag_count = (selm->beginframe == anim->selectframe) ? 0 : 3;
anim->org_point = selm->position;
if (anim->select == anim->camera->target) {
anim->GetCubeMatrix(anim->camera, anim->drag_move, anim->drag_rot, anim->drag_scale);
} else {
anim->GetCubeMatrix(anim->select, anim->drag_move, anim->drag_rot, anim->drag_scale);
}
anim->drag_mat = anim->drag_move * anim->drag_rot * anim->drag_scale;
} else {
anim->SelectMotion(selm);
anim->selectstatus = SelNone;
anim->Redraw();
}
}
}
void TWinDisplay::EvLButtonDown (UINT modKeys, TPoint& point)
{
TWindow::EvLButtonDown(modKeys, point);
// INSERT>> 追加コードはここに
switch(anim->opstat) {
case OpDefault:
anim->selectstatus = SelMode;
anim->drag_point = point;
break;
case OpSelZoom:
OpZoomBegin(modKeys, point);
break;
case OpLight:
OpLightBegin(modKeys, point);
break;
case OpPlay:
anim->OpModeDefault();
break;
}
anim->drag_point = point;
}
void TWinDisplay::EvMouseMove (UINT modKeys, TPoint& point)
{
TWindow::EvMouseMove(modKeys, point);
// INSERT>> 追加コードはここに
if (anim->selectstatus == SelNone) {
if (anim->opstat != OpLight && anim->select == NULL) {
DisplayCursorObject(modKeys, point);
}
return;
}
Vector v;
if (type == SelXY) {
v.x = double(point.x - anim->drag_point.x);
v.y = -double(point.y - anim->drag_point.y);
v.z = 0.0;
} else if (type == SelYZ) {
v.x = 0.0;
v.y= double(point.x - anim->drag_point.x);
v.z = -double(point.y - anim->drag_point.y);
} else {
v.x = double(point.x - anim->drag_point.x);
v.y = 0.0;
v.z = -double(point.y - anim->drag_point.y);
}
switch(anim->opstat) {
case OpDefault:
if (anim->selectstatus == SelMode) {
if (anim->select != NULL) {
OpCubeBegin(modKeys, point);
if (anim->selectstatus == SelMode) {
OpBezierBegin(modKeys, point);
}
} else {
OpSelectMotionAndDrag(modKeys, point, v);
}
if (anim->selectstatus == SelMode) {
anim->selectstatus = SelNone;
} else {
SetCapture();
}
}
if (anim->selectstatus == SelBezier || anim->selectstatus == SelCube) {
OpBezierDrag(modKeys, point, v);
} else {
OpCubeDrag(modKeys, point, v);
}
break;
case OpSelZoom:
break;
case OpLight:
OpLightDrag(modKeys, point, v);
break;
}
}
void TWinDisplay::EvLButtonUp (UINT modKeys, TPoint& point)
{
TWindow::EvLButtonUp(modKeys, point);
// INSERT>> 追加コードはここに
ReleaseCapture();
if (anim->selectstatus == SelNone) {
return;
}
Vector v;
if (type == SelXY) {
v.x = double(point.x - anim->drag_point.x);
v.y = -double(point.y - anim->drag_point.y);
v.z = 0.0;
} else if (type == SelYZ) {
v.x = 0.0;
v.y= double(point.x - anim->drag_point.x);
v.z = -double(point.y - anim->drag_point.y);
} else {
v.x = double(point.x - anim->drag_point.x);
v.y = 0.0;
v.z = -double(point.y - anim->drag_point.y);
}
switch(anim->opstat) {
case OpDefault:
if (anim->selectstatus == SelMode) {
OpSelectMotion(modKeys, point, v);
} else if (anim->selectstatus == SelBezier || anim->selectstatus == SelCube) {
OpBezierEnd(modKeys, point, v);
} else {
OpCubeEnd(modKeys, point, v);
}
break;
case OpLight:
OpLightEnd(modKeys, point, v);
}
anim->selectstatus = SelNone;
}
void TWinDisplay::EvRButtonDown (UINT modKeys, TPoint& point)
{
TWindow::EvRButtonDown(modKeys, point);
// INSERT>> 追加コードはここに
switch(anim->opstat) {
case OpDefault:
if (anim->selectstatus != SelNone) {
if (anim->selectstatus == SelCube || anim->selectstatus == SelBezier) {
if (anim->select->motiondata != NULL) {
anim->select->motiondata->bezier->point[anim->drag_count] = anim->org_point;
}
}
anim->selectstatus = SelNone;
anim->Redraw();
} else if (anim->select != NULL) {
anim->SelectMotion(NULL);
anim->Redraw();
}
break;
case OpSelZoom:
case OpLight:
anim->OpModeDefault();
break;
}
ReleaseCapture();
}
void TWinDisplay::Paint (TDC& dc, BOOL erase, TRect& rect)
{
TWindow::Paint(dc, erase, rect);
// INSERT>> 追加のコードはここに
SelectType t;
if (type == SelYZ) {
t = SelX;
} else if (type == SelZX) {
t = SelY;
} else {
t = SelZ;
}
anim->Redraw(t);
}
void TWinDisplay::Redraw(void)
{
#if 0
TClientDC dc(*this);
#else
TClientDC cdc(*this);
TMemoryDC dc(cdc);
TBitmap bitmap(cdc, Attr.W, Attr.H);
dc.SelectObject(bitmap);
#endif
dc.SelectObject(TPen(cBackGround));
dc.SelectObject(TBrush(cBackGround));
dc.Rectangle(dc.GetClipBox());
ShowMesh(dc);
dc.SetBkColor(cBackGround);
dc.SetTextColor(TColor::White);
switch (type) {
case SelXY:
dc.TextOut(0,0,"上");
break;
case SelYZ:
dc.TextOut(0,0,"前");
break;
case SelZX:
dc.TextOut(0,0,"横");
break;
}
for (Motion *mot = anim->motion; mot != NULL; mot = mot->next) {
if (mot != anim->select) {
ShowMotion(dc, mot);
ShowBezier(dc, mot, FALSE);
}
}
if ((anim->select != anim->camera && anim->select != anim->camera->target)
|| (anim->camera->motiondata != NULL && anim->selectframe != BEGIN && anim->selectframe != anim->maxframe)) {
ShowMotion(dc, anim->camera);
}
if (anim->select == NULL) {
ShowBezier(dc, anim->camera->target, FALSE);
ShowBezier(dc, anim->camera, FALSE);
if (anim->opstat == OpDefault) {
dc.SetROP2(R2_COPYPEN);
dc.SelectObject(TPen(cMarker));
dc.SelectObject(TBrush(cMarker));
for (Motion *mot = anim->motion; mot != NULL; mot = mot->next) {
if (mot != anim->select) {
ShowMarker(dc, mot);
}
}
ShowMarker(dc, anim->camera);
ShowMarker(dc, anim->camera->target);
}
} else if (anim->select == anim->camera) {
ShowBezier(dc, anim->camera->target, FALSE);
ShowBezier(dc, anim->camera, TRUE);
} else if (anim->select == anim->camera->target) {
ShowBezier(dc, anim->camera, FALSE);
ShowBezier(dc, anim->camera->target, TRUE);
} else {
ShowBezier(dc, anim->camera, FALSE);
ShowBezier(dc, anim->camera->target, FALSE);
ShowMotion(dc, anim->select);
ShowBezier(dc, anim->select, TRUE);
}
cdc.BitBlt(0,0,Attr.W, Attr.H, dc, 0, 0, SRCCOPY);
}
void TWinDisplay::ShowMotion(TDC& dc, Motion *mot)
{
if (anim->selectframe < mot->beginframe || mot->endframe < anim->selectframe) {
// || mot == anim->camera->target
// || ((mot == anim->sele&& anim->camera->motioindata != NULL || )) {
return;
}
int cx = Attr.W/2, cy = Attr.H/2;
Matrix m = anim->GetMatrix(mot);
dc.SetROP2(R2_COPYPEN);
if (mot == anim->select || (mot == anim->camera && anim->select == anim->camera->target)) {
dc.SelectObject(TPen(cWireSelect));
} else if (mot == anim->camera) {
if (anim->select != NULL || anim->opstat == OpLight) {
dc.SelectObject(TPen(cWireCameraNoSelect));
} else {
dc.SelectObject(TPen(cWireCamera));
}
} else {
if (anim->select != NULL || anim->opstat == OpLight) {
dc.SelectObject(TPen(cWireNoSelect));
} else {
dc.SelectObject(TPen(cWireNormal));
}
}
int *ppx, *ppy;
switch(type) {
case SelYZ:
ppx = mot->point_y;
ppy = mot->point_z;
break;
case SelZX:
ppx = mot->point_x;
ppy = mot->point_z;
break;
case SelXY:
ppx = mot->point_x;
ppy = mot->point_y;
break;
}
int begin, end = -1;
if (mot->boxflag == FALSE) {
int lno = 0;
if (mot == anim->camera) {
begin = mot->line_1[0];
end = mot->line_2[0];
if (anim->select != NULL || anim->opstat == OpLight) {
dc.SelectObject(TPen(cWireCameraNoSelect,1,PS_DOT));
dc.MoveTo(cx + ppx[begin], cy - ppy[begin]);
dc.LineTo(cx + ppx[end], cy - ppy[end]);
dc.SelectObject(TPen(cWireCameraNoSelect));
} else {
dc.SelectObject(TPen(cWireCamera,1,PS_DOT));
dc.MoveTo(cx + ppx[begin], cy - ppy[begin]);
dc.LineTo(cx + ppx[end], cy - ppy[end]);
dc.SelectObject(TPen(cWireCamera));
}
lno++;
}
for (; lno < mot->lines; ++lno) {
if ((begin = mot->line_1[lno]) != end) {
dc.MoveTo(cx + ppx[begin], cy - ppy[begin]);
}
end = mot->line_2[lno];
dc.LineTo(cx + ppx[end], cy - ppy[end]);
}
} else if (mot->motiondata == NULL) {
dc.MoveTo(cx+ppx[0], cy-ppy[0]);
dc.LineTo(cx+ppx[1], cy-ppy[1]);
dc.LineTo(cx+ppx[2], cy-ppy[2]);
dc.LineTo(cx+ppx[3], cy-ppy[3]);
dc.LineTo(cx+ppx[0], cy-ppy[0]);
dc.LineTo(cx+ppx[4], cy-ppy[4]);
dc.LineTo(cx+ppx[5], cy-ppy[5]);
dc.LineTo(cx+ppx[6], cy-ppy[6]);
dc.LineTo(cx+ppx[7], cy-ppy[7]);
dc.LineTo(cx+ppx[4], cy-ppy[4]);
dc.MoveTo(cx+ppx[1], cy-ppy[1]);
dc.LineTo(cx+ppx[5], cy-ppy[5]);
dc.MoveTo(cx+ppx[2], cy-ppy[2]);
dc.LineTo(cx+ppx[6], cy-ppy[6]);
dc.MoveTo(cx+ppx[3], cy-ppy[3]);
dc.LineTo(cx+ppx[7], cy-ppy[7]);
} else {
dc.MoveTo(cx+ppx[0], cy-ppy[0]);
dc.LineTo(cx+ppx[1], cy-ppy[1]);
dc.LineTo(cx+ppx[2], cy-ppy[2]);
dc.LineTo(cx+ppx[0], cy-ppy[0]);
dc.LineTo(cx+ppx[3], cy-ppy[3]);
dc.LineTo(cx+ppx[4], cy-ppy[4]);
}
}
void TWinDisplay::ShowBezier(TDC& dc, Motion *mot, int flag)
{
if (mot->motiondata == NULL) {
return;
}
Bezier *bez = mot->motiondata->bezier;
Matrix m = GetMatrix();
if (flag == FALSE) {
dc.SetROP2(R2_COPYPEN);
if (anim->select == NULL) {
dc.SelectObject(TPen(cWireLocus));
} else {
dc.SelectObject(TPen(cWireLocusNoSelect,1,PS_DOT));
}
} else {
dc.SetROP2(R2_XORPEN);
dc.SelectObject(TPen(cWireLocusSelect));
// dc.SelectObject(TPen(cBackGround));
}
#if 0
Vector *p = bez->point;
Vector v = m * p[0];
double v0x = v.x, v0y = v.y;
dc.MoveTo(v0x, v0y);
for (int j = 0; j < bez->points; ++j) {
double v1x, v1y, v2x, v2y, v3x, v3y;
v = m * p[1]; v1x = v.x; v1y = v.y;
v = m * p[2]; v2x = v.x; v2y = v.y;
v = m * p[3]; v3x = v.x; v3y = v.y;
for (int i = 1; i < 16; ++i) {
double vx = v0x * bezierrate[i][0] + v1x * bezierrate[i][1] + v2x * bezierrate[i][2] + v3x * bezierrate[i][3];
double vy = v0y * bezierrate[i][0] + v1y * bezierrate[i][1] + v2y * bezierrate[i][2] + v3y * bezierrate[i][3];
dc.LineTo(vx, vy);
}
dc.LineTo(v3x, v3y);
v0x = v3x;
v0y = v3y;
p += 3;
}
#else
{
Vector v0 = m * bez->point[0];
Vector v1 = m * bez->point[1];
Vector v2 = m * bez->point[2];
Vector v3 = m * bez->point[3];
dc.MoveTo(v0.x, v0.y);
for (int i = 1; i < 16; ++i) {
double vx = v0.x * bezierrate[i][0] + v1.x * bezierrate[i][1] + v2.x * bezierrate[i][2] + v3.x * bezierrate[i][3];
double vy = v0.y * bezierrate[i][0] + v1.y * bezierrate[i][1] + v2.y * bezierrate[i][2] + v3.y * bezierrate[i][3];
dc.LineTo(vx, vy);
}
dc.LineTo(v3.x, v3.y);
}
#endif
if (flag == FALSE) {
return;
}
Vector v0 = m * bez->point[0];
Vector v3 = m * bez->point[3];
Vector v1 = m * ((3.0 / 2.0) * bez->point[0] - (1.0/2.0) * bez->point[1]);
Vector v2 = m * ((3.0 / 2.0) * bez->point[3] - (1.0/2.0) * bez->point[2]);
Vector v0v = m * bez->GetVector(0.0) - m.v[3];
v0v.z = 0.0;
Vector v3v = m * bez->GetVector(1.0) - m.v[3];
v3v.z = 0.0;
dc.SelectObject(TPen(cWireBezierSelect,1,PS_DOT));
dc.MoveTo(v0.x, v0.y); dc.LineTo(v1.x, v1.y);
dc.MoveTo(v3.x, v3.y); dc.LineTo(v2.x, v2.y);
dc.SetROP2(R2_COPYPEN);
dc.SelectObject(TPen(cMarkerSelect));
dc.SelectObject(TBrush(cMarkerSelect));
if (v1.x != v0.x || v1.y != v0.y) {
dc.Rectangle(v1.x-markersize, v1.y-markersize,
v1.x+markersize, v1.y+markersize);
}
if (v2.x != v3.x || v2.y != v3.y) {
dc.Rectangle(v2.x-markersize, v2.y-markersize,
v2.x+markersize, v2.y+markersize);
}
dc.SelectObject(TPen(cMarker));
dc.SelectObject(TBrush(cMarker));
double l;
if ((l = v0v.length()) > minimumdouble) {
v0v *= (markersize*1.5/l);
TPoint p[3];
p[0] = TPoint(v0.x + v0v.x , v0.y + v0v.y);
p[1] = TPoint(v0.x - 0.5 * v0v.x - 0.8 * v0v.y, v0.y - 0.5 * v0v.y + 0.8 * v0v.x);
p[2] = TPoint(v0.x - 0.5 * v0v.x + 0.8 * v0v.y, v0.y - 0.5 * v0v.y - 0.8 * v0v.x);
dc.Polygon(p, 3);
} else {
dc.Rectangle(v0.x-markersize, v0.y-markersize,
v0.x+markersize, v0.y+markersize);
}
if ((l = v3v.length()) > minimumdouble) {
v3v *= (markersize*1.5/l);
TPoint p[3];
p[0] = TPoint(v3.x + v3v.x , v3.y + v3v.y);
p[1] = TPoint(v3.x - 0.5 * v3v.x - 0.8 * v3v.y, v3.y - 0.5 * v3v.y + 0.8 * v3v.x);
p[2] = TPoint(v3.x - 0.5 * v3v.x + 0.8 * v3v.y, v3.y - 0.5 * v3v.y - 0.8 * v3v.x);
dc.Polygon(p, 3);
} else {
dc.Rectangle(v3.x-markersize, v3.y-markersize,
v3.x+markersize, v3.y+markersize);
}
}
void TWinDisplay::ShowMarker(TDC& dc, Motion *mot)
{
Matrix m = GetMatrix();
Vector v;
v = m * mot->position;
dc.Rectangle(v.x-markersize, v.y-markersize,
v.x+markersize, v.y+markersize);
}
void TWinDisplay::ShowMesh(TDC& dc)
{
if (anim->meshflag == FALSE) {
return;
}
Vector v = convmatrix * anim->displayoffset;
double bx = - (1.0 / anim->displayscale) * (v.x + Attr.W / 2);
double by = - (1.0 / anim->displayscale) * (v.y + Attr.H / 2);
int cx = (1.0 / anim->displayscale) * (double)Attr.W / (double)anim->meshspacing+1;
int cy = (1.0 / anim->displayscale) * (double)Attr.H / (double)anim->meshspacing+1;
dc.SetROP2(R2_COPYPEN);
dc.SelectObject(TPen(cGrid));
dc.SelectObject(TPen(cGrid,1,PS_DOT));
dc.SetBkMode(TRANSPARENT);
int i;
if (bx < 0) {
bx = -((long)(-bx/anim->meshspacing) ) * anim->meshspacing;
} else {
bx = ((long)( bx/anim->meshspacing)+1) * anim->meshspacing;
}
for (i = 0; i < cx; ++i) {
int x = bx * anim->displayscale + v.x + Attr.W / 2;
if (-anim->meshspacing/2 < bx && bx < anim->meshspacing/2) {
dc.SelectObject(TPen(cGridZero));
dc.MoveTo(x,0);
dc.LineTo(x,Attr.H);
dc.SelectObject(TPen(cGrid,1,PS_DOT));
// dc.SelectObject(TPen(cGrid));
} else {
dc.MoveTo(x,0);
dc.LineTo(x,Attr.H);
}
bx += anim->meshspacing;
}
if (by < 0) {
by = -((long)(-by/anim->meshspacing) ) * anim->meshspacing;
} else {
by = ((long)( by/anim->meshspacing)+1) * anim->meshspacing;
}
for (i = 0; i < cy; ++i) {
int y = -by * anim->displayscale - v.y + Attr.H / 2;
if (-anim->meshspacing/2 < by && by < anim->meshspacing/2) {
dc.SelectObject(TPen(cGridZero));
dc.MoveTo(0,y);
dc.LineTo(Attr.W,y);
dc.SelectObject(TPen(cGrid,1,PS_DOT));
// dc.SelectObject(TPen(cGrid));
} else {
dc.MoveTo(0,y);
dc.LineTo(Attr.W,y);
}
by += anim->meshspacing;
}
}
Matrix TWinDisplay::GetMatrix(void)
{
return Matrix::m_move(Vector(Attr.W/2, Attr.H/2, 0)).scale(Vector(1,-1,1))
* convmatrix.move(anim->displayoffset).scale(anim->displayscale);
}
Matrix TWinDisplay::GetInvMatrix(void)
{
return (Matrix::m_scale(1.0/anim->displayscale).move(-anim->displayoffset) * convmatrix.inv())
.scale(Vector(1, -1, 1)).move(Vector(-Attr.W/2, -Attr.H/2, 0));
}