diff options
Diffstat (limited to 'Magic2/UVMapView.cpp')
-rw-r--r-- | Magic2/UVMapView.cpp | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/Magic2/UVMapView.cpp b/Magic2/UVMapView.cpp new file mode 100644 index 0000000..d775b5c --- /dev/null +++ b/Magic2/UVMapView.cpp @@ -0,0 +1,474 @@ +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: UVMapView.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Implementation of the UVMapView class +*/ + +#include "stdafx.h" +#include "Magic.h" + +#include "MagicDoc.h" +#include "UVMapView.h" +#include "Selector.h" +#include "Selection.h" + +#include "ActiveWindow.h" +#include "Color.h" +#include "Screen.h" +#include "Video.h" + +DWORD GetRealTime(); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// +--------------------------------------------------------------------+ + +UVMapView::UVMapView(Window* c) + : View(c), material(0), zoom(1), x_offset(0), y_offset(0), + nmarks(0), select_mode(SELECT_REPLACE), active(false) +{ +} + +UVMapView::~UVMapView() +{ +} + +// +--------------------------------------------------------------------+ + +const int BATCH_SIZE = 64; + +void +UVMapView::Refresh() +{ + video = Video::GetInstance(); + if (!video) + return; + + window->FillRect(window->GetRect(), Color::LightGray); + + if (material && material->tex_diffuse) { + Bitmap* bmp = material->tex_diffuse; + int w = bmp->Width(); + int h = bmp->Height(); + + double cx = window->Width() / 2 + x_offset; + double cy = window->Height() / 2 + y_offset; + + int x1 = (int) (cx - (zoom * w/2)); + int x2 = (int) (cx + (zoom * w/2)); + int y1 = (int) (cy - (zoom * h/2)); + int y2 = (int) (cy + (zoom * h/2)); + + window->DrawBitmap(x1, y1, x2, y2, bmp); + + ListIter<Poly> iter = polys; + while (++iter) { + Poly* p = iter.value(); + VertexSet* vset = p->vertex_set; + + if (p->material != material) + continue; + + for (int i = 0; i < p->nverts; i++) { + int n1 = p->verts[i]; + int n2 = p->verts[0]; + if (i < p->nverts-1) + n2 = p->verts[i+1]; + + double tu1 = vset->tu[n1]; + double tv1 = vset->tv[n1]; + double tu2 = vset->tu[n2]; + double tv2 = vset->tv[n2]; + + x1 = (int) (cx + zoom * w * (tu1-0.5)); + x2 = (int) (cx + zoom * w * (tu2-0.5)); + y1 = (int) (cy + zoom * h * (tv1-0.5)); + y2 = (int) (cy + zoom * h * (tv2-0.5)); + + window->DrawLine(x1, y1, x2, y2, Color::Yellow); + + if (IsSelected(p, i)) + window->FillRect(x1-3, y1-3, x1+3, y1+3, Color::Yellow); + else + window->DrawRect(x1-2, y1-2, x1+2, y1+2, Color::Yellow); + } + } + } + + if (active && nmarks > 1) { + float points[4*BATCH_SIZE + 4]; + + for (int batch = 0; batch < nmarks; batch += BATCH_SIZE) { + int end = batch + BATCH_SIZE; + if (end > nmarks-1) + end = nmarks-1; + int nlines = end-batch; + + for (int i = 0; i < nlines; i++) { + points[4*i+0] = (float) marks[batch + i].x; + points[4*i+1] = (float) marks[batch + i].y; + points[4*i+2] = (float) marks[batch + i + 1].x; + points[4*i+3] = (float) marks[batch + i + 1].y; + } + + video->DrawScreenLines(nlines, points, Color::Cyan); + } + } + + const char* title = "UV Editor"; + + int len = strlen(title); + Rect r(6,4,200,20); + + r.x += window->GetRect().x; + r.y += window->GetRect().y; + + video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::Black); + + r.x--; + r.y--; + + video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::White); +} + +// +--------------------------------------------------------------------+ + +void +UVMapView::UseMaterial(Material* m) +{ + if (material != m) { + material = m; + zoom = 1; + x_offset = 0; + y_offset = 0; + } +} + +void +UVMapView::UsePolys(List<Poly>& p) +{ + polys.clear(); + polys.append(p); +} + +void +UVMapView::MoveBy(double dx, double dy) +{ + x_offset += dx; + y_offset += dy; +} + +void +UVMapView::DragBy(double dx, double dy) +{ + if (!material || !material->tex_diffuse || selverts.size() < 1) + return; + + Bitmap* bmp = material->tex_diffuse; + double w = zoom * bmp->Width(); + double h = zoom * bmp->Height(); + float du = (float) (dx/w); + float dv = (float) (dy/h); + + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + DWORD value = *svi; + DWORD p = value >> 16; + DWORD n = value & 0xffff; + + Poly* poly = polys[p]; + if (poly && n < poly->nverts) { + VertexSet* vset = poly->vertex_set; + int v = poly->verts[n]; + + vset->tu[v] += du; + vset->tv[v] += dv; + } + } +} + +// +----------------------------------------------------------------------+ + +void +UVMapView::Clear() +{ + selverts.clear(); +} + +void +UVMapView::Begin(int seln_mode) +{ + nmarks = 0; + select_mode = seln_mode; + active = true; +} + +void +UVMapView::AddMark(CPoint& p) +{ + if (nmarks < MAX_MARK) + marks[nmarks++] = p; +} + +void +UVMapView::End() +{ + active = false; + + // get the model: + if (!nmarks || !material || !material->tex_diffuse) return; + + // if not adding to selection: + if (select_mode == SELECT_REPLACE) { + Clear(); + } + + Bitmap* bmp = material->tex_diffuse; + int w = bmp->Width(); + int h = bmp->Height(); + + double cx = window->Width() / 2 + x_offset; + double cy = window->Height() / 2 + y_offset; + + + // if only one mark: + if (nmarks < 2) { + // find all selected verts: + ListIter<Poly> iter = polys; + while (++iter) { + Poly* p = iter.value(); + VertexSet* vset = p->vertex_set; + + for (int i = 0; i < p->nverts; i++) { + int n1 = p->verts[i]; + double tu1 = vset->tu[n1]; + double tv1 = vset->tv[n1]; + + int x1 = (int) (cx + zoom * w * (tu1-0.5)); + int y1 = (int) (cy + zoom * h * (tv1-0.5)); + + int dx = abs(marks[0].x - x1); + int dy = abs(marks[0].y - y1); + + if (dx < 4 && dy < 4) { + WORD p_index = iter.index(); + DWORD value = (p_index << 16) | i; + + if (select_mode == SELECT_REMOVE) { + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) { + selverts.erase(svi); + } + } + } + else { + bool contains = false; + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) { + contains = true; + } + } + if (!contains) + selverts.push_back(value); + } + } + } + } + } + + // otherwise, build a region: + else { + CRgn rgn; + rgn.CreatePolygonRgn(marks, nmarks, WINDING); + + // find all selected verts: + ListIter<Poly> iter = polys; + while (++iter) { + Poly* p = iter.value(); + VertexSet* vset = p->vertex_set; + + for (int i = 0; i < p->nverts; i++) { + int n1 = p->verts[i]; + double tu1 = vset->tu[n1]; + double tv1 = vset->tv[n1]; + + int x1 = (int) (cx + zoom * w * (tu1-0.5)); + int y1 = (int) (cy + zoom * h * (tv1-0.5)); + + CPoint p(x1,y1); + + if (rgn.PtInRegion(p)) { + WORD p_index = iter.index(); + DWORD value = (p_index << 16) | i; + + if (select_mode == SELECT_REMOVE) { + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) + selverts.erase(svi); + } + } + else { + bool contains = false; + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) + contains = true; + } + if (!contains) + selverts.push_back(value); + } + } + } + } + } + + nmarks = 0; +} + +// +----------------------------------------------------------------------+ + +void +UVMapView::SelectAll() +{ + selverts.clear(); + + ListIter<Poly> iter = polys; + while (++iter) { + Poly* p = iter.value(); + + if (p->material != material) + continue; + + for (int i = 0; i < p->nverts; i++) { + WORD p_index = iter.index(); + DWORD value = (p_index << 16) | i; + selverts.push_back(value); + } + } +} + +void +UVMapView::SelectNone() +{ + selverts.clear(); +} + +void +UVMapView::SelectInverse() +{ + ListIter<Poly> iter = polys; + while (++iter) { + Poly* p = iter.value(); + + if (p->material != material) + continue; + + for (int i = 0; i < p->nverts; i++) { + WORD p_index = iter.index(); + DWORD value = (p_index << 16) | i; + + bool contains = false; + auto svi = selverts.begin(); + for (; svi != selverts.end(); ++svi) { + if (*svi == value) { + contains = true; + break; + } + } + + if (contains) + selverts.erase(svi); + else + selverts.push_back(value); + } + } +} + +bool +UVMapView::IsSelected(Poly* poly, WORD v) +{ + WORD p = polys.index(poly); + DWORD value = (p << 16) | v; + + bool contains = false; + + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) + return true; + } + + return false; +} + +bool +UVMapView::WillSelect(CPoint& p) +{ + if (!material || !material->tex_diffuse) + return false; + + Bitmap* bmp = material->tex_diffuse; + int w = bmp->Width(); + int h = bmp->Height(); + + double cx = window->Width() / 2 + x_offset; + double cy = window->Height() / 2 + y_offset; + + // find first selected vert: + ListIter<Poly> iter = polys; + while (++iter) { + Poly* poly = iter.value(); + VertexSet* vset = poly->vertex_set; + + for (int i = 0; i < poly->nverts; i++) { + int n1 = poly->verts[i]; + double tu1 = vset->tu[n1]; + double tv1 = vset->tv[n1]; + + int x1 = (int) (cx + zoom * w * (tu1-0.5)); + int y1 = (int) (cy + zoom * h * (tv1-0.5)); + + int dx = abs(p.x - x1); + int dy = abs(p.y - y1); + + if (dx < 4 && dy < 4) { + return true; + } + } + } + + return false; +} |